Advertisement
musifter

AoC 2022, day 18 (perl)

Dec 18th, 2022 (edited)
1,692
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 1.47 KB | Source Code | 0 0
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. use List::AllUtils  qw(minmax pairwise all);
  7.  
  8. my @dirs = ([1,0,0], [-1,0,0], [0,1,0], [0,-1,0], [0,0,1], [0,0,-1]);
  9.  
  10. sub vec_sum ($$) {
  11.     my ($v, $w) = @_;
  12.     return ([pairwise {$a + $b} @$v, @$w]);
  13. }
  14.  
  15. sub to_key ($) {
  16.     my $pos = shift;
  17.     return (join($;, @$pos));
  18. }
  19.  
  20. sub get_surface {
  21.     my %seen;
  22.     my $surface = 0;
  23.  
  24.     foreach my $cell (@_) {
  25.         $seen{ to_key $cell }++;
  26.         $surface += 6;
  27.  
  28.         foreach my $np (map {vec_sum($cell, $_)} @dirs) {
  29.             $surface -= 2 if (exists $seen{ to_key $np });
  30.         }
  31.     }
  32.  
  33.     return ($surface);
  34. }
  35.  
  36. my @cells = map { [m#(\d+)#g] } <>;
  37. print "Part 1: ", &get_surface( @cells ), "\n";
  38.  
  39. my %droplet = map { to_key($_) => 1 } @cells;
  40.  
  41. # Get bounding box:
  42. my ($min, $max) = vec_sum( [minmax map { @$_ } @cells], [-1,1] )->@*;
  43.  
  44. # BFS the world outside the droplet (but inside the bounds)
  45. my @queue = ([$min, $min, $min]);
  46. my %encase;
  47.  
  48. while (my $pos = shift @queue) {
  49.     next if ($encase{ to_key $pos }++);
  50.  
  51.     foreach my $np (map {vec_sum($pos, $_)} @dirs) {
  52.         next if ($droplet{ to_key $np });
  53.         push( @queue, $np ) if (all {$min <= $_ <= $max} @$np);
  54.     }
  55. }
  56.  
  57. # Get the full encasing surface, then minus the world facing side
  58. my $encase_surface = &get_surface( map { [split($;, $_)] } keys %encase );
  59. my $outer_surface  = 6 * (($max - $min + 1) ** 2);
  60.  
  61. print "Part 2: ", $encase_surface - $outer_surface, "\n";
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement