Skip to content

Commit d3b7697

Browse files
committed
WIP Day 21
1 parent eb4a32a commit d3b7697

File tree

4 files changed

+145
-0
lines changed

4 files changed

+145
-0
lines changed

β€Žlib/input/day_21.txtβ€Ž

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
382A
2+
176A
3+
463A
4+
083A
5+
789A

β€Žlib/solutions/day_21.rbβ€Ž

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
require 'set'
2+
3+
class Day21
4+
5+
def part_one(input)
6+
sequences = input.split("\n")
7+
sim = DayOne.new(sequences)
8+
sim.run!
9+
end
10+
11+
class DayOne
12+
13+
def initialize(sequences)
14+
@sequences = sequences
15+
16+
@moves_cache = {}
17+
@scores_cache = {}
18+
end
19+
20+
# Define the numeric keypad with coordinates
21+
NUMPAD = {
22+
'7' => [0, 0],
23+
'8' => [0, 1],
24+
'9' => [0, 2],
25+
'4' => [1, 0],
26+
'5' => [1, 1],
27+
'6' => [1, 2],
28+
'1' => [2, 0],
29+
'2' => [2, 1],
30+
'3' => [2, 2],
31+
' ' => [3, 0],
32+
'0' => [3, 1],
33+
'A' => [3, 2]
34+
}.freeze
35+
36+
# Define the directional keypad movements with corresponding commands
37+
KEYPAD = {
38+
' ' => [0, 0],
39+
'^' => [0, 1],
40+
'A' => [0, 2],
41+
'<' => [1, 0],
42+
'v' => [1, 1],
43+
'>' => [0, 2]
44+
}.freeze
45+
46+
47+
def xdir(x)
48+
x > 0 ? 'v' : '^'
49+
end
50+
51+
def ydir(y)
52+
y > 0 ? '>' : '<'
53+
end
54+
55+
def run!
56+
result = 0
57+
@sequences.each do |sequence|
58+
value = Float::INFINITY
59+
500.times do
60+
@moves_cache.clear
61+
@scores_cache.clear
62+
value = [value, score(sequence, 3, 0) * sequence[0..-2].to_i].min
63+
end
64+
result += value
65+
end
66+
result
67+
end
68+
69+
def score(sequence, depth, current = 0)
70+
cache_key = [sequence, depth, current]
71+
# puts "scores_cache: #{@scores_cache}"
72+
return @scores_cache[cache_key] if @scores_cache.key?(cache_key)
73+
74+
return sequence.length if depth == 0
75+
76+
total = current
77+
sequence.chars.each_with_index do |key, index|
78+
next_key = sequence[index - 1]
79+
total += score(moves(next_key, key), depth - 1)
80+
end
81+
82+
@scores_cache[cache_key] = total
83+
end
84+
85+
def moves(current_key, next_key)
86+
cache_key = [current_key, next_key]
87+
88+
return @moves_cache[cache_key] if @moves_cache.key?(cache_key)
89+
90+
# Pick the pad given the current and next key
91+
pad = (KEYPAD.key?(current_key) && KEYPAD.key?(next_key)) ? KEYPAD : NUMPAD
92+
93+
# puts "-" * 40
94+
# puts "current_key: #{current_key}, next_key: #{next_key}"
95+
# puts "#{KEYPAD.keys}"
96+
# puts "pad: #{pad}"
97+
# puts "pad[current_key]: #{pad[current_key]}, pad[next_key]: #{pad[next_key]}"
98+
# puts "-" * 40
99+
100+
# Get x,y distances to move
101+
distance = [pad[next_key][0] - pad[current_key][0], pad[next_key][1] - pad[current_key][1]]
102+
# Map out key presses
103+
presses = xdir(distance[0]) * distance[0].abs + ydir(distance[1]) * distance[1].abs
104+
105+
if pad[" "] == [pad[next_key][0], pad[current_key][1]]
106+
result = presses.reverse + 'A'
107+
elsif pad[" "] == [pad[current_key][0], pad[next_key][1]]
108+
result = presses + 'A'
109+
else
110+
result = (rand < 0.5 ? presses : presses.reverse) + 'A'
111+
end
112+
113+
@moves_cache[cache_key] = result
114+
end
115+
end
116+
end

β€Žspec/input/day_21_test.txtβ€Ž

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
029A
2+
980A
3+
179A
4+
456A
5+
379A
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
require "spec_helper"
2+
require "solutions/day_21"
3+
4+
RSpec.describe Day21 do
5+
let(:input) { File.read(File.join(__dir__, '..', '..', 'spec', 'input', 'day_21_test.txt')).strip }
6+
7+
describe '#part_one' do
8+
it 'calculates the correct solutions for part one' do
9+
expect(subject.part_one(input)).to eq(126384)
10+
end
11+
end
12+
13+
describe '#part_two' do
14+
xit 'calculates the correct solutions for part two' do
15+
expect(subject.part_two(input)).to eq(0)
16+
end
17+
end
18+
end
19+

0 commit comments

Comments
Β (0)