Оглавление > Счет букв в числительных
09.03.2023

Счет букв в числительных

Если записать числа от 1 до 5 английскими словами (one; two; three; four; five) то используется всего 3 + 3 + 5 + 4 + 4 = 19 букв.

Сколько букв понадобится для записи всех чисел от 1 до 1000 (one thousand) включительно?

Примечание: Не считайте пробелы и дефисы. Например, число 342 (three hundred and forty-two) состоит из 23 букв; число 115 (one hundred and fifteen) - из 20 букв. Использование "and" при записи чисел соответствует правилам британского английского.

Решение (F#)

  1. сделаем словарь числительных voc
  2. напишем рекурсивную функцию преобразования числа в словесное представление
    • если число есть в словаре то мы знаем как его писать
    • если число меньше 100, тогда округляем до десятков x/10*10 и берем в словаре количество 10 затем, через дефис добавляем кол-во единиц
    • если больше или равно 100 но меньше 1000, тогда пишем кол-во тысяч, а с остатком делаем рекурсивный вызов, если остаток не равен 0
  3. Заполняем последовательность словесными представлениями
  4. создаем функцию подсчета количества символов в словах, кроме дефисов и пробелов letters_only
  5. считаем сумму длин при помощи этой функции
  6. выводим результат
let voc = 
        [ 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"
          1000, "one thousand" ] |> Map.ofList 

let rec word x =
    match x with
    | _ when Map.containsKey x voc -> voc[x]
    | _ when x < 100 -> voc[x / 10 * 10] +  "-" + word (x % 10)
    | _ when x < 1000 ->
        voc[x / 100]
        + " hundred"
        + if x % 100 <> 0 then " and " + word (x % 100) else ""
    | _ -> "unknown"

let s = seq { for i in 1..1000 -> word i }

let letters_only (s: string) =
    s.ToCharArray() |> Array.sumBy (fun c -> if c = ' ' || c = '-' then 0 else 1)

let answer = Seq.sumBy letters_only s

printfn $"the answer is {answer}" //the answer is 21124