Advertisement
musifter

AoC 2021 day 14 (Perl)

Dec 14th, 2021
1,910
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 1.62 KB | None | 0 0
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. # Helpful chain iterator:
  7. sub chain (&@) {
  8.     my $block = shift;
  9.     return (map { &$block( $_[$_-1], $_[$_] ) } (1 .. $#_));
  10. }
  11.  
  12. # Read in data
  13. chomp( $_ = <> );
  14. my @poly = split //;
  15. my @Ends = ($poly[-1], $poly[0]);
  16.  
  17. <>;                     # toss blank line
  18.  
  19. my %Rules = map { chomp; split / -> /, $_ } <>;
  20.  
  21. # Convert pair count hash into letter counts and give diff between max and min
  22. sub get_letter_diff (\%) {
  23.     my $pairs = shift;
  24.  
  25.     # plus one to ends to account for sides "off edges"
  26.     my %letters = ($Ends[0] => 1, $Ends[1] => 1);
  27.  
  28.     foreach my $pair (keys %$pairs) {
  29.         $letters{$_} += $pairs->{$pair}  foreach (split //, $pair);
  30.     }
  31.  
  32.     # half because we count each from both sides
  33.     %letters = map { $_ => $letters{$_} / 2 } keys %letters;
  34.  
  35.     # don't actually care about the letters, just look at values now
  36.     my @sort = sort { $a <=> $b } values %letters;
  37.  
  38.     return ($sort[-1] - $sort[0]);
  39. }
  40.  
  41. # Load counts with the chain iterator
  42. my %counts = chain { join('', @_) => 1 } @poly;
  43.  
  44. # Run 40 steps of polymer insersions (output part 1 at 10)
  45. foreach my $time (1 .. 40) {
  46.     my %new_counts;
  47.  
  48.     foreach my $pair (keys %counts) {
  49.         my @parts = split //, $pair;
  50.  
  51.         # Note: all possible rules definted so this works
  52.         $new_counts{"$parts[0]$Rules{$pair}"} += $counts{$pair};
  53.         $new_counts{"$Rules{$pair}$parts[1]"} += $counts{$pair};
  54.     }
  55.  
  56.     %counts = %new_counts;
  57.  
  58.     print "Part 1: ", &get_letter_diff( \%counts ), "\n"  if ($time == 10);
  59. }
  60.  
  61. print "Part 2: ", &get_letter_diff( \%counts ), "\n";
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement