Ruby on Rails PL Forum

Forum poświęcone Ruby on Rails i językowi programowania Ruby

Nie jesteś zalogowany.

#1 2009-03-20 22:04:16

hosiawak
Administrator
Od: Sheffield
Zarejestrowany: 2005-11-26
Posty: 752

Problem 17

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

 

#2 2009-03-20 22:13:27

Tomash
RoR Guru
Zarejestrowany: 2007-04-01
Posty: 1721

Re: Problem 17

Fuj, mieszanie matematyki i programowania do żenującej zagadki lingwistycznej.

Offline

 

#3 2009-03-20 23:19:39

hosiawak
Administrator
Od: Sheffield
Zarejestrowany: 2005-11-26
Posty: 752

Re: Problem 17

Kod: ruby

  1. def to_words(num)
  2. a0 = %w{ one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen }
  3. a1 = %w{ twenty thirty forty fifty sixty seventy eighty ninety }
  4. case num
  5. when 1..19
  6. a0[num-1]
  7. when 20..99
  8. num % 10 != 0 ? "#{a1[(num-20)/10]}#{a0[num % 10 - 1]}" : a1[(num-20)/10]
  9. when 100..999
  10. num % 100 != 0 ? "#{to_words(num/100)}hundredand#{to_words(num % 100)}" : "#{to_words(num/100)}hundred"
  11. when 1000
  12. "onethousand"
  13. end
  14. end
  15.  
  16. puts (1..1000).inject('') { |acc,n| acc << to_words(n)}.size

Offline

 

#4 2009-04-03 15:52:39

hipertracker
Administrator
Od: Irlandia
Zarejestrowany: 2006-01-10
Posty: 205
Serwis

Re: Problem 17

Dla odmiany w Pythonie:

Kod: python

  1. def to_words(num):
  2. a0 = 'one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen'.split(' ')
  3. a1 = 'twenty thirty forty fifty sixty seventy eighty ninety'.split(' ')
  4. if 1<= num <= 19: return a0[num-1]
  5. if 20 <= num <= 99:
  6. return "%s%s" % (a1[(num-20)/10], a0[num % 10 - 1]) if num % 10 != 0 else a1[(num-20)/10]
  7. if 100 <= num <= 999:
  8. return "%shundredand%s" % (to_words(num/100), to_words(num % 100)) \
  9. if num % 100 != 0 else "%shundred" % to_words(num/100)
  10. if num == 1000: return "onethousand"
  11.  
  12. print sum([len(to_words(n)) for n in range(1,1001)])

W sumie sprawdzanie zakresów nie jest potrzebne:

Kod: python

  1. def to_words(num):
  2. a0 = 'one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen'.split(' ')
  3. a1 = 'twenty thirty forty fifty sixty seventy eighty ninety'.split(' ')
  4. if num <= 19: return a0[num-1]
  5. if num <= 99: return "%s%s" % (a1[(num-20)/10], a0[num % 10 - 1]) if num % 10 != 0 else a1[(num-20)/10]
  6. if num <= 999: return "%shundredand%s" % (to_words(num/100), to_words(num % 100)) if num % 100 != 0 else "%shundred" % to_words(num/100)
  7. if num == 1000: return "onethousand"

Offline

 

#5 2009-04-04 20:11:17

teamon
Obserwator
Od: Bydgoszcz
Zarejestrowany: 2009-03-19
Posty: 56
Serwis

Re: Problem 17

@jzabiello - a kiedy w clojure :>?

Offline

 

#6 2009-04-04 23:59:12

radarek
RoR Spammer
Od: Kraków
Zarejestrowany: 2006-11-05
Posty: 745
Serwis

Re: Problem 17

@teamon oraz w scali, erlangu i haskellu.

Offline

 

#7 2009-04-05 06:05:16

hipertracker
Administrator
Od: Irlandia
Zarejestrowany: 2006-01-10
Posty: 205
Serwis

Re: Problem 17

Ten sam algorytm napisany w Scali:

Kod: ruby

  1. def to_words(num: Int): String = {
  2. val a0 = ("one two three four five six seven eight nine ten" +
  3. "eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen")
  4. .split(' ')
  5. val a1 = "twenty thirty forty fifty sixty seventy eighty ninety".split(' ')
  6. if (1 to 19 contains num) return a0(num-1)
  7. if (20 to 99 contains num) return if (num % 10 != 0)
  8. "%s%s".format(a1((num-20)/10), a0(num % 10 - 1))
  9. else a1((num-20)/10)
  10. if (100 to 999 contains num) return if (num % 100 != 0)
  11. "%shundredand%s".format(to_words(num/100), to_words(num % 100))
  12. else "%shundred".format(to_words(num/100))
  13. if (num == 1000) "onethousand" else ""
  14. }
  15.  
  16. 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:

Kod: ruby

  1. def to_words(num: Int): String = {
  2. val a0 = "one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen".split(' ')
  3. val a1 = "twenty thirty forty fifty sixty seventy eighty ninety".split(' ')
  4. if (num <= 19) return a0(num-1)
  5. if (num <= 99) return if (num % 10 != 0) "%s%s".format(a1((num-20)/10), a0(num % 10 - 1)) else a1((num-20)/10)
  6. 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))
  7. if (num == 1000) "onethousand" else ""
  8. }

A tu wersja używająca pattern matching:

Kod: ruby

  1. val to_words: Int => String = {
  2. val a0 = ("one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen").split(' ')
  3. val a1 = "twenty thirty forty fifty sixty seventy eighty ninety".split(' ')
  4. (num: Int) => num match {
  5. case n if n <= 19 => a0(n-1)
  6. 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)
  7. 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))
  8. case n if n == 1000 => "onethousand"
  9. case _ => "out of 1..1000"
  10. }
  11. }

Offline

 

#8 2009-04-09 10:03:22

hosiawak
Administrator
Od: Sheffield
Zarejestrowany: 2005-11-26
Posty: 752

Re: Problem 17

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:

Kod: lisp

  1. (def a0 '("one" "two" "three" "four" "five" "six" "seven" "eight"
  2. "nine" "ten" "eleven" "twelve" "thirteen" "fourteen" "fifteen"
  3. "sixteen" "seventeen" "eighteen" "nineteen"))
  4. (def a1 '("twenty" "thirty" "forty" "fifty" "sixty" "seventy"
  5. "eighty" "ninety"))
  6.  
  7. (defn to_words [n]
  8. (cond
  9. (< n 20) (nth a0 (dec n))
  10. (< n 100) (if (zero? (rem n 10))
  11. (nth a1 (/ (- n 20) 10))
  12. (str (nth a1 (/ (- n 20) 10)) (nth a0 (dec (rem n 10)))))
  13. (< n 1000) (if (zero? (rem n 100))
  14. (str (to_words (/ n 100)) "hundred")
  15. (str (to_words (/ n 100)) "hundredand" (to_words (rem n 100))))
  16. (= n 1000) "onethousand"))
  17.  
  18. (.length (reduce str (map to_words (range 1 1001))))

Offline

 

Stopka forum

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson