#!/usr/bin/env perl6
use v6.c;
# Solution for Project Euler problem 104 https://projecteuler.net/problem=104
sub MAIN(Int $digits where 1..9 = 9, Bool :v(:$verbose) = False)
{
# Store all permutations of 1..$digits in a set for easy checking
say "Creating set of permutations of 1..$digits ..." if $verbose;
my $pan = set (1..$digits).permutations.map(+*.join);
say "Starting..." if $verbose;
my $mod = 10**$digits; # For checking right-pandigital
my $max = 10**($digits+5); # For left-pandigital (5 extra for rounding)
my $lfibo = 0; # Left digits of Fibonacci sequence
my $lfibo-next = 1;
my $rfibo = 0; # Right digits of Fibonacci sequence
my $rfibo-next = 1;
my $extra-digits = 0; # Remember how many digits we cut off
for 1..* -> $k {
# Iterate left fibonacci Sequence. Divide both numbers by 10
# when the get too big. (Keep 5 digits extra to prevent rounding issues.)
($lfibo, $lfibo-next) = ($lfibo-next, $lfibo+$lfibo-next);
if $lfibo > $max {
$lfibo = ($lfibo + 5) div 10;
$lfibo-next = ($lfibo-next + 5) div 10;
$extra-digits++;
}
# Iterate right Fibonacci sequence. This one can simply use modulo.
($rfibo, $rfibo-next) = ($rfibo-next, ($rfibo+$rfibo-next) % $mod);
# First, check if right-pandigital
if $rfibo ∈ $pan {
say "$k: right-pandigital" if $verbose;
# Then, check if left-pandigital
if +$lfibo.substr(0,$digits) ∈ $pan {
# We have a winner!
say '' if $verbose;
say "$lfibo...$rfibo" if $verbose;
say '' if $verbose;
say "Fibonacci number {$k} (length {$lfibo.chars+$extra-digits}) ",
"is the first that is left and right {$digits}-pandigital.";
last;
}
}
}
}
Comments