-
Notifications
You must be signed in to change notification settings - Fork 0
/
eu79.hs
58 lines (46 loc) · 1.82 KB
/
eu79.hs
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import Network.HTTP
import Data.List
import Data.List.Split
import Control.Monad
import Data.Function
import System.IO
url = "http://projecteuler.net/project/keylog.txt"
data Nat = Zero | Succ Nat
shortest' [] _ = ([], False)
shortest' _ [] = ([], True)
shortest' (a : as) (b : bs) = (r : rs, bChosen) where
(rs, bChosen) = shortest' as bs
r | bChosen = b
| otherwise = a
shortest as bs = fst $ shortest' as bs
consumeChar :: Char -> [String] -> [String]
consumeChar x = (>>= consume)
where
consume (c : t)
| c == x = if null t then [] else [t]
| otherwise = [c:t]
sim :: [String] -> String -> [[String]]
sim attempts chars = scanl (flip consumeChar) attempts chars
hack :: [String] -> String
hack attempts = go attempts where
go :: [String] -> String
go [] = ""
go attempts = foldr shortest (repeat $ error "should not be used!") $ do
let
heads = nub (map head attempts)
forcings = [x|x<-heads,all(not.elem x.tail)attempts]
x <- case forcings of
[] -> heads
(h : _) -> return h
guard $ any ((==x).head) attempts
return $ {- (if null forcings then "b" else "f") ++ -} ( x : go (consumeChar x attempts))
showSpine :: [a] -> String
showSpine [] = "[]"
showSpine (h:t) = "_:" ++ showSpine t
showSpineFirst :: Show a => [a] -> String
showSpineFirst l = showSpine l ++ ". " ++ show l
getInput = fmap (wordsBy (`elem` "\r\n")) $ simpleHTTP (getRequest url) >>= getResponseBody
initt = hSetBuffering stdout NoBuffering >> hSetBuffering stdin NoBuffering
main = initt >> getInput >>= putStrLn . showSpineFirst . hack
main' = initt >> getInput >>= \inp -> getContents >>= \userInput -> mapM_ print $ sim inp userInput
-- The input is disappointing. All the digits were forced (the first digit is 7 because 7 only occurs in the first position etc).