|
|
|
|
|
|
|
"""From https://github.com/peresolb/number-conversion/""" |
|
import sys |
|
import os |
|
import nltk |
|
|
|
|
|
|
|
b = { |
|
1: "én", |
|
2: "to", |
|
3: "tre", |
|
4: "fire", |
|
5: "fem", |
|
6: "seks", |
|
7: "sju", |
|
8: "åtte", |
|
9: "ni", |
|
10: "ti", |
|
} |
|
b_nn = { |
|
1: "ein", |
|
2: "to", |
|
3: "tre", |
|
4: "fire", |
|
5: "fem", |
|
6: "seks", |
|
7: "sju", |
|
8: "åtte", |
|
9: "ni", |
|
10: "ti", |
|
} |
|
|
|
|
|
t = { |
|
11: "elleve", |
|
12: "tolv", |
|
13: "tretten", |
|
14: "fjorten", |
|
15: "femten", |
|
16: "seksten", |
|
17: "sytten", |
|
18: "atten", |
|
19: "nitten", |
|
} |
|
|
|
|
|
|
|
do = { |
|
20: "tjue", |
|
30: "tretti", |
|
40: "førti", |
|
50: "femti", |
|
60: "seksti", |
|
70: "sytti", |
|
80: "åtti", |
|
90: "nitti", |
|
} |
|
|
|
|
|
|
|
doo = {100: "hundre"} |
|
|
|
|
|
|
|
dooo = {1000: "tusen"} |
|
|
|
|
|
|
|
def _revdict(numberdict): |
|
newdict = {} |
|
for k, v in numberdict.items(): |
|
newdict[v] = k |
|
return newdict |
|
|
|
|
|
|
|
|
|
b_r, b_nn_r, t_r, do_r, doo_r, dooo_r = ( |
|
_revdict(b), |
|
_revdict(b_nn), |
|
_revdict(t), |
|
_revdict(do), |
|
_revdict(doo), |
|
_revdict(dooo), |
|
) |
|
|
|
|
|
def _oneten(nr, reverse=False, nn=False): |
|
"""Function taking an int from 1-10 and returning the corresponding word, |
|
or, if reverse=True, taking a numberword from 1-10 and returning the digit""" |
|
if reverse == False: |
|
if not type(nr) is int: |
|
return None |
|
if nr <= 10: |
|
if nn == False: |
|
return b[nr] |
|
else: |
|
return b_nn[nr] |
|
else: |
|
if not type(nr) is str: |
|
return None |
|
if nn == False: |
|
if nr in b_r.keys(): |
|
return b_r[nr] |
|
else: |
|
if nr in b_nn_r.keys(): |
|
return b_nn_r[nr] |
|
|
|
|
|
def _onedig(nr, reverse=False, nn=False): |
|
if reverse == False: |
|
if not _oneten(nr) == "ti": |
|
if nn == False: |
|
return _oneten(nr) |
|
else: |
|
return _oneten(nr, nn=True) |
|
if reverse == True: |
|
if not _oneten(nr, reverse=True) == 10: |
|
if nn == False: |
|
return _oneten(nr, reverse=True) |
|
else: |
|
return _oneten(nr, reverse=True, nn=True) |
|
|
|
|
|
def _teen(nr, reverse=False): |
|
"""Function taking a primitive two-digit int in the teen range and returning the |
|
corresponding word, or, if reverse=True, the corresponding number word""" |
|
if reverse == False: |
|
if not type(nr) is int: |
|
return None |
|
if nr in t.keys(): |
|
return t[nr] |
|
else: |
|
if not type(nr) is str: |
|
return None |
|
if nr in t_r.keys(): |
|
return t_r[nr] |
|
|
|
|
|
def _twodig(nr, reverse=False): |
|
"""Function taking a primitive two-digit int in the range 20-90 and returning |
|
the corresponding word, or, if reverse=True, the corresponding number word""" |
|
if reverse == False: |
|
if not type(nr) is int: |
|
return None |
|
if nr in do.keys(): |
|
return do[nr] |
|
else: |
|
if not type(nr) is str: |
|
return None |
|
if nr in do_r.keys(): |
|
return do_r[nr] |
|
|
|
|
|
def _numparser(numword, nn=False): |
|
"""Parse word to see if they start with a wd in firstnumwords. |
|
If yes, return firstnumword and second part""" |
|
if not type(numword) is str: |
|
return None |
|
firstpart = "" |
|
scndpart = "" |
|
firstnumwords = list(do_r.keys()) |
|
for s in firstnumwords: |
|
if numword.startswith(s): |
|
slength = len(s) |
|
firstpart = s |
|
scndpart = numword[slength:] |
|
if nn == False: |
|
if ( |
|
scndpart in b_r.keys() and b_r[scndpart] < 10 |
|
): |
|
return (firstpart, scndpart) |
|
else: |
|
if ( |
|
scndpart in b_nn_r.keys() and b_nn_r[scndpart] < 10 |
|
): |
|
return (firstpart, scndpart) |
|
|
|
|
|
def _one_to_nineteen(nr, reverse=False, nn=False): |
|
"""Function taking a primitive two-digit int in the range 1-19 |
|
and returning the corresponding word, or, if reverse=True, the corresponding number word""" |
|
if reverse == False: |
|
if not type(nr) is int: |
|
return None |
|
if nr < 11: |
|
if nn == False: |
|
return _oneten(nr) |
|
else: |
|
return _oneten(nr, nn=True) |
|
elif nr < 20: |
|
return _teen(nr) |
|
else: |
|
if not type(nr) is str: |
|
return None |
|
if nn == False: |
|
if type(_oneten(nr, reverse=True)) is int: |
|
return _oneten(nr, reverse=True) |
|
elif type(_teen(nr, reverse=True)): |
|
return _teen(nr, reverse=True) |
|
else: |
|
if type(_oneten(nr, reverse=True, nn=True)) is int: |
|
return _oneten(nr, reverse=True, nn=True) |
|
elif type(_teen(nr, reverse=True)): |
|
return _teen(nr, reverse=True) |
|
|
|
|
|
def _one_to_nn(nr, reverse=False, nn=False): |
|
"""Function taking an int in the range 1-99 and returning the corresponding word. Reverse as before""" |
|
if reverse == False: |
|
if not type(nr) is int: |
|
return None |
|
if nr > 0: |
|
if nr < 20: |
|
if nn == False: |
|
return _one_to_nineteen(nr) |
|
else: |
|
return _one_to_nineteen(nr, nn=True) |
|
elif nr < 100: |
|
if nr in do.keys(): |
|
return _twodig(nr) |
|
else: |
|
nrstring = str(nr) |
|
frstdig = int(nrstring[0]) * 10 |
|
scndig = int(nrstring[1]) |
|
frstwd = _twodig(frstdig) |
|
if nn == False: |
|
scnwd = _onedig(scndig) |
|
else: |
|
scnwd = _onedig(scndig, nn=True) |
|
nrwd = frstwd + scnwd |
|
return nrwd |
|
else: |
|
if not type(nr) is str: |
|
return None |
|
if nn == False: |
|
if type(_one_to_nineteen(nr, reverse=True)) is int: |
|
return _one_to_nineteen(nr, reverse=True) |
|
elif type(_twodig(nr, reverse=True)) is int: |
|
return _twodig(nr, reverse=True) |
|
else: |
|
if _numparser(nr) == None: |
|
return None |
|
parsed = _numparser(nr) |
|
first = _twodig(parsed[0], reverse=True) |
|
second = _one_to_nineteen(parsed[1], reverse=True) |
|
return first + second |
|
else: |
|
if type(_one_to_nineteen(nr, reverse=True, nn=True)) is int: |
|
return _one_to_nineteen(nr, reverse=True, nn=True) |
|
elif type(_twodig(nr, reverse=True)) is int: |
|
return _twodig(nr, reverse=True) |
|
else: |
|
if _numparser(nr, nn=True) == None: |
|
return None |
|
parsed = _numparser(nr, nn=True) |
|
first = _twodig(parsed[0], reverse=True) |
|
second = _one_to_nineteen(parsed[1], reverse=True, nn=True) |
|
return first + second |
|
|
|
|
|
def _one_to_nnn(nr, reverse=False, nn=False): |
|
"""Function taking an int in the range 1-999 and returning the corresponding word. Reverse as before""" |
|
if reverse == False: |
|
if not type(nr) is int: |
|
return None |
|
if nr == 0: |
|
return None |
|
if nr < 100: |
|
if nn == False: |
|
return _one_to_nn(nr) |
|
else: |
|
return _one_to_nn(nr, nn=True) |
|
elif nr < 1000: |
|
if nr == 100: |
|
return doo[100] |
|
else: |
|
nrstring = str(nr) |
|
frstdig = int(nrstring[0]) |
|
scndig = int(nrstring[1]) |
|
thrdig = int(nrstring[2]) |
|
scthdig = int(nrstring[1:]) |
|
if nn == False: |
|
frstwd = _onedig(frstdig) |
|
else: |
|
frstwd = _onedig(frstdig, nn=True) |
|
nrwd = "" |
|
if scndig == 0: |
|
if thrdig == 0: |
|
nrwd = "%s %s" % (frstwd, doo[100]) |
|
else: |
|
if nn == False: |
|
thrdwd = _one_to_nn(thrdig) |
|
else: |
|
thrdwd = _one_to_nn(thrdig, nn=True) |
|
if frstdig != 1: |
|
nrwd = "%s %s og %s" % ( |
|
frstwd, |
|
doo[100], |
|
thrdwd, |
|
) |
|
else: |
|
nrwd = "%s og %s" % (doo[100], thrdwd) |
|
else: |
|
scthwd = "" |
|
if nn == False: |
|
scthwd = _one_to_nn(scthdig) |
|
else: |
|
scthwd = _one_to_nn(scthdig, nn=True) |
|
if frstdig != 1: |
|
nrwd = "%s %s og %s" % (frstwd, doo[100], scthwd) |
|
else: |
|
nrwd = "%s og %s" % (doo[100], scthwd) |
|
return nrwd |
|
else: |
|
if not type(nr) is str: |
|
return None |
|
if type(doo_r.get(nr, None)) is int: |
|
return doo_r[nr] |
|
elif ( |
|
len(nr.split(" ")) == 1 |
|
and type(_one_to_nn(nr, reverse=True)) is int |
|
and nn == False |
|
): |
|
return _one_to_nn(nr, reverse=True) |
|
elif ( |
|
len(nr.split(" ")) == 1 |
|
and type(_one_to_nn(nr, reverse=True, nn=True)) is int |
|
and nn == True |
|
): |
|
return _one_to_nn(nr, reverse=True, nn=True) |
|
elif len(nr.split(" ")) == 2: |
|
splitwords = nr.split(" ") |
|
if nn == False and nr == "ett hundre": |
|
return 100 |
|
elif nn == True and nr == "eitt hundre": |
|
return 100 |
|
elif ( |
|
type(_one_to_nn(splitwords[0], reverse=True)) is int |
|
and splitwords[1] == "hundre" |
|
): |
|
return _one_to_nn(splitwords[0], reverse=True) * 100 |
|
elif len(nr.split(" ")) == 3: |
|
splitwords = nr.split(" ") |
|
if splitwords[0] == "hundre" and splitwords[1] == "og": |
|
if nn == False: |
|
if type(_one_to_nn(splitwords[2], reverse=True)) is int: |
|
return 100 + _one_to_nn(splitwords[2], reverse=True) |
|
else: |
|
if type(_one_to_nn(splitwords[2], reverse=True, nn=True)) is int: |
|
return 100 + _one_to_nn(splitwords[2], reverse=True, nn=True) |
|
else: |
|
return None |
|
elif len(nr.split(" ")) == 4: |
|
splitwords = nr.split(" ") |
|
if nn == False: |
|
if ( |
|
splitwords[0] == "ett" |
|
and splitwords[1] == "hundre" |
|
and splitwords[2] == "og" |
|
and type(_one_to_nn(splitwords[3], reverse=True)) is int |
|
): |
|
return 100 + _one_to_nn(splitwords[3], reverse=True) |
|
elif ( |
|
type(_one_to_nn(splitwords[0], reverse=True)) is int |
|
and _one_to_nn(splitwords[0], reverse=True) < 10 |
|
and splitwords[1] == "hundre" |
|
and splitwords[2] == "og" |
|
and type(_one_to_nn(splitwords[3], reverse=True)) is int |
|
): |
|
hundreds = _one_to_nn(splitwords[0], reverse=True) * 100 |
|
tens = _one_to_nn(splitwords[3], reverse=True) |
|
return hundreds + tens |
|
else: |
|
return None |
|
else: |
|
if ( |
|
splitwords[0] == "eitt" |
|
and splitwords[1] == "hundre" |
|
and splitwords[2] == "og" |
|
and type(_one_to_nn(splitwords[3], reverse=True, nn=True)) is int |
|
): |
|
return 100 + _one_to_nn(splitwords[3], reverse=True, nn=True) |
|
elif ( |
|
type(_one_to_nn(splitwords[0], reverse=True, nn=True)) is int |
|
and _one_to_nn(splitwords[0], reverse=True, nn=True) < 10 |
|
and splitwords[1] == "hundre" |
|
and splitwords[2] == "og" |
|
and type(_one_to_nn(splitwords[3], reverse=True, nn=True)) is int |
|
): |
|
hundreds = _one_to_nn(splitwords[0], reverse=True, nn=True) * 100 |
|
tens = _one_to_nn(splitwords[3], reverse=True, nn=True) |
|
return hundreds + tens |
|
else: |
|
return None |
|
|
|
|
|
def _high_hundred(nr, nn=False): |
|
"""In Norwegian, as in English, it is possible to express the numbers 1100-1999 with hundreds, |
|
e.g. "tolv hundre og nittiåtte", /twelve hundred and ninety-eight/. We want to be able to convert |
|
these to integers. However, we don't need to produce them, so this algoritm only goes from strings to integers""" |
|
if not type(nr) is str: |
|
return None |
|
if len(nr.split(" ")) > 1: |
|
frstwd = nr.split(" ")[0] |
|
if not type(_teen(frstwd, reverse=True)) is int: |
|
return None |
|
frstdig = _teen(frstwd, reverse=True) |
|
if len(nr.split(" ")) == 2 and nr.split(" ")[1] == "hundre": |
|
return frstdig * 100 |
|
elif ( |
|
len(nr.split(" ")) == 4 |
|
and nr.split(" ")[1] == "hundre" |
|
and nr.split(" ")[2] == "og" |
|
): |
|
if ( |
|
nn == False and type(_one_to_nn(nr.split(" ")[3], reverse=True)) is int |
|
): |
|
lastdigs = _one_to_nn(nr.split(" ")[3], reverse=True) |
|
return (frstdig * 100) + lastdigs |
|
elif ( |
|
nn == True |
|
and type(_one_to_nn(nr.split(" ")[3], reverse=True, nn=True)) is int |
|
): |
|
lastdigs = _one_to_nn(nr.split(" ")[3], reverse=True, nn=True) |
|
return (frstdig * 100) + lastdigs |
|
|
|
|
|
def _one_to_nnnnnn(nr, reverse=False, nn=False): |
|
"""Function taking an int in the range 1-999999 and returning the corresponding word. Reverse as before""" |
|
if reverse == False: |
|
if not type(nr) is int: |
|
return None |
|
if nr == 0: |
|
return None |
|
if nr < 1000: |
|
if nn == False: |
|
return _one_to_nnn(nr) |
|
else: |
|
return _one_to_nnn(nr, nn=True) |
|
elif nr < 1000000: |
|
if nr == 1000: |
|
if nn == False: |
|
return "ett tusen" |
|
else: |
|
return "eitt tusen" |
|
else: |
|
nrstring = str(nr) |
|
ultdig = int(nrstring[-1]) |
|
penultdig = int(nrstring[-2]) |
|
antepenultdig = int(nrstring[-3]) |
|
ult_and_penultdig = int(nrstring[-2:]) |
|
ult_penult_antepenultdig = int(nrstring[-3:]) |
|
tailstring = "" |
|
if antepenultdig == 0: |
|
if penultdig == 0: |
|
if ultdig == 0: |
|
tailstring = "tusen" |
|
else: |
|
if nn == False: |
|
ultstring = _one_to_nnn(ultdig) |
|
tailstring = "tusen og %s" % ultstring |
|
else: |
|
ultstring = _one_to_nnn(ultdig, nn=True) |
|
tailstring = "tusen og %s" % ultstring |
|
else: |
|
if nn == False: |
|
ult_and_penultstring = _one_to_nnn(ult_and_penultdig) |
|
tailstring = ( |
|
"tusen og %s" % ult_and_penultstring |
|
) |
|
else: |
|
ult_and_penultstring = _one_to_nnn( |
|
ult_and_penultdig, nn=True |
|
) |
|
tailstring = ( |
|
"tusen og %s" % ult_and_penultstring |
|
) |
|
else: |
|
if nn == False: |
|
ult_penult_antepenultstring = _one_to_nnn( |
|
ult_penult_antepenultdig |
|
) |
|
if str(ult_penult_antepenultdig)[0] == "1": |
|
tailstring = ( |
|
"tusen ett %s" % ult_penult_antepenultstring |
|
) |
|
else: |
|
tailstring = ( |
|
"tusen %s" % ult_penult_antepenultstring |
|
) |
|
else: |
|
ult_penult_antepenultstring = _one_to_nnn( |
|
ult_penult_antepenultdig, nn=True |
|
) |
|
if str(ult_penult_antepenultdig)[0] == "1": |
|
tailstring = ( |
|
"tusen eitt %s" % ult_penult_antepenultstring |
|
) |
|
else: |
|
tailstring = ( |
|
"tusen %s" % ult_penult_antepenultstring |
|
) |
|
startdigs = int( |
|
nrstring[:-3] |
|
) |
|
startstring = "" |
|
if startdigs == 1: |
|
if nn == False: |
|
startstring = "ett" |
|
else: |
|
startstring = "eitt" |
|
elif startdigs > 99 and startdigs < 200: |
|
if nn == False: |
|
startnumstring = _one_to_nnn(startdigs) |
|
startstring = "ett %s" % startnumstring |
|
else: |
|
startnumstring = _one_to_nnn(startdigs, nn=True) |
|
startstring = "eitt %s" % startnumstring |
|
else: |
|
if nn == False: |
|
startstring = _one_to_nnn(startdigs) |
|
else: |
|
startstring = _one_to_nnn(startdigs, nn=True) |
|
numstring = "%s %s" % (startstring, tailstring) |
|
return numstring |
|
else: |
|
if not type(nr) is str: |
|
return None |
|
if type(_one_to_nnn(nr, reverse=True)) is int and nn == False: |
|
return _one_to_nnn(nr, reverse=True) |
|
elif type(_one_to_nnn(nr, reverse=True, nn=True)) is int and nn == True: |
|
return _one_to_nnn(nr, reverse=True, nn=True) |
|
elif nr == "tusen": |
|
return 1000 |
|
elif ( |
|
len(nr.split(" ")) > 1 and nr.split(" ")[-1] == "tusen" |
|
): |
|
wdlist = nr.split(" ") |
|
firstphrase = " ".join(wdlist[:-1]) |
|
if type(_one_to_nnn(firstphrase, reverse=True)) is int and nn == False: |
|
firstdig = _one_to_nnn(firstphrase, reverse=True) |
|
return firstdig * 1000 |
|
elif ( |
|
type(_one_to_nnn(firstphrase, reverse=True, nn=True)) is int |
|
and nn == True |
|
): |
|
firstdig = _one_to_nnn(firstphrase, reverse=True, nn=True) |
|
return firstdig * 1000 |
|
elif ( |
|
len(nr.split(" ")) == 2 and nr.split(" ")[0] == "ett" and nn == False |
|
): |
|
return 1000 |
|
elif len(nr.split(" ")) == 2 and nr.split(" ")[0] == "eitt" and nn == True: |
|
return 1000 |
|
else: |
|
return None |
|
else: |
|
if len(nr.split(" ")) > 1: |
|
numwordlist = nr.split(" ") |
|
if ( |
|
"tusen" in numwordlist |
|
): |
|
tusenind = numwordlist.index("tusen") |
|
lastwords = numwordlist[tusenind:] |
|
firstwords = numwordlist[:tusenind] |
|
lastdigs = 0 |
|
if len(lastwords) == 3: |
|
if lastwords[1] == "og": |
|
lastword = lastwords[-1] |
|
if nn == False: |
|
lastdigs = _one_to_nnn(lastword, reverse=True) |
|
elif nn == True: |
|
lastdigs = _one_to_nnn(lastword, reverse=True, nn=True) |
|
elif ( |
|
nn == False |
|
and type(_one_to_nnn(" ".join(lastwords[1:]), reverse=True)) |
|
is int |
|
and lastwords[2] == "hundre" |
|
): |
|
hundredphrase = " ".join(lastwords[1:]) |
|
lastdigs = _one_to_nnn(hundredphrase, reverse=True) |
|
elif ( |
|
nn == True |
|
and type( |
|
_one_to_nnn( |
|
" ".join(lastwords[1:]), reverse=True, nn=True |
|
) |
|
) |
|
is int |
|
and lastwords[2] == "hundre" |
|
): |
|
hundredphrase = " ".join(lastwords[1:]) |
|
lastdigs = _one_to_nnn(hundredphrase, reverse=True, nn=True) |
|
else: |
|
return None |
|
elif ( |
|
len(lastwords) == 5 and lastwords[2] == "hundre" |
|
): |
|
hundredphrase = " ".join(lastwords[1:]) |
|
if nn == False: |
|
lastdigs = _one_to_nnn(hundredphrase, reverse=True) |
|
else: |
|
lastdigs = _one_to_nnn(hundredphrase, reverse=True, nn=True) |
|
else: |
|
return None |
|
firstdigs = 0 |
|
firstphrase = " ".join(firstwords) |
|
if len(firstwords) == 0: |
|
firstdigs = 1000 |
|
elif ( |
|
len(firstwords) == 1 and firstwords[0] == "ett" and nn == False |
|
): |
|
firstdigs = 1000 |
|
elif ( |
|
len(firstwords) == 1 and firstwords[0] == "eitt" and nn == True |
|
): |
|
firstdigs = 1000 |
|
elif ( |
|
type(_one_to_nnn(firstphrase, reverse=True)) is int |
|
and nn == False |
|
): |
|
firstdigs = _one_to_nnn(firstphrase, reverse=True) * 1000 |
|
elif ( |
|
type(_one_to_nnn(firstphrase, reverse=True, nn=True)) is int |
|
and nn == True |
|
): |
|
firstdigs = ( |
|
_one_to_nnn(firstphrase, reverse=True, nn=True) * 1000 |
|
) |
|
else: |
|
return None |
|
if type(firstdigs) is int and type(lastdigs) is int: |
|
return firstdigs + lastdigs |
|
|
|
|
|
def convert_nums(nr, reverse=False, nn=False): |
|
"""Functions for converting numbers. Only works for numbers in range 0-999999 for now""" |
|
if reverse == False: |
|
if type(nr) is int: |
|
returnstring = "" |
|
if nr == 0: |
|
returnstring = "null" |
|
elif nr < 1000000: |
|
if nn == False: |
|
returnstring = _one_to_nnnnnn(nr) |
|
else: |
|
returnstring = _one_to_nnnnnn(nr, nn=True) |
|
else: |
|
return None |
|
return returnstring |
|
else: |
|
if type(nr) is str: |
|
returnint = 0 |
|
if nr == "null": |
|
returnint = 0 |
|
elif nn == False and type(_one_to_nnnnnn(nr, reverse=True)) is int: |
|
returnint = _one_to_nnnnnn(nr, reverse=True) |
|
elif nn == True and type(_one_to_nnnnnn(nr, reverse=True, nn=True)) is int: |
|
returnint = _one_to_nnnnnn(nr, reverse=True, nn=True) |
|
elif nn == False and type(_high_hundred(nr)) is int: |
|
returnint = _high_hundred(nr) |
|
elif nn == True and type(_high_hundred(nr, nn=True)) is int: |
|
returnint = _high_hundred(nr, nn=True) |
|
else: |
|
return None |
|
return returnint |
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
mydigit = 243564 |
|
mynumstring = "hundre og atten tusen fire hundre og trettién" |
|
mydigit_nn = 34381 |
|
mynumstring_nn = "tre hundre og førtiein" |
|
|
|
print( |
|
"Digit conversion bm: %s\nString conversion bm: %s" |
|
% (convert_nums(mydigit), convert_nums(mynumstring, reverse=True)) |
|
) |
|
print( |
|
"Digit conversion nn: %s\nString conversion nn: %s" |
|
% ( |
|
convert_nums(mydigit_nn, nn=True), |
|
convert_nums(mynumstring_nn, nn=True, reverse=True), |
|
) |
|
) |
|
|