My solutions to 2018's advent of code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

day16.nim 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import sequtils, strutils
  2. let ops = [
  3. proc(regs: seq[int], a,b: int): int = regs[a] + b,
  4. proc(regs: seq[int], a,b: int): int = regs[a] + regs[b],
  5. proc(regs: seq[int], a,b: int): int = regs[a] * b,
  6. proc(regs: seq[int], a,b: int): int = regs[a] * regs[b],
  7. proc(regs: seq[int], a,b: int): int = regs[a] and b,
  8. proc(regs: seq[int], a,b: int): int = regs[a] and regs[b],
  9. proc(regs: seq[int], a,b: int): int = regs[a] or b,
  10. proc(regs: seq[int], a,b: int): int = regs[a] or regs[b],
  11. proc(regs: seq[int], a,b: int): int = a,
  12. proc(regs: seq[int], a,b: int): int = regs[a],
  13. proc(regs: seq[int], a,b: int): int = cast[int](a > regs[b]),
  14. proc(regs: seq[int], a,b: int): int = cast[int](regs[a] > b),
  15. proc(regs: seq[int], a,b: int): int = cast[int](regs[a] > regs[b]),
  16. proc(regs: seq[int], a,b: int): int = cast[int](a == regs[b]),
  17. proc(regs: seq[int], a,b: int): int = cast[int](regs[a] == b),
  18. proc(regs: seq[int], a,b: int): int = cast[int](regs[a] == regs[b]),
  19. ]
  20. func toInstr(line: string): seq[int] = line.strip.split(" ").map(parseInt)
  21. func toRegisterSample(line: string): seq[int] = line.substr(9, line.len - 2).split(", ").map(parseInt)
  22. proc execute(regs: var seq[int], instr: seq[int], opcodes: array[16, proc(regs: seq[int], a,b: int): int]) =
  23. regs[instr[3]] = opcodes[instr[0]](regs, instr[1], instr[2])
  24. var
  25. before, instr, after: seq[int]
  26. opPossibilities: array[16, array[16, bool]]
  27. opMappings: array[16, proc(regs: seq[int], a,b: int): int]
  28. threeOrMore = 0
  29. step = 0
  30. registers = @[0, 0, 0, 0]
  31. for line in readFile("data/16.txt").splitlines:
  32. if step == 0 and line.len > 6 and line[0..5] == "Before":
  33. before = line.toRegisterSample
  34. step.inc
  35. elif step == 1:
  36. instr = line.toInstr
  37. step.inc
  38. elif step == 2:
  39. after = line.toRegisterSample
  40. var count = 0
  41. for i, op in ops:
  42. var actual: seq[int]
  43. actual.shallowCopy(before)
  44. actual[instr[3]] = op(before, instr[1], instr[2])
  45. if actual == after:
  46. count.inc
  47. else:
  48. opPossibilities[instr[0]][i] = true
  49. if count >= 3:
  50. threeOrMore.inc
  51. step = 0
  52. if step == 0 and line.len > 5 and line[0].isdigit:
  53. # First instruction found after the samples -- figure out which
  54. # opcode belongs to which...
  55. var found: array[16, bool]
  56. while not found.all(proc(v: bool): bool = v):
  57. for opcode, possibilities in opPossibilities:
  58. let matrix = zip(possibilities, found)
  59. if matrix.count((false, false)) == 1:
  60. let index = matrix.find((false, false))
  61. found[index] = true
  62. opMappings[opcode] = ops[index]
  63. step = -1
  64. if step == -1 and line.len > 5:
  65. registers.execute(line.toInstr, opMappings)
  66. echo threeOrMore
  67. echo registers[0]