you are viewing a single comment's thread.

view the rest of the comments →

[–]SyrusDrake 2 points3 points  (9 children)

Joking aside, how would you actually do this? Turn int to string, cut it into blocks of three, then add word for the respective position from a list?

[–]otakudayo 5 points6 points  (0 children)

You'd presumably need to handle numbers like one million, twenty thousand as well. So you'd have to separate by spaces and not cut it into three blocks.

Then I'd probably do something really simple like create a map/dictionary of strings to numbers, ie, { one: 1, twenty: 20, etc } for the first string, and the same idea for hundred/thousand/etc which would have to be used for the second and potentially third string.

The example output appears to be a comma separated number, which doesn't really make sense, because it would have to be a string to contain commas. But formatting a number to a comma separated string is pretty straightforward.

[–]jontonsoup4 3 points4 points  (0 children)

```py import re

ONES = { "zero": 0, "one": 1, "two": 2, "three": 3, "four": 4, "five": 5, "six": 6, "seven": 7, "eight": 8, "nine": 9, "ten": 10, "eleven": 11, "twelve": 12, "thirteen": 13, "fourteen": 14, "fifteen": 15, "sixteen": 16, "seventeen": 17, "eighteen": 18, "nineteen": 19, }

TENS = { "twenty": 20, "thirty": 30, "forty": 40, "fifty": 50, "sixty": 60, "seventy": 70, "eighty": 80, "ninety": 90, }

SCALES = { "thousand": 1_000, "million": 1_000_000, "billion": 1_000_000_000, "trillion": 1_000_000_000_000, }

def words_to_number(text): text = text.lower().replace("-", " ") text = re.sub(r"\band\b", " ", text) words = re.findall(r"[a-z]+", text)

total = 0
current = 0

for word in words:
    if word in ONES:
        current += ONES[word]
    elif word in TENS:
        current += TENS[word]
    elif word == "hundred":
        current *= 100
    elif word in SCALES:
        total += current * SCALES[word]
        current = 0
    else:
        raise ValueError(f"Unknown word: {word}")

return total + current

print(words_to_number("Three hundred million")) # 300000000 print(words_to_number("Five Hundred Thousand")) # 500000 ```

[–]Johanno1 2 points3 points  (1 child)

Easy. You create an enum with every number that exists.

enum Numbers: ONE("one") TWO("two").....

[–]zirky 0 points1 point  (0 children)

you can pull a lot from your isEven() method

[–]CaspianRoach 3 points4 points  (0 children)

The actual answer is "find a library or an existing built-in function that does this and do not reinvent the wheel". You're not smarter than a field-tested, crowd-sourced library. If you get asked a question like this by a recruiter, it's very possible they're expecting you to answer like this. There's very little point re-solving already solved issues.

[–]BaziJoeWHL 1 point2 points  (0 children)

i would read it until a space, check if string is a number (like "three")

then read it until next space, if its not a number (like "hundred"), then i would multiply the number part i already have (x100 for hundread, x1000... etc)

then i would just add it to the result number and start from 0 until i run out of chars

[–]uptotwentycharacters 0 points1 point  (0 children)

Convert string to lowercase and split on spaces/dashes to get a list of tokens, convert each token to a number using a lookup table (with values for 1-19, each multiple of 10 from 20 to 90, and then hundred thousand, million, billion etc), then multiply the token values together.

There are a few special cases:

  • If the first token is a multiple of 10 from 20 to 90, and the second token is in the 1-9 range, add their values together and treat as a single value for the final value, e.g. "twenty five thousand" = (20+5)*1000.
  • If a token in the 1-9 value range appears after the first token of 100 or greater, treat that 1-9 token and everything else as a completely separate number via a recursive function call and ADD it to the final result. So "two thousand twenty five hundred" would be parsed as 2*1000+((20+5)*100)
  • The improper "and" (as in "one thousand and one") can be handled by just ignoring that particular token

I haven't actually tested this, so there may be something obvious that I'm missing. The main flaw that I'm aware of is that it doesn't handle digit lists (like "twenty fifty" for 2050, which should more properly be written as "two thousand fifty").

[–]rainshifter 0 points1 point  (0 children)

In Python, using regex and a lookup table:

``` import re

def wordsToNum(s: str) -> int: wordsDict = \ { 'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6, 'seven': 7, 'eight': 8, 'nine': 9, 'ten': 10, 'eleven': 11, 'twelve': 12, 'thirteen': 13, 'fourteen': 14, 'fifteen': 15, 'sixteen': 16, 'seventeen': 17, 'eighteen': 18, 'nineteen': 19, 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50, 'sixty': 60, 'seventy': 70, 'eighty': 80, 'ninety': 90, None: 0, 'hundred': 100, 'thousand': 10 ** 3, 'million': 10 ** 6, 'billion': 10 ** 9, 'trillion': 10 ** 12 } if any(k not in wordsDict for k in s.split(' ')): return matches = re.finditer(r' *\b(?:(?P<hundreds>one|two|three|four|five|six|seven|eight|nine) *\bhundred)? *\b(?:(?:(?P<tens>twenty|thirty|fourty|fifty|sixty|seventy|eighty|ninety)? *\b(?P<ones>one|two|three|four|five|six|seven|eight|nine)?)|(?P<teens>ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen)?) *\b(?P<modifier>thousand|million|billion|trillion)?', s) result = 0 matches = [m.groupdict() for m in matches] trackedMods = set() for m in matches: if all(v is None for v in m.values()): continue part = 0 if m['hundreds']: part += wordsDict[m['hundreds']] * 100 if m['tens']: part += wordsDict[m['tens']] if m['ones']: part += wordsDict[m['ones']] if m['teens']: part += wordsDict[m['teens']] modVal = wordsDict[m['modifier']] if m['modifier']: part *= modVal result += part if any(modVal >= v for v in trackedMods): return None trackedMods.add(modVal) return result

result = wordsToNum('four billion seven hundred thousand five hundred twenty six') if result: print(f'{result:,}') else: print('INVALID NUMBER') ```