Forum poświęcone Ruby on Rails i językowi programowania Ruby
Nie jesteś zalogowany.
Problem 17
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.
Offline
Fuj, mieszanie matematyki i programowania do żenującej zagadki lingwistycznej.
Offline
def to_words(num) a0 = %w{ one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen } a1 = %w{ twenty thirty forty fifty sixty seventy eighty ninety } case num when 1..19 a0[num-1] when 20..99 num % 10 != 0 ? "#{a1[(num-20)/10]}#{a0[num % 10 - 1]}" : a1[(num-20)/10] when 100..999 num % 100 != 0 ? "#{to_words(num/100)}hundredand#{to_words(num % 100)}" : "#{to_words(num/100)}hundred" when 1000 "onethousand" end end puts (1..1000).inject('') { |acc,n| acc << to_words(n)}.size
Offline
Dla odmiany w Pythonie:
def to_words(num): a0 = 'one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen'.split(' ') a1 = 'twenty thirty forty fifty sixty seventy eighty ninety'.split(' ') if 1<= num <= 19: return a0[num-1] if 20 <= num <= 99: return "%s%s" % (a1[(num-20)/10], a0[num % 10 - 1]) if num % 10 != 0 else a1[(num-20)/10] if 100 <= num <= 999: return "%shundredand%s" % (to_words(num/100), to_words(num % 100)) \ if num % 100 != 0 else "%shundred" % to_words(num/100) if num == 1000: return "onethousand" print sum([len(to_words(n)) for n in range(1,1001)])
W sumie sprawdzanie zakresów nie jest potrzebne:
def to_words(num): a0 = 'one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen'.split(' ') a1 = 'twenty thirty forty fifty sixty seventy eighty ninety'.split(' ') if num <= 19: return a0[num-1] if num <= 99: return "%s%s" % (a1[(num-20)/10], a0[num % 10 - 1]) if num % 10 != 0 else a1[(num-20)/10] if num <= 999: return "%shundredand%s" % (to_words(num/100), to_words(num % 100)) if num % 100 != 0 else "%shundred" % to_words(num/100) if num == 1000: return "onethousand"
Offline
Offline
@teamon oraz w scali, erlangu i haskellu.
Offline
Ten sam algorytm napisany w Scali:
def to_words(num: Int): String = { val a0 = ("one two three four five six seven eight nine ten" + "eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen") .split(' ') val a1 = "twenty thirty forty fifty sixty seventy eighty ninety".split(' ') if (1 to 19 contains num) return a0(num-1) if (20 to 99 contains num) return if (num % 10 != 0) "%s%s".format(a1((num-20)/10), a0(num % 10 - 1)) else a1((num-20)/10) if (100 to 999 contains num) return if (num % 100 != 0) "%shundredand%s".format(to_words(num/100), to_words(num % 100)) else "%shundred".format(to_words(num/100)) if (num == 1000) "onethousand" else "" } println((for(n <- 1 to 1000) yield to_words(n).length).foldLeft(0)(_ + _))
Algorytm można trochę skrócić, bo zakresy nie są potrzebne. Np. można tą funkcję zapisać tak:
def to_words(num: Int): String = { val a0 = "one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen".split(' ') val a1 = "twenty thirty forty fifty sixty seventy eighty ninety".split(' ') if (num <= 19) return a0(num-1) if (num <= 99) return if (num % 10 != 0) "%s%s".format(a1((num-20)/10), a0(num % 10 - 1)) else a1((num-20)/10) if (num <= 999) return if (num % 100 != 0) "%shundredand%s".format(to_words(num/100), to_words(num % 100)) else "%shundred".format(to_words(num/100)) if (num == 1000) "onethousand" else "" }
A tu wersja używająca pattern matching:
val to_words: Int => String = { val a0 = ("one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen").split(' ') val a1 = "twenty thirty forty fifty sixty seventy eighty ninety".split(' ') (num: Int) => num match { case n if n <= 19 => a0(n-1) case n if n <= 99 => if (n % 10 != 0) "%s%s".format(a1((n-20)/10), a0(n % 10 - 1)) else a1((n-20)/10) case n if n <= 999 => if (n % 100 != 0) "%shundredand%s".format(to_words(n/100), to_words(n % 100)) else "%shundred".format(to_words(n/100)) case n if n == 1000 => "onethousand" case _ => "out of 1..1000" } }
Offline
teamon napisał:
@jzabiello - a kiedy w clojure :>?
Definicja zestawu słów powinna być poza funkcją (niezależnie od języka) - będzie szybsza. W Clojure np:
(def a0 '("one" "two" "three" "four" "five" "six" "seven" "eight" "nine" "ten" "eleven" "twelve" "thirteen" "fourteen" "fifteen" "sixteen" "seventeen" "eighteen" "nineteen")) (def a1 '("twenty" "thirty" "forty" "fifty" "sixty" "seventy" "eighty" "ninety")) (defn to_words [n] (cond (< n 20) (nth a0 (dec n)) (< n 100) (if (zero? (rem n 10)) (nth a1 (/ (- n 20) 10)) (str (nth a1 (/ (- n 20) 10)) (nth a0 (dec (rem n 10))))) (< n 1000) (if (zero? (rem n 100)) (str (to_words (/ n 100)) "hundred") (str (to_words (/ n 100)) "hundredand" (to_words (rem n 100)))) (= n 1000) "onethousand")) (.length (reduce str (map to_words (range 1 1001))))
Offline