parent
ef98db2967
commit
3d7ac83d3f
@ -0,0 +1,215 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"bufio" |
||||
"fmt" |
||||
"log" |
||||
"math" |
||||
"os" |
||||
"strconv" |
||||
"strings" |
||||
) |
||||
|
||||
var particles map[int]*Particle |
||||
var confidenceThreshold int |
||||
|
||||
func main() { |
||||
inp := StdinToStrings() |
||||
particles = make(map[int]*Particle) |
||||
for i := range inp { |
||||
particles[i] = NewParticle(inp[i], i) |
||||
} |
||||
confidenceThreshold = 1000 |
||||
doPart := 2 |
||||
if len(os.Args) > 1 { |
||||
if os.Args[1] == "-1" { |
||||
doPart = 1 |
||||
} |
||||
} |
||||
switch doPart { |
||||
case 1: |
||||
part1(inp) |
||||
case 2: |
||||
part2(inp) |
||||
} |
||||
} |
||||
|
||||
func part1(inp []string) { |
||||
var ticks, confidence, last int |
||||
cPart := -1 |
||||
for { |
||||
cDist := 10000000000 |
||||
ticks++ |
||||
for i := range particles { |
||||
particles[i].Tick() |
||||
if particles[i].GetDistance() < cDist { |
||||
cPart = i |
||||
cDist = particles[i].GetDistance() |
||||
} |
||||
} |
||||
if cPart == last { |
||||
confidence++ |
||||
} else { |
||||
confidence = 0 |
||||
last = cPart |
||||
} |
||||
if confidence >= confidenceThreshold { |
||||
break |
||||
} |
||||
} |
||||
fmt.Println("After", ticks, "the closest is", cPart) |
||||
} |
||||
|
||||
func part2(inp []string) { |
||||
var ticks, lastNum, confidence int |
||||
for { |
||||
ticks++ |
||||
for i := range particles { |
||||
particles[i].Tick() |
||||
} |
||||
var collisions []int |
||||
for k1, v1 := range particles { |
||||
for k2, v2 := range particles { |
||||
if k1 == k2 { |
||||
continue |
||||
} |
||||
if v1.Collides(v2) { |
||||
collisions = AddToSlice(collisions, k1) |
||||
collisions = AddToSlice(collisions, k2) |
||||
break |
||||
} |
||||
} |
||||
} |
||||
for i := len(collisions) - 1; i >= 0; i-- { |
||||
delete(particles, collisions[i]) |
||||
} |
||||
if len(particles) == lastNum { |
||||
confidence++ |
||||
} else { |
||||
confidence = 0 |
||||
lastNum = len(particles) |
||||
} |
||||
if confidence >= confidenceThreshold { |
||||
break |
||||
} |
||||
} |
||||
fmt.Println("After", ticks, "there are", len(particles), "particles left") |
||||
} |
||||
|
||||
func AddToSlice(sl []int, v int) []int { |
||||
for i := range sl { |
||||
if sl[i] == v { |
||||
return sl |
||||
} |
||||
} |
||||
sl = append(sl, v) |
||||
return sl |
||||
} |
||||
|
||||
type Coordinate struct { |
||||
X, Y, Z int |
||||
} |
||||
|
||||
func NewCoordinate(inp string) Coordinate { |
||||
inp = inp[1 : len(inp)-1] |
||||
pts := strings.Split(inp, ",") |
||||
px, py, pz := Atoi(pts[0]), Atoi(pts[1]), Atoi(pts[2]) |
||||
return Coordinate{X: px, Y: py, Z: pz} |
||||
} |
||||
|
||||
func (c *Coordinate) toString() string { |
||||
return fmt.Sprintf("<%d,%d,%d>", c.X, c.Y, c.Z) |
||||
} |
||||
|
||||
type Particle struct { |
||||
Index int |
||||
Position Coordinate |
||||
Velocity Coordinate |
||||
Acceleration Coordinate |
||||
|
||||
LastPosition Coordinate |
||||
} |
||||
|
||||
func NewParticle(inp string, idx int) *Particle { |
||||
ret := new(Particle) |
||||
ret.Index = idx |
||||
pts := strings.Split(inp, " ") |
||||
for i := range pts { |
||||
keyVal := strings.Split(pts[i], "=") |
||||
if keyVal[1][len(keyVal[1])-1] == ',' { |
||||
keyVal[1] = keyVal[1][:len(keyVal[1])-1] |
||||
} |
||||
switch keyVal[0] { |
||||
case "p": |
||||
ret.Position = NewCoordinate(keyVal[1]) |
||||
case "v": |
||||
ret.Velocity = NewCoordinate(keyVal[1]) |
||||
case "a": |
||||
ret.Acceleration = NewCoordinate(keyVal[1]) |
||||
} |
||||
} |
||||
ret.LastPosition = NewCoordinate(ret.Position.toString()) |
||||
return ret |
||||
} |
||||
|
||||
func (p *Particle) Collides(tst *Particle) bool { |
||||
if p.Position.X == tst.Position.X && |
||||
p.Position.Y == tst.Position.Y && |
||||
p.Position.Z == tst.Position.Z { |
||||
return true |
||||
} |
||||
return false |
||||
} |
||||
|
||||
func (p *Particle) String() string { |
||||
return fmt.Sprintf( |
||||
"p=<%d,%d,%d>, v=<%d,%d,%d>, a=<%d,%d,%d>", |
||||
p.Position.X, p.Position.Y, p.Position.Z, |
||||
p.Velocity.X, p.Velocity.Y, p.Velocity.Z, |
||||
p.Acceleration.X, p.Acceleration.Y, p.Acceleration.Z, |
||||
) |
||||
} |
||||
|
||||
func (p *Particle) Tick() { |
||||
p.LastPosition = NewCoordinate(p.Position.toString()) |
||||
p.Velocity.X += p.Acceleration.X |
||||
p.Velocity.Y += p.Acceleration.Y |
||||
p.Velocity.Z += p.Acceleration.Z |
||||
p.Position.X += p.Velocity.X |
||||
p.Position.Y += p.Velocity.Y |
||||
p.Position.Z += p.Velocity.Z |
||||
} |
||||
|
||||
func (p *Particle) IsDone() bool { |
||||
return p.GetDistance() == p.GetLastDistance() |
||||
} |
||||
|
||||
func (p *Particle) GetDistance() int { |
||||
return GetAbs(p.Position.X) + GetAbs(p.Position.Y) + GetAbs(p.Position.Z) |
||||
} |
||||
|
||||
func (p *Particle) GetLastDistance() int { |
||||
return int(math.Abs(float64(p.LastPosition.X + p.LastPosition.Y + p.LastPosition.Z))) |
||||
} |
||||
|
||||
func StdinToStrings() []string { |
||||
var input []string |
||||
scanner := bufio.NewScanner(os.Stdin) |
||||
for scanner.Scan() { |
||||
input = append(input, scanner.Text()) |
||||
} |
||||
return input |
||||
} |
||||
|
||||
func GetAbs(v int) int { |
||||
return int(math.Abs(float64(v))) |
||||
} |
||||
|
||||
func Atoi(i string) int { |
||||
var ret int |
||||
var err error |
||||
if ret, err = strconv.Atoi(i); err != nil { |
||||
log.Fatal("Invalid Atoi") |
||||
} |
||||
return ret |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,2 @@ |
||||
p=<3,0,0>, v=<2,0,0>, a=<-1,0,0> |
||||
p=<4,0,0>, v=<0,0,0>, a=<-2,0,0> |
Loading…
Reference in new issue