Skip to content

Instantly share code, notes, and snippets.

@mscha
Last active December 13, 2024 11:48
Show Gist options
  • Save mscha/ebad7c247c5ef7445dc13ef56013c233 to your computer and use it in GitHub Desktop.
Save mscha/ebad7c247c5ef7445dc13ef56013c233 to your computer and use it in GitHub Desktop.
Advent of Code 2024 day 13
#!/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 $m0;
# 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 $n0;
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