Skip to content

Commit

Permalink
Day 13 - Puzzle 2
Browse files Browse the repository at this point in the history
  • Loading branch information
ariejan committed Dec 13, 2024
1 parent 5e07a94 commit 2cfb881
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 17 deletions.
73 changes: 62 additions & 11 deletions lib/solutions/day_13.rb
Original file line number Diff line number Diff line change
@@ -1,51 +1,72 @@
class Day13
def part_one(input)
run(input, 100)
end

def part_two(input)
run(input, nil)
end

def run(input, max_presses = nil)
input.split(/(?:^\r?\n)+/).map do |block|
lines = block.split("\n")
a_match = lines[0].match(/^Button A:\s+X\+(\d+),\s+Y\+(\d+)$/)
b_match = lines[1].match(/^Button B:\s+X\+(\d+),\s+Y\+(\d+)$/)
prize_match = lines[2].match(/^Prize:\s+X=(\d+),\s+Y=(\d+)$/)

prize_x = prize_match[1].to_i
prize_y = prize_match[2].to_i

if max_presses.nil?
prize_x += 10_000_000_000_000
prize_y += 10_000_000_000_000
end

ClawMachine.new(
a_match[1].to_i,
a_match[2].to_i,
b_match[1].to_i,
b_match[2].to_i,
prize_match[1].to_i,
prize_match[2].to_i
prize_x,
prize_y,
max_presses
)
end.map(&:solve!)
.compact
.map(&:first)
.sum
end

def part_two(input)
0
end
end

class ClawMachine
attr_accessor :ax, :ay, :bx, :by, :prize_x, :prize_y
attr_accessor :ax, :ay, :bx, :by, :prize_x, :prize_y, :max_presses

MAX_PRESSES = 100
COST_A = 3
COST_B = 1

def initialize(ax, ay, bx, by, prize_x, prize_y)
def initialize(ax, ay, bx, by, prize_x, prize_y, max_presses = nil)
@ax = ax
@ay = ay
@bx = bx
@by = by
@prize_x = prize_x
@prize_y = prize_y
@max_presses = max_presses
end

def solve!
if max_presses.nil?
advanced_math_solution!
else
brute_force!
end
end

def brute_force!
cheapest = nil

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

cheapest
end

def advanced_math_solution!
# SEe https://en.wikipedia.org/wiki/Cramer%27s_rule
# Applications -> Small systems

# WE need to solve
# A.ax + B.bx = prize_x
# A.ay + B.by = prize_y

# Enter the matrix
# [ ax bx ] [ A ] = [ prize_x]
# [ ay by ] [ B ] = [ prize_y]

# compute Determinatn
det = ax * by - ay * bx
return nil if det == 0

# Check if there is an int solution
_a = (prize_x * by - prize_y * bx)
_b = (ax * prize_y - ay * prize_x)
return nil unless _a % det == 0 && _b % det == 0

# Verify we have positive solutions
push_a = _a / det
push_b = _b / det
return nil if push_a < 0 || push_b < 0

# Done ;-)
[COST_A * push_a + COST_B * push_b, push_a, push_b]
end
end
28 changes: 22 additions & 6 deletions spec/solutions/day_13_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@

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

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

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

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

Expand All @@ -31,8 +31,24 @@
end

describe '#part_two' do
it 'calculates the correct solutions for part two' do
expect(subject.part_two(input)).to eq(0)
it 'calculates machine 1' do
m = ClawMachine.new(94, 34, 22, 67, 10_000_000_008_400, 10_000_000_005_400)
expect(m.solve!).to be_nil
end

it 'calculates machine 2' do
m = ClawMachine.new(26, 66, 67, 21, 10_000_000_012_748, 10_000_000_012_176)
expect(m.solve!).not_to be_nil
end

it 'calculates machine 3' do
m = ClawMachine.new(17, 86, 84, 37, 10_000_000_007_870, 10_000_000_006_450)
expect(m.solve!).to be_nil
end

it 'calculates machine 2' do
m = ClawMachine.new(69, 23, 27, 71, 10_000_000_018_641, 10_000_000_010_279)
expect(m.solve!).not_to be_nil
end
end
end

0 comments on commit 2cfb881

Please sign in to comment.