Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

day13.py 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import json
  2. import pathlib
  3. import sys
  4. def parse(puzzle_input: str) -> list[list[int, ...]]:
  5. """Convert str representations of lists into real int lists"""
  6. str_pkts: list[list[str, str]] = [
  7. packet.splitlines() for packet in puzzle_input.split("\n\n")
  8. ]
  9. int_pkts: list[list[int, ...]] = []
  10. for pkt in str_pkts:
  11. int_pk: list[int, ...] = []
  12. for pk in pkt:
  13. # Here's the magick - I'm highly averse to eval()
  14. int_pk.append(json.loads(pk))
  15. int_pkts.append(int_pk)
  16. return int_pkts
  17. def compare(l: int, r: int) -> int:
  18. """Compare 2 ints, return 1, 0, -1 depending on values"""
  19. if l < r:
  20. return 1
  21. elif l > r:
  22. return -1
  23. else:
  24. return 0
  25. def compare_packets(left: list[int, ...], right: list[int, ...]) -> int:
  26. """Compare 2 lists to establish correct order"""
  27. match left, right:
  28. case int(), int():
  29. return compare(left, right)
  30. case int(), list():
  31. return compare_packets([left], right)
  32. case list(), int():
  33. return compare_packets(left, [right])
  34. case list(), list():
  35. for l, r in zip(left, right):
  36. res = compare_packets(l, r)
  37. if res != 0:
  38. return res
  39. return compare_packets(len(left), len(right))
  40. def part1(pairs: list[list[int, ...]]) -> int:
  41. """Solve part 1"""
  42. sum_of_indices: int = 0
  43. for idx, pair in enumerate(pairs):
  44. if compare_packets(*pair) == 1:
  45. sum_of_indices += idx + 1
  46. return sum_of_indices
  47. def flatten(l: list[list[int]]) -> list[int]:
  48. """Flatten a nested list one level"""
  49. return [item for sublist in l for item in sublist]
  50. def find_index(l: list[list[int]], item: list[int]) -> int:
  51. """Return index of where item falls in list"""
  52. item_idx: int = 0
  53. for pkt in flatten(l):
  54. if compare_packets(pkt, item) == 1:
  55. item_idx += 1
  56. return item_idx
  57. def part2(pairs: list[list[int, ...]]) -> int:
  58. """Solve part 2"""
  59. # Remove one layer of list to match flattened list above
  60. first_divider: list[int] = [2]
  61. second_divider: list[int] = [6]
  62. first_pos: int = find_index(pairs, first_divider) + 1
  63. second_pos: int = find_index(pairs, second_divider) + 2
  64. return first_pos * second_pos
  65. def solve(puzzle_input: str) -> tuple[int, int]:
  66. """Solve the puzzle for the given input"""
  67. data: list[list[int, ...]] = parse(puzzle_input)
  68. solution1: int = part1(data) # Correct answer was 4734 (with my data)
  69. solution2: int = part2(data) # Correct answer was 21836 (with my data)
  70. return solution1, solution2
  71. if __name__ == "__main__":
  72. for path in sys.argv[1:]:
  73. print(f"{path}:")
  74. puzzle_input = pathlib.Path(path).read_text().strip()
  75. solutions = solve(puzzle_input)
  76. print("\n".join(str(solution) for solution in solutions))