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.
[…] 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 […]
My Haskell solution (see http://bonsaicode.wordpress.com/2009/06/02/programming-praxis-pig-latin/ for a version with comments):
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(‘ ‘)])
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))))