#!/usr/bin/perl use v5.35.0; use List::Util qw(sum); use Data::Dumper; my $verbose = 0; # Read disk map, build lists of files and gaps my (@files, @gaps); my $is_file = 0; my $lba = 0; while (<>) { while (/(.)/g) { $is_file = !$is_file; if ($1) { if ($is_file) { push @files, [$lba, 0+$1]; } else { push @gaps, [$lba, 0+$1]; } } $lba += $1; } } say Dumper \@files, \@gaps if $verbose; # Compact the disk for my $file (reverse @files) { my ($file_start, $file_size) = @$file; for my $i (0 .. $#gaps) { my ($gap_start, $gap_size) = @{$gaps[$i]}; last unless $gap_start < $file_start; if ($gap_size >= $file_size) { @$file = ($gap_start, $file_size); if ($gap_size == $file_size) { splice @gaps, $i, 1; } else { @{$gaps[$i]} = ($gap_start += $file_size, $gap_size -= $file_size); } last; } } } say Dumper \@files, \@gaps if $verbose; # Calculate filesystem checksum say sum map { my ($start, $size) = @{$files[$_]}; $_ * $size * ($start + $start + $size - 1) / 2; } (0 .. $#files);