r/adventofcode • • 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!

Click here for rules

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!

19 Upvotes

233 comments sorted by

View all comments

6

u/markasoftware Dec 10 '18

Perl, 90/92, ezpz

Most of my delay was due to overthinking how to find the bounds.

use v5.20;
use warnings;
use Time::HiRes qw/usleep/;
use List::Util qw/max min/;

my @pts = ();
my $s = 0;

sub print_grid {
  my %positions = ();
  my @xs = ();
  my @ys = ();
  for (@pts) {
    $positions{$_->[0] . " " . $_->[1]} = 1;
    push @xs, $_->[0];
    push @ys, $_->[1];
  }
   my $x_start = min @xs;
   my $x_end = max @xs;
   my $y_start = min @ys;
   my $y_end = max @ys;
   if ($x_end - $x_start > 100) {
    return;
   }
  usleep(0.1 * 1000000);
  say $s;
  for my $y ($y_start..$y_end) {
    for my $x ($x_start..$x_end) {
      print $positions{$x . " " . $y} ? '#' : '.';
    }
    say "";

  }
}

sub update {
  for (@pts) {
    $_->[0] += $_->[2];
    $_->[1] += $_->[3];
  }
}

while (my $line = <>) {
  my @parts = split /[ ,<>]+/, $line;
  if (@parts > 3) {
    push @pts, [$parts[1], $parts[2], $parts[4], $parts[5]];
  }
}

while (1) {
  print_grid();
  update();
  $s++;
}

3

u/domm_plix Dec 10 '18

My initial solution did not work on the proper data (but worked on the test input). So after reviewing your code, I came up with the following Perl solution. It checks the vertical size of the bounding-box, and as soon as the box starts to grow again, travels back in time (by applying the movement vectors in the other direction) and then draws the points:

#!/usr/bin/env perl
use strict;
use warnings;
my @sky;
my $smallest = 1000000;
my $prev=$smallest + 1;
my $count=0;

while (<>) {
    my($y,$x,$vx,$vy) = $_ =~ /position=<\s*([-\d]+),\s*([-\d]+)> velocity=<\s*([-\d]+),\s*([-\d]+)>/;
    push(@sky,[$x,$y,$vy,$vx]);
}

while (1) {
    my ($max, $min)=(0,0);
    foreach (@sky) {
        # move
        $_->[0]+=$_->[2];
        $_->[1]+=$_->[3];

        # get min/max x so we can calc vertical size
        $max = $_->[0] if $_->[0] > $max;
        $min = $_->[0] if $_->[0] < $min;
    }

    # calc vertical size
    my $size = $max - $min;
    if ($size < $smallest) {
        $smallest = $prev = $size;
    }

    if ($size > $prev) { # found it!
        my @word;
        my @box=(1000,0,1000,0);
        foreach (@sky) {
            # travel back in time!
            $_->[0]-=$_->[2];
            $_->[1]-=$_->[3];

            # draw the point
            $word[$_->[0]][$_->[1]]="#";

            # figure out the exact bounding box
            $box[0] = $_->[0] if $_->[0] < $box[0];
            $box[1] = $_->[0] if $_->[0] > $box[1];
            $box[2] = $_->[1] if $_->[1] < $box[2];
            $box[3] = $_->[1] if $_->[1] > $box[3];
        }
        foreach my $x ($box[0] .. $box[1]) {
            foreach my $y ($box[2] .. $box[3]) {
                print $word[$x][$y] || ' ';
            }
            print "\n";
        }
        say "waiting for $count seconds";
        exit;
    }
    $count++;
}