aoc-all

My solutions to all Advent of Code
git clone https://git.instinctive.eu/aoc-all.git
Log | Files | Refs | README | LICENSE

commit b4ccb3a2eff5bda2b0ba6227d85d9a3ea559fc0e
parent 3d102d8c3a39a8746d36f14e287e5432f3f1201a
Author: Natasha Kerensikova <natgh@instinctive.eu>
Date:   Fri, 20 Dec 2024 17:54:53 +0000

Day 20 reference and solutions
Diffstat:
A2024/day20.nim | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A2024/ref/day20.txt | 15+++++++++++++++
2 files changed, 127 insertions(+), 0 deletions(-)

diff --git a/2024/day20.nim b/2024/day20.nim @@ -0,0 +1,112 @@ +# Copyright (c) 2024, Natacha Porté +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from std/algorithm import sorted +from std/sequtils import toSeq +from std/tables import `[]`, `[]=`, getOrDefault, initTable, keys, pairs, Table + +# Read input file + +type + Point = tuple + x, y: int + +func `+`(a, b: Point): Point = (x: a.x + b.x, y: a.y + b.y) +func `[]`(m: seq[string], p: Point): char = m[p.y][p.x] + +func neighbors(m: seq[string], p: Point): seq[Point] = + let s = @[(x: p.x + 1, y: p.y), (x: p.x - 1, y: p.y), (x: p.x, y: p.y - 1), (x: p.x, y: p.y + 1)] + for n in s: + if n.x >= 0 and n.y >= 0 and n.y < len(m) and n.x < len(m[n.y]) and m[n] != '#': + result.add(n) + +func race_path(m: seq[string]): seq[Point] = + for y in 0 ..< len(m): + for x in 0 ..< len(m[y]): + if m[y][x] == 'S': + assert len(result) == 0 + result.add((x: x, y: y)) + assert len(neighbors(m, result[0])) == 1 + result.add(neighbors(m, result[0])[0]) + + while m[result[^1]] != 'E': + let n = neighbors(m, result[^1]) + assert len(n) == 2 + if n[0] == result[^2]: + result.add(n[1]) + else: + assert n[1] == result[^2] + result.add(n[0]) + +let + data = stdin.lines().toSeq() + path = race_path(data) + +# Puzzle 1 + +func count_shortcuts1(s: seq[Point]): Table[int, int] = + for start in 0 .. len(s) - 4: + for dest in start + 3 .. len(s) - 1: + if (s[start].x == s[dest].x and abs(s[start].y - s[dest].y) == 2) or (s[start].y == s[dest].y and abs(s[start].x - s[dest].x) == 2): + let k = dest - start - 2 + result[k] = result.getOrDefault(k, 0) + 1 + +proc puzzle1(s: seq[Point]): void = + let shortcuts = count_shortcuts1(path) + var sum = 0 + + for k, v in shortcuts.pairs: + if k >= 100: + sum += v + + if sum == 0: + echo "Puzzle 1:" + for k in shortcuts.keys.toSeq.sorted: + if shortcuts[k] >= 2: + echo " - There are ", shortcuts[k], " cheats saving ", k, " ps" + else: + echo " - There is one cheat saving ", k, " ps" + else: + echo "Puzzle 1: ", sum + +puzzle1(path) + +# Puzzle 2 + +func count_shortcuts2(s: seq[Point]): Table[int, int] = + for start in 0 .. len(s) - 4: + for dest in start + 3 .. len(s) - 1: + let + d = abs(s[start].x - s[dest].x) + abs(s[start].y - s[dest].y) + k = dest - start - d + if d <= 20 and k > 0: + result[k] = result.getOrDefault(k, 0) + 1 + +proc puzzle2(s: seq[Point]): void = + let shortcuts = count_shortcuts2(path) + var sum = 0 + + for k, v in shortcuts.pairs: + if k >= 100: + sum += v + + if sum == 0: + echo "Puzzle 2:" + for k in shortcuts.keys.toSeq.sorted: + if k >= 50: + echo " - There are ", shortcuts[k], " cheats saving ", k, " ps" + else: + echo "Puzzle 2: ", sum + +puzzle2(path) diff --git a/2024/ref/day20.txt b/2024/ref/day20.txt @@ -0,0 +1,15 @@ +############### +#...#...#.....# +#.#.#.#.#.###.# +#S#...#.#.#...# +#######.#.#.### +#######.#.#...# +#######.#.###.# +###..E#...#...# +###.#######.### +#...###...#...# +#.#####.#.###.# +#.#...#.#.#...# +#.#.#.#.#.#.### +#...#...#...### +###############