Берут числом и вернуть английский языковой репрезентации


Как и многие, я начал с процедурного программирования. Конечно, при изучении функционального языка, от старых привычек трудно, поэтому я написал довольно тривиальная мелочь, которая принимает целое число и возвращает список англоязычных представление.

Несколько дней спустя, я снова написал это, чтобы попытаться использовать хвостовую рекурсию в главном по порядку величины функция; я охотно признаю, что не была сделана попытка добавить хвостовой рекурсии для вычисления чисел меньше 1000, но так как они имеют фиксированное максимальная глубина 3 (максимум 5 звонков в любом случае) я решил не беспокоиться об этом сейчас.

Любые замечания и критику, пожалуйста, бизнес их на меня, что я могу научиться делать вещи в менее процедурным способом.

-module(titoa).
-export([itoa/1]).

itoa(0)                    -> "zero";
itoa(N) when is_float(N)   -> no_float_support;
itoa(N) when N < 0         -> "negative " ++ itoa(abs(N));
itoa(N) when is_integer(N) -> itoa_render(N);
itoa(_)                    -> severe_error.

itoa_render(N) when N >= 1100, N < 10000, N rem 100 == 0, N rem 1000 /= 0 ->
    itoa_render(N, ["", "hundred"], 100, []);
itoa_render(N) when N >= 1000 ->
    itoa_render(N,["",
        "thousand","million","billion","trillion","quadrillion","quintillion",
        "sextillion","septillion","octillion","nontillion","dectillion"
        ],1000, []
    );
itoa_render(N) when N >= 100, N rem 100 == 0 ->
    itoa_render(N div 100) ++ " hundred";
itoa_render(N) when N >= 100 ->
    Hun_diff = N rem 100,
    itoa_render(N - Hun_diff) ++ [32 | itoa_render(Hun_diff)];
itoa_render(N) when N > 19, N rem 10 == 0 ->
    lists:nth(N div 10 - 1, [
        "twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"
    ]);
itoa_render(N) when N > 19 ->
    Ten_diff = N rem 10,
    itoa_render(N - Ten_diff) ++ "-" ++ itoa_render(Ten_diff);
itoa_render(N) when N > 0 ->
    lists:nth(N, [
        "one","two","three","four","five","six","seven","eight","nine",
        "ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen",
        "seventeen","eighteen","nineteen"
    ]);
itoa_render(_) -> []. % 0

itoa_render(0, _, _, After) -> After;
itoa_render(_, [], _, _) -> overflow;
itoa_render(N, [Magnitude | Remaining_Magnitudes], Factor, After) ->
    This_OOM = itoa_render(N rem Factor),
    This_Rep = if
        This_OOM  == [] -> [];
        Magnitude == [] -> This_OOM;
        true            -> This_OOM ++ [32 | Magnitude] ++ if
            After     == [] -> [];
            true            -> [32]
        end
    end,
    itoa_render(N div Factor, Remaining_Magnitudes, Factor, This_Rep ++ After).


381
5
задан 1 октября 2011 в 11:10 Источник Поделиться
Комментарии
2 ответа

На первый взгляд, вы пытаетесь быть немного милый здесь, и это делает ваш код более сложным, чем это необходимо. Например, почему бы не ручки 11 и 12, так как часть подростков, и почему бы просто не ввести подростка и имена десятилетие в полном объеме, а не дополнительную логику, чтобы добавить не-достаточно распространенный суффикс ("подросток" и "ты")?

Для Н < 1000 у вас есть следующие правила (пусть значит "н в словах", % среднее по модулю и // означает целочисленное деление):

if 100 <= n then <n // 100> " hundred" ++ 
(if n % 100 == 0 then "" else " and " ++ <n % 100>)
if 20 <= n then {"", "twenty", ..., "ninety"}[n // 10] ++
(if n % 10 == 0 then "" else " " ++ <n % 10>)
otherwise {"zero", "one", "two", ..., "ten", "eleven", ..., "nineteen"}[n]

Теперь нужно только разобраться с порядков ("тысяча", "миллион" и др.).

1
ответ дан 3 октября 2011 в 01:10 Источник Поделиться


  1. Защитное Программирование не рекомендуется на Erlang, который означает, что вы можете/должны снимать no_float_support и severe_error пункта.

  2. Использование списков:nth-это вообще плохая практика, так как у него есть о(n) сложности, а это означает, используя свой список как массив. Для фиксированного размера списков, вместо того, чтобы использовать кортежи. Вот пример:

    element(N div 10 - 1,
    {twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"}
    );

1
ответ дан 1 марта 2012 в 09:03 Источник Поделиться