advent_of_ruby 0.3.5 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of advent_of_ruby might be problematic. Click here for more details.

Files changed (212) hide show
  1. checksums.yaml +4 -4
  2. data/data/solutions/github/ZogStriP/2024/01_1.yml +1 -0
  3. data/data/solutions/github/ZogStriP/2024/01_2.yml +7 -0
  4. data/data/solutions/github/ZogStriP/2024/02_1.yml +1 -0
  5. data/data/solutions/github/ZogStriP/2024/02_2.yml +9 -0
  6. data/data/solutions/github/ZogStriP/2024/03_1.yml +1 -0
  7. data/data/solutions/github/ZogStriP/2024/03_2.yml +7 -0
  8. data/data/solutions/github/ZogStriP/2024/04_1.yml +1 -0
  9. data/data/solutions/github/ZogStriP/2024/04_2.yml +15 -0
  10. data/data/solutions/github/ZogStriP/2024/05_1.yml +1 -0
  11. data/data/solutions/github/ZogStriP/2024/05_2.yml +16 -0
  12. data/data/solutions/github/ZogStriP/2024/06_1.yml +1 -0
  13. data/data/solutions/github/ZogStriP/2024/06_2.yml +38 -0
  14. data/data/solutions/github/ZogStriP/2024/07_1.yml +1 -0
  15. data/data/solutions/github/ZogStriP/2024/07_2.yml +9 -0
  16. data/data/solutions/github/ZogStriP/2024/08_1.yml +1 -0
  17. data/data/solutions/github/ZogStriP/2024/08_2.yml +27 -0
  18. data/data/solutions/github/ZogStriP/2024/09_1.yml +1 -0
  19. data/data/solutions/github/ZogStriP/2024/09_2.yml +1 -0
  20. data/data/solutions/github/ZogStriP/2024/10_1.yml +1 -0
  21. data/data/solutions/github/ZogStriP/2024/10_2.yml +1 -0
  22. data/data/solutions/github/ZogStriP/2024/11_1.yml +1 -0
  23. data/data/solutions/github/ZogStriP/2024/11_2.yml +1 -0
  24. data/data/solutions/github/ZogStriP/2024/12_1.yml +1 -0
  25. data/data/solutions/github/ZogStriP/2024/12_2.yml +1 -0
  26. data/data/solutions/github/ZogStriP/2024/13_1.yml +1 -0
  27. data/data/solutions/github/ZogStriP/2024/13_2.yml +1 -0
  28. data/data/solutions/github/ZogStriP/2024/14_1.yml +1 -0
  29. data/data/solutions/github/ZogStriP/2024/14_2.yml +1 -0
  30. data/data/solutions/github/ZogStriP/2024/15_1.yml +1 -0
  31. data/data/solutions/github/ZogStriP/2024/15_2.yml +1 -0
  32. data/data/solutions/github/ZogStriP/2024/16_1.yml +1 -0
  33. data/data/solutions/github/ZogStriP/2024/16_2.yml +1 -0
  34. data/data/solutions/github/ZogStriP/2024/17_1.yml +1 -0
  35. data/data/solutions/github/ZogStriP/2024/17_2.yml +1 -0
  36. data/data/solutions/github/ZogStriP/2024/18_1.yml +1 -0
  37. data/data/solutions/github/ZogStriP/2024/18_2.yml +1 -0
  38. data/data/solutions/github/ZogStriP/2024/19_1.yml +1 -0
  39. data/data/solutions/github/ZogStriP/2024/19_2.yml +1 -0
  40. data/data/solutions/github/ZogStriP/2024/20_1.yml +1 -0
  41. data/data/solutions/github/ZogStriP/2024/20_2.yml +1 -0
  42. data/data/solutions/github/ZogStriP/2024/21_1.yml +1 -0
  43. data/data/solutions/github/ZogStriP/2024/21_2.yml +1 -0
  44. data/data/solutions/github/ZogStriP/2024/22_1.yml +1 -0
  45. data/data/solutions/github/ZogStriP/2024/22_2.yml +1 -0
  46. data/data/solutions/github/ZogStriP/2024/23_1.yml +1 -0
  47. data/data/solutions/github/ZogStriP/2024/23_2.yml +1 -0
  48. data/data/solutions/github/ZogStriP/2024/24_1.yml +1 -0
  49. data/data/solutions/github/ZogStriP/2024/24_2.yml +1 -0
  50. data/data/solutions/github/ZogStriP/2024/25_1.yml +1 -0
  51. data/data/solutions/github/ZogStriP/2025/01_1.yml +1 -0
  52. data/data/solutions/github/ZogStriP/2025/01_2.yml +1 -0
  53. data/data/solutions/github/ZogStriP/2025/02_1.yml +1 -0
  54. data/data/solutions/github/ZogStriP/2025/02_2.yml +1 -0
  55. data/data/solutions/github/ZogStriP/2025/03_1.yml +1 -0
  56. data/data/solutions/github/ZogStriP/2025/03_2.yml +1 -0
  57. data/data/solutions/github/ZogStriP/2025/04_1.yml +1 -0
  58. data/data/solutions/github/ZogStriP/2025/04_2.yml +1 -0
  59. data/data/solutions/github/ZogStriP/2025/05_1.yml +1 -0
  60. data/data/solutions/github/ZogStriP/2025/05_2.yml +1 -0
  61. data/data/solutions/github/ZogStriP/2025/06_1.yml +1 -0
  62. data/data/solutions/github/ZogStriP/2025/06_2.yml +1 -0
  63. data/data/solutions/github/ZogStriP/2025/07_1.yml +1 -0
  64. data/data/solutions/github/ZogStriP/2025/07_2.yml +1 -0
  65. data/data/solutions/github/ZogStriP/2025/08_1.yml +1 -0
  66. data/data/solutions/github/ZogStriP/2025/08_2.yml +1 -0
  67. data/data/solutions/github/ZogStriP/2025/09_1.yml +1 -0
  68. data/data/solutions/github/ZogStriP/2025/09_2.yml +1 -0
  69. data/data/solutions/github/ZogStriP/2025/10_1.yml +1 -0
  70. data/data/solutions/github/ZogStriP/2025/10_2.yml +1 -0
  71. data/data/solutions/github/ZogStriP/2025/11_1.yml +1 -0
  72. data/data/solutions/github/ZogStriP/2025/11_2.yml +1 -0
  73. data/data/solutions/github/ZogStriP/2025/12_1.yml +1 -0
  74. data/data/solutions/github/ZogStriP/2025/12_2.yml +1 -0
  75. data/data/solutions/github/ahorner/2025/01_1.yml +1 -0
  76. data/data/solutions/github/ahorner/2025/01_2.yml +37 -0
  77. data/data/solutions/github/ahorner/2025/02_1.yml +1 -0
  78. data/data/solutions/github/ahorner/2025/02_2.yml +41 -0
  79. data/data/solutions/github/ahorner/2025/03_1.yml +1 -0
  80. data/data/solutions/github/ahorner/2025/03_2.yml +24 -0
  81. data/data/solutions/github/ahorner/2025/04_1.yml +1 -0
  82. data/data/solutions/github/ahorner/2025/04_2.yml +39 -0
  83. data/data/solutions/github/ahorner/2025/05_1.yml +1 -0
  84. data/data/solutions/github/ahorner/2025/05_2.yml +48 -0
  85. data/data/solutions/github/ahorner/2025/06_1.yml +1 -0
  86. data/data/solutions/github/ahorner/2025/06_2.yml +44 -0
  87. data/data/solutions/github/ahorner/2025/07_1.yml +1 -0
  88. data/data/solutions/github/ahorner/2025/07_2.yml +56 -0
  89. data/data/solutions/github/ahorner/2025/08_1.yml +1 -0
  90. data/data/solutions/github/ahorner/2025/08_2.yml +59 -0
  91. data/data/solutions/github/ahorner/2025/09_1.yml +1 -0
  92. data/data/solutions/github/ahorner/2025/09_2.yml +101 -0
  93. data/data/solutions/github/ahorner/2025/10_1.yml +1 -0
  94. data/data/solutions/github/ahorner/2025/10_2.yml +72 -0
  95. data/data/solutions/github/ahorner/2025/11_1.yml +1 -0
  96. data/data/solutions/github/ahorner/2025/11_2.yml +45 -0
  97. data/data/solutions/github/ahorner/2025/12_1.yml +1 -0
  98. data/data/solutions/github/eregon/2025/01_1.yml +17 -0
  99. data/data/solutions/github/eregon/2025/01_2.yml +14 -0
  100. data/data/solutions/github/eregon/2025/02_1.yml +22 -0
  101. data/data/solutions/github/eregon/2025/02_2.yml +58 -0
  102. data/data/solutions/github/eregon/2025/03_1.yml +13 -0
  103. data/data/solutions/github/eregon/2025/03_2.yml +13 -0
  104. data/data/solutions/github/eregon/2025/04_1.yml +14 -0
  105. data/data/solutions/github/eregon/2025/04_2.yml +16 -0
  106. data/data/solutions/github/eregon/2025/05_1.yml +1 -0
  107. data/data/solutions/github/eregon/2025/05_2.yml +1 -0
  108. data/data/solutions/github/eregon/2025/06_1.yml +1 -0
  109. data/data/solutions/github/eregon/2025/06_2.yml +1 -0
  110. data/data/solutions/github/eregon/2025/07_1.yml +1 -0
  111. data/data/solutions/github/eregon/2025/07_2.yml +1 -0
  112. data/data/solutions/github/eregon/2025/08_1.yml +1 -0
  113. data/data/solutions/github/eregon/2025/08_2.yml +1 -0
  114. data/data/solutions/github/eregon/2025/09_1.yml +1 -0
  115. data/data/solutions/github/eregon/2025/09_2.yml +1 -0
  116. data/data/solutions/github/eregon/2025/10_1.yml +1 -0
  117. data/data/solutions/github/eregon/2025/10_2.yml +1 -0
  118. data/data/solutions/github/eregon/2025/11_1.yml +1 -0
  119. data/data/solutions/github/eregon/2025/11_2.yml +1 -0
  120. data/data/solutions/github/eregon/2025/12_1.yml +1 -0
  121. data/data/solutions/github/erikw/2025/01_1.yml +1 -0
  122. data/data/solutions/github/erikw/2025/01_2.yml +1 -0
  123. data/data/solutions/github/erikw/2025/02_1.yml +1 -0
  124. data/data/solutions/github/erikw/2025/02_2.yml +1 -0
  125. data/data/solutions/github/erikw/2025/03_1.yml +1 -0
  126. data/data/solutions/github/erikw/2025/03_2.yml +1 -0
  127. data/data/solutions/github/erikw/2025/04_1.yml +1 -0
  128. data/data/solutions/github/erikw/2025/04_2.yml +1 -0
  129. data/data/solutions/github/erikw/2025/05_1.yml +1 -0
  130. data/data/solutions/github/erikw/2025/05_2.yml +1 -0
  131. data/data/solutions/github/erikw/2025/06_1.yml +1 -0
  132. data/data/solutions/github/erikw/2025/06_2.yml +1 -0
  133. data/data/solutions/github/erikw/2025/07_1.yml +1 -0
  134. data/data/solutions/github/erikw/2025/07_2.yml +1 -0
  135. data/data/solutions/github/erikw/2025/08_1.yml +1 -0
  136. data/data/solutions/github/erikw/2025/08_2.yml +1 -0
  137. data/data/solutions/github/erikw/2025/09_1.yml +1 -0
  138. data/data/solutions/github/erikw/2025/09_2.yml +1 -0
  139. data/data/solutions/github/erikw/2025/10_1.yml +1 -0
  140. data/data/solutions/github/erikw/2025/10_2.yml +1 -0
  141. data/data/solutions/github/erikw/2025/11_1.yml +1 -0
  142. data/data/solutions/github/erikw/2025/11_2.yml +1 -0
  143. data/data/solutions/github/erikw/2025/12_1.yml +1 -0
  144. data/data/solutions/github/erikw/2025/12_2.yml +1 -0
  145. data/data/solutions/github/gchan/2025/01_1.yml +25 -0
  146. data/data/solutions/github/gchan/2025/01_2.yml +32 -0
  147. data/data/solutions/github/gchan/2025/02_1.yml +18 -0
  148. data/data/solutions/github/gchan/2025/02_2.yml +21 -0
  149. data/data/solutions/github/gchan/2025/03_1.yml +15 -0
  150. data/data/solutions/github/gchan/2025/03_2.yml +23 -0
  151. data/data/solutions/github/gchan/2025/04_1.yml +27 -0
  152. data/data/solutions/github/gchan/2025/04_2.yml +40 -0
  153. data/data/solutions/github/gchan/2025/05_1.yml +20 -0
  154. data/data/solutions/github/gchan/2025/05_2.yml +36 -0
  155. data/data/solutions/github/gchan/2025/06_1.yml +11 -0
  156. data/data/solutions/github/gchan/2025/06_2.yml +28 -0
  157. data/data/solutions/github/gchan/2025/07_1.yml +33 -0
  158. data/data/solutions/github/gchan/2025/07_2.yml +29 -0
  159. data/data/solutions/github/gchan/2025/08_1.yml +48 -0
  160. data/data/solutions/github/gchan/2025/08_2.yml +48 -0
  161. data/data/solutions/github/gchan/2025/09_1.yml +16 -0
  162. data/data/solutions/github/gchan/2025/09_2.yml +60 -0
  163. data/data/solutions/github/gchan/2025/10_1.yml +49 -0
  164. data/data/solutions/github/gchan/2025/10_2.yml +154 -0
  165. data/data/solutions/github/gchan/2025/11_1.yml +43 -0
  166. data/data/solutions/github/gchan/2025/11_2.yml +33 -0
  167. data/data/solutions/github/gchan/2025/12_1.yml +51 -0
  168. data/data/solutions/reddit/ruby/2017/06.yml +0 -2
  169. data/data/solutions/reddit/ruby/2020/02.yml +0 -1
  170. data/data/solutions/reddit/ruby/2024/02.yml +0 -1
  171. data/data/solutions/reddit/ruby/2025/01.yml +187 -0
  172. data/data/solutions/reddit/ruby/2025/02.yml +185 -0
  173. data/data/solutions/reddit/ruby/2025/03.yml +369 -0
  174. data/data/solutions/reddit/ruby/2025/04.yml +217 -0
  175. data/data/solutions/reddit/ruby/2025/05.yml +324 -0
  176. data/data/solutions/reddit/ruby/2025/06.yml +246 -0
  177. data/data/solutions/reddit/ruby/2025/07.yml +213 -0
  178. data/data/solutions/reddit/ruby/2025/08.yml +73 -0
  179. data/data/solutions/reddit/ruby/2025/09.yml +26 -0
  180. data/data/solutions/reddit/ruby/2025/10.yml +73 -0
  181. data/data/solutions/reddit/ruby/2025/11.yml +69 -0
  182. data/data/solutions/reddit/ruby/2025/12.yml +1 -0
  183. data/lib/arb/arb.rb +0 -5
  184. data/lib/arb/cli/bootstrap.rb +1 -1
  185. data/lib/arb/cli/commit.rb +1 -1
  186. data/lib/arb/cli/progress.rb +4 -8
  187. data/lib/arb/cli/run.rb +1 -1
  188. data/lib/arb/cli/shared/git.rb +3 -4
  189. data/lib/arb/cli/shared/year_day_validator.rb +3 -8
  190. data/lib/arb/files/spec.rb +2 -2
  191. data/lib/arb/util.rb +58 -0
  192. data/lib/arb/version.rb +1 -1
  193. metadata +184 -23
  194. data/lib/download_solutions/api/github/repos.rb +0 -54
  195. data/lib/download_solutions/api/github.rb +0 -164
  196. data/lib/download_solutions/api/reddit/add_missing_replies.rb +0 -43
  197. data/lib/download_solutions/api/reddit/clean_bodies.rb +0 -64
  198. data/lib/download_solutions/api/reddit/filter_by_language.rb +0 -32
  199. data/lib/download_solutions/api/reddit/get_initial_response.rb +0 -30
  200. data/lib/download_solutions/api/reddit/get_serial_comments.rb +0 -145
  201. data/lib/download_solutions/api/reddit/megathread_ids.rb +0 -19
  202. data/lib/download_solutions/api/reddit/params.rb +0 -40
  203. data/lib/download_solutions/api/reddit/reject_unwanted_replies.rb +0 -31
  204. data/lib/download_solutions/api/reddit/remove_ids.rb +0 -26
  205. data/lib/download_solutions/api/reddit/remove_language_tags.rb +0 -29
  206. data/lib/download_solutions/api/reddit.rb +0 -101
  207. data/lib/download_solutions/cli/cli/shared.rb +0 -35
  208. data/lib/download_solutions/cli/github.rb +0 -107
  209. data/lib/download_solutions/cli/reddit.rb +0 -64
  210. data/lib/download_solutions/download_solutions.rb +0 -18
  211. data/lib/download_solutions/reverse_markdown/converters/br.rb +0 -15
  212. data/lib/download_solutions/reverse_markdown/converters/pre.rb +0 -46
@@ -0,0 +1,56 @@
1
+ ---
2
+ - :name: 07.rb
3
+ :url: https://github.com/ahorner/advent-of-code/blob/main/lib/2025
4
+ :solution: |-
5
+ require "matrix"
6
+
7
+ MANIFOLD = INPUT.split("\n").each_with_index.each_with_object({}) do |(row, y), manifold|
8
+ row.chars.each_with_index do |char, x|
9
+ manifold[Vector[x, y]] = char unless char == "."
10
+ end
11
+ end
12
+
13
+ START_POSITION = MANIFOLD.invert["S"]
14
+ HEIGHT = INPUT.split("\n").size
15
+
16
+ def step(particles, manifold)
17
+ new_particles = Hash.new(0)
18
+ splits = 0
19
+
20
+ particles.each do |(particle, timelines)|
21
+ drop = (particle + Vector[0, 1])
22
+
23
+ case manifold[drop]
24
+ when "^"
25
+ splits += 1
26
+ new_particles[(drop + Vector[-1, 0])] += timelines
27
+ new_particles[(drop + Vector[1, 0])] += timelines
28
+ else
29
+ new_particles[drop] += timelines
30
+ end
31
+ end
32
+
33
+ [new_particles, splits]
34
+ end
35
+
36
+ def teleport(manifold)
37
+ total_splits = 0
38
+ particles = {START_POSITION => 1}
39
+ step = 0
40
+
41
+ loop do
42
+ break if step >= HEIGHT
43
+
44
+ particles, splits = step(particles, manifold)
45
+ total_splits += splits
46
+ step += 1
47
+ end
48
+
49
+ [particles, total_splits]
50
+ end
51
+
52
+ final_particles, splits = teleport(MANIFOLD)
53
+ solve!("The total number of splits performed is:", splits)
54
+
55
+ total_timelines = final_particles.values.sum
56
+ solve!("The total number of timelines after splitting is:", total_timelines)
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1,59 @@
1
+ ---
2
+ - :name: '08.rb'
3
+ :url: https://github.com/ahorner/advent-of-code/blob/main/lib/2025
4
+ :solution: |-
5
+ require "matrix"
6
+
7
+ JUNCTION_BOXES = INPUT.split("\n").map do |row|
8
+ Vector[*row.split(",").map(&:to_i)]
9
+ end
10
+
11
+ N_CLOSEST ||= 1000 # rubocop:disable Lint/OrAssignmentToConstant
12
+
13
+ def pairs(boxes)
14
+ boxes.combination(2).sort_by { |a, b| (a - b).magnitude }
15
+ end
16
+
17
+ def circuits(boxes)
18
+ connections = pairs(boxes).first(N_CLOSEST)
19
+ flattened = connections.flatten
20
+ boxes = connections.flatten.uniq.sort_by { |box| flattened.count(box) }
21
+
22
+ circuits = connections
23
+ loop do
24
+ break circuits if boxes.empty?
25
+ box = boxes.shift
26
+
27
+ connected, circuits = circuits.partition { |boxes| boxes.include?(box) }
28
+ circuit = Set.new(connected.flatten)
29
+ circuits << circuit.to_a
30
+ end
31
+ end
32
+
33
+ solve!(
34
+ "The product of the sizes of the three largest circuits is:",
35
+ circuits(JUNCTION_BOXES).map(&:size).sort.last(3).reduce(:*)
36
+ )
37
+
38
+ def last_connection(boxes)
39
+ target = boxes.size
40
+ connections = pairs(boxes)
41
+
42
+ used = Set.new
43
+ connection = nil
44
+
45
+ loop do
46
+ break false if connections.empty?
47
+ break connection if used.size == target
48
+
49
+ connection = connections.shift
50
+ used << connection[0]
51
+ used << connection[1]
52
+ end
53
+ end
54
+
55
+ final = last_connection(JUNCTION_BOXES)
56
+ solve!(
57
+ "The product of X coordinates of the last connection is:",
58
+ final.map(&:first).reduce(:*)
59
+ )
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1,101 @@
1
+ ---
2
+ - :name: '09.rb'
3
+ :url: https://github.com/ahorner/advent-of-code/blob/main/lib/2025
4
+ :solution: |-
5
+ require "matrix"
6
+
7
+ RED_TILES = INPUT.split("\n").map { |line| Vector[*line.split(",").map(&:to_i)] }
8
+
9
+ def area(v1, v2)
10
+ width = (v2[0] - v1[0]).abs + 1
11
+ height = (v2[1] - v1[1]).abs + 1
12
+ width * height
13
+ end
14
+
15
+ def optimal_corners(tiles)
16
+ tiles.combination(2).max_by { |v1, v2| area(v1, v2) }
17
+ end
18
+
19
+ largest = area(*optimal_corners(RED_TILES))
20
+
21
+ solve!("The largest rectangular area is:", largest)
22
+
23
+ LOOP = (RED_TILES + [RED_TILES[0]]).each_cons(2).to_a
24
+
25
+ def point_contained?(point, loop)
26
+ intersections = 0
27
+
28
+ loop.each do |v1, v2|
29
+ if v1[1] == v2[1]
30
+ x1 = (v1[0] < v2[0]) ? v1[0] : v2[0]
31
+ x2 = (v1[0] > v2[0]) ? v1[0] : v2[0]
32
+
33
+ return true if point[1] == v1[1] && point[0] >= x1 && point[0] <= x2
34
+ else
35
+ y1 = (v1[1] < v2[1]) ? v1[1] : v2[1]
36
+ y2 = (v1[1] > v2[1]) ? v1[1] : v2[1]
37
+
38
+ return true if point[0] == v1[0] && point[1] >= y1 && point[1] <= y2
39
+ intersections += 1 if point[0] < v1[0] && point[1] > y1 && point[1] <= y2
40
+ end
41
+ end
42
+
43
+ intersections % 2 == 1
44
+ end
45
+
46
+ def edge_intersects?((p1, p2), loop)
47
+ loop.any? do |v1, v2|
48
+ next false if (p1[1] == p2[1]) == (v1[1] == v2[1])
49
+
50
+ x1 = (v1[0] < v2[0]) ? v1[0] : v2[0]
51
+ x2 = (v1[0] > v2[0]) ? v1[0] : v2[0]
52
+ y1 = (v1[1] < v2[1]) ? v1[1] : v2[1]
53
+ y2 = (v1[1] > v2[1]) ? v1[1] : v2[1]
54
+
55
+ if p1[1] == p2[1]
56
+ x1 > p1[0] && x1 < p2[0] && p1[1] > y1 && p1[1] < y2
57
+ else
58
+ p1[0] > x1 && p1[0] < x2 && y1 > p1[1] && y1 < p2[1]
59
+ end
60
+ end
61
+ end
62
+
63
+ def optimal_contained(tiles, loop)
64
+ tiles.combination(2).sort_by { |v1, v2| -area(v1, v2) }.detect do |v1, v2|
65
+ minx = (v1[0] < v2[0]) ? v1[0] : v2[0]
66
+ maxx = (v1[0] > v2[0]) ? v1[0] : v2[0]
67
+ miny = (v1[1] < v2[1]) ? v1[1] : v2[1]
68
+ maxy = (v1[1] > v2[1]) ? v1[1] : v2[1]
69
+
70
+ corners = [
71
+ Vector[minx, miny],
72
+ Vector[maxx, miny],
73
+ Vector[maxx, maxy],
74
+ Vector[minx, maxy]
75
+ ]
76
+ unless corners.all? { |corner| point_contained?(corner, loop) }
77
+ # puts v1, v2, "rejected bc corner"
78
+ next false
79
+ end
80
+
81
+ edges = [
82
+ [corners[0], corners[1]],
83
+ [corners[1], corners[2]],
84
+ [corners[3], corners[2]],
85
+ [corners[0], corners[3]]
86
+ ]
87
+ if edges.any? { |edge| edge_intersects?(edge, loop) }
88
+ # puts v1, v2, "rejected bc edge"
89
+ next false
90
+ end
91
+
92
+ true
93
+ end
94
+ end
95
+
96
+ optimal = optimal_contained(RED_TILES, LOOP)
97
+
98
+ solve!(
99
+ "The largest fully-contained rectangular area is:",
100
+ area(*optimal)
101
+ )
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1,72 @@
1
+ ---
2
+ - :name: 10.rb
3
+ :url: https://github.com/ahorner/advent-of-code/blob/main/lib/2025
4
+ :solution: |-
5
+ require "z3"
6
+
7
+ LIGHT_SEQUENCE_MATCHER = /\[(.*?)\]/
8
+ BUTTON_PATTERN_MATCHER = /\((.*?)\)/
9
+ JOLTAGE_PATTERN_MATCHER = /\{(.*?)\}/
10
+
11
+ Machine = Data.define(:goal, :buttons, :joltages)
12
+
13
+ MACHINES = INPUT.split("\n").map do |line|
14
+ goal = line.match(LIGHT_SEQUENCE_MATCHER)[1].chars.map { |c| (c == "#") ? 1 : 0 }
15
+ buttons = line.scan(BUTTON_PATTERN_MATCHER).map { |bp| bp[0].split(",").map(&:to_i) }
16
+ joltages = line.match(JOLTAGE_PATTERN_MATCHER)[1].split(",").map(&:to_i)
17
+
18
+ Machine.new(goal:, buttons:, joltages:)
19
+ end
20
+
21
+ def min_sequence_presses(machine)
22
+ goal = machine.goal
23
+ buttons = machine.buttons
24
+
25
+ combinations = (1..buttons.size).flat_map { |n| buttons.combination(n).to_a }
26
+ working = combinations.select do |combo|
27
+ pressed = Array.new(goal.size, 0)
28
+ combo.each { |button| button.each { |pos| pressed[pos] ^= 1 } }
29
+
30
+ pressed == goal
31
+ end
32
+
33
+ working.map(&:size).min
34
+ end
35
+
36
+ solve!(
37
+ "The minimal number of button presses is:",
38
+ MACHINES.sum { |machine| min_sequence_presses(machine) }
39
+ )
40
+
41
+ def min_joltage_presses(machine)
42
+ optimizer = Z3::Optimize.new
43
+
44
+ buttons = machine.buttons.each_with_index.map do |button, i|
45
+ count = Z3::Int("b#{i}")
46
+ optimizer.assert(count >= 0)
47
+
48
+ count
49
+ end
50
+
51
+ machine.joltages.each_with_index do |joltage, i|
52
+ values = buttons.each_with_index.map do |count, j|
53
+ button_value = Z3::Int("v#{j}_#{i}")
54
+ value = machine.buttons[j].include?(i) ? 1 : 0
55
+
56
+ optimizer.assert(button_value == (count * value))
57
+ button_value
58
+ end
59
+
60
+ optimizer.assert(joltage == values.sum)
61
+ end
62
+
63
+ presses = Z3::Int("presses")
64
+ optimizer.assert(presses == buttons.sum)
65
+ optimizer.minimize(presses)
66
+ optimizer.model[presses].to_i if optimizer.satisfiable?
67
+ end
68
+
69
+ solve!(
70
+ "The minimal number of presses to reach all target joltages is:",
71
+ MACHINES.sum { |machine| min_joltage_presses(machine) }
72
+ )
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1,45 @@
1
+ ---
2
+ - :name: 11.rb
3
+ :url: https://github.com/ahorner/advent-of-code/blob/main/lib/2025
4
+ :solution: |-
5
+ MAP = INPUT.split("\n").each_with_object({}) do |line, map|
6
+ loc, neighbors = line.split(": ")
7
+ map[loc] = neighbors.split(" ")
8
+ end
9
+
10
+ def paths(map, current, goal, known = Hash.new { |h, k| h[k] = 0 })
11
+ return 1 if current == goal
12
+ return known[current] if known.key?(current)
13
+ return 0 if !map[current]
14
+
15
+ map[current].each do |neighbor|
16
+ known[current] += paths(map, neighbor, goal, known)
17
+ end
18
+
19
+ known[current]
20
+ end
21
+
22
+ solve!(
23
+ "The total number of paths from `you` to `out` is:",
24
+ paths(MAP, "you", "out")
25
+ )
26
+
27
+ # Given the nature of the problem, we know that there are no loops possible,
28
+ # so data can only visit `fft` and `dac` in one specific order. We check to see
29
+ # which direction data flows, and break the path into segments based on that.
30
+ fft_paths = paths(MAP, "fft", "dac")
31
+ dac_paths = paths(MAP, "dac", "fft")
32
+
33
+ path_segments = [
34
+ (paths(MAP, "svr", "fft") if fft_paths > 0),
35
+ (paths(MAP, "svr", "dac") if dac_paths > 0),
36
+ (fft_paths if fft_paths > 0),
37
+ (dac_paths if dac_paths > 0),
38
+ (paths(MAP, "dac", "out") if fft_paths > 0),
39
+ (paths(MAP, "fft", "out") if dac_paths > 0)
40
+ ].compact
41
+
42
+ solve!(
43
+ "The total number of output paths from the server through `fft` and `dac` is:",
44
+ path_segments.reduce(1, :*)
45
+ )
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1,17 @@
1
+ ---
2
+ - :name: 1a.rb
3
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
4
+ :solution: |-
5
+ dial = 50
6
+ p $<.map {
7
+ dial = (dial + it.tr('LR', '-+').to_i) % 100
8
+ }.count(0)
9
+ - :name: 1a_golf.rb
10
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
11
+ :solution: d=50;p$<.map{(d+=it.tr('LR','-+').to_i)%100}.count 0
12
+ - :name: 1a_golf2.rb
13
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
14
+ :solution: |-
15
+ d=50;n=0
16
+ $<.map{eval"d#{it.sub(?L,'-=').sub(?R,'+=')};n+=1 if d%100==0"}
17
+ p n
@@ -0,0 +1,14 @@
1
+ ---
2
+ - :name: 1b.rb
3
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
4
+ :solution: |-
5
+ zeros = 0
6
+ dial = 50
7
+ $<.each {
8
+ step = it[0] == 'L' ? -1 : +1
9
+ it[1..].to_i.times {
10
+ dial = (dial + step) % 100
11
+ zeros += 1 if dial == 0
12
+ }
13
+ }
14
+ p zeros
@@ -0,0 +1,22 @@
1
+ ---
2
+ - :name: 2a.rb
3
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
4
+ :solution: "ranges = $<.read.strip.split(\",\").map {\n a, b = it.split('-')\n a = '1' + '0' * a.size if a.size.odd? \n b = '9' * (b.size - 1) if b.size.odd?\n next if a.to_i > b.to_i\n raise unless a.size == b.size && a.size.even?\n [a, b, a.to_i..b.to_i]\n}.compact\n\nsilly = []\nranges.each { |a, b, range|\n s = a.size\n (a[0...s/2]..b[0...s/2]).each { |half|\n n = (half * 2).to_i\n silly << n if range.cover? n\n }\n}\np silly.sum"
5
+ - :name: 2a_golf.rb
6
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
7
+ :solution: |-
8
+ r=[]
9
+ $<.read.chomp.split(?,).map{
10
+ a,b=it.split ?-
11
+ a=?1+?0*a.size if a.size.odd?
12
+ b=?9*(b.size-1)if b.size.odd?
13
+ s=a.size
14
+ (a[0,s/2]..b[0,s/2]).each{
15
+ n=(it*2).to_i
16
+ r<<n if a.to_i<=n&&n<=b.to_i
17
+ }
18
+ }
19
+ p r.sum
20
+ - :name: 2a_golf2.rb
21
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
22
+ :solution: p$<.read.chomp.split(?,).sum{a,b=it.split ?-;(a[..s=a.size/-2-1].to_i..b[..s].to_i).sum{a.to_i<=(n="#{it}#{it}".to_i)&&n<=b.to_i ? n:0}}
@@ -0,0 +1,58 @@
1
+ ---
2
+ - :name: 2b.rb
3
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
4
+ :solution: |-
5
+ ranges = $<.read.strip.split(",").flat_map {
6
+ a, b = it.split('-')
7
+ raise if a.to_i > b.to_i
8
+
9
+ if a.size == b.size
10
+ a..b
11
+ else
12
+ raise unless a.size + 1 == b.size
13
+ [
14
+ a..('9' * a.size),
15
+ ('1' + '0' * a.size)..b
16
+ ]
17
+ end
18
+ }
19
+
20
+ silly = Set.new
21
+ ranges.each { |range|
22
+ a, b = range.begin, range.end
23
+ s = a.size
24
+
25
+ (1..s/2).each { |stride|
26
+ if s % stride == 0
27
+ repeats = s / stride
28
+ (a[0...stride]..b[0...stride]).each { |part|
29
+ n = part * repeats
30
+ silly << n.to_i if range.cover? n
31
+ }
32
+ end
33
+ }
34
+ }
35
+
36
+ p silly.sum
37
+ - :name: 2b_golf.rb
38
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
39
+ :solution: |-
40
+ r=Set[]
41
+ $<.read.strip.split(?,).flat_map{
42
+ a,b=it.split(?-)
43
+ (s=a.size)==b.size ? [[a,b]]:[[a,?9*s],[?1+?0*s,b]]
44
+ }.each{|a,b|
45
+ s=a.size
46
+ (1..s/2).each{|z|
47
+ if s%z==0
48
+ (a[0,z]..b[0,z]).each{
49
+ n=it*(s/z)
50
+ r << n.to_i if (a..b).cover? n
51
+ }
52
+ end
53
+ }
54
+ }
55
+ p r.sum
56
+ - :name: 2b_golf2.rb
57
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
58
+ :solution: "$<.read.split(/\\D/).each_slice(2){|a,b,d=(c=b).size|s=a.size;b=?9*s if s<d;(1..s/2).map{|z|(a[0,z]..b[0,z]).map{n=it*(s/z);$*<<n.to_i if(a..b).cover? n}if s%z==0};a,b=?1+?0*s,c;redo if s<d};p$*.uniq.sum"
@@ -0,0 +1,13 @@
1
+ ---
2
+ - :name: 3a.rb
3
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
4
+ :solution: |-
5
+ p $<.sum {
6
+ d = it.chomp.chars
7
+ a = d[..-2].max
8
+ b = d[d.index(a)+1..].max
9
+ (a+b).to_i
10
+ }
11
+ - :name: 3a_golf.rb
12
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
13
+ :solution: p$<.sum{(a=(d=it.to_i.digits)[1..].max)*10+d[...d.rindex(a)].max}
@@ -0,0 +1,13 @@
1
+ ---
2
+ - :name: 3b.rb
3
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
4
+ :solution: |-
5
+ p $<.sum {
6
+ d = it.chomp.chars.map(&:to_i)
7
+ i = 0
8
+ 12.times.map { |nth|
9
+ max = d[i..-(12 - nth)].max
10
+ i += d[i..].index(max) + 1
11
+ max
12
+ }.join.to_i
13
+ }
@@ -0,0 +1,14 @@
1
+ ---
2
+ - :name: 4a.rb
3
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
4
+ :solution: |-
5
+ set = Set[]
6
+ $<.each_with_index {|row,y|
7
+ row.chomp.chars.each_with_index{|v,x|
8
+ set << y.i+x if v == '@'
9
+ }
10
+ }
11
+
12
+ p set.count { |c|
13
+ (set & Set[c-1i-1, c-1i, c-1i+1, c-1, c+1, c+1i-1, c+1i, c+1i+1]).size < 4
14
+ }
@@ -0,0 +1,16 @@
1
+ ---
2
+ - :name: 4b.rb
3
+ :url: https://github.com/eregon/adventofcode/blob/master/2025
4
+ :solution: |-
5
+ set = Set[]
6
+ $<.each_with_index {|row,y|
7
+ row.chomp.chars.each_with_index{|v,x|
8
+ set << y.i+x if v == '@'
9
+ }
10
+ }
11
+ init = set.dup
12
+
13
+ true while set.reject! { |c|
14
+ (set & Set[c-1i-1, c-1i, c-1i+1, c-1, c+1, c+1i-1, c+1i, c+1i+1]).size < 4
15
+ }
16
+ p (init-set).size
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []
@@ -0,0 +1 @@
1
+ --- []