Skip to content

Instantly share code, notes, and snippets.

@robhol
Created July 12, 2017 15:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robhol/0a2d176a170135820aa3c0866ef742ed to your computer and use it in GitHub Desktop.
Save robhol/0a2d176a170135820aa3c0866ef742ed to your computer and use it in GitHub Desktop.
import math, re
simple_names = {
1: "en",
2: "to",
3: "tre",
4: "fire",
5: "fem",
6: "seks",
7: "syv",
8: "åtte",
9: "ni",
10: "ti",
11: "elleve",
12: "tolv",
13: "tretten",
14: "fjorten",
15: "femten",
16: "seksten",
17: "sytten",
18: "atten",
19: "nitten"
}
ten_names = {
2: "tjue",
3: "tretti",
4: "førti",
5: "femti",
6: "seksti",
7: "sytti",
8: "åtti",
9: "nitti"
}
power_names = {
2: "hundre",
3: "tusen",
6: "million/er",
9: "milliard/er",
12: "billion/er",
15: "billiard/er",
18: "trillion/er",
21: "trilliard/er"
}
power_isneuter = {
2: True,
3: True
}
power_exponents = list(reversed(list(power_names.keys())))
def div_mod(n, m):
return (n // m, n % m)
def to_list(ls, delimiter=", ", conjunction="og"):
if not conjunction:
return delimiter.join(ls)
if len(ls) < 2:
return ls[0] if ls else ""
return "{} {} {}".format(', '.join(ls[:-1]), conjunction, ls[-1])
def pluralize_power(n, pstr):
return "{}".format(re.sub("/.*" if abs(n) == 1 else "/", "", pstr))
def compose_number_text(n, ls, initial, neuter):
if n < 0:
raise ValueError
if n == 0:
if initial:
ls.append("null")
return
if n == 1:
return ls.append("ett" if neuter else "en")
if n < 20:
return ls.append(simple_names[n])
if n < 100:
tens, ones = div_mod(n, 10)
return ls.append("{}{}".format(ten_names[tens], simple_names[ones] if ones != 0 else ''))
log = int(math.floor(math.log10(n)))
power = next(p for p in power_exponents if log >= p);
units, remainder = div_mod(n, 10 ** power)
quantity = get_norwegian_number_text(units, neuter = power_isneuter.get(power, False))
ls.append("{} {}".format(quantity, pluralize_power(units, power_names.get(power))))
compose_number_text(remainder, ls, False, neuter)
def get_norwegian_number_text(n, neuter=False):
if n < 0:
return "minus " + get_norwegian_number_text(-n, neuter);
ls = list()
compose_number_text(n, ls, True, neuter)
conjunction = "og" if n % 100 != 0 else None
output = to_list(ls, conjunction=conjunction)
return output
def assert_result(n, expected):
actual = get_norwegian_number_text(n)
success = actual == expected
print("{}: {}{}".format(n, actual, "" if success else ("\n" + (' ' * (len(str(n)) + 2)) + expected + ")")))
return success
test_array = [
(0, "null"),
(1, "en"),
(2, "to"),
(10, "ti"),
(11, "elleve"),
(-11, "minus elleve"),
(16, "seksten"),
(20, "tjue"),
(30, "tretti"),
(32, "trettito"),
(99, "nittini"),
(100, "ett hundre"),
(101, "ett hundre og en"),
(107, "ett hundre og syv"),
(110, "ett hundre og ti"),
(111, "ett hundre og elleve"),
(120, "ett hundre og tjue"),
(147, "ett hundre og førtisyv"),
(293, "to hundre og nittitre"),
(500, "fem hundre"),
(999, "ni hundre og nittini"),
(1000, "ett tusen"),
(1001, "ett tusen og en"),
(1010, "ett tusen og ti"),
(1011, "ett tusen og elleve"),
(1100, "ett tusen, ett hundre"),
(1101, "ett tusen, ett hundre og en"),
(1111, "ett tusen, ett hundre og elleve"),
(1700, "ett tusen, syv hundre"),
(2000, "to tusen"),
(2300, "to tusen, tre hundre"),
(9999, "ni tusen, ni hundre og nittini"),
(10000, "ti tusen"),
(10001, "ti tusen og en"),
(10010, "ti tusen og ti"),
(10047, "ti tusen og førtisyv"),
(10500, "ti tusen, fem hundre"),
(14000, "fjorten tusen"),
(14100, "fjorten tusen, ett hundre"),
(20000, "tjue tusen"),
(65536, "sekstifem tusen, fem hundre og trettiseks"),
(-65536, "minus sekstifem tusen, fem hundre og trettiseks"),
(99999, "nittini tusen, ni hundre og nittini"),
(100000, "ett hundre tusen"),
(100001, "ett hundre tusen og en"),
(100010, "ett hundre tusen og ti"),
(100100, "ett hundre tusen, ett hundre"),
(100111, "ett hundre tusen, ett hundre og elleve"),
(101000, "ett hundre og ett tusen"),
(131072, "ett hundre og trettien tusen og syttito"),
(999999, "ni hundre og nittini tusen, ni hundre og nittini"),
(1000000, "en million"),
(1000001, "en million og en"),
(1000100, "en million, ett hundre"),
(1001000, "en million, ett tusen"),
(1001100, "en million, ett tusen, ett hundre"),
(1100000, "en million, ett hundre tusen"),
(1101000, "en million, ett hundre og ett tusen"),
(1101100, "en million, ett hundre og ett tusen, ett hundre"),
(2000000, "to millioner"),
(47000000, "førtisyv millioner"),
(100000000, "ett hundre millioner"),
(101000000, "ett hundre og en millioner"),
(437000000, "fire hundre og trettisyv millioner"),
(123456789, "ett hundre og tjuetre millioner, fire hundre og femtiseks tusen, syv hundre og åttini"),
(999999999, "ni hundre og nittini millioner, ni hundre og nittini tusen, ni hundre og nittini"),
(1000000000, "en milliard"),
(1000000001, "en milliard og en"),
(1000000048, "en milliard og førtiåtte"),
(1001000000, "en milliard, en million"),
(2000000000, "to milliarder"),
(20000000000, "tjue milliarder"),
(200000000000, "to hundre milliarder"),
(123456789012, "ett hundre og tjuetre milliarder, fire hundre og femtiseks millioner, syv hundre og åttini tusen og tolv"),
(999999999999, "ni hundre og nittini milliarder, ni hundre og nittini millioner, ni hundre og nittini tusen, ni hundre og nittini"),
(1000000000000, "en billion"),
(2000000000000, "to billioner"),
(9999999999999, "ni billioner, ni hundre og nittini milliarder, ni hundre og nittini millioner, ni hundre og nittini tusen, ni hundre og nittini"),
(10000000000000, "ti billioner"),
(-10000000000000, "minus ti billioner"),
(234567890123456, "to hundre og trettifire billioner, fem hundre og sekstisyv milliarder, åtte hundre og nitti millioner, ett hundre og tjuetre tusen, fire hundre og femtiseks"),
(1000000000000000, "en billiard"),
(1232543918273755, "en billiard, to hundre og trettito billioner, fem hundre og førtitre milliarder, ni hundre og atten millioner, to hundre og syttitre tusen, syv hundre og femtifem"),
#(9999999999999999, "ni billiarder, ni hundre og nittini billioner, ni hundre og nittini milliarder, ni hundre og nittini millioner, ni hundre og nittini tusen, ni hundre og nittini")
]
success = 0
total = 0
for number, expected_name in test_array:
total = total + 1
success = (success + 1) if assert_result(number, expected_name) else success
print("\n\n{}/{} succeeded ({} failures)".format(success,total, total - success))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment