Skip to content

Instantly share code, notes, and snippets.

@mscha
Last active December 14, 2024 15:51
Show Gist options
  • Save mscha/2bdd2dbdf13823f917d11a10996f6297 to your computer and use it in GitHub Desktop.
Save mscha/2bdd2dbdf13823f917d11a10996f6297 to your computer and use it in GitHub Desktop.
Advent of Code 2024 day 14
#!/usr/bin/env raku
use v6.d;
$*OUT.out-buffer = False; # Autoflush
# Advent of Code 2024 day 14 -- https://adventofcode.com/2024/day/14
class Vector
{
has Int $.x;
has Int $.y;
method xy { $!x, $!y }
method Str { "($!x,$!y)" }
method gist { self.Str }
method WHICH { ValueObjAt.new("Vector|$!x|$!y") }
}
multi sub vector(Int() $x, Int() $y) { Vector.new(:$x, :$y) }
multi sub vector(@xy) { vector(@xy[0], @xy[1]) }
multi sub infix:<*>(Numeric $n, Vector $v) { vector($n «*« $v.xy) }
multi sub infix:<+>(Vector $v, Vector $w) { vector($v.xy »+« $w.xy) }
multi sub infix:<->(Vector $v, Vector $w) { vector($v.xy »-« $w.xy) }
multi sub infix:<%>(Vector $v, Vector $m) { vector($v.xy »%« $m.xy) }
class Robot
{
has Vector $.position;
has Vector $.velocity;
method Str { "Robot at $!position going $!velocity" }
method gist { self.Str }
method move(Int $times = 1, Vector :$modulo)
{
$!position += $times*$!velocity;
$!position %= $modulo if $modulo;
}
}
class BathroomFloor
{
has Str @.robot-spec;
has Int $.width;
has Int $.height;
has Robot @.robots;
has Vector $!modulo = vector($!width, $!height);
submethod TWEAK
{
for @!robot-spec.comb(/ '-'? \d+ /) -> $px,$py, $vx,$vy {
my $position = vector($px,$py);
my $velocity = vector($vx,$vy);
@!robots.append(Robot.new(:$position, :$velocity));
}
}
method wait(Int $seconds = 1)
{
@!robots».move($seconds, :$!modulo);
}
method safety-factor
{
my ($mid-x, $mid-y) = (($!width-1)/2, ($!height-1)/2);
my $nw = +@!robots».position.grep({ .x < $mid-x && .y < $mid-y });
my $ne = +@!robots».position.grep({ .x > $mid-x && .y < $mid-y });
my $sw = +@!robots».position.grep({ .x < $mid-x && .y > $mid-y });
my $se = +@!robots».position.grep({ .x > $mid-x && .y > $mid-y });
return $nw*$ne*$sw*$se;
}
# Detect the longest vertical robot line
method longest-line
{
my $occupied = set @!robots».position;
my $longest = 0;
# Check for vertical lines at each horizontal position
for ^$!width -> $x {
my $line = 0;
for ^$!height -> $y {
if $occupied{vector($x,$y)} {
$line++;
$longest max= $line;
}
else {
$line = 0;
}
}
}
return $longest;
}
method Str
{
my @grid = [[' ' xx $!width] xx (($!height+1) div 2)];
for @!robots».position -> $p {
if $p.y %% 2 {
with @grid[$p.y div 2;$p.x] {
$_ = '' when ' ';
$_ = '' when '';
}
}
else {
with @grid[$p.y div 2;$p.x] {
$_ = '' when ' ';
$_ = '' when '';
}
}
}
return @grid».join.join("\n");
}
method gist { self.Str }
}
sub MAIN(IO() $inputfile where *.f = 'aoc14.input', Bool :v(:$verbose) = False)
{
my @robot-spec = $inputfile.lines;
my ($width, $height) = $inputfile ~~ /sample/ ?? (11,7) !! (101,103);
my $floor = BathroomFloor.new(:@robot-spec, :$width, :$height);
say "Initial positions:\n{ $floor.robots.join("\n") }\n" if $verbose;
$floor.wait(100);
say "After 100 seconds:\n{ $floor.robots.join("\n") }\n" if $verbose;
say "Part 1: the safety factor is ", $floor.safety-factor;
$floor = BathroomFloor.new(:@robot-spec, :$width, :$height);
my $min-length = $inputfile ~~ /sample/ ?? 4 !! 10;
my $seconds = 0;
while $floor.longest-line < $min-length {
$floor.wait;
$seconds++;
say "($seconds seconds...)" if $verbose && $seconds %% 100;
}
say "Part 2: after $seconds seconds, a picture is shown.";
say $floor if $verbose;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment