Advertisement
musifter

AoC day 16(pt2), Perl w/curses

Dec 16th, 2020 (edited)
2,949
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 2.37 KB | None | 0 0
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. use List::AllUtils  qw(notall indexes product);
  7.  
  8. use Curses;
  9. use Time::HiRes  qw(sleep);
  10.  
  11. my $DELAY = 0.1;
  12.  
  13. my $cur = new Curses;
  14. Curses::initscr();
  15. $cur->clear();
  16.  
  17. $/ = '';
  18.  
  19. my @valid;
  20. my @f_valid;
  21.  
  22. # Read ranges:
  23. $_ = <>;
  24.  
  25. my @field_names;
  26.  
  27. my $f_num = 0;
  28. foreach (split( "\n" )) {
  29.     m#(.*):#g;
  30.     push( @field_names, ucfirst $1 );
  31.  
  32.     foreach my $range (map { s#-#..#r } (m#\d+-\d+#g)) {
  33.         foreach (eval( $range )) {
  34.             $valid[ $_ ] = 1;
  35.             $f_valid[ $f_num ][ $_ ] = 1;
  36.         }
  37.     }
  38.     $f_num++;
  39. }
  40. $f_num--;
  41.  
  42. # Read my ticket:
  43. $_ = <>;
  44.  
  45. my @mine = m#\d+#g;
  46. foreach my $i (0 .. $f_num) {
  47.     $cur->addstr( $i + 1, 5, sprintf( "%s   %3d", ',' x ($f_num + 1), $mine[$i] ) );
  48. }
  49. $cur->refresh();
  50.  
  51. # Read nearby tickets:
  52. $_ = <>;
  53.  
  54. my @f_table;
  55. foreach my $i (0 .. $f_num) {
  56.     %{$f_table[$i]} = map { $_ => 1 } (0 .. $f_num);    # init table to all valid
  57. }
  58.  
  59. foreach (split( "\n" )) {
  60.     my @ticket = m#\d+#g;
  61.  
  62.     next if (!@ticket || notall { $valid[$_] } @ticket);    # toss out invalid ones
  63.  
  64.     # scan to remove invalid possibilities from table:
  65.     foreach my $i (0 .. $f_num) {
  66.         foreach my $f (0 .. $f_num) {
  67.             if (!$f_valid[$f][ $ticket[$i] ]) {
  68.                 delete $f_table[$i]{$f};
  69.                 $cur->addch( $i + 1, 5 + $f, 'X' );
  70.                 $cur->refresh();
  71.                 sleep( $DELAY / 10 );
  72.             }
  73.         }
  74.     }
  75. }
  76.  
  77. # Find the ones with only one choice, mark them in the key, delete for others, repeat
  78. #printf "\nSolving:\n";
  79. my @answer_key;
  80. foreach (0 .. $f_num) {
  81.     foreach my $i (indexes { keys %$_ == 1 } @f_table) {
  82.         my $ans = (keys %{$f_table[$i]})[0];
  83.  
  84.         $answer_key[$ans] = $i;
  85.  
  86.         $cur->addch( $i + 1, 5 + $ans, 'O' );
  87.         $cur->refresh();
  88.         sleep( $DELAY );
  89.  
  90.         foreach (0 .. $f_num) {
  91.             delete $f_table[$_]{$ans};
  92.             $cur->addch( $_ + 1, 5 + $ans, '.' ) if ($_ != $i);
  93.         }
  94.  
  95.         $cur->addstr( $i + 1, $f_num + 13 , $field_names[ $ans ] );
  96.         $cur->refresh();
  97.         sleep( $DELAY );
  98.     }
  99. }
  100. #
  101. # Hardcoding in fields 0-5, because these are the "departure" ones in my input
  102. $cur->addstr( 3 + $f_num, 5, sprintf( "Part 2: %d", product( map { $mine[ $answer_key[$_] ] } (0 .. 5) )));
  103. $cur->refresh();
  104.  
  105. Curses::endwin();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement