Pig Latin

June 2, 2009

We provide a single function, pig-latin, that works in both directions; strings that contain a hyphen are translated from Pig Latin to English, and strings without a hyphen are translated from English to Pig Latin.

(define (pig-latin word)
  (let* ((vowels (string->list "aeiouAEIOU"))
         (ws (string->list word)) (rs (reverse ws)))
    (if (member #\- ws)
        ; pig-latin to english
        (let* ((front (take-while (lambda (c) (not (char=? c #\-))) ws))
               (back (drop (+ (length front) 1) ws)))
          (if (string=? (list->string back) "way") (list->string front)
            (list->string (append (take (- (length back) 2) back) front))))
        ; english to pig-latin
        (if (member (car ws) vowels) (string-append word "-way")
          (let ((init-cons (take-while (lambda (c) (not (member c vowels))) ws)))
            (list->string (append (drop (length init-cons) ws) (list #\-) init-cons (list #\a #\y))))))))

Here are some examples, in both directions; notice the translation of art-way, which resolves the ambiguity of art and wart in favor of art.

> (map pig-latin '("art" "eagle" "start" "door" "spray" "prays" "wart"))
("art-way" "eagle-way" "art-stay" "oor-day" "ay-spray" "ays-pray" "art-way")
> (map pig-latin '("art-way" "eagle-way" "art-stay"
    "oor-day" "ay-spray" "ays-pray" "art-way"))
("art" "eagle" "start" "door" "spray" "prays" "art")

Pig-latin uses take, drop and take-while from the Standard Prelude. You can run pig-latin at http://programmingpraxis.codepad.org/hRfVoxCA.

Pages: 1 2

4 Responses to “Pig Latin”

  1. […] Praxis – Pig Latin By Remco Niemeijer Today’s Programming Praxis problem is about Pig Latin. Our target is 11 lines (the size of the provided […]

  2. Remco Niemeijer said

    My Haskell solution (see http://bonsaicode.wordpress.com/2009/06/02/programming-praxis-pig-latin/ for a version with comments):

    toPigLatin :: String -> String
    toPigLatin w = let (h, t) = break (flip elem "aeiouAEIOU") w
                   in t ++ "-" ++ (if null h then "w" else h) ++ "ay"
    
    fromPigLatin :: String -> String
    fromPigLatin w = let ('y':'a':h, '-':t) = break (== '-') $ reverse w
                     in reverse $ t ++ if h == "w" then "" else h
    
    pigLatin :: String -> String
    pigLatin w = if elem '-' w then fromPigLatin w else toPigLatin w
    
    main :: IO ()
    main = do
        print . map pigLatin $ words "art eagle start door spray prays wart"
        print . map pigLatin $ words
            "art-way eagle-way art-stay oor-day ay-spray ays-pray art-way"
    
  3. Jieren Chen said

    vowellist = [‘a’,’e’,’i’,’o’,’u’,’A’,’E’,’I’,’O’,’U’]

    def e2pword(engword):
    if engword[0] in vowellist:
    return engword + “-way”
    else:
    return engword[1:] + “-” + engword[0] + “ay”

    def e2p(engstr):
    return ” “.join([e2pword(word) for word in engstr.split(‘ ‘)])

    def p2eword(pigword):
    pigsplit = pigword.split(‘-‘)
    if pigsplit[1][0]==’w’:
    return pigsplit[0]
    else:
    return pigsplit[1][0]+pigsplit[0]

    def p2e(pigstr):
    return ” “.join([p2eword(word) for word in pigstr.split(‘ ‘)])

  4. jcs said

    This problems cries out for regular expressions. Here’s a solution in Emacs lisp:


    (defun eng->pl (wd)
      (if (member (aref wd 0) '(?a ?e ?i ?o ?u))
          (concat wd "-way")
        (replace-regexp-in-string "^\\([^aeiou]+\\)\\(.*\\)$" "\\2-\\1ay" wd)))

    (defun pl->eng (wd)
      (string-match "^\\([^-]+\\)-\\(.*\\)ay$" wd)
      (if (string= (match-string 2 wd) "w")
          (match-string 1 wd)
        (concat (match-string 2 wd) (match-string 1 wd))))

Leave a comment