My solutions to 2018's advent of code
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
Ce dépôt est archivé. Vous pouvez voir les fichiers et le cloner, mais vous ne pouvez pas pousser ni ouvrir de ticket/demande d'ajout.

day06.nim 3.0KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import math, sequtils, strutils
  2. type
  3. Point = array[2, int]
  4. func read_coords(text: string): seq[Point] =
  5. for line in text.strip.splitlines:
  6. let parts = line.split(", ").map(parseInt)
  7. result &= [parts[0], parts[1]]
  8. func bounds(coords: seq[Point]): array[4, int] =
  9. let
  10. xs = coords.map(proc(coord: Point): int = coord[0])
  11. ys = coords.map(proc(coord: Point): int = coord[1])
  12. result = [min(xs), max(xs), min(ys), max(ys)]
  13. func distance(point1: Point, point2: Point): int =
  14. abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
  15. func nearest(coords: seq[Point], point: Point): int =
  16. let
  17. distances = coords.map(proc(coord: Point): int = coord.distance(point))
  18. lowest = min(distances)
  19. lowest_count = distances.filter(proc (distance: int): bool = distance == lowest).len
  20. if lowest_count == 1:
  21. distances.find(lowest)
  22. else:
  23. -1
  24. func inrange(coords: seq[Point], point: Point): bool = coords.map(proc (coord: Point): int =
  25. coord.distance(point)).sum < 10000
  26. func part1(coords: seq[Point], extents: array[4, int]): int =
  27. var
  28. counts = newSeqWith(coords.len, 0)
  29. excluded = newSeqWith(coords.len, false)
  30. for x in extents[0] .. extents[1]:
  31. for y in extents[2] .. extents[3]:
  32. let coord = coords.nearest([x, y])
  33. if coord != -1:
  34. counts[coord].inc
  35. # If the area reaches the edge of the grid, it will continue infinitely.
  36. # Mark that area as excluded.
  37. if x == extents[0] or x == extents[1] or y == extents[2] or y == extents[3]:
  38. excluded[coord] = true
  39. zip(counts, excluded)
  40. .filter(proc(x: tuple[a: int, b: bool]): bool = not x.b)
  41. .map(proc(x: tuple[a: int, b: bool]): int = x.a)
  42. .max
  43. func part2(coords: seq[Point], extents: array[4, int]): int =
  44. var
  45. size = 0
  46. found = false
  47. let
  48. extension = int(10000 / coords.len)
  49. y_start = extents[2] - extension
  50. y_finish = extents[3] + extension
  51. y_range = y_finish - y_start
  52. # The region we're in is going to be contiguous so once we've found some
  53. # 'safe' areas and subsequently hit a row/column with none in, we can abort
  54. for x in extents[0] - extension .. extents[1] + extension:
  55. var
  56. min_y = int.high
  57. max_y = int.high
  58. for y in extents[2] - extension .. extents[3] + extension:
  59. if coords.inrange([x,y]):
  60. if min_y == int.high:
  61. min_y = y
  62. max_y = y
  63. elif max_y != int.high:
  64. break
  65. if min_y != int.high:
  66. size += abs(max_y - min_y) + 1
  67. found = true
  68. elif found:
  69. break
  70. size
  71. let
  72. coords = read_coords(readFile("data/06.txt"))
  73. extents = coords.bounds
  74. echo part1(coords, extents)
  75. echo part2(coords, extents)