aboutsummaryrefslogtreecommitdiff
path: root/2022/nim/day09/src/main.nim
blob: 7432fd29a7941bd60aaeeb912e3f34297772cbb2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# Day 9: Rope Bridge
import std/[os, strutils, sequtils, sets]

let input = paramStr(1).readFile().strip().split("\n")
let directions = input.mapIt(it.split(" ")).mapIt((it[0][0], it[1].parseInt()))

type Pos = ref object # must be ref for mutation
  x: int
  y: int

type Knot = ref object
  pos: Pos
  prev: Knot

func init(_: typedesc[Knot], prev: Knot): Knot =
  return Knot(pos: Pos(x: 0, y: 0), prev: prev)

proc update(loc, knot: Knot) =
  let dx = loc.pos.x - knot.pos.x
  let dy = loc.pos.y - knot.pos.y

  if abs(dx) == 2:
    knot.pos.x += dx div 2
    if dy != 0:
      knot.pos.y += dy div abs(dy)
  elif abs(dy) == 2:
    knot.pos.y += dy div 2
    if dx != 0:
      knot.pos.x += dx div abs(dx)

proc update(knots: varargs[Knot]) =
  for i, knot in knots:
    update(knot.prev, knot)

var visited = initHashSet[(int, int)]()
var visitedAgain = initHashSet[(int, int)]()

var
  head = Knot.init(nil)
  tail = Knot.init(head)

var
  one = Knot.init(head)
  two = Knot.init(one)
  three = Knot.init(two)
  four = Knot.init(three)
  five = Knot.init(four)
  six = Knot.init(five)
  seven = Knot.init(six)
  eight = Knot.init(seven)
  nine = Knot.init(eight)

for dir in directions:
  for i in 0 ..< dir[1]:
    if dir[0]   == 'R': head.pos.x += 1
    elif dir[0] == 'L': head.pos.x -= 1
    elif dir[0] == 'U': head.pos.y += 1
    elif dir[0] == 'D': head.pos.y -= 1

    update(head, tail)
    visited.incl((tail.pos.x, tail.pos.y))
    update(one, two, three, four, five, six, seven, eight, nine)
    visitedAgain.incl((nine.pos.x, nine.pos.y))

echo visited.len
echo visitedAgain.len