Skip to content

Commit 2cfb881

Browse files
committed
Day 13 - Puzzle 2
1 parent 5e07a94 commit 2cfb881

File tree

2 files changed

+84
-17
lines changed

2 files changed

+84
-17
lines changed

lib/solutions/day_13.rb

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,72 @@
11
class Day13
22
def part_one(input)
3+
run(input, 100)
4+
end
5+
6+
def part_two(input)
7+
run(input, nil)
8+
end
9+
10+
def run(input, max_presses = nil)
311
input.split(/(?:^\r?\n)+/).map do |block|
412
lines = block.split("\n")
513
a_match = lines[0].match(/^Button A:\s+X\+(\d+),\s+Y\+(\d+)$/)
614
b_match = lines[1].match(/^Button B:\s+X\+(\d+),\s+Y\+(\d+)$/)
715
prize_match = lines[2].match(/^Prize:\s+X=(\d+),\s+Y=(\d+)$/)
816

17+
prize_x = prize_match[1].to_i
18+
prize_y = prize_match[2].to_i
19+
20+
if max_presses.nil?
21+
prize_x += 10_000_000_000_000
22+
prize_y += 10_000_000_000_000
23+
end
24+
925
ClawMachine.new(
1026
a_match[1].to_i,
1127
a_match[2].to_i,
1228
b_match[1].to_i,
1329
b_match[2].to_i,
14-
prize_match[1].to_i,
15-
prize_match[2].to_i
30+
prize_x,
31+
prize_y,
32+
max_presses
1633
)
1734
end.map(&:solve!)
1835
.compact
1936
.map(&:first)
2037
.sum
2138
end
22-
23-
def part_two(input)
24-
0
25-
end
2639
end
2740

2841
class ClawMachine
29-
attr_accessor :ax, :ay, :bx, :by, :prize_x, :prize_y
42+
attr_accessor :ax, :ay, :bx, :by, :prize_x, :prize_y, :max_presses
3043

31-
MAX_PRESSES = 100
3244
COST_A = 3
3345
COST_B = 1
3446

35-
def initialize(ax, ay, bx, by, prize_x, prize_y)
47+
def initialize(ax, ay, bx, by, prize_x, prize_y, max_presses = nil)
3648
@ax = ax
3749
@ay = ay
3850
@bx = bx
3951
@by = by
4052
@prize_x = prize_x
4153
@prize_y = prize_y
54+
@max_presses = max_presses
4255
end
4356

4457
def solve!
58+
if max_presses.nil?
59+
advanced_math_solution!
60+
else
61+
brute_force!
62+
end
63+
end
64+
65+
def brute_force!
4566
cheapest = nil
4667

47-
(0..MAX_PRESSES).each do |a|
48-
(0..MAX_PRESSES).each do |b|
68+
(0..max_presses).each do |a|
69+
(0..max_presses).each do |b|
4970
# Check if this combination hits the prize location
5071
if a * ax + b * bx == prize_x && a * ay + b * by == prize_y
5172
cost = COST_A * a + COST_B * b
@@ -56,4 +77,34 @@ def solve!
5677

5778
cheapest
5879
end
80+
81+
def advanced_math_solution!
82+
# SEe https://en.wikipedia.org/wiki/Cramer%27s_rule
83+
# Applications -> Small systems
84+
85+
# WE need to solve
86+
# A.ax + B.bx = prize_x
87+
# A.ay + B.by = prize_y
88+
89+
# Enter the matrix
90+
# [ ax bx ] [ A ] = [ prize_x]
91+
# [ ay by ] [ B ] = [ prize_y]
92+
93+
# compute Determinatn
94+
det = ax * by - ay * bx
95+
return nil if det == 0
96+
97+
# Check if there is an int solution
98+
_a = (prize_x * by - prize_y * bx)
99+
_b = (ax * prize_y - ay * prize_x)
100+
return nil unless _a % det == 0 && _b % det == 0
101+
102+
# Verify we have positive solutions
103+
push_a = _a / det
104+
push_b = _b / det
105+
return nil if push_a < 0 || push_b < 0
106+
107+
# Done ;-)
108+
[COST_A * push_a + COST_B * push_b, push_a, push_b]
109+
end
59110
end

spec/solutions/day_13_spec.rb

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@
66

77
describe '#part_one' do
88
it 'calculates machine 1' do
9-
m = ClawMachine.new(94, 34, 22, 67, 8400, 5400)
9+
m = ClawMachine.new(94, 34, 22, 67, 8400, 5400, 100)
1010
expect(m.solve!).to eq([280, 80, 40])
1111
end
1212

1313
it 'calculates machine 2' do
14-
m = ClawMachine.new(26, 66, 67, 21, 12_748, 12_176)
14+
m = ClawMachine.new(26, 66, 67, 21, 12_748, 12_176, 100)
1515
expect(m.solve!).to be_nil
1616
end
1717

1818
it 'calculates machine 3' do
19-
m = ClawMachine.new(17, 86, 84, 37, 7870, 6450)
19+
m = ClawMachine.new(17, 86, 84, 37, 7870, 6450, 100)
2020
expect(m.solve!).to eq([200, 38, 86])
2121
end
2222

2323
it 'calculates machine 2' do
24-
m = ClawMachine.new(69, 23, 27, 71, 18_641, 10_279)
24+
m = ClawMachine.new(69, 23, 27, 71, 18_641, 10_279, 100)
2525
expect(m.solve!).to be_nil
2626
end
2727

@@ -31,8 +31,24 @@
3131
end
3232

3333
describe '#part_two' do
34-
it 'calculates the correct solutions for part two' do
35-
expect(subject.part_two(input)).to eq(0)
34+
it 'calculates machine 1' do
35+
m = ClawMachine.new(94, 34, 22, 67, 10_000_000_008_400, 10_000_000_005_400)
36+
expect(m.solve!).to be_nil
37+
end
38+
39+
it 'calculates machine 2' do
40+
m = ClawMachine.new(26, 66, 67, 21, 10_000_000_012_748, 10_000_000_012_176)
41+
expect(m.solve!).not_to be_nil
42+
end
43+
44+
it 'calculates machine 3' do
45+
m = ClawMachine.new(17, 86, 84, 37, 10_000_000_007_870, 10_000_000_006_450)
46+
expect(m.solve!).to be_nil
47+
end
48+
49+
it 'calculates machine 2' do
50+
m = ClawMachine.new(69, 23, 27, 71, 10_000_000_018_641, 10_000_000_010_279)
51+
expect(m.solve!).not_to be_nil
3652
end
3753
end
3854
end

0 commit comments

Comments
 (0)