Last active
December 13, 2024 11:48
-
-
Save mscha/ebad7c247c5ef7445dc13ef56013c233 to your computer and use it in GitHub Desktop.
Advent of Code 2024 day 13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env raku | |
use v6.d; | |
$*OUT.out-buffer = False; # Autoflush | |
# Advent of Code 2024 day 13 -- https://adventofcode.com/2024/day/13 | |
sub button-presses($ax,$ay, $bx,$by, $px,$py) | |
{ | |
# We need to find (non-negative integer) m and n so that | |
# m × (ax,ay) + n × (bx,by) = (px,py) | |
# Or in matrix form: | |
# | |
# ( ax bx ) ( m ) ( px ) | |
# ( ay by ) ( n ) = ( py ) | |
# | |
# Solving the matrix equation gives | |
# | |
# ( m ) ________1________ ( by -bx ) ( px ) | |
# ( n ) = ax × by - ay × bx ( -ay ax ) ( py ) | |
# ( ax bx ) | |
# Calculate the determinant of matrix ( ay by ) | |
# If it's 0, then A and B are linear. There may be 0 or ∞ | |
# solutions in this case, but we don't handle that. | |
my $det = $ax*$by - $ay*$bx; | |
die "Oops: ($ax,$ay) and ($bx,$by) are linear!" if $det == 0; | |
# Calculate m. If it's not a non-negative integer, there's no solution. | |
my $num-m = $by*$px - $bx*$py; | |
return Empty unless $num-m %% $det; | |
my $m = $num-m div $det; | |
return Empty unless $m ≥ 0; | |
# Calculate n. If it's not a non-negative integer, there's no solution. | |
my $num-n = $ax*$py - $ay*$px; | |
return Empty unless $num-n %% $det; | |
my $n = $num-n div $det; | |
return Empty unless $n ≥ 0; | |
return $m, $n; | |
} | |
sub MAIN(IO() $inputfile where *.f = 'aoc13.input', Bool :v(:$verbose) = False) | |
{ | |
my @numbers = $inputfile.comb(/\d+/); | |
my $part1-cost = 0; | |
for @numbers -> $ax,$ay, $bx,$by, $px,$py { | |
my ($m,$n) = button-presses($ax,$ay, $bx,$by, $px,$py); | |
if (defined($m) && defined($n)) { | |
my $cost = 3×$m + $n; | |
$part1-cost += $cost; | |
say "($ax,$ay), ($bx,$by) → ($px,$py): 3×$m + $n = $cost" if $verbose; | |
} | |
else { | |
say "($ax,$ay), ($bx,$by) → ($px,$py): no solutions" if $verbose; | |
} | |
} | |
say "Part 1: total cost = $part1-cost"; | |
my $part2-cost = 0; | |
for @numbers -> $ax,$ay, $bx,$by, $px,$py { | |
my ($qx,$qy) = ($px,$py) »+» 10_000_000_000_000; | |
my ($m,$n) = button-presses($ax,$ay, $bx,$by, $qx,$qy); | |
if (defined($m) && defined($n)) { | |
my $cost = 3×$m + $n; | |
$part2-cost += $cost; | |
say "($ax,$ay), ($bx,$by) → ($qx,$qy): 3×$m + $n = $cost" if $verbose; | |
} | |
else { | |
say "($ax,$ay), ($bx,$by) → ($qx,$qy): no solutions" if $verbose; | |
} | |
} | |
say "Part 2: total cost = $part2-cost"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment