I'm an amateur programmer making a career change into web development. I've found Advent of Code challenges are great way to sharpen my skills. I've cleaned up this solution for Day 10, 2020 as much as I know how.
Here's a link to the description of the problem and my solution on GitHub. I've also summarized the problem and attached my code below.
Part 1:
Begin with a list of unique ordered integers, called "joltage adapters." Find the difference between each adjacent pair of integers, and count up how many differences of 1 and how many differences of 3 there are. What is the product of the differences of 1 and differences of 3?
For example, examine the adapter list [0, 3, 4, 5, 7, 10, 13]. There are 2 differences of 1 and 3 differences of 3, making the answer 6.
Part 2:
We can connect "joltage adapters" into chains if their difference is 3 or less. For example, 8 can connect to 7, 6, or 5, but not 4. A chain of valid connections might look like:
15 => 14 => 12 => 11 => 9 => 8 => 5 => 4 => 3 => 1 => 0
Here's the question: given a list of "joltage adapters," how many valid chains can we make? As a constraint, chains must start with the greatest adapter in the list and end with the smallest.
I'm simplifying a few things in this description (for example: we always add the "outlet" and the "device" to the list with values of 0 and the highest value plus three), but it hopefully will be enough to understand the code.
The answers for part 1 and part 2 are 2380 and 48358655787008. My solution for part 2 uses both memorization and recursion. I make regular use of hashes throughout.
Here is my solution:
class Adapter_Array
def initialize(filepath)
@adapters = load_adapters(filepath)
end
def load_adapters(filepath)
adapters = File.readlines(filepath, chomp: true)
.map(&:to_i)
.sort
add_charger_and_device(adapters)
end
def add_charger_and_device(adapters)
adapters.dup
.unshift(0)
.push(adapters.last + 3)
end
def part_1_answer
jolt_differences[1] * jolt_differences[3]
end
def jolt_differences
return @count if @count
@count = Hash.new(0)
@adapters.each_with_index do |adapter, i|
next if is_charger?(adapter)
prev_adapter = @adapters[i-1]
@count[adapter - prev_adapter] += 1
end
@count
end
def part_2_answer
ways_to_reach_charger(@adapters.last)
end
def ways_to_reach_charger(adapter)
@memorized_ways = { 0 => 1 } unless @memorized_ways
return @memorized_ways[adapter] if @memorized_ways[adapter]
@memorized_ways[adapter] = lower_jolt_connections(adapter)
.sum { |connection| ways_to_reach_charger(connection) }
end
def lower_jolt_connections(adapter)
return [] if is_charger?(adapter)
connections = []
i = (to_index(adapter) - 1)
potential_connection = @adapters[i]
while valid_connection?(adapter, potential_connection) && i >= 0
connections << potential_connection
i -= 1
potential_connection = @adapters[i]
end
connections
end
def valid_connection?(adapter_1, adapter_2)
(adapter_1 - adapter_2).abs <= 3
end
def to_index(adapter)
return @adapter_to_index_hash[adapter] if @adapter_to_index_hash
@adapter_to_index_hash = Hash.new
@adapters.each_with_index do |an_adapter, i|
@adapter_to_index_hash[an_adapter] = i
end
@adapter_to_index_hash[adapter]
end
def is_charger?(adapter)
adapter.zero?
end
end
aa = Adapter_Array.new("input.txt")
puts aa.part_1_answer
puts aa.part_2_answer
And here is my input:
153
69
163
123
89
4
135
9
124
74
141
132
75
3
18
134
84
15
61
91
90
98
99
51
131
166
127
77
106
50
22
70
43
28
41
160
44
117
66
60
76
17
138
105
97
161
116
49
104
169
71
100
16
54
168
42
57
103
1
32
110
48
12
143
112
82
25
81
148
133
144
118
80
63
156
88
47
115
36
2
94
128
35
62
109
29
40
19
37
122
142
167
7
147
121
159
87
83
111
162
150
8
149