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 2.0KB

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