From 568a43b115d81f1d86ac6446471621702aea6fcd Mon Sep 17 00:00:00 2001 From: kageru Date: Mon, 16 Oct 2023 12:05:22 +0200 Subject: [PATCH] import 2017 solutions I found in my github gists --- 2017/README.md | 4 ++ 2017/day08.nim | 69 +++++++++++++++++++++++++++++++ 2017/day19.nim | 83 +++++++++++++++++++++++++++++++++++++ 2017/day20.nim | 108 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 264 insertions(+) create mode 100644 2017/README.md create mode 100644 2017/day08.nim create mode 100644 2017/day19.nim create mode 100644 2017/day20.nim diff --git a/2017/README.md b/2017/README.md new file mode 100644 index 0000000..dedab47 --- /dev/null +++ b/2017/README.md @@ -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. diff --git a/2017/day08.nim b/2017/day08.nim new file mode 100644 index 0000000..7b18ba6 --- /dev/null +++ b/2017/day08.nim @@ -0,0 +1,69 @@ +import tables +import nre +import strutils + + +let pattern = re"(?\w+)\s(?(inc|dec))\s(?-?\d+)\sif\s(?\w+)\s(?(<|>|==|!=|<=|>=))\s(?-?\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) diff --git a/2017/day19.nim b/2017/day19.nim new file mode 100644 index 0000000..33df4d8 --- /dev/null +++ b/2017/day19.nim @@ -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) diff --git a/2017/day20.nim b/2017/day20.nim new file mode 100644 index 0000000..b88d512 --- /dev/null +++ b/2017/day20.nim @@ -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=.(?-?\d+),(?-?\d+),(?-?\d+).,\sv=.(?-?\d+),(?-?\d+),(?-?\d+).,\sa=.(?-?\d+),(?-?\d+),(?-?\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)