Solution to Project Euler problem 43

db4
Aaron Schaefer 2008-02-05 16:42:50 -05:00
parent 09f40aa17e
commit c68e70877d
2 changed files with 100 additions and 3 deletions

View File

@ -0,0 +1,97 @@
! Copyright (c) 2008 Aaron Schaefer.
! See http://factorcode.org/license.txt for BSD license.
USING: combinators.lib hashtables kernel math math.combinatorics math.parser
math.ranges project-euler.common sequences sorting ;
IN: project-euler.043
! http://projecteuler.net/index.php?section=problems&id=43
! DESCRIPTION
! -----------
! The number, 1406357289, is a 0 to 9 pandigital number because it is made up
! of each of the digits 0 to 9 in some order, but it also has a rather
! interesting sub-string divisibility property.
! Let d1 be the 1st digit, d2 be the 2nd digit, and so on. In this way, we note
! the following:
! * d2d3d4 = 406 is divisible by 2
! * d3d4d5 = 063 is divisible by 3
! * d4d5d6 = 635 is divisible by 5
! * d5d6d7 = 357 is divisible by 7
! * d6d7d8 = 572 is divisible by 11
! * d7d8d9 = 728 is divisible by 13
! * d8d9d10 = 289 is divisible by 17
! Find the sum of all 0 to 9 pandigital numbers with this property.
! SOLUTION
! --------
! Brute force generating all the pandigitals then checking 3-digit divisiblity
! properties...this is very slow!
<PRIVATE
: subseq-divisible? ( n index seq -- ? )
[ 1- dup 3 + ] dip subseq 10 swap digits>integer swap mod zero? ;
: interesting? ( seq -- ? )
{
[ 17 8 pick subseq-divisible? ]
[ 13 7 pick subseq-divisible? ]
[ 11 6 pick subseq-divisible? ]
[ 7 5 pick subseq-divisible? ]
[ 5 4 pick subseq-divisible? ]
[ 3 3 pick subseq-divisible? ]
[ 2 2 pick subseq-divisible? ]
} && nip ;
PRIVATE>
: euler043 ( -- answer )
1234567890 number>digits all-permutations
[ interesting? ] subset [ 10 swap digits>integer ] map sum ;
! [ euler043 ] time
! 125196 ms run / 19548 ms GC time
! ALTERNATE SOLUTIONS
! -------------------
! Build the number from right to left, generating the next 3-digits according
! to the divisiblity rules and combining them with the previous digits if they
! overlap and still have all unique digits. When done with that, add whatever
! missing digit is needed to make the number pandigital.
<PRIVATE
: candidates ( n -- seq )
1000 over <range> [ number>digits 3 0 pad-left ] map [ all-unique? ] subset ;
: overlap? ( seq -- ? )
dup first 2 tail* swap second 2 head = ;
: clean ( seq -- seq )
[ unclip 1 head add* concat ] map [ all-unique? ] subset ;
: add-missing-digit ( seq -- seq )
dup natural-sort 10 seq-diff first add* ;
: interesting-pandigitals ( -- seq )
17 candidates { 13 11 7 5 3 2 } [
candidates swap cartesian-product [ overlap? ] subset clean
] each [ add-missing-digit ] map ;
PRIVATE>
: euler043a ( -- answer )
interesting-pandigitals [ 10 swap digits>integer ] sigma ;
! [ euler043a ] 100 ave-time
! 19 ms run / 1 ms GC ave time - 100 trials
MAIN: euler043a

View File

@ -12,9 +12,9 @@ USING: definitions io io.files kernel math math.parser project-euler.ave-time
project-euler.029 project-euler.030 project-euler.031 project-euler.032
project-euler.033 project-euler.034 project-euler.035 project-euler.036
project-euler.037 project-euler.038 project-euler.039 project-euler.040
project-euler.041 project-euler.042 project-euler.048 project-euler.052
project-euler.067 project-euler.075 project-euler.097 project-euler.134
project-euler.169 project-euler.173 project-euler.175 ;
project-euler.041 project-euler.042 project-euler.043 project-euler.048
project-euler.052 project-euler.067 project-euler.075 project-euler.097
project-euler.134 project-euler.169 project-euler.173 project-euler.175 ;
IN: project-euler
<PRIVATE