-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathp024.hs
More file actions
42 lines (37 loc) · 1.52 KB
/
p024.hs
File metadata and controls
42 lines (37 loc) · 1.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{-
- Solution to Project Euler problem 24
- Copyright (c) Project Nayuki. All rights reserved.
-
- https://www.nayuki.io/page/project-euler-solutions
- https://github.com/nayuki/Project-Euler-solutions
-}
{-
- We initialize an array as the lowest permutation of the given digits, which is the sequence
- (0,1,2,3,4,5,6,7,8,9). Then we call the next permutation algorithm on it 999 999 times
- (because the index in the problem is 1-based), and stringify the resulting sequence.
-
- The next permutation algorithm is well-known and a bit long to explain.
- See: https://www.nayuki.io/page/next-lexicographical-permutation-algorithm
-}
main = putStrLn ans
ans = case (iterate (>>= nextPerm) (Just [0..9])) !! (10^6 - 1)
of Just digits -> concatToString digits -- Extract from Just wrapper
nextPerm :: [Int] -> Maybe [Int]
nextPerm [] = Nothing
nextPerm xs =
let
len = length xs
revSuffix = findPrefix (reverse xs) -- Reverse of longest non-increasing suffix
suffixLen = length revSuffix
prefixMinusPivot = take (len - suffixLen - 1) xs
pivot = xs !! (len - suffixLen - 1)
suffixHead = takeWhile (<= pivot) revSuffix
newPivot : suffixTail = drop (length suffixHead) revSuffix
newSuffix = suffixHead ++ (pivot : suffixTail)
in
if suffixLen == len then Nothing else Just (prefixMinusPivot ++ (newPivot : newSuffix))
where
findPrefix [] = []
findPrefix (x:xs) = x : (if xs /= [] && x <= (head xs) then (findPrefix xs) else [])
concatToString :: [Int] -> String
concatToString xs = foldl (++) "" (map show xs)