Codewars - Tongues

Per previous notes, I'm playing with Haskell. In particular, how does learning Haskell feel as someone who is reasonably comfortable with Python and a few similar languages?

For this round I worked through the "Tongues" challenge. The goal is to replace the characters in a string with other characters, according to a pattern described on the challenge.

... spoilers ...

Haskell

I tried it in Haskell first.

vowels :: String
vowels = "aAiIyYeEoOuU"

consonants :: String
consonants = "bBkKxXzZnNhHdDcCwWgGpPvVjJqQtTsSrRlLmMfF"

tongues :: String -> String
tongues "" = ""
tongues (x:xs) =
  let vindex = x `elemIndex` vowels
      cindex = x `elemIndex` consonants
  in
    advance vindex cindex x : tongues xs
  where
    advance Nothing Nothing x = x
    advance (Just v) Nothing _ = (cycle vowels) !! (v + 6)
    advance Nothing (Just c) _ = (cycle consonants) !! (c + 20)

This actually executes the transformation rules from the challenge. It's worth appreciating that I learned about elemIndex through previous Codewars challenges; being able to see other's code helps!

That said; I didn't closely follow a particular structure, and it took me a few hours to actually make this work.

Python

def tongues(text):

  vowels = "aiyeou"
  consonants = "bkxznhdcwgpvjqtsrlmf"
  codex = {}

  for i in range(len(vowels)):
    codex[vowels[i]] = vowels[(i + 3) % 6]
    codex[vowels[i].upper()] = vowels[(i + 3) % 6].upper()

  for i in range(len(consonants)):
    codex[consonants[i]] = consonants[(i + 10) % 20]
    codex[consonants[i].upper()] = consonants[(i + 10) % 20].upper()

  decoded = ""
  for t in text:
    decoded += codex.get(t, t)

  return decoded

This also executes the translation rules from the challenge, but only once. It builds up a dict and uses that to actually swap out the characters. This took longer than I'd have liked (about an hour) because I got hung up with the modulo operation.

Comparison

Both solutions use about the same amount of code. Haskell still takes me far too long for practical purposes. There is something satisfying about figuring it out, but even now I can't simply read what I did in order to make it work. It almost feels like waking up as a child again, having to sound out words instead of just knowing what they mean at a glance.

Nice solutions I'm studying