Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- use strict;
- use warnings;
- use feature qw(say);
- my $seed = <>;
- chomp $seed;
- # Table of tail parities:
- my $par = 0;
- my @Table = (0, map {$par ^= $_} split( //, $seed ));
- $par = 0;
- push( @Table, 0, map {$par ^= !$_} split( //, reverse $seed ) );
- my $Block_Size = length( $seed ) + 1;
- my $Odd_Parity = @{[$seed =~ m#1#g]} % 2;
- my $Odd_Length = length( $seed ) % 2;
- # Returns A255070(n+1) & 1:
- # The parity of 1s at index n of the dragon curve starting with "0".
- # A255070 is (1/2)*(n - #runs in binary expansion of n)
- sub dragon_parity {
- my $n = shift;
- $n++;
- my $num = $n ^ ($n >> 1);
- # Count bits using classic bit iterator
- my $bitcount = 0;
- for ($bitcount = 0; $num; $bitcount++) {
- $num &= $num - 1;
- }
- return ((($n - $bitcount) >> 1) & 1);
- }
- sub calc_chksum {
- my $data_length = shift;
- # Data length is divided into sections of the largest power of 2 that divides it
- my $sect_size = $data_length & ~($data_length - 1);
- my $chksum_len = $data_length / $sect_size;
- my $result = '';
- my $prev = 0;
- foreach my $sect (1 .. $chksum_len) {
- my $end = $sect * $sect_size;
- my $index = int($end / $Block_Size) * 2 - 1;
- my $full = &dragon_parity( $Odd_Length ? $index : int($index/2) );
- $full ^= $Table[$end % ($Block_Size * 2)]; # add parity of tail
- $full ^= 1 if ($Odd_Parity and $index % 4 < 2); # odd seed adjustment
- $result .= ($prev ^ $full ^ 1); # want range and complement
- $prev = $full;
- }
- return ($result);
- }
- say "Part 1: ", &calc_chksum( 272 );
- say "Part 2: ", &calc_chksum( 35651584 );
Advertisement
Add Comment
Please, Sign In to add comment