Last active
December 14, 2024 15:51
-
-
Save mscha/2bdd2dbdf13823f917d11a10996f6297 to your computer and use it in GitHub Desktop.
Advent of Code 2024 day 14
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 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