advent_of_ruby 0.3.5 → 0.4.0
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.
- checksums.yaml +4 -4
- data/data/solutions/github/ZogStriP/2024/01_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/01_2.yml +7 -0
- data/data/solutions/github/ZogStriP/2024/02_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/02_2.yml +9 -0
- data/data/solutions/github/ZogStriP/2024/03_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/03_2.yml +7 -0
- data/data/solutions/github/ZogStriP/2024/04_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/04_2.yml +15 -0
- data/data/solutions/github/ZogStriP/2024/05_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/05_2.yml +16 -0
- data/data/solutions/github/ZogStriP/2024/06_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/06_2.yml +38 -0
- data/data/solutions/github/ZogStriP/2024/07_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/07_2.yml +9 -0
- data/data/solutions/github/ZogStriP/2024/08_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/08_2.yml +27 -0
- data/data/solutions/github/ZogStriP/2024/09_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/09_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/10_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/10_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/11_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/11_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/12_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/12_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/13_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/13_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/14_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/14_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/15_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/15_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/16_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/16_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/17_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/17_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/18_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/18_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/19_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/19_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/20_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/20_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/21_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/21_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/22_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/22_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/23_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/23_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/24_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/24_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2024/25_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/01_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/01_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/02_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/02_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/03_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/03_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/04_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/04_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/05_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/05_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/06_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/06_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/07_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/07_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/08_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/08_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/09_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/09_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/10_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/10_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/11_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/11_2.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/12_1.yml +1 -0
- data/data/solutions/github/ZogStriP/2025/12_2.yml +1 -0
- data/data/solutions/github/ahorner/2025/01_1.yml +1 -0
- data/data/solutions/github/ahorner/2025/01_2.yml +37 -0
- data/data/solutions/github/ahorner/2025/02_1.yml +1 -0
- data/data/solutions/github/ahorner/2025/02_2.yml +41 -0
- data/data/solutions/github/ahorner/2025/03_1.yml +1 -0
- data/data/solutions/github/ahorner/2025/03_2.yml +24 -0
- data/data/solutions/github/ahorner/2025/04_1.yml +1 -0
- data/data/solutions/github/ahorner/2025/04_2.yml +39 -0
- data/data/solutions/github/ahorner/2025/05_1.yml +1 -0
- data/data/solutions/github/ahorner/2025/05_2.yml +48 -0
- data/data/solutions/github/ahorner/2025/06_1.yml +1 -0
- data/data/solutions/github/ahorner/2025/06_2.yml +44 -0
- data/data/solutions/github/ahorner/2025/07_1.yml +1 -0
- data/data/solutions/github/ahorner/2025/07_2.yml +56 -0
- data/data/solutions/github/ahorner/2025/08_1.yml +1 -0
- data/data/solutions/github/ahorner/2025/08_2.yml +59 -0
- data/data/solutions/github/ahorner/2025/09_1.yml +1 -0
- data/data/solutions/github/ahorner/2025/09_2.yml +101 -0
- data/data/solutions/github/ahorner/2025/10_1.yml +1 -0
- data/data/solutions/github/ahorner/2025/10_2.yml +72 -0
- data/data/solutions/github/ahorner/2025/11_1.yml +1 -0
- data/data/solutions/github/ahorner/2025/11_2.yml +45 -0
- data/data/solutions/github/ahorner/2025/12_1.yml +1 -0
- data/data/solutions/github/eregon/2025/01_1.yml +17 -0
- data/data/solutions/github/eregon/2025/01_2.yml +14 -0
- data/data/solutions/github/eregon/2025/02_1.yml +22 -0
- data/data/solutions/github/eregon/2025/02_2.yml +58 -0
- data/data/solutions/github/eregon/2025/03_1.yml +13 -0
- data/data/solutions/github/eregon/2025/03_2.yml +13 -0
- data/data/solutions/github/eregon/2025/04_1.yml +14 -0
- data/data/solutions/github/eregon/2025/04_2.yml +16 -0
- data/data/solutions/github/eregon/2025/05_1.yml +1 -0
- data/data/solutions/github/eregon/2025/05_2.yml +1 -0
- data/data/solutions/github/eregon/2025/06_1.yml +1 -0
- data/data/solutions/github/eregon/2025/06_2.yml +1 -0
- data/data/solutions/github/eregon/2025/07_1.yml +1 -0
- data/data/solutions/github/eregon/2025/07_2.yml +1 -0
- data/data/solutions/github/eregon/2025/08_1.yml +1 -0
- data/data/solutions/github/eregon/2025/08_2.yml +1 -0
- data/data/solutions/github/eregon/2025/09_1.yml +1 -0
- data/data/solutions/github/eregon/2025/09_2.yml +1 -0
- data/data/solutions/github/eregon/2025/10_1.yml +1 -0
- data/data/solutions/github/eregon/2025/10_2.yml +1 -0
- data/data/solutions/github/eregon/2025/11_1.yml +1 -0
- data/data/solutions/github/eregon/2025/11_2.yml +1 -0
- data/data/solutions/github/eregon/2025/12_1.yml +1 -0
- data/data/solutions/github/erikw/2025/01_1.yml +1 -0
- data/data/solutions/github/erikw/2025/01_2.yml +1 -0
- data/data/solutions/github/erikw/2025/02_1.yml +1 -0
- data/data/solutions/github/erikw/2025/02_2.yml +1 -0
- data/data/solutions/github/erikw/2025/03_1.yml +1 -0
- data/data/solutions/github/erikw/2025/03_2.yml +1 -0
- data/data/solutions/github/erikw/2025/04_1.yml +1 -0
- data/data/solutions/github/erikw/2025/04_2.yml +1 -0
- data/data/solutions/github/erikw/2025/05_1.yml +1 -0
- data/data/solutions/github/erikw/2025/05_2.yml +1 -0
- data/data/solutions/github/erikw/2025/06_1.yml +1 -0
- data/data/solutions/github/erikw/2025/06_2.yml +1 -0
- data/data/solutions/github/erikw/2025/07_1.yml +1 -0
- data/data/solutions/github/erikw/2025/07_2.yml +1 -0
- data/data/solutions/github/erikw/2025/08_1.yml +1 -0
- data/data/solutions/github/erikw/2025/08_2.yml +1 -0
- data/data/solutions/github/erikw/2025/09_1.yml +1 -0
- data/data/solutions/github/erikw/2025/09_2.yml +1 -0
- data/data/solutions/github/erikw/2025/10_1.yml +1 -0
- data/data/solutions/github/erikw/2025/10_2.yml +1 -0
- data/data/solutions/github/erikw/2025/11_1.yml +1 -0
- data/data/solutions/github/erikw/2025/11_2.yml +1 -0
- data/data/solutions/github/erikw/2025/12_1.yml +1 -0
- data/data/solutions/github/erikw/2025/12_2.yml +1 -0
- data/data/solutions/github/gchan/2025/01_1.yml +25 -0
- data/data/solutions/github/gchan/2025/01_2.yml +32 -0
- data/data/solutions/github/gchan/2025/02_1.yml +18 -0
- data/data/solutions/github/gchan/2025/02_2.yml +21 -0
- data/data/solutions/github/gchan/2025/03_1.yml +15 -0
- data/data/solutions/github/gchan/2025/03_2.yml +23 -0
- data/data/solutions/github/gchan/2025/04_1.yml +27 -0
- data/data/solutions/github/gchan/2025/04_2.yml +40 -0
- data/data/solutions/github/gchan/2025/05_1.yml +20 -0
- data/data/solutions/github/gchan/2025/05_2.yml +36 -0
- data/data/solutions/github/gchan/2025/06_1.yml +11 -0
- data/data/solutions/github/gchan/2025/06_2.yml +28 -0
- data/data/solutions/github/gchan/2025/07_1.yml +33 -0
- data/data/solutions/github/gchan/2025/07_2.yml +29 -0
- data/data/solutions/github/gchan/2025/08_1.yml +48 -0
- data/data/solutions/github/gchan/2025/08_2.yml +48 -0
- data/data/solutions/github/gchan/2025/09_1.yml +16 -0
- data/data/solutions/github/gchan/2025/09_2.yml +60 -0
- data/data/solutions/github/gchan/2025/10_1.yml +49 -0
- data/data/solutions/github/gchan/2025/10_2.yml +154 -0
- data/data/solutions/github/gchan/2025/11_1.yml +43 -0
- data/data/solutions/github/gchan/2025/11_2.yml +33 -0
- data/data/solutions/github/gchan/2025/12_1.yml +51 -0
- data/data/solutions/reddit/ruby/2017/06.yml +0 -2
- data/data/solutions/reddit/ruby/2020/02.yml +0 -1
- data/data/solutions/reddit/ruby/2024/02.yml +0 -1
- data/data/solutions/reddit/ruby/2025/01.yml +187 -0
- data/data/solutions/reddit/ruby/2025/02.yml +185 -0
- data/data/solutions/reddit/ruby/2025/03.yml +369 -0
- data/data/solutions/reddit/ruby/2025/04.yml +217 -0
- data/data/solutions/reddit/ruby/2025/05.yml +324 -0
- data/data/solutions/reddit/ruby/2025/06.yml +246 -0
- data/data/solutions/reddit/ruby/2025/07.yml +213 -0
- data/data/solutions/reddit/ruby/2025/08.yml +73 -0
- data/data/solutions/reddit/ruby/2025/09.yml +26 -0
- data/data/solutions/reddit/ruby/2025/10.yml +73 -0
- data/data/solutions/reddit/ruby/2025/11.yml +69 -0
- data/data/solutions/reddit/ruby/2025/12.yml +1 -0
- data/lib/arb/arb.rb +0 -5
- data/lib/arb/cli/bootstrap.rb +1 -1
- data/lib/arb/cli/commit.rb +1 -1
- data/lib/arb/cli/progress.rb +4 -8
- data/lib/arb/cli/run.rb +1 -1
- data/lib/arb/cli/shared/git.rb +3 -4
- data/lib/arb/cli/shared/year_day_validator.rb +3 -8
- data/lib/arb/files/spec.rb +2 -2
- data/lib/arb/util.rb +58 -0
- data/lib/arb/version.rb +1 -1
- metadata +184 -23
- data/lib/download_solutions/api/github/repos.rb +0 -54
- data/lib/download_solutions/api/github.rb +0 -164
- data/lib/download_solutions/api/reddit/add_missing_replies.rb +0 -43
- data/lib/download_solutions/api/reddit/clean_bodies.rb +0 -64
- data/lib/download_solutions/api/reddit/filter_by_language.rb +0 -32
- data/lib/download_solutions/api/reddit/get_initial_response.rb +0 -30
- data/lib/download_solutions/api/reddit/get_serial_comments.rb +0 -145
- data/lib/download_solutions/api/reddit/megathread_ids.rb +0 -19
- data/lib/download_solutions/api/reddit/params.rb +0 -40
- data/lib/download_solutions/api/reddit/reject_unwanted_replies.rb +0 -31
- data/lib/download_solutions/api/reddit/remove_ids.rb +0 -26
- data/lib/download_solutions/api/reddit/remove_language_tags.rb +0 -29
- data/lib/download_solutions/api/reddit.rb +0 -101
- data/lib/download_solutions/cli/cli/shared.rb +0 -35
- data/lib/download_solutions/cli/github.rb +0 -107
- data/lib/download_solutions/cli/reddit.rb +0 -64
- data/lib/download_solutions/download_solutions.rb +0 -18
- data/lib/download_solutions/reverse_markdown/converters/br.rb +0 -15
- data/lib/download_solutions/reverse_markdown/converters/pre.rb +0 -46
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
- :name: day-10-part-2.rb
|
|
3
|
+
:url: https://github.com/gchan/advent-of-code-ruby/blob/main/2025/day-10
|
|
4
|
+
:solution: |-
|
|
5
|
+
machines = input.split("\n").map { _1.split(/(?<=\]) | (?=\{)/) }
|
|
6
|
+
.map! { |_lights, buttons, joltage|
|
|
7
|
+
joltage = joltage[1...-1].split(",").map(&:to_i)
|
|
8
|
+
|
|
9
|
+
buttons = buttons
|
|
10
|
+
.scan(/
|
|
11
|
+
\( # Opening parenthesis
|
|
12
|
+
(\d+(?:,\d+)*) # One or more digits separated by commas
|
|
13
|
+
\) # Closing parenthesis
|
|
14
|
+
/x)
|
|
15
|
+
.flatten
|
|
16
|
+
.map { _1.split(",").map(&:to_i) }
|
|
17
|
+
|
|
18
|
+
[joltage, buttons]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@cache = {}
|
|
22
|
+
def generate_selections(n, k)
|
|
23
|
+
return @cache[[n, k]] if @cache.key?([n, k])
|
|
24
|
+
result = []
|
|
25
|
+
|
|
26
|
+
distribute = ->(i, remaining, counts) do
|
|
27
|
+
if i == n - 1
|
|
28
|
+
counts[i] = remaining
|
|
29
|
+
result << counts
|
|
30
|
+
return
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
(0..remaining).each do |count|
|
|
34
|
+
counts[i] = count
|
|
35
|
+
distribute.call(i + 1, remaining - count, counts.dup)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
distribute.call(0, k, Array.new(n, 0))
|
|
40
|
+
result = result.sort!.reverse!
|
|
41
|
+
@cache[[n, k]] = result
|
|
42
|
+
result
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
machines
|
|
46
|
+
.map.with_index { |(joltage, buttons), line|
|
|
47
|
+
# # puts [joltage, buttons].inspect
|
|
48
|
+
puts line
|
|
49
|
+
|
|
50
|
+
# Create button mapping (which buttons affect which positions)
|
|
51
|
+
button_map = Array.new(joltage.size) { [] }
|
|
52
|
+
buttons.each_with_index do |button, idx|
|
|
53
|
+
button.each { |pos| button_map[pos] << idx }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Sort by button size (largest first) for better pruning
|
|
57
|
+
button_map.map! { |idxs| idxs.sort_by { |i| -buttons[i].size } }
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
queue = [[joltage.clone, 0, Array.new(buttons.size, 0)]]
|
|
61
|
+
visited = Hash.new(Float::INFINITY) # state -> min_presses to reach that state
|
|
62
|
+
count = nil
|
|
63
|
+
max_button_size = buttons.map(&:size).max
|
|
64
|
+
|
|
65
|
+
while queue.any?
|
|
66
|
+
state, presses, skip_buttons = queue.shift
|
|
67
|
+
|
|
68
|
+
# Skip if we've reached this state with fewer presses before
|
|
69
|
+
next if visited[state] <= presses
|
|
70
|
+
visited[state] = presses
|
|
71
|
+
|
|
72
|
+
puts "----------------------------------------"
|
|
73
|
+
puts "line #{line}:"
|
|
74
|
+
puts "Queue size: #{queue.size}"
|
|
75
|
+
puts "Current state: #{state.inspect}"
|
|
76
|
+
puts "Buttons: #{buttons.inspect}"
|
|
77
|
+
puts "skip_buttons: #{skip_buttons.inspect}"
|
|
78
|
+
puts "skip_buttons: #{skip_buttons.map.with_index { buttons[_2] if _1 == 1 }.compact.inspect}"
|
|
79
|
+
|
|
80
|
+
# puts button_map.inspect
|
|
81
|
+
button_to_press = button_map.each.with_index.min_by { |idxs, (btn)|
|
|
82
|
+
available_idxs = idxs.reject { |idx| skip_buttons[idx] == 1 }
|
|
83
|
+
|
|
84
|
+
size = available_idxs.size.zero? ? Float::INFINITY : available_idxs.size
|
|
85
|
+
|
|
86
|
+
#size
|
|
87
|
+
[size, -state[btn]]
|
|
88
|
+
}.last
|
|
89
|
+
|
|
90
|
+
# puts "Button to press: #{button_to_press}"
|
|
91
|
+
potential_buttons = button_map[button_to_press]
|
|
92
|
+
.reject { |idx| skip_buttons[idx] != 0 }
|
|
93
|
+
.sort_by { -buttons[_1].size }
|
|
94
|
+
|
|
95
|
+
next if potential_buttons.empty?
|
|
96
|
+
|
|
97
|
+
puts "Number of potential buttons: #{potential_buttons.size}"
|
|
98
|
+
|
|
99
|
+
puts "Presses so far: #{presses}"
|
|
100
|
+
required_presses = state[button_to_press]
|
|
101
|
+
puts "Required presses: #{required_presses}"
|
|
102
|
+
|
|
103
|
+
# Prune if this path would exceed current best solution
|
|
104
|
+
next if count && presses + required_presses >= count
|
|
105
|
+
|
|
106
|
+
selections = generate_selections(potential_buttons.size, required_presses)
|
|
107
|
+
|
|
108
|
+
selections.each do |selection|
|
|
109
|
+
# Early exit if we've found a solution that's as good as this path
|
|
110
|
+
break if count && presses + required_presses >= count
|
|
111
|
+
|
|
112
|
+
new_state = state.dup
|
|
113
|
+
|
|
114
|
+
selection.each_with_index do |press, idx|
|
|
115
|
+
buttons[potential_buttons[idx]].each { |pos| new_state[pos] -= press }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
next if new_state.any? { _1 < 0 }
|
|
119
|
+
|
|
120
|
+
# Calculate lower bound: minimum presses needed to reach solution from new_state
|
|
121
|
+
remaining_sum = new_state.sum
|
|
122
|
+
lower_bound = (remaining_sum.to_f / max_button_size).ceil
|
|
123
|
+
next if count && presses + required_presses + lower_bound >= count
|
|
124
|
+
|
|
125
|
+
next if visited[new_state] <= presses + required_presses
|
|
126
|
+
|
|
127
|
+
if new_state.all? { _1 == 0 }
|
|
128
|
+
count = [count, presses + required_presses].compact.min
|
|
129
|
+
puts "Found solution with #{count} presses"
|
|
130
|
+
break
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# puts new_state.inspect
|
|
134
|
+
new_skip_buttons = skip_buttons.dup
|
|
135
|
+
|
|
136
|
+
potential_buttons.each do |idx|
|
|
137
|
+
new_skip_buttons[idx] = 1
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
queue.unshift [new_state, presses + required_presses, new_skip_buttons]
|
|
141
|
+
#queue = [] if count
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
#puts state.inspect
|
|
145
|
+
#puts
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# puts
|
|
149
|
+
|
|
150
|
+
raise if count.nil?
|
|
151
|
+
count
|
|
152
|
+
}
|
|
153
|
+
.sum
|
|
154
|
+
.tap { puts _1 }
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
- :name: day-11-part-1.rb
|
|
3
|
+
:url: https://github.com/gchan/advent-of-code-ruby/blob/main/2025/day-11
|
|
4
|
+
:solution: |-
|
|
5
|
+
devices = input
|
|
6
|
+
.split("\n")
|
|
7
|
+
.map {
|
|
8
|
+
src, *dest = _1.split(/: | /)
|
|
9
|
+
|
|
10
|
+
[src, dest]
|
|
11
|
+
}
|
|
12
|
+
.to_h
|
|
13
|
+
|
|
14
|
+
count = 0
|
|
15
|
+
queue = [["you"]]
|
|
16
|
+
|
|
17
|
+
while queue.any?
|
|
18
|
+
path = queue.shift
|
|
19
|
+
current = path.last
|
|
20
|
+
|
|
21
|
+
devices[current].each do |neighbour|
|
|
22
|
+
new_path = path + [neighbour]
|
|
23
|
+
|
|
24
|
+
if neighbour == "out"
|
|
25
|
+
count += 1
|
|
26
|
+
else
|
|
27
|
+
queue << new_path
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
puts count
|
|
33
|
+
|
|
34
|
+
# Recursive DFS solution
|
|
35
|
+
def dfs(input, devices)
|
|
36
|
+
return 1 if input == "out"
|
|
37
|
+
|
|
38
|
+
devices[input].sum do |output|
|
|
39
|
+
dfs(output, devices)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
puts dfs("you", devices)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
- :name: day-11-part-2.rb
|
|
3
|
+
:url: https://github.com/gchan/advent-of-code-ruby/blob/main/2025/day-11
|
|
4
|
+
:solution: |-
|
|
5
|
+
devices = input
|
|
6
|
+
.split("\n")
|
|
7
|
+
.map {
|
|
8
|
+
src, *dest = _1.split(/: | /)
|
|
9
|
+
|
|
10
|
+
[src, dest]
|
|
11
|
+
}
|
|
12
|
+
.to_h
|
|
13
|
+
|
|
14
|
+
def dfs(devices:, input:, memo: {}, dac: false, fft: false)
|
|
15
|
+
if input == "out"
|
|
16
|
+
return 1 if dac && fft
|
|
17
|
+
return 0
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
devices[input].sum do |output|
|
|
21
|
+
key = [output, dac, fft]
|
|
22
|
+
|
|
23
|
+
memo[key] ||= dfs(
|
|
24
|
+
devices:,
|
|
25
|
+
input: output,
|
|
26
|
+
memo:,
|
|
27
|
+
dac: dac || output == "dac",
|
|
28
|
+
fft: fft || output == "fft"
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
puts dfs(devices:, input: "svr")
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
- :name: day-12-part-1.rb
|
|
3
|
+
:url: https://github.com/gchan/advent-of-code-ruby/blob/main/2025/day-12
|
|
4
|
+
:solution: |-
|
|
5
|
+
shapes = input.split("\n\n")
|
|
6
|
+
|
|
7
|
+
regions = shapes.pop.split("\n")
|
|
8
|
+
.map {
|
|
9
|
+
size, shape_qty = _1.split(?:)
|
|
10
|
+
|
|
11
|
+
[
|
|
12
|
+
size.split(?x).map(&:to_i),
|
|
13
|
+
shape_qty.split.map(&:to_i)
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
shapes.map! {
|
|
18
|
+
_, *shape = _1.split(?\n)
|
|
19
|
+
|
|
20
|
+
shape.join
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
# Cheeky solution - just compare areas
|
|
24
|
+
# Only works with the input provided and not the sample input
|
|
25
|
+
shape_areas = shapes.map.with_index { |shape, idx|
|
|
26
|
+
shape.chars.count { _1 == ?# }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
regions
|
|
30
|
+
.count { |(size_x, size_y), shape_qty|
|
|
31
|
+
total_area = size_x * size_y
|
|
32
|
+
|
|
33
|
+
shape_area = shape_qty.each_with_index.sum do |qty, idx|
|
|
34
|
+
shape_areas[idx] * shape_qty[idx]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
shape_area <= total_area
|
|
38
|
+
}
|
|
39
|
+
.tap { puts _1 }
|
|
40
|
+
|
|
41
|
+
# Another cheeky solution - check if there is 9 spaces for each shape
|
|
42
|
+
regions
|
|
43
|
+
.count { |(size_x, size_y), shape_qty|
|
|
44
|
+
total_spaces = size_x * size_y / 9
|
|
45
|
+
|
|
46
|
+
shape_spaces = shape_qty.sum
|
|
47
|
+
shape_spaces <= total_spaces
|
|
48
|
+
}
|
|
49
|
+
.tap { puts _1 }
|
|
50
|
+
|
|
51
|
+
# TODO - Proper solution for the sample input
|
|
@@ -142,7 +142,6 @@
|
|
|
142
142
|
**Ruby** simply using mem-string(join) instead of array of mem-arrays as comparison made it fast enough.
|
|
143
143
|
|
|
144
144
|
```ruby
|
|
145
|
-
|
|
146
145
|
data = input.split("\t").strip.map(&:to_i)
|
|
147
146
|
results = []
|
|
148
147
|
|
|
@@ -173,7 +172,6 @@
|
|
|
173
172
|
cycles += 1
|
|
174
173
|
end
|
|
175
174
|
puts 'part2 -------', cycles, '----------'
|
|
176
|
-
|
|
177
175
|
```
|
|
178
176
|
:replies:
|
|
179
177
|
- :author: jschulenklopper
|
|
@@ -262,7 +262,6 @@
|
|
|
262
262
|
:url: https://www.reddit.com/r/adventofcode/comments/1h4ncyr/2024_day_2_solutions/m02ns7r
|
|
263
263
|
:body: |-
|
|
264
264
|
```ruby
|
|
265
|
-
|
|
266
265
|
puts File.read('input.txt').split("\\n").map { |line| line.split.map(&:to\_i) }.then { |data| safe = ->(r) { (r.each\_cons(2).all? { |a, b| a < b } || r.each\_cons(2).all? { |a, b| a > b }) && r.each\_cons(2).all? { |a, b| (1..3).cover?((a - b).abs) } }; "#{data.count { |r| safe\[r\] }} #{data.count { |r| safe\[r\] || (0...r.length).any? { |i| safe\[r\[0...i\] + r\[(i+1)..-1\]\] } }}"}
|
|
267
266
|
```
|
|
268
267
|
:replies: []
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
---
|
|
2
|
+
- :author: StillFast7545
|
|
3
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pb3y8p/2025_day_1_solutions/nsku8t6
|
|
4
|
+
:body: |-
|
|
5
|
+
Part 1: [https://github.com/MarioPerac/AdventOfCode2025/blob/main/day\_1/secret\_entrance\_part\_1.rb](https://github.com/MarioPerac/AdventOfCode2025/blob/main/day_1/secret_entrance_part_1.rb)
|
|
6
|
+
|
|
7
|
+
Part 2: [https://github.com/MarioPerac/AdventOfCode2025/blob/main/day\_1/secret\_entrance\_part\_2.rb](https://github.com/MarioPerac/AdventOfCode2025/blob/main/day_1/secret_entrance_part_2.rb)
|
|
8
|
+
|
|
9
|
+
Puzzle solved with a circular linked list.
|
|
10
|
+
:replies: []
|
|
11
|
+
- :author: Few-Orchid-8393
|
|
12
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pb3y8p/2025_day_1_solutions/ns61umj
|
|
13
|
+
:body: |-
|
|
14
|
+
part two in 9 lines (at a comfy and traditional 80-char width):
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
position = 50
|
|
18
|
+
password = 0
|
|
19
|
+
ARGF.each_line do |instruction|
|
|
20
|
+
rotation = instruction.sub(/^L/, "-").sub(/^R/, "").to_i
|
|
21
|
+
direction = rotation <=> 0
|
|
22
|
+
password += ((direction * rotation) + ((direction * position) % 100)) / 100
|
|
23
|
+
position = (position + rotation) % 100
|
|
24
|
+
end
|
|
25
|
+
puts password
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
I chose Ruby because it's an elegant language, and I've been doing a little scripting in it recently. It's not as popular as it deserves to be, imo.
|
|
29
|
+
|
|
30
|
+
Since I stripped the comments from this rendition, here's the whole idea: because integer division with negatives is a little weird, for password computation purposes I render "negative" (leftward) rotation as "positive) (rightward) rotation. To do that I want to flip the sign on the rotation if it's positive, and flip the sign on the position (before restoring it to Zmod100, no negatives allowed).
|
|
31
|
+
|
|
32
|
+
By computing the sign of the rotation, I get to do this without any `if` expressions, which is pretty cool. When the direction is rightward, all the extra computation in the `password +=` expression does nothing; it's the same as `(position + rotation) / 100`. But when the direction is leftward, that formula inverts both the original position and the rotation, treating it as rightward rotation from the equivalent complementary position on the dial.
|
|
33
|
+
:replies: []
|
|
34
|
+
- :author: Nnnes
|
|
35
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pb3y8p/2025_day_1_solutions/nro9mh3
|
|
36
|
+
:body: |-
|
|
37
|
+
Not very many half-punchcard solutions yet (and an unfortunate number of oversized solutions in comments). Here's one for both parts including an attempt at descriptive comments:
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
puts STDIN.readlines.reduce([50, 0, 0]) { |a, x| # [Initial position, P1, P2]
|
|
41
|
+
n = a[0] + x.tr('LR', '-+').to_i # Current dial position (not mod 100 yet)
|
|
42
|
+
z = n % 100 == 0 ? 1 : 0 # Is it set to zero now?
|
|
43
|
+
[n % 100, a[1] + z, a[2] + n.abs / 100 + (a[0] > 0 && n <= 0 ? 1 : 0)]
|
|
44
|
+
}[1, 2] # ^P1 , ^P2: ^Count spins, ^Add 1 if it decreased to/past 0
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For parsing, `L`s and `R`s are simply turned into `-`s and `+`s before the string is parsed as an integer.
|
|
48
|
+
|
|
49
|
+
For Part 2's edge case handling, I initially used a multiply-by-zero trick `(a[0] * (n - 1) < 0 ? 1 : 0)`, but that's the same length as the much clearer version above.
|
|
50
|
+
|
|
51
|
+
Results are added up using a simple `.reduce()` accumulator (the `a`).
|
|
52
|
+
:replies:
|
|
53
|
+
- :author: riffraff
|
|
54
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pb3y8p/2025_day_1_solutions/nroeeh5
|
|
55
|
+
:body: the `tr`usage is very clever, love it!
|
|
56
|
+
:replies: []
|
|
57
|
+
- :author: SleepingInsomniac
|
|
58
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pb3y8p/2025_day_1_solutions/nrqu8i5
|
|
59
|
+
:body: |-
|
|
60
|
+
## Part 1
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
def solve(input)
|
|
64
|
+
pointer = 50
|
|
65
|
+
zeros = 0
|
|
66
|
+
|
|
67
|
+
until input.eof?
|
|
68
|
+
rotation = input.readline&.chomp
|
|
69
|
+
dist = rotation.gsub('L', '-').gsub('R', '').to_i
|
|
70
|
+
pointer = (pointer + dist) % 100
|
|
71
|
+
zeros += 1 if pointer == 0
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
zeros
|
|
75
|
+
end
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Part 2
|
|
79
|
+
|
|
80
|
+
```ruby
|
|
81
|
+
def solve(input, size = 100)
|
|
82
|
+
pointer = 50
|
|
83
|
+
zeros = 0
|
|
84
|
+
|
|
85
|
+
while rotation = input.readline&.chomp
|
|
86
|
+
dist = rotation.gsub('L', '-').gsub('R', '').to_i
|
|
87
|
+
prev_pointer = pointer
|
|
88
|
+
pointer += dist
|
|
89
|
+
crossings, pointer = pointer.divmod(size)
|
|
90
|
+
crossings = crossings.abs
|
|
91
|
+
|
|
92
|
+
crossings -= 1 if pointer == 0 && dist.positive?
|
|
93
|
+
crossings -= 1 if prev_pointer == 0 && dist.negative?
|
|
94
|
+
crossings += 1 if pointer == 0
|
|
95
|
+
|
|
96
|
+
zeros += crossings
|
|
97
|
+
|
|
98
|
+
break if input.eof?
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
zeros
|
|
102
|
+
end
|
|
103
|
+
```
|
|
104
|
+
:replies: []
|
|
105
|
+
- :author: riffraff
|
|
106
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pb3y8p/2025_day_1_solutions/nroeoal
|
|
107
|
+
:body: |-
|
|
108
|
+
straightforward but verbose, there are better solutions
|
|
109
|
+
|
|
110
|
+
```ruby
|
|
111
|
+
def solve_easy(lines)
|
|
112
|
+
res = 0
|
|
113
|
+
pos = 50
|
|
114
|
+
lines.each do |line|
|
|
115
|
+
move = line[0] == 'L' ? -1 : 1
|
|
116
|
+
num = line[1..].to_i
|
|
117
|
+
pos = (pos + move * num) % 100
|
|
118
|
+
res += 1 if pos == 0
|
|
119
|
+
end
|
|
120
|
+
res
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def solve_hard(lines)
|
|
124
|
+
res = 0
|
|
125
|
+
pos = 50
|
|
126
|
+
lines.each do |line|
|
|
127
|
+
move = line[0] == 'L' ? -1 : 1
|
|
128
|
+
num = line[1..].to_i
|
|
129
|
+
num.times do
|
|
130
|
+
pos = (pos + move) % 100
|
|
131
|
+
res += 1 if pos == 0
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
res
|
|
135
|
+
end
|
|
136
|
+
```
|
|
137
|
+
:replies: []
|
|
138
|
+
- :author: im_sofi
|
|
139
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pb3y8p/2025_day_1_solutions/nrow8a0
|
|
140
|
+
:body: |-
|
|
141
|
+
Couldn't wrap my head around Day 1 part 2 for the longest of times, but with some tests made it quite trivial to implement without using counting.
|
|
142
|
+
|
|
143
|
+
https://codeberg.org/soupglasses/advent-of-code/src/branch/main/2025/day\_01.rb
|
|
144
|
+
:replies: []
|
|
145
|
+
- :author: onyx_and_iris
|
|
146
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pb3y8p/2025_day_1_solutions/nroyuzs
|
|
147
|
+
:body: "[https://git.onyxandiris.online/onyx\\_online/aoc2025/src/branch/main/day\\_01](https://git.onyxandiris.online/onyx_online/aoc2025/src/branch/main/day_01)"
|
|
148
|
+
:replies: []
|
|
149
|
+
- :author: justjarvo
|
|
150
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pb3y8p/2025_day_1_solutions/nrq9co3
|
|
151
|
+
:body: |-
|
|
152
|
+
Initially did both parts with floor/modulo but kept getting off-by-one errors for part 2 so I just stepped through like a heathen
|
|
153
|
+
|
|
154
|
+
```ruby
|
|
155
|
+
dial, p1, p2 = 50, 0, 0
|
|
156
|
+
|
|
157
|
+
input.each do |ins|
|
|
158
|
+
ins[1..].to_i.times do
|
|
159
|
+
dial += ins[0] == "R" ? 1 : -1
|
|
160
|
+
dial = 99 if dial == -1
|
|
161
|
+
dial = 0 if dial == 100
|
|
162
|
+
p2 += 1 if dial == 0
|
|
163
|
+
end
|
|
164
|
+
p1 += 1 if dial == 0
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
p [p1, p2]
|
|
168
|
+
```
|
|
169
|
+
:replies:
|
|
170
|
+
- :author: kronn
|
|
171
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pb3y8p/2025_day_1_solutions/nrqr5md
|
|
172
|
+
:body: I was equally frustrated and came to the same low as you did.
|
|
173
|
+
:replies: []
|
|
174
|
+
- :author: srugh
|
|
175
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pb3y8p/2025_day_1_solutions/nrs0rxs
|
|
176
|
+
:body: |-
|
|
177
|
+
Part 1 (solve\_part\_1) and Part 2 (solve\_part\_2) each individually solved in a single file with a shared parsing function (parse\_input):
|
|
178
|
+
|
|
179
|
+
[GitHub 2025/Day-01.rb](https://github.com/srugh/AdventOfCode/blob/main/2025/day-01.rb)
|
|
180
|
+
:replies: []
|
|
181
|
+
- :author: Sharparam
|
|
182
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pb3y8p/2025_day_1_solutions/nro151z
|
|
183
|
+
:body: |-
|
|
184
|
+
[GitHub](https://github.com/Sharparam/advent-of-code/blob/main/src/y2025/d01/solve.rb)
|
|
185
|
+
|
|
186
|
+
In my sleep deprived state I can't come up with a cleaner version for now, maybe I'll come back later™ and make it nicer.
|
|
187
|
+
:replies: []
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
---
|
|
2
|
+
- :author: StillFast7545
|
|
3
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pbzqcx/2025_day_2_solutions/nskv362
|
|
4
|
+
:body: |-
|
|
5
|
+
Part 1: [https://github.com/MarioPerac/AdventOfCode2025/blob/main/day\_2/gift\_shop\_part\_1.rb](https://github.com/MarioPerac/AdventOfCode2025/blob/main/day_2/gift_shop_part_1.rb)
|
|
6
|
+
|
|
7
|
+
Part 2: [https://github.com/MarioPerac/AdventOfCode2025/blob/main/day\_2/gift\_shop\_part\_2.rb](https://github.com/MarioPerac/AdventOfCode2025/blob/main/day_2/gift_shop_part_2.rb)
|
|
8
|
+
:replies: []
|
|
9
|
+
- :author: justjarvo
|
|
10
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pbzqcx/2025_day_2_solutions/nrupo4w
|
|
11
|
+
:body: ". I am not good at math, so string manipulation it is \U0001F605 I wouldn't mind being pointed to some material to help me figure out how to approach this without all the string work.\n\n```ruby\ndef p1_invalid?(str)\n n = str.size\n n.even? && str[0, n/2] == str[n/2, n/2]\nend\n\ndef p2_invalid?(str)\n n = str.size\n\n (1...n).each do |m|\n next unless n % m == 0\n return true if str == str[0, m] * (n / m)\n end\n\n false\nend\n\ninput = File.read(\"input/d02.txt\").split(\",\")\np1, p2 = 0, 0\ninput.each do |range|\n Range.new(*range.split(\"-\").map(&:to_i)).each do |num|\n p1 += num if p1_invalid?(num.to_s)\n p2 += num if p2_invalid?(num.to_s)\n end\nend\n\np [p1, p2]\n```"
|
|
12
|
+
:replies: []
|
|
13
|
+
- :author: srugh
|
|
14
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pbzqcx/2025_day_2_solutions/nrxw6zq
|
|
15
|
+
:body: |-
|
|
16
|
+
Shared parsing, other wise part 1 (compare halves of string) and part 2 (compare chunks to full string) both independently solved.
|
|
17
|
+
|
|
18
|
+
[GitHub: Day-02 parts 1 and 2](https://github.com/srugh/AdventOfCode/blob/main/2025/day-02.rb)
|
|
19
|
+
:replies: []
|
|
20
|
+
- :author: pedantic_git
|
|
21
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pbzqcx/2025_day_2_solutions/nruo72g
|
|
22
|
+
:body: |-
|
|
23
|
+
It's brute force, sure, but I'm really happy with how elegant my solution is, thanks to regexps. It could be terser still but I wanted it to still be readable!
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
#!/usr/bin/env ruby
|
|
27
|
+
|
|
28
|
+
acc1, acc2 = 0, 0
|
|
29
|
+
|
|
30
|
+
ARGF.read.scan(/(\d+)-(\d+)/) do |l,r|
|
|
31
|
+
(l.to_i).upto(r.to_i) do
|
|
32
|
+
acc1 += it if /\A(.+)\1\Z/ =~ it.to_s
|
|
33
|
+
acc2 += it if /\A(.+)\1+\Z/ =~ it.to_s
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
puts acc1, acc2
|
|
38
|
+
```
|
|
39
|
+
:replies:
|
|
40
|
+
- :author: _tfa
|
|
41
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pbzqcx/2025_day_2_solutions/nruokq9
|
|
42
|
+
:body: Nice. To make it even shorter you could use strings in the upto-loop and only call to\_i when adding "it" to the accumulators.
|
|
43
|
+
:replies:
|
|
44
|
+
- :author: pedantic_git
|
|
45
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pbzqcx/2025_day_2_solutions/nrur3dt
|
|
46
|
+
:body: Ooh - it feels dirty using `upto` on a string, like it's going to sort them asciibetically or something, but it does seem to work!
|
|
47
|
+
:replies: []
|
|
48
|
+
- :author: SleepingInsomniac
|
|
49
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pbzqcx/2025_day_2_solutions/nrwuvy2
|
|
50
|
+
:body: |-
|
|
51
|
+
## Part 1
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
class IDRange
|
|
55
|
+
def self.parse(file)
|
|
56
|
+
return nil if file.eof?
|
|
57
|
+
IDRange.new(*file.gets(',').gsub(/,$/, '').split('-'))
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def initialize(start, stop)
|
|
61
|
+
@start, @stop = start.to_i, stop.to_i
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def range = (@start..@stop)
|
|
65
|
+
def invalid_ids = range.select { |n| n.to_s =~ /^(\d+)\1$/ }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def solve(input)
|
|
69
|
+
total = 0
|
|
70
|
+
while range = IDRange.parse(input)
|
|
71
|
+
total += range.invalid_ids.sum
|
|
72
|
+
end
|
|
73
|
+
total
|
|
74
|
+
end
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Part 2
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
...
|
|
81
|
+
def invalid_ids = range.select { |n| n.to_s =~ /^(\d+)\1+$/ }
|
|
82
|
+
...
|
|
83
|
+
```
|
|
84
|
+
:replies: []
|
|
85
|
+
- :author: im_sofi
|
|
86
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pbzqcx/2025_day_2_solutions/nrxps5w
|
|
87
|
+
:body: |-
|
|
88
|
+
Absolutely got stuck on an assumption that 1-9 was valid numbers for part 2.
|
|
89
|
+
|
|
90
|
+
Part 1 and 2 are done by enforcing each rule and picking the lowest next number. Regex is only used for parsing. :)
|
|
91
|
+
|
|
92
|
+
https://codeberg.org/soupglasses/advent-of-code/src/branch/main/2025/day\_02.rb
|
|
93
|
+
:replies: []
|
|
94
|
+
- :author: riffraff
|
|
95
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pbzqcx/2025_day_2_solutions/nruhu7c
|
|
96
|
+
:body: |-
|
|
97
|
+
The simplest thing I could think of, tho it is quite slow since it creates a ton of garbage, but it works. Fun fact: `Integer#digits` gives the numbers ordered from the least significant to the most, but it seems to work anyway.
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
def parse(io)
|
|
101
|
+
io.read.scan(/(\d+)-(\d+)/).map { |a, b| (a.to_i)..(b.to_i) }.to_a
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def same_subarray?(array, length)
|
|
105
|
+
parts = array.each_slice(length)
|
|
106
|
+
parts.uniq.length == 1
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def invalid?(digits)
|
|
110
|
+
return false if digits.length.odd?
|
|
111
|
+
same_subarray?(digits, digits.length / 2)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def invalid_hard?(digits)
|
|
115
|
+
1.upto(digits.length / 2).any? { |len| same_subarray?(digits, len) }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def solve(ranges, &block)
|
|
119
|
+
ranges.sum do |r|
|
|
120
|
+
r.sum do |number|
|
|
121
|
+
block.call(number.digits) ? number : 0
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def solve_easy(ranges)
|
|
127
|
+
solve(ranges) { |number| invalid?(number) }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def solve_hard(ranges)
|
|
131
|
+
solve(ranges) { |number| invalid_hard?(number) }
|
|
132
|
+
end
|
|
133
|
+
```
|
|
134
|
+
:replies:
|
|
135
|
+
- :author: riffraff
|
|
136
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pbzqcx/2025_day_2_solutions/nruiioj
|
|
137
|
+
:body: btw, this works with ranges of strings too, as you can do `'1'..'20'` and get `"1","2","3",..,"20"` but I never trust that :)
|
|
138
|
+
:replies: []
|
|
139
|
+
- :author: systemnate
|
|
140
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pbzqcx/2025_day_2_solutions/nrwmy2f
|
|
141
|
+
:body: |-
|
|
142
|
+
```ruby
|
|
143
|
+
data = data.split(",")
|
|
144
|
+
.map { |range| range.split("-") }
|
|
145
|
+
.map { |first, last| (first.to_i..last.to_i) }
|
|
146
|
+
|
|
147
|
+
class Product
|
|
148
|
+
def self.invalid?(product_id)
|
|
149
|
+
product_id = product_id.to_s
|
|
150
|
+
middle_point = product_id.length / 2
|
|
151
|
+
product_id.chars[0...middle_point] == product_id.chars[middle_point..]
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def self.really_invalid?(product_id)
|
|
155
|
+
product_id = product_id.to_s
|
|
156
|
+
|
|
157
|
+
(1..product_id.length / 2).each do |length|
|
|
158
|
+
pattern = product_id[0...length]
|
|
159
|
+
|
|
160
|
+
return true if pattern * (product_id.length / length) == product_id
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
false
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# part 1
|
|
168
|
+
invalid_numbers = data.each_with_object([]) do |range, invalids|
|
|
169
|
+
invalids << range.select { |n| Product.invalid?(n) }
|
|
170
|
+
end.flatten.compact
|
|
171
|
+
|
|
172
|
+
puts invalid_numbers.sum
|
|
173
|
+
|
|
174
|
+
# part 2
|
|
175
|
+
invalid_numbers = data.each_with_object([]) do |range, invalids|
|
|
176
|
+
invalids << range.select { |n| Product.really_invalid?(n) }
|
|
177
|
+
end.flatten.compact
|
|
178
|
+
|
|
179
|
+
puts invalid_numbers.sum
|
|
180
|
+
```
|
|
181
|
+
:replies: []
|
|
182
|
+
- :author: onyx_and_iris
|
|
183
|
+
:url: https://www.reddit.com/r/adventofcode/comments/1pbzqcx/2025_day_2_solutions/nrukvww
|
|
184
|
+
:body: "[https://git.onyxandiris.online/onyx\\_online/aoc2025/src/branch/main/day\\_02](https://git.onyxandiris.online/onyx_online/aoc2025/src/branch/main/day_02)"
|
|
185
|
+
:replies: []
|