## Programming Praxis – Bifid Cipher

Today’s Programming Praxis problem is another cipher, specifically Bifid’s cipher. Let’s get started, shall we?

Some imports:

```import Data.Char
import Data.List
import Data.List.HT hiding (unzip)
import Data.Map ((!), fromList)
```

There’s no J in the Bifid alphabet.

```alphabet :: String
alphabet = delete 'J' ['A'..'Z']
```

Next we need some functions to get the index from a character and vice versa. The second line in fromIndex is only to get rid of a compiler warning; you can leave it out if you want to.

```indices :: [(Int, Int)]
indices = zip (concatMap (replicate 5) [1..5]) (cycle [1..5])

toIndex :: Char -> (Int, Int)
toIndex c = fromList (zip alphabet indices) ! c

fromIndex :: [Int] -> Char
fromIndex [x, y] = fromList (zip indices alphabet) ! (x, y)
fromIndex _      = undefined
```

Next, we need a way to prepare the strings for the algorithm.

```prepare :: String -> String
prepare = filter (`elem` alphabet) . replace "J" "I" . map toUpper
```

The basic structure of encode and decode is the same, only the way of getting the intermediate data in the right order differs.

```encode :: String -> String
encode = map fromIndex . sliceVertical 2 . uncurry (++) .
unzip . map toIndex . prepare

decode :: String -> String
decode xs = map fromIndex . sliceHorizontal (length xs) .
concatMap ((\(x, y) -> [x, y]) . toIndex) \$ prepare xs
```

And, as usual, some tests to see if everything’s working properly:

```main :: IO ()
main = do print \$ encode "BONSAICODE"
print . decode \$ encode "BONSAICODE"
```

Looks like it is. Another one down.