RosettaCodeData/Task/Number-names/ALGOL-68/number-names-2.alg
2023-07-01 13:44:08 -04:00

89 lines
2.7 KiB
Text

MODE EXCEPTION = STRUCT(STRING name, PROC VOID handler);
EXCEPTION value error = ("Value Error", stop);
PROC raise = (EXCEPTION exception, STRING str error)VOID: (
put(stand error, (name OF exception,": ",str error, new line));
handler OF exception
);
MODE LINT = LONG LONG INT;
BOOL locale euro := TRUE;
PROC spell integer = (LINT n)STRING: (
[]STRING tens = []STRING (~, ~, "twenty", "thirty", "forty",
"fifty", "sixty", "seventy", "eighty", "ninety")[@0];
[]STRING small = []STRING ("zero", "one", "two", "three", "four", "five",
"six", "seven", "eight", "nine", "ten", "eleven",
"twelve", "thirteen", "fourteen", "fifteen",
"sixteen", "seventeen", "eighteen", "nineteen")[@0];
[]STRING bl = []STRING (~, ~, "m", "b", "tr", "quadr",
"quint", "sext", "sept", "oct", "non", "dec")[@0];
PROC nonzero = (STRING c, LINT n)STRING:
IF n = 0 THEN "" ELSE c + spell integer(n) FI;
PROC big =(INT e, LINT n)STRING:
spell integer(n) +
CASE e+1 IN
#0# "",
#1# " thousand"
OUT
" " +
IF locale euro THEN # handle millard, billard & trillard etc #
bl[e OVER 2 + 1 ]+"ill" + CASE e MOD 2 IN "ard" OUT "ion" ESAC
ELSE
bl[e]+"illion"
FI
ESAC;
PROC base1000 rev = (LINT in n, PROC (INT,LINT)VOID yield)VOID: (
# generates the value of the digits of n in base 1000 #
# (i.e. 3-digit chunks), in reverse. #
LINT n := in n;
FOR e FROM 0 WHILE n /= 0 DO
LINT r = n MOD 1000;
n := n OVER 1000;
yield(e, r)
OD
);
IF n < 1000 THEN
INT ssn := SHORTEN SHORTEN n;
IF ssn < 0 THEN
raise (value error, "spell integer: negative input"); ~
ELIF ssn < 20 THEN
small[ssn]
ELIF ssn < 100 THEN
INT a = ssn OVER 10,
b = ssn MOD 10;
tens[a] + nonzero("-", b)
ELIF ssn < 1000 THEN
INT a = ssn OVER 100,
b = ssn MOD 100;
small[a] + " hundred" + ( b NE 0 | " and" | "") + nonzero(" ", b)
FI
ELSE
STRING out := "", sep:="";
# FOR e, x IN # base1000 rev(n, # DO #
(INT e, LINT x)VOID:
IF x NE 0 THEN
big(e,x) + sep +=: out;
sep := IF e = 0 AND x < 100 THEN " and " ELSE ", " FI
FI
)
# OD #;
out
FI
);
PROC example = (LINT n)VOID:
print((whole(n,0),": ", spell integer(n), new line));
# examples #
LINT prod := 0;
FOR i TO 6 DO prod := prod * 10**i + i; example(prod) OD;
example(1278); example(1572); example(2010)