Saying a number in the shortest way

4

A string of digits (positive integer) can be converted to plain English in various ways. For instance, 115 can be read as "hundredfifteen", "oneonefive", "elevenfive", "twoonesfive". So question's challenge is to output the shortest string representation for a given digits string.

Rules:

  • The input string can start with a zero and the output should account for that.
  • Maximum length of input is 18. So you deal with numbers less than a Quintillion.
  • You should use only the following mathematical words for numbers in your output: zero, one, ..., nine, ten, eleven, ..., twenty, ..., ninety, hundred, million, billion, trillion. You can use their plural forms for sequences (i.e. "fivetens" for 1010101010). No synonyms (i.e. "oh" for 0) or slang (i.e. legs for 11) are allowed. You don't need to include a "one" prefix for cases like 100, just "hundred" is fine.
  • You don't need to put spaces between different words in your output.
  • The output shouldn't be ambigous. This means, from the output string one should be able to determine the input unambigously. So for 705 you can't output "seventyfive" since it may be the output of 75 also. You may use "and" if that'll remove ambiguity, otherwise you don't need to include "and" in your output.
  • Winner is the entry that will have the shortest code length excluding import statements and if not some user finds out a deficit in the code (i.e. a shorter representation than the program spits out for a particular input ).
  • Please post your output for the following test cases to make evaluation easier: 1234, 00505, 122333, 565577555555666888, 1000010, 10001000, 10101010.
  • No reading from an input file, so usage of a dictionary or hash map should count towards your code length.

edit1: Changed the competition type to code-golf per comments and added test cases.

edit2: Restricted the words that can be used in the output. Thanks to @PeterTaylor for the examples.

pembeci

Posted 2014-05-30T22:22:28.760

Reputation: 151

6Could you put a hard limit on the input numbers? Or do I have to support "Septendecillion"? Furthermore, I think with a slightly more rigid spec this would be a great code-golf question. I don't really see why it has to popularity-contest. The current spec is already too tight to leave a lot of room for the kind of creativity that is rewarded by popularity contests. – Martin Ender – 2014-05-30T22:32:47.207

@m.buettner, do you think changing the criteria to "output longest string" will enable more creativity and make it more suitable to popularity-contest? Secondly, can you elaborate on how we can make the spec more rigid to make it a good code-golf question? Having a limit makes sense for inputs like 1000000 so I'll add it. Thanks for pointing. – pembeci – 2014-05-31T01:37:05.937

I agree with @m.buettner; this would be a better code-golf question. – Jwosty – 2014-05-31T03:25:39.687

1I think this would work best as a code challenge. You have a secret list of 5000 numbers, after a week you reveal the numbers and whichever program represents them with the least total characters wins. – Hovercouch – 2014-05-31T03:29:52.897

@Hovercouch: only if finding the shortest solution for each number is very hard to do optimally, and I'm not convinced that's the case, because the amount of possible strings per number seems rather limited. – Martin Ender – 2014-05-31T06:23:20.457

3Why isn't "18403" the shortest way to say the number 18403? – Glen O – 2014-05-31T11:15:20.280

1The spec is too imprecise as it stands, so it just sets up lots of arguments as to whether a string represents the given number or not. – Peter Taylor – 2014-05-31T11:36:46.250

Let's say that you need to communicate a number in a phone conversation. You will say some words and the other party will be able to write the number down in an unambiguous way. Additionally, you want to use the least amount of letters when you "say" this number. That's the specs of this question. @PeterTaylor, is it more clear now? Shall I add this to the question? – pembeci – 2014-06-02T07:47:50.627

No, that doesn't make it any more clear. Some phrases are unarguably correct: e.g. for 00 it is definitely ok to say zero zero. But some people might say oh oh - or should that be written o o? And for 11, English bingo players might say legs, which is probably unbeatable but certainly controversial. In order to avoid clashes over acceptability, I think you need to give an exhaustive list of permissible words. – Peter Taylor – 2014-06-02T08:26:45.427

@PeterTaylor, I see what you meant more clearly now. I listed the permissible words in the rules. – pembeci – 2014-06-03T13:19:26.017

Answers

7

4

