import 2017 solutions I found in my github gists
This commit is contained in:
parent
fc0f216511
commit
568a43b115
|
@ -0,0 +1,4 @@
|
||||||
|
# 2017
|
||||||
|
While going through my Github gists, I found a few AoC days from 2017, so I decided to include them here for later reference.
|
||||||
|
|
||||||
|
Apparently, I got a total of 15 stars that year, but I have no idea where my code for most of the solutions is.
|
|
@ -0,0 +1,69 @@
|
||||||
|
import tables
|
||||||
|
import nre
|
||||||
|
import strutils
|
||||||
|
|
||||||
|
|
||||||
|
let pattern = re"(?<target>\w+)\s(?<opcode>(inc|dec))\s(?<value>-?\d+)\sif\s(?<comptarget>\w+)\s(?<compop>(<|>|==|!=|<=|>=))\s(?<comp2>-?\d+)"
|
||||||
|
|
||||||
|
var registers = initTable[string, int]();
|
||||||
|
|
||||||
|
|
||||||
|
proc parseLine(li: string): RegexMatch =
|
||||||
|
let found = nre.find(li, pattern)
|
||||||
|
if found.isNone:
|
||||||
|
echo("mismatch")
|
||||||
|
return
|
||||||
|
return found.get()
|
||||||
|
|
||||||
|
|
||||||
|
proc compare(target: string, val2: int, op: string): bool =
|
||||||
|
# text parsing done right ヽ( ゚ヮ・)ノ
|
||||||
|
let val1 = registers[target]
|
||||||
|
case op
|
||||||
|
of "<":
|
||||||
|
return val1 < val2;
|
||||||
|
of ">":
|
||||||
|
return val1 > val2;
|
||||||
|
of "==":
|
||||||
|
return val1 == val2;
|
||||||
|
of "!=":
|
||||||
|
return val1 != val2;
|
||||||
|
of "<=":
|
||||||
|
return val1 <= val2;
|
||||||
|
of ">=":
|
||||||
|
return val1 >= val2;
|
||||||
|
else: discard
|
||||||
|
|
||||||
|
|
||||||
|
proc changeRegister(r: string, op: string, val: int): void =
|
||||||
|
# only ‘inc’ and ‘dec’ are possible
|
||||||
|
if op == "inc":
|
||||||
|
registers[r] += val
|
||||||
|
else:
|
||||||
|
registers[r] -= val
|
||||||
|
|
||||||
|
|
||||||
|
proc executeLine(ins: Table): void =
|
||||||
|
# set registers to 0 if they haven’t been initialized
|
||||||
|
if not registers.hasKey(ins["comptarget"]):
|
||||||
|
registers[ins["comptarget"]] = 0
|
||||||
|
if not registers.hasKey(ins["target"]):
|
||||||
|
registers[ins["target"]] = 0
|
||||||
|
# do math... or don’t
|
||||||
|
if compare(ins["comptarget"], parseInt(ins["comp2"]), ins["compop"]):
|
||||||
|
changeRegister(ins["target"], ins["opcode"], parseInt(ins["value"]))
|
||||||
|
|
||||||
|
|
||||||
|
for line in lines "day8.txt":
|
||||||
|
let parsed = parseLine(line)
|
||||||
|
executeLine(parsed.captures.toTable())
|
||||||
|
|
||||||
|
|
||||||
|
# returning a list like with python’s dict.values doesn’t seem to work.
|
||||||
|
# is there a way to convert iterables to arrays?
|
||||||
|
var maximum = 0
|
||||||
|
for v in values(registers):
|
||||||
|
if v > maximum:
|
||||||
|
maximum = v
|
||||||
|
|
||||||
|
echo(maximum)
|
|
@ -0,0 +1,83 @@
|
||||||
|
import sequtils
|
||||||
|
import future
|
||||||
|
import nre except toSeq
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
type
|
||||||
|
Direction = enum
|
||||||
|
up = 0, left = 1, down = 2, right = 3
|
||||||
|
Grid = seq[seq[char]]
|
||||||
|
|
||||||
|
const directions = [up, left, down, right]
|
||||||
|
|
||||||
|
proc indexOf(hay: seq[char], needle: char): int =
|
||||||
|
# It almost seems weird that this doesn’t already exist...
|
||||||
|
# It probably does, and I just missed it. Whatever, no error handling because :lul:
|
||||||
|
var i = 0
|
||||||
|
while hay[i] != needle:
|
||||||
|
i += 1
|
||||||
|
return i
|
||||||
|
|
||||||
|
|
||||||
|
proc gridGet(g: Grid, p: array[2, int]): char =
|
||||||
|
return g[p[0]][p[1]]
|
||||||
|
|
||||||
|
|
||||||
|
proc changePosition(current: array[2, int], dir: Direction): array[2, int] =
|
||||||
|
if dir == up:
|
||||||
|
return [current[0]-1, current[1]]
|
||||||
|
if dir == left:
|
||||||
|
return [current[0], current[1]-1]
|
||||||
|
if dir == down:
|
||||||
|
return [current[0]+1, current[1]]
|
||||||
|
if dir == right:
|
||||||
|
return [current[0], current[1]+1]
|
||||||
|
|
||||||
|
|
||||||
|
proc oppositeDirection(d: Direction): Direction =
|
||||||
|
# the better solution would be something like
|
||||||
|
# mod(getEnumOrdinal(direction, $direction) + 2, 4)
|
||||||
|
# but that doesn’t quite work because I’m bad at this whole thing
|
||||||
|
case d
|
||||||
|
of up: return down
|
||||||
|
of left: return right
|
||||||
|
of down: return up
|
||||||
|
of right: return left
|
||||||
|
else: discard
|
||||||
|
|
||||||
|
proc changeDirection(g: Grid, pos: array[2, int], direction: Direction): Direction =
|
||||||
|
for d in directions:
|
||||||
|
if d != oppositeDirection(direction) and gridGet(g, changePosition(pos, d)) != ' ':
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
let grid = lc[toSeq(line.items()) | (line <- lines("input.txt")), seq[char]]
|
||||||
|
|
||||||
|
var position = [0, indexOf(grid[0], '|')]
|
||||||
|
var direction = down
|
||||||
|
var done = false
|
||||||
|
var visited = ""
|
||||||
|
var newchar: char
|
||||||
|
var steps = 1
|
||||||
|
|
||||||
|
while not done:
|
||||||
|
#echo position[0], ", ", position[1]
|
||||||
|
#echo direction
|
||||||
|
var newpos = changePosition(position, direction)
|
||||||
|
newchar = gridGet(grid, newpos)
|
||||||
|
#echo(newchar)
|
||||||
|
if newchar in ['|', '-']:
|
||||||
|
inc steps
|
||||||
|
elif newchar == '+':
|
||||||
|
inc steps
|
||||||
|
direction = changeDirection(grid, newpos, direction)
|
||||||
|
elif nre.contains($newchar, re"[A-Z]"):
|
||||||
|
inc steps
|
||||||
|
visited &= newchar
|
||||||
|
elif newchar == ' ':
|
||||||
|
done = true
|
||||||
|
position = newpos
|
||||||
|
|
||||||
|
echo(visited)
|
||||||
|
echo(steps)
|
|
@ -0,0 +1,108 @@
|
||||||
|
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)
|
Loading…
Reference in New Issue
Block a user