Project Euler Problem 17
Number letter counts
If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.
If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?
NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters. The use of “and” when writing out numbers is in compliance with British usage.
Link to original description
Source code examples on Github
Erlang version 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #!/usr/bin/env escript %% -*- erlang -*- %%! -smp enable -sname p17 % vim:syn=erlang -mode(compile). main(_) -> io:format("Answer: ~p ~n", [lists:foldl(fun(E,A)-> A + length(ci(E)) end,0,lists:seq(1,1000))]). word(N) -> L = [ { 0, "" }, { 1, "one" }, { 2, "two" }, { 3, "three" }, { 4, "four" }, { 5, "five" }, { 6, "six" }, { 7, "seven" }, { 8, "eight" }, { 9, "nine" }, { 10, "ten" }, { 11, "eleven" }, { 12, "twelve" }, { 13, "thirteen" }, { 14, "fourteen" }, { 15, "fifteen" }, { 16, "sixteen" }, { 17, "seventeen"}, { 18, "eighteen" }, { 19, "nineteen" }, { 20, "twenty" }, { 30, "thirty" }, { 40, "forty" }, { 50, "fifty" }, { 60, "sixty" }, { 70, "seventy" }, { 80, "eighty" }, { 90, "ninety" }, { 100, "hundred" }, {1000, "thousand" } ], proplists:get_value(N, L). ci(1000) -> word(1) ++ word(1000); ci(100) -> word(1) ++ word(100); ci(N) when N > 100 -> S = ci(N div 100) ++ word(100), case N rem 100 of 0 -> S; M -> S ++ "and" ++ ci(M) end; ci(N) -> case word(N) of undefined -> ci((N div 10)*10) ++ ci(N rem 10) ;W -> W end. |
Erlang version 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | #!/usr/bin/env escript %% -*- erlang -*- %%! -smp enable -sname p17 % vim:syn=erlang -mode(compile). main(_) -> io:format("Answer: ~p ~n", [lists:foldl(fun(E,A)-> A + length(t17(E)) end,0,lists:seq(1,1000))]). words() -> [ { 0, "" }, { 1, "one" }, { 2, "two" }, { 3, "three" }, { 4, "four" }, { 5, "five" }, { 6, "six" }, { 7, "seven" }, { 8, "eight" }, { 9, "nine" }, { 10, "ten" }, { 11, "eleven" }, { 12, "twelve" }, { 13, "thirteen" }, { 14, "fourteen" }, { 15, "fifteen" }, { 16, "sixteen" }, { 17, "seventeen"}, { 18, "eighteen" }, { 19, "nineteen" }, { 20, "twenty" }, { 30, "thirty" }, { 40, "forty" }, { 50, "fifty" }, { 60, "sixty" }, { 70, "seventy" }, { 80, "eighty" }, { 90, "ninety" }, { 100, "hundred" }, {1000, "thousand" } ]. w(N) -> proplists:get_value(N, words()). t17(1000) -> w(1) ++ w(1000); t17(100) -> w(1) ++ w(100); t17(N) when N =< 20 -> w(N); t17(N) when N < 100 -> t17i(N, lists:reverse(words())); t17(N) when N rem 100 =:= 0 -> w(N div 100) ++ w(100); t17(N) -> w(N div 100) ++ w(100) ++ "and" ++ t17(N rem 100). t17i(N, [{N, W}|_]) -> W; t17i(N, [{M, W}|_]) when N > M -> W ++ w(N-M); t17i(N, [_|T]) -> t17i(N, T). |
Python version
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | #!/usr/bin/python words = [ ( 1, 'one' , '' ), ( 2, 'two' , '' ), ( 3, 'three' , '' ), ( 4, 'four' , '' ), ( 5, 'five' , '' ), ( 6, 'six' , '' ), ( 7, 'seven' , '' ), ( 8, 'eight' , '' ), ( 9, 'nine' , '' ), ( 10, 'ten' , '' ), ( 11, 'eleven' , '' ), ( 12, 'twelve' , '' ), ( 13, 'thirteen' , '' ), ( 14, 'fourteen' , '' ), ( 15, 'fifteen' , '' ), ( 16, 'sixteen' , '' ), ( 17, 'seventeen', '' ), ( 18, 'eighteen' , '' ), ( 19, 'nineteen' , '' ), ( 20, 'twenty' , '' ), ( 30, 'thirty' , '' ), ( 40, 'forty' , '' ), ( 50, 'fifty' , '' ), ( 60, 'sixty' , '' ), ( 70, 'seventy' , '' ), ( 80, 'eighty' , '' ), ( 90, 'ninety' , '' ), ( 100, 'hundred' , 'and' ), (1000, 'thousand' , 'and' ), ] words.reverse() def spell(n, words): word = [] while n > 0: for num in words: if num[0] <= n: div = n / num[0] n = n % num[0] if num[2]: word.append(' '.join(spell(div, words))) word.append(num[1]) if num[2] and n: word.append(num[2]) break return word print sum(len(word) for n in xrange(1, 1001) for word in spell(n, words)) |