Advertisement
musifter

AoC day 22 (pt2), Perl

Dec 22nd, 2020
1,807
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 1.75 KB | None | 0 0
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. $| = 1;
  7. $/ = '';
  8.  
  9. my $Game = 0;
  10.  
  11. # Read decks:
  12. my @deck;
  13. foreach my $p (0 .. 1) {
  14.     $_ = <>;
  15.     $deck[$p]->@* = split( "\n" );
  16.     shift @{$deck[$p]};
  17. }
  18.  
  19. sub score_deck {
  20.     my $score = 0;
  21.     my $i = 1;
  22.     while (@_) {
  23.         $score += ($i * pop @_);
  24.         $i++;
  25.     }
  26.     return ($score);
  27. }
  28.  
  29. sub make_state {
  30.     my ($pd0, $pd1) = @_;
  31.     return (join( ',', @$pd0 ) . ':' . join( ',', @$pd1 ));
  32. }
  33.  
  34. sub recurse_game {
  35.     my ($depth, $d0, $d1 ) = @_;
  36.  
  37.     my %state;
  38.  
  39.     $Game++;
  40.     print "Starting game #$Game at depth $depth\r"  if ($Game % 100 == 0);
  41.  
  42.     while (@$d0 && @$d1) {
  43.         # loop detection:
  44.         my $curr_state = &make_state( $d0, $d1 );
  45.         if (exists $state{$curr_state}) {
  46.             return (($depth > 0) ? 0 : &score_deck( @$d0 ));
  47.         }
  48.         $state{$curr_state}++;
  49.  
  50.         # draw cards:
  51.         my ($c0, $c1) = (shift @$d0, shift @$d1);
  52.  
  53.         my $winner;
  54.         if ($c0 <= scalar(@$d0) && $c1 <= scalar(@$d1)) {
  55.             my @new_d0 = map { $d0->[$_] } (0 .. $c0 - 1);
  56.             my @new_d1 = map { $d1->[$_] } (0 .. $c1 - 1);
  57.             $winner = &recurse_game( $depth + 1, \@new_d0, \@new_d1 );
  58.         } elsif ($c0 > $c1) {
  59.             $winner = 0;
  60.         } else {
  61.             $winner = 1;
  62.         }
  63.  
  64.         # winner takes cards
  65.         if ($winner == 0) {
  66.             push( @$d0, ($c0, $c1) );
  67.         } else {
  68.             push( @$d1, ($c1, $c0) );
  69.         }
  70.     }
  71.  
  72.     # sub games return winner, main game returns score
  73.     if ($depth > 0) {
  74.         return ((@$d0) ? 0 : 1);
  75.     } else {
  76.         return (&score_deck( @$d0 || @$d1 ));
  77.     }
  78. }
  79.  
  80. print "\nPart 2: ", &recurse_game( 0, $deck[0], $deck[1] ), "\n";
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement