#!/usr/bin/runghc import Data.HashSet (HashSet) import Data.List import Data.Maybe import Debug.Trace (trace) import DetectEnglish import TranspositionDecrypt import TranspositionEncrypt -- This is a monolithing recursive way of solving the problem: -- | -- >>> hackTransposition ["HI", "THERE"] 0.2 (encryptString 6 "hi there transposition") -- "hi there transposition " hackTransposition :: HashSet String -> Float -> String -> (Int, String) hackTransposition = hackTranspositionRec 1 -- | -- >>> hackTranspositionRec 1 ["HI", "THERE"] 0.2 (encryptString 6 "hi there transposition") -- "hi there transposition " hackTranspositionRec :: Int -> HashSet String -> Float -> String -> (Int, String) hackTranspositionRec key wordList threshold message = let decrypted = decryptString (numOfColumns key message) message english = isEnglish wordList threshold decrypted in if english then (key, decrypted) else trace (show (key, decrypted)) $ hackTranspositionRec (key + 1) wordList threshold message -- The above design does not have a "not-found" condition. -- An alternative design is below: -- use `find` with decryptSuccess predicate for single message, across [1..] -- | -- >>> decryptSuccess 6 ["HI", "THERE"] 0.2 (encryptString 6 "hi there transposition") -- Just (6,"hi there transposition ") -- | -- >>> decryptSuccess 1 ["HI", "THERE"] 0.2 (encryptString 6 "hi there transposition") -- Nothing decryptSuccess :: Int -> HashSet String -> Float -> String -> Bool decryptSuccess key wordList threshold message = let decrypted = decryptString (numOfColumns key message) message in isEnglish wordList threshold decrypted main :: IO () main = do hashDict <- importDictionary let encryptedMessage = encryptString 6 "This is a long message that is in English, and it will be cracked." print (hackTransposition hashDict 0.2 encryptedMessage) putStrLn "Another method, key was: " case find (\x -> decryptSuccess x hashDict 0.2 encryptedMessage) [1 ..] of Just crackedKey -> print (crackedKey, decryptString (numOfColumns crackedKey encryptedMessage) encryptedMessage) Nothing -> putStrLn "No key found"