Skip to content

Instantly share code, notes, and snippets.

@nfunato
Created October 3, 2013 22:19
Show Gist options
  • Save nfunato/6818019 to your computer and use it in GitHub Desktop.
Save nfunato/6818019 to your computer and use it in GitHub Desktop.
project euler problem 17
p17 = p17' [1..1000]
p17' = sum . map (length . filter(`notElem` " -") . itoa)
itoa i
| i < 0 = "minus " ++ itoa (-i)
| i < 20 = smalls i
| i < 100 = f (quotRem i 10) tens "-" smalls
| i < 1000 = f (quotRem i 100) ((++" hundred").smalls) " and " itoa
| i ==1000 = "one thousand"
| otherwise = error "unsupported range"
where f (q,0) a _ _ = a q
f (q,r) a b c = a q ++ b ++ c r
smalls = (["zero", "one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen"] !!)
tens = ([undefined, undefined, "twenty", "thirty", "forty", "fifty",
"sixty", "seventy", "eighty", "ninety"] !!)
-- try ghc -O4 -fno-cse --make p17b.hs
import Data.List (intercalate, unfoldr)
main = print $ p17' [1..123456789012345678901234567890123456]
p17 = p17' [1..1000]
p17' = sum . map (length . filter(`notElem` ", -") . itoa)
itoa i
| i < 0 = "minus " ++ itoa (-i)
| i < 20 = smalls i
| i < 100 = f (quotRem i 10) tens "-" smalls
| i < 1000 = f (quotRem i 100) ((++" hundred").smalls) " and " itoa
-- | otherwise = error "unsupported range"
| otherwise = intercalate ", " $ itoa' i
where f (q,0) a _ _ = a q
f (q,r) a b c = a q ++ b ++ c r
smalls = ((["zero", "one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]
!!).fromInteger)
tens = (([undefined, undefined, "twenty", "thirty", "forty", "fifty",
"sixty", "seventy", "eighty", "ninety"]
!!).fromInteger)
pref_b = ["m", "b", "tr", "quadr", "quint", "sext", "sept", "oct", "non", "dec"]
bigs = ((("" : " thousand" : map f pref_b) !!).fromInteger)
where f s = " "++s++"illion"
itoa' = map f . reverse . filter ((0/=).snd) . zip [0..] . triplize
where f (n,i) = itoa i ++ bigs n
triplize = unfoldr (\i -> if i==0 then Nothing else Just $ f i)
where f = uncurry (flip (,)) . flip quotRem 1000
{-
*Main> itoa 123456789012345678901234567890123456
"one hundred and twenty-three decillion, four hundred and fifty-six nonillion, seven hundred and eighty-nine octillion, twelve septillion, three hundred and forty-five sextillion, six hundred and seventy-eight quintillion, nine hundred and one quadrillion, two hundred and thirty-four trillion, five hundred and sixty-seven billion, eight hundred and ninety million, one hundred and twenty-three thousand, four hundred and fifty-six"
(0.01 secs, 1613288 bytes)
-}
import Data.List (intercalate, unfoldr)
main = print $ p17' [1..123456789012345678901234567890123456]
p17 = p17' [1..1000]
p17' = sum . map itoa2
_and_ = 3
_minus_ = 5
_hundred_ = 7
itoa2 i
| i < 0 = _minus_ + itoa2 (-i)
| i < 20 = smalls' i
| i < 100 = f (quotRem i 10) tens' 0 smalls'
| i < 1000 = f (quotRem i 100) ((_hundred_+).smalls') _and_ itoa2
-- | otherwise = error "unsupported range"
| otherwise = sum $ itoa2' i
where f (q,0) a _ _ = a q
f (q,r) a b c = a q + b + c r
smalls = ["zero", "one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]
smalls'= (xs!!) . fromInteger where xs = map length smalls
tens = ["", "", "twenty", "thirty", "forty", "fifty",
"sixty", "seventy", "eighty", "ninety"]
tens' = (xs!!) . fromInteger where xs = map length tens
bigs = ["", "thousand", "million", "billion", "trillion", "quadrillion",
"quintillion", "sextillion", "septillion", "octillion", "nonillion",
"decillion"]
bigs' = (xs!!) . fromInteger where xs = map length bigs
itoa2' = map f . filter ((0/=).snd) . zip [0..] . triplize
where f (n,i) = itoa2 i + bigs' n
triplize = unfoldr (\i -> if i==0 then Nothing else Just $ f i)
where f = uncurry (flip (,)) . flip quotRem 1000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment