views:

115

answers:

1

Hi
For project euler 59, I came up with this to return a list of tuples containing the decyphered string and the key used (and yes I know about Data.Bits):

module XOR where
import Data.List
import Data.Char
decToBin :: Integer -> [Integer]
decToBin x = reverse $ decToBin' x
    where
        decToBin' 0 = []
        decToBin' y = let (a,b) = quotRem y 2 in [b] ++ decToBin' a
binToDec ::  [Integer] -> Integer
binToDec xs = foldl (+) 0 $ map (\(x,y) -> x*(2^y) ) $reverse $ zip (reverse xs) [0..]

bitwise f x y = zipWith f x y

lenBin :: Integer -> Integer
lenBin x= length$ decToBin x

xor :: Integer -> Integer -> Bool
xor x y  | x == y = 0
         | x /= y = 1
         | otherwise = error "Impossible"

bitwiseXOR :: Integer -> Integer -> Integer    
bitwiseXOR a b | (lenBin a) > (lenBin b) = binToDec $ bitwise xor ((replicate ((lenBin a) - (lenBin b)) 0)++(decToBin b)) (decToBin a)
               | (lenBin a) < (lenBin b) = binToDec $ bitwise xor ((replicate ((lenBin b) - (lenBin a)) 0)++(decToBin a)) (decToBin b)
               | otherwise =binToDec $ bitwise xor (decToBin b) (decToBin a)

decyph :: [char] -> [char]
decyph key = map chr $ map (\(x,y)-> bitwiseXOR x (ord y) ) $ zip numbers $ cycle key

brute :: [([Char],[Char])]
brute = [(n,k)|k<- (sequence $ replicate 3 ['a'..'z']) ,n <- decyph k, "the" `isInfixOf` n]

numbers :: [Integer]
numbers = [79,59,12,2,79,35,8...]

The problem is that when I can't run decyph because the tuples it is producing only contain one character in the first part and the key in the second rather than the entire decrypted text with the key used. How can I fix this?

PS: Is it reasonable to assume the text will contain string "the"?

+2  A: 

decyph key returns the deciphered text as a [Char]. With the syntax

n <- decyph k

in your list comprehension, n will be of type Char and be assigned the individual characters of the deciphered text, but what you want here is that it is assigned the full result of decyph so make it

let n = decyph k

Finally, check the type of elem:

> :t elem
elem :: (Eq a) => a -> [a] -> Bool

with the type of n being [Char], the first argument must be Char, but you have another string there. If you wish to work with elems, you could split up the deciphered text in words:

"the" `elem` words n

This will compile here then.

PS: Is it reasonable to assume the text will contain string "the"?

It is most certainly a common English word, but the text could possibly be all-uppercase or the might only appear as The at the beginning of a sentence.

Rüdiger Hanke