1 ! Copyright (c) 2008 Aaron Schaefer.
2 ! See https://factorcode.org/license.txt for BSD license.
3 USING: assocs io.encodings.ascii io.files kernel make math
4 math.parser sequences sets project-euler.common ;
7 ! https://projecteuler.net/problem=79
12 ! A common security method used for online banking is to ask the
13 ! user for three random characters from a passcode. For example,
14 ! if the passcode was 531278, they may asked for the 2nd, 3rd,
15 ! and 5th characters; the expected reply would be: 317.
17 ! The text file, keylog.txt, contains fifty successful login
20 ! Given that the three characters are always asked for in order,
21 ! analyse the file so as to determine the shortest possible
22 ! secret passcode of unknown length.
30 : source-079 ( -- seq )
31 "resource:extra/project-euler/079/keylog.txt" ascii file-lines ;
33 : >edges ( seq -- seq )
35 [ string>digits [ 2 head , ] keep 2 tail* , ] each
38 : find-source ( seq -- elt )
40 [ "Topological sort failed" throw ] [ first ] if-empty ;
42 : remove-source ( seq elt -- seq )
43 [ swap member? ] curry reject ;
45 : (topological-sort) ( seq -- )
47 dup find-source dup , remove-source (topological-sort)
49 [ first [ , ] each ] unless-empty
54 : topological-sort ( seq -- seq )
55 [ [ (topological-sort) ] { } make ] keep
56 union-all over diff append ;
58 : euler079 ( -- answer )
59 source-079 >edges topological-sort digits>number ;
61 ! [ euler079 ] 100 ave-time
62 ! 1 ms ave run time - 0.46 SD (100 trials)
64 ! TODO: set words on sequences are relatively slow; topological sort could be
65 ! cleaned up and generalized much better, but it works for this problem