Advertisement
musifter

AoC 2024, day 9, part 2, faster (Perl)

Dec 9th, 2024 (edited)
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 1.26 KB | Source Code | 0 0
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. use feature         qw(say);
  7.  
  8. my @input = map { chomp; split // } <>;
  9.  
  10. # Read in disk
  11. my @disk;
  12.  
  13. my $id = 0;
  14. while (@input) {
  15.     my $size = shift @input;
  16.     my $gap  = shift @input;
  17.  
  18.     push( @disk, {id => $id++, size => int $size} );
  19.     push( @disk, {id => -1,    size => int $gap } )   if ($gap);
  20. }
  21.  
  22. # Defragment disk
  23. my $idx = $#disk;
  24. for (my $file_id = $id - 1; $file_id > 0; $file_id--) {
  25.     $idx--  while ($disk[$idx]{id} != $file_id);
  26.  
  27.     my $span = 0;
  28.     $span++ while ($span < $idx and ($disk[$span]{id} != -1
  29.                                     or $disk[$span]{size} < $disk[$idx]{size}));
  30.  
  31.     next if ($span >= $idx);
  32.  
  33.     # get amount of span still not used:
  34.     my $unused_size = $disk[$span]{size} - $disk[$idx]{size};
  35.  
  36.     # move data:
  37.     $disk[$span]->%* = $disk[$idx]->%*;
  38.     $disk[$idx]{id}  = -1;
  39.  
  40.     splice( @disk, $span + 1, 0, {size => $unused_size, id => -1} ) if ($unused_size);
  41. }
  42.  
  43. # Calculate checksum
  44. my $part2 = 0;
  45. my $pos = 0;
  46. foreach my $b (@disk) {
  47.     if ($b->{id} != -1 and $b->{size} > 0) {
  48.         for (my $i = 0; $i < $b->{size}; $i++) {
  49.             $part2 += $b->{id} * ($pos + $i);
  50.         }
  51.     }
  52.     $pos += $b->{size};
  53. }
  54. say "Part 2: $part2";
  55.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement