#!/usr/bin/env perl6 use v6.c; #use Digest::MD5; # Too slow, use Perl 5 version through Inline::Perl5 use Digest::MD5:from 'md5_hex'; sub md5_repeated(Str $str is copy, Int $iterations) { # Way too slow - probably overhead of using Inline::Perl5 2017 times #$str = md5_hex($str) for ^$iterations; #return $str; # Do the whole thing in Perl 5 code instead use MONKEY-SEE-NO-EVAL; return EVAL "my \$s = '$str'; for (1..$iterations) \{ \$s = md5_hex(\$s); \}; \$s;", :lang; } my regex triple { (\w) ** 3 } sub triples(Str $s) { # Only the first one! #return $s.comb(&triple).unique».substr(0, 1); return $s.comb(&triple, 1)».substr(0, 1); } my regex quintuple { (\w) ** 5 } sub quintuples(Str $s) { return $s.comb(&quintuple).unique».substr(0, 1); } sub key-info(Str $salted-index) { #my $hash = md5_hex($salted-index); # part 1 my $hash = md5_repeated($salted-index, 2017); # part 2 return { hash=>$hash, triples=>triples($hash), quintuples=>quintuples($hash) }; } sub test-key(Str $salt, Int $index) { state %key-info; %key-info{$salt~$index} //= key-info($salt~$index); my @triples = %key-info{$salt~$index}.flat; # Not sure why flat is needed return Nil unless @triples; for $index+1 .. $index+1000 -> $i { %key-info{$salt~$i} //= key-info($salt~$i); my @quintuples = %key-info{$salt~$i}.flat; return %key-info{$salt~$index} if @quintuples && any(@triples) eq any(@quintuples); } return Nil; } multi sub MAIN(IO() $inputfile where *.f) { my ($salt) = $inputfile.words; MAIN($salt); } multi sub MAIN(Str $salt where !*.IO.f) { my @keys; for 1..∞ -> $i { if my $hash = test-key($salt, $i) { @keys.push($hash); say "[#@keys.elems()] $i: $hash"; last if @keys.elems == 64; } } }