import 2017 solutions I found in my github gists

This commit is contained in:
kageru 2023-10-16 12:05:22 +02:00
parent fc0f216511
commit 568a43b115
4 changed files with 264 additions and 0 deletions

4
2017/README.md Normal file
View File

@ -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.

69
2017/day08.nim Normal file
View File

@ -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)

83
2017/day19.nim Normal file
View File

@ -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)

108
2017/day20.nim Normal file
View File

@ -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)