This is cheeky and a cheat. I wrote this script about a year ago based off of this comic (tad of profanity).

The idea goes like this. Given any number as a string, adding the number of characters will eventually condense to 4. Four itself is 4 letters long and thus the end of the line.

For example:

  • 10 -> 'ten'
  • 'ten' -> 3 (letters long)
  • 3 -> 'three'
  • 'three' -> 5 (letters long)
  • 5 -> 'five'
  • 'five' -> 4 (letters long)

I verified up to 100,000. Very hacky but got the job done:

to20 = [
        'zero'
        ,'one'
        ,'two'
        ,'three'
        ,'four'
        ,'five'
        ,'six'
        ,'seven'
        ,'eight'
        ,'nine'
        ,'ten'
        ,'eleven'
        ,'twelve'
        ,'thirteen'
        ,'fourteen'
        ,'fifteen'
        ,'sixteen'
        ,'seventeen'
        ,'eighteen'
        ,'nineteen'
        ]

by10s = ['twenty'
         ,'thirty'
         ,'forty'
         ,'fifty'
         ,'sixty'
         ,'seventy'
         ,'eighty'
         ,'ninety'
         ]

by10powers = [
             'hundred'
             ,'thousand'
             ]

def cosmetize(number):

    # the number is too damn high!
    if number >= 100000:
        return "Too high"

    numstr = str(number)

    # Do ones
    if number < 10:
        return to20[number]

    # Pshh.. who needs zero anymore?
    to20[0] = ''

    # Do tens
    numstr10 = numstr[-2:]
    if int(numstr10) < 20:
        numstr10 = to20[int(numstr10)]
    else:
        numstr10 = by10s[int(numstr10[0])-2] + to20[int(numstr10[1])]
    if number < 100:
        return numstr10

    # Do hundreds
    numstr100 = numstr[-3]
    if numstr10 == '':
        numstr10 = "" 
        numstr100 = to20[int(numstr100)] + by10powers[0]
    elif int(numstr[-2:]) > 19:
        numstr100 = to20[int(numstr100)] + by10powers[0]
        numstr100 += 'and'
    else:
        numstr100 = 'and'
    if number < 1000:
        return numstr100 + numstr10

    # Do thousands
    numstr1000 = numstr[:-3]
    if numstr100 == 'hundred':
        numstr100 = ""
    if int(numstr1000) < 20:
        numstr1000 = to20[int(numstr1000)] + by10powers[1]
    else:
        numstr1000 = by10s[int(numstr1000[0])-2] + by10powers[1]

    return numstr1000 + numstr100 + numstr10


i = 0
mx = []
z = 0
while i < 100000:
    length = cosmetize(i)
    x = [length]
    while not len(length) == 4:
        length = cosmetize(len(length))
    i += 1

# No inifinite loop? what magic is this?
print "OMG"

Dylan Madisetti

Posted 2014-05-30T22:22:28.760

Reputation: 3 381

2

Python - (191 - 38) = 153 bytes

This code has the worst case length of 18 for input of 000000000000000000. I'm not sure if this is system dependant. If it's not, I could remove a couple characters.

from string import*
from math import*
s=digits+lowercase+uppercase
c=raw_input()
b=len(s)
a=int(c)
print'-'*(len(c)-len(c.lstrip('0')))+''.join(s[a/b**i%b]for i in range(int(log(a,b)),-1,-1))

For the last line I have to give credit to this fellow. Example outputs:

> 1234
9j
> 00505
--3Z
> 122333
6Vn
> 565577555555666888
5haShÄøŠé
> 1000010
êÌõ
> 10001000
48Šõ
> 10101010
4ewª

Disclaimer: This answer is not a serious answer and it's not trying to compete. This is taking advantage of ambiguity of the rules.

seequ

Posted 2014-05-30T22:22:28.760

Reputation: 1 714

Clever one but "êÌõ" is not plain English as mentioned in the first sentence. I thought it was clear from the examples but it seems like I need to state this explicitly. – pembeci – 2014-06-02T07:54:49.183

@pembeci As I said, the point of this was to show how ambiguous the rules are. – seequ – 2014-06-02T08:02:50.120