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

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