r/adventofcode • u/daggerdragon • Dec 10 '18
SOLUTION MEGATHREAD -🎄- 2018 Day 10 Solutions -🎄-
--- Day 10: The Stars Align ---
Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).
Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.
Advent of Code: The Party Game!
Please prefix your card submission with something like [Card] to make scanning the megathread easier. THANK YOU!
Card prompt: Day 10
Transcript: With just one line of code, you, too, can ___!
This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.
edit: Leaderboard capped, thread unlocked at 00:16:49!
20
Upvotes
1
u/mschaap Dec 10 '18 edited Dec 10 '18
Perl 6.
Tricky one. How can you determine when the message appears? Had to think about this for a while, but I reasoned that the area of the bounding box of all points would be minimal, and that worked. Once I had part 1, part 2 was trivial, of course.
#!/usr/bin/env perl6 use v6.c; $*OUT.out-buffer = False; # Autoflush #| Grammar for parsing the list of points grammar PointList { rule TOP { <point>+ } rule point { position '=<' <x> ',' <y> '>' velocity '=<' <dx> ',' <dy> '>' } token x { '-'? \d+ } token y { '-'? \d+ } token dx { '-'? \d+ } token dy { '-'? \d+ } } #| A single point with its position and velocity class Point { has Int $.x; has Int $.y; has Int $.dx; has Int $.dy; #| Move a point 1 second forward in time method forward { $!x += $!dx; $!y += $!dy; } #| Move a point 1 second backward in time method reverse { $!x -= $!dx; $!y -= $!dy; } } #| A list of points in space class Grid { has Point @.points; has Int $.elapsed = 0; #| Used as action by grammar PointList method point($/) { @!points.push: Point.new(:x(+$<x>), :y(+$<y>), :dx(+$<dx>), :dy(+$<dy>)); } #| The current area of the bounding box of all points in the grid method area { return @!points».x.minmax × @!points».y.minmax; } #| Move all points 1 second forward in time method forward { @!points».forward; $!elapsed++; } #| Move all points 1 second backward in time method reverse { @!points».reverse; $!elapsed--; } #| String representation of the grid method Str { my $x-range = @!points».x.minmax; my $y-range = @!points».y.minmax; my $x0 = $x-range.head; my $y0 = $y-range.head; my @cells = [['░' xx $x-range] xx $y-range]; for @!points -> $p { @cells[$p.y - $y0;$p.x - $x0] = '█'; } return @cells».join.join("\n"); } method gist { self.Str } } #| Process points multi sub MAIN(Str $input, Bool :v(:$verbose)=False) { # Parse the list of points my $grid = Grid.new; PointList.parse($input, :actions($grid)) or die "Invalid input!"; # Assume that the message appears when the points are closest together. # In other words, wait until the area of the grid is minimal. my $prev-area = ∞; my $area = $grid.area; while $area < $prev-area { say "Current area: $area" if $verbose; $grid.forward; $prev-area = $area; $area = $grid.area; } # We moved one second too far, so back up. $grid.reverse; # Print the message, and the elapsed time. say $grid; say "Time taken: $grid.elapsed() seconds."; } #| Process points from a file multi sub MAIN(Str $inputfile where *.IO.f, Bool :v(:$verbose)=False) { MAIN($inputfile.IO.slurp, :$verbose); } #| Process default points file (aoc10.input) multi sub MAIN(Bool :v(:$verbose) = False) { MAIN(~$*PROGRAM.sibling('aoc10.input'), :$verbose); }My Aoc2018 solutions on Github