advent-of-code/2017/day20.nim

109 lines
2.8 KiB
Nim

import strutils
import future
import nre
# 3-dimensional vector type with attributes for x, y, and z
# Mainly used for readability
type Vector = object
x, y, z: int
# Are there proper constructors in nim?
# I guess this is... something.
proc newVector(x: int, y: int, z: int): Vector =
var v: Vector
v.x = x
v.y = y
v.z = z
return v
# Manhattan Distance. Should be self-explanatory
method manhattan(this: Vector): int {.base.} =
return abs(this.x) + abs(this.y) + abs(this.z)
proc countZeros(v: Vector): int =
var z = 0
for c in [v.x, v.y, v.z]:
if c == 0:
inc z
return z
proc `$`(v: Vector): string =
return $v.x & ", " & $v.y & ", " & $v.z
proc `<`(a: Vector, b:Vector): bool =
if manhattan(a) == manhattan(b):
return countZeros(a) < countZeros(b)
return manhattan(a) < manhattan(b)
proc `>`(a: Vector, b:Vector): bool =
if a == b:
return countZeros(a) > countZeros(b)
return manhattan(a) > manhattan(b)
proc `==`(a: Vector, b:Vector): bool =
return a.x == b.x and a.y == b.y and a.z == b.z
proc `!=`(a: Vector, b:Vector): bool =
return not (a == b)
type Particle = object
number: int
velocity: Vector
acceleration: Vector
position: Vector
proc newParticle(n: int, vel: Vector, acc: Vector, pos: Vector): Particle =
var p: Particle
p.number = n
p.velocity = vel
p.acceleration = acc
p.position = pos
return p
proc `>`(a: Particle, b: Particle): bool =
if a.acceleration == b.acceleration:
if a.velocity == b.velocity:
return a.position > b.position
return a.velocity > b.velocity
return a.acceleration > b.acceleration
proc `<`(a: Particle, b: Particle): bool =
if a.acceleration == b.acceleration:
if a.velocity == b.velocity:
return a.position < b.position
return a.velocity < b.velocity
return a.acceleration < b.acceleration
proc min(arr: seq[Particle]): Particle =
var m = arr[0]
for p in arr:
if p < m:
m = p
return m
let input = lc[line | (line <- lines("input.txt")), string]
var particles: seq[Particle] = @[]
# p=<-1027,-979,-188>, v=<7,60,66>, a=<9,1,-7>
for i in 0..(len(input)-1):
let line = input[i]
let parsed = nre.match(line, re"p=.(?<px>-?\d+),(?<py>-?\d+),(?<pz>-?\d+).,\sv=.(?<vx>-?\d+),(?<vy>-?\d+),(?<vz>-?\d+).,\sa=.(?<ax>-?\d+),(?<ay>-?\d+),(?<az>-?\d+)")
if parsed.isNone():
echo("Could not parse ", line)
continue
let matched = parsed.get().captures
# echo(i, ": ", line)
particles.add(
newParticle(i,
newVector(parseInt(matched["vx"]), parseInt(matched["vy"]), parseInt(matched["vz"])),
newVector(parseInt(matched["ax"]), parseInt(matched["ay"]), parseInt(matched["az"])),
newVector(parseInt(matched["px"]), parseInt(matched["py"]), parseInt(matched["pz"]))
)
)
echo(min(particles).number)