aoc-all

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

day08.nim (2670B)


      1 # Copyright (c) 2024, Natacha Porté
      2 #
      3 # Permission to use, copy, modify, and distribute this software for any
      4 # purpose with or without fee is hereby granted, provided that the above
      5 # copyright notice and this permission notice appear in all copies.
      6 #
      7 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      8 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      9 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     10 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     11 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     12 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     13 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     14 
     15 from std/math     import gcd
     16 from std/sequtils import addUnique, concat, deduplicate, toSeq
     17 
     18 # Read input file
     19 
     20 type Point = tuple
     21   x, y: int
     22 
     23 func process_data(data: seq[string]): array[62, seq[Point]] =
     24   var i: int
     25   for y in 0 ..< len(data):
     26     for x in 0 ..< len(data[y]):
     27       case data[y][x]
     28       of '.':
     29         continue
     30       of '0' .. '9':
     31         i = ord(data[y][x]) - ord('0')
     32       of 'A' .. 'Z':
     33         i = ord(data[y][x]) - ord('A') + 10
     34       of 'a' .. 'z':
     35         i = ord(data[y][x]) - ord('a') + 36
     36       else:
     37         assert(false)
     38 
     39       result[i].add((x, y))
     40 
     41 let
     42   data = stdin.lines().toSeq()
     43   nlines = len(data)
     44   ncols = len(data[0])
     45   coord = process_data(data)
     46 
     47 # Puzzle 1
     48 
     49 func antinodes(s: seq[Point], corner: Point): seq[Point] =
     50   for i in 0 ..< len(s):
     51     for j in 0 ..< len(s):
     52       if i == j:
     53         continue
     54       let n = (x: 2*s[i].x - s[j].x, y: 2*s[i].y - s[j].y)
     55       if n.x >= 0 and n.y >= 0 and n.x <= corner.x and n.y <= corner.y:
     56         result.addUnique(n)
     57 
     58 func all_antinodes(d: openArray[seq[Point]], corner: Point): seq[Point] =
     59   for s in d:
     60     result = deduplicate(concat(result, antinodes(s, corner)))
     61 
     62 echo "Puzzle 1: ", len(all_antinodes(coord, (ncols - 1, nlines - 1)))
     63 
     64 # Puzzle 2
     65 
     66 func antinodes2(s: seq[Point], corner: Point): seq[Point] =
     67   for i in 0 ..< len(s):
     68     for j in 0 ..< len(s):
     69       if i == j:
     70         continue
     71       let
     72         ld = (x: s[i].x - s[j].x, y: s[i].y - s[j].y)
     73         g = gcd(ld.x, ld.y)
     74         d = (x: ld.x div g, y: ld.y div g)
     75       var p = s[i]
     76       while p.x >= 0 and p.y >= 0 and p.x <= corner.x and p.y <= corner.y:
     77         result.addUnique(p)
     78         p.x += d.x
     79         p.y += d.y
     80 
     81 func all_antinodes2(d: openArray[seq[Point]], corner: Point): seq[Point] =
     82   for s in d:
     83     result = deduplicate(concat(result, antinodes2(s, corner)))
     84 
     85 echo "Puzzle 2: ", len(all_antinodes2(coord, (ncols - 1, nlines - 1)))