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

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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: distances.find(lowest) else: -1
  21. func inrange(coords: seq[Point], point: Point): bool = coords.map(proc (coord: Point): int =
  22. coord.distance(point)).sum < 10000
  23. func part1(coords: seq[Point], extents: array[4, int]): int =
  24. var
  25. counts = newSeqWith(coords.len, 0)
  26. excluded = newSeqWith(coords.len, false)
  27. for x in extents[0] .. extents[1]:
  28. for y in extents[2] .. extents[3]:
  29. let coord = coords.nearest([x, y])
  30. if coord != -1:
  31. counts[coord] += 1
  32. # If the area reaches the edge of the grid, it will continue infinitely.
  33. # Mark that area as excluded.
  34. if x == extents[0] or x == extents[1] or y == extents[2] or y == extents[3]:
  35. excluded[coord] = true
  36. zip(counts, excluded)
  37. .filter(proc(x: tuple[a: int, b: bool]): bool = not x.b)
  38. .map(proc(x: tuple[a: int, b: bool]): int = x.a)
  39. .max
  40. func part2(coords: seq[Point], extents: array[4, int]): int =
  41. var
  42. size = 0
  43. found = false
  44. let
  45. extension = int(10000 / coords.len)
  46. y_start = extents[2] - extension
  47. y_finish = extents[3] + extension
  48. y_range = y_finish - y_start
  49. # The region we're in is going to be contiguous so once we've found some
  50. # 'safe' areas and subsequently hit a row/column with none in, we can abort
  51. for x in extents[0] - extension .. extents[1] + extension:
  52. var
  53. min_y = int.high
  54. max_y = int.high
  55. for y in extents[2] - extension .. extents[3] + extension:
  56. if coords.inrange([x,y]):
  57. if min_y == int.high:
  58. min_y = y
  59. max_y = y
  60. elif max_y != int.high:
  61. break
  62. if min_y != int.high:
  63. size += abs(max_y - min_y) + 1
  64. found = true
  65. elif found:
  66. break
  67. size
  68. let
  69. coords = read_coords(readFile("data/06.txt"))
  70. extents = coords.bounds
  71. echo part1(coords, extents)
  72. echo part2(coords, extents)