35
\$\begingroup\$

To interpret a positive integer very literally, write it in English words (without "and"), replace hyphens with spaces, replace each resulting word with its number value, and concatenate the results into a single number.

To write a positive integer more than 99 but less than 1000 in English words, prefix its last two digits written in English with [first digit in English]hundred with a trailing space.

To write a positive integer more than 999 but less than 1 million in English words, use the following syntax: [part before the last 3 digits in English]thousand[last 3 digits in English], all separated by spaces.

The task is to input a positive integer (less than 1 million) and output it, interpreted very literally.

Examples

1 -> 1                       (one)
10 -> 10                     (ten)
16 -> 16                     (sixteen)
23 -> 203                    (twenty three)
111 -> 110011                (one hundred eleven)
123 -> 1100203               (one hundred twenty three)
1234 -> 110002100304         (one thousand two hundred thirty four)
12345 -> 1210003100405       (twelve thousand three hundred forty five)
123456 -> 110020310004100506 (one hundred twenty three thousand four hundred fifty six)
1056 -> 11000506             (one thousand fifty six)
101101 -> 11001100011001     (one hundred one thousand one hundred one)
110110 -> 1100101000110010   (one hundred ten thousand one hundred ten)

Feel free to add more test cases if necessary.

This is tagged , so the shortest code wins.

\$\endgroup\$
  • \$\begingroup\$ Link to deleted sandbox post \$\endgroup\$ – someone Nov 1 at 13:49
  • \$\begingroup\$ May I suggest a couple test cases where there are 0s in the middle of the number? e.g. 1056 -> 11000506 \$\endgroup\$ – Business Cat Nov 1 at 15:47
  • \$\begingroup\$ Also, what output should be given for 100? I would assume it should be 1100 (one hundred)? \$\endgroup\$ – Business Cat Nov 1 at 16:01
  • \$\begingroup\$ @BusinessCat That's correct. I will add some more test cases later. \$\endgroup\$ – someone Nov 1 at 16:13

10 Answers 10

2
\$\begingroup\$

05AB1E, 26 23 21 bytes

₄вεтвεSÐP@θ1Ký0Û]тý₄ý

Port of @Neil's Charcoal answer, so make sure to upvote him as well.
-5 bytes thanks to @Grimy.

Try it online or verify all test cases.

Explanation:

₄в                # Convert the (implicit) input-integer to base-1000 as list
                  #  i.e. 119100 → [119,100]
                  #  i.e. 23 → [23]
  ε               # Map each value to:
   тв             #  Convert the value to base-100 as list
                  #   i.e. [119,100] → [[1,19],[1,0]]
                  #   i.e. [23] → [[23]]
     ε            #  Map each value `y` to:
      S           #   Convert the current value to a list of digits
                  #    i.e. [[1,19],[1,0]] → [[[1],[1,9]],[[1],[0]]]
                  #    i.e. [[23]] → [[[2,3]]]
       Ð          #   Triplicate this list
        P         #   Take the product of each inner list of digits
                  #    i.e. [[[1],[1,9]],[[1],[0]]] → [[[1],[9]],[[1],[0]]
                  #    i.e. [[[2,3]]] → [[6]]
         @        #   Check if it's larger than or equal to each digit
                  #    i.e. [[[1],[1,9]],[[1],[0]]] and [[[1],[9]],[[1],[0]]
                  #     → [[[1],[1,1]],[[1],[1]]]
                  #    i.e. [[[2,3]]] and [[6]] → [[[0,0]]]
          θ       #   Keep only the last check of each
                  #    i.e. [[[1],[1,1]],[[1],[1]]] → [[[1],[1]],[[1],[1]]]
                  #    i.e. [[[0]]]
           1K     #   Remove all 1s from each 'string'
                  #    i.e. [[[1],[1]],[[1],[1]]] → [[[""],[""]],[[""],[""]]]
                  #    i.e. [[["0"]]]
             ý    #   Join the list of digits by this string
                  #    i.e. [[[1],[1,9]],[[1],[0]]] and [["",""],["",""]]→ [[1,19],[1,0]]
                  #    i.e. [[[2,3]]] and [["0"]] → [[203]]
      0Û          #   Remove any trailing 0s
                  #    i.e. [[1,19],[1,0]] → [[1,19],[1,""]]
                  #    i.e. [[203]] → [[203]]
  ]               # Close both maps
   тý             # Join the inner lists by "100"
                  #  i.e. [[1,19],[1,""]] → [110019,1100]
                  #  i.e. [[203]] → [203]
     ₄ý           # And then those strings by "1000"
                  #  i.e. [110019,1100] → 11001910001100
                  #  i.e. [203] → 203
                  # (after which the result is output implicitly)
\$\endgroup\$
  • 1
    \$\begingroup\$ yĀ× to , y20›yθĀ* to ySPyθ›. TIO. \$\endgroup\$ – Grimmy Nov 4 at 17:47
  • 1
    \$\begingroup\$ @Grimmy Thanks. That ySPyθ› is smart! :D Too bad the duplicated yS cannot be golfed. I saw a few alternatives, but all the same byte-count. Unless you know an alternative for the 0#× for "0" if truthy; "" if falsey? \$\endgroup\$ – Kevin Cruijssen Nov 4 at 18:24
  • 1
    \$\begingroup\$ Actually the duplicated yS can be golfed: 22. EDIT: 21. \$\endgroup\$ – Grimmy Nov 4 at 22:54
  • 1
    \$\begingroup\$ @Grimmy Ah, that 21 is smart. First doing the >= check, and only then getting the last value. And also that 1K for "0" or "". Nice one! \$\endgroup\$ – Kevin Cruijssen Nov 5 at 8:12
  • 2
    \$\begingroup\$ @Grimmy I like that replacement of ">20 and >0 (mod 10)" with "digitial product exceeds last digit" - it saved me two bytes on my Charcoal answer too, thanks! \$\endgroup\$ – Neil Nov 6 at 21:37
12
\$\begingroup\$

Python 2, 76 bytes

f=lambda n,k=1000:n>19and(f(n/k,k/10)+`k-k%4*5`)*(n>=k)+f(n%k,k/10)or`n`[:n]

Try it online!

Test suite from Chas Brown.

A fully recursive solution that splits on place values k=1000, k=100, and k=10. The separator for the place values is computed as k-k%4*5, which maps

1000 -> 1000
100  -> 100
10   -> 0

By stopping when n<=19, we avoid one-word numbers in the teens being split up.

\$\endgroup\$
4
\$\begingroup\$

Gaia, 44 43 bytes

:(!>
ℍZ:₸Z¤1>∧'0פṙ$×:dẏ×,↑ℍṙ×
@3eZ,↑¦↓3eṙ×

Longer than my original answer, but it works now.

fixed my code again but now it's twice as sad

Try it online!

@3eZ,↑¦↓3eṙ×  Main function.
@3eZ          Input divmod 1000, pushes input div 1000 then input mod 1000
    ,         Pair those two value into a list
     ↑¦       Run the upper function on both
       ↓      Call the function below (loops to top function)
        3eṙ   The string "1000"
           ×  Join the list with "1000"

ℍZ:₸Z¤1>∧'0פṙ$×:dẏ×,↑ℍṙ×  Helper function. Called with 1 argument.
ℍZ                          Divmod with 100
  :₸Z                       Copy the mod part and divmod with 10
                            Stack is: [100s digit, arg mod 100, 10s digit, 1s digit]
     ¤1>                    Bring 10s digit to the top and check if it's greater than 1
        ∧                   Logical AND with 1s digit. (results in 0 or 1)
         '0×                Multiply the character 0 by that result
            ¤               Bring 'arg mod 100' to the top
             ṙ$             Get its string representation and split it into characters
                            (simply doing digit list doesn't work in the case it's 0)
               ×            Join this with the multiplied '0' string
                :d          Copy and parse as a number
                  ẏ         Is it positive? (0 or 1)
                   ×        Multiply the string of the number by that result.
                    ,       Pair: gives the list [100s digit, string from above]
                     ↑      Call the function above
                      >     Remove the first ^ elements from the pair
                       ℍṙ×  Join the resulting list with the string "100"

:(!>  Helper function 2. In this program it is only called with a list.
:(    Copy and get the first element.
  !   Boolean negate (0 or 1)
   >  Remove that many characters from the start of the list
\$\endgroup\$
3
\$\begingroup\$

PHP, 137 136 143 bytes

function f($n){return$n>99?$n>999?f(substr($n,0,-3)).(1e3).f(substr($n,-3)):$n[0].'100'.f($n[1].$n[2]):($n>20&&$n%10?(0^$n/10).'0'.$n[1]:+$n);}

Try it online!

\$\endgroup\$
  • 2
    \$\begingroup\$ Also doesn't work for the 1056 case \$\endgroup\$ – JBernardo Nov 1 at 16:49
  • 1
    \$\begingroup\$ @JBernardo thanks, fixed. \$\endgroup\$ – Night2 Nov 1 at 19:49
3
\$\begingroup\$

Python 3+inflect, 193 bytes

import inflect,re
exec("for i in re.sub('(and)|\W',' ',%sinput())).split():\n for j in range(0,6**8):\n  if i in %sj):\n   print(j,end='')\n   break"%(('inflect.engine().number_to_words(',)*2))

Try it online!

Very naive solution which uses Python's inflect library. Here is the unfurled code:

import inflect,re
for i in re.sub('(and)|\W+',' ',inflect.engine().number_to_words(input())).split():
 for j in range(0,6**8):
  if i in inflect.engine().number_to_words(j):
   print(j,end='')
   break
\$\endgroup\$
  • \$\begingroup\$ Replace 6**8 with 9**9 and this should work in theory for all inputs under a billion, but would take ages. \$\endgroup\$ – 79037662 Nov 1 at 17:56
  • \$\begingroup\$ So you're using a 3rd party library that is exactly to convert numbers to words... So why don't you create a library that completes the exercise and just use that. I bet you can do it in less than 10 bytes \$\endgroup\$ – JBernardo Nov 1 at 20:15
  • 1
    \$\begingroup\$ @JBernardo For the same reason you can't just write a language that solves the question in 0 bytes, but my mistake was not putting the library in the header. codegolf.meta.stackexchange.com/questions/7243/… \$\endgroup\$ – 79037662 Nov 1 at 20:34
  • \$\begingroup\$ Or am I wrong about that? \$\endgroup\$ – 79037662 Nov 1 at 20:37
3
\$\begingroup\$

JavaScript, 69 bytes

Recursively splits and joins based on place values stored in k. Inspired by xnor's Python answer.

f=(n,k=1e3)=>n<20?+n||'':(n<k?'':f(n/k|0,k/10)+[k-10&&k])+f(n%k,k/10)

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Charcoal, 34 32 31 29 bytes

⪫E↨Nφ⪫E↨ι¹⁰⁰⪫↨λχ…0›Πλ﹪λχ100Iφ

Try it online! Link is to verbose version of code. Edit: Saved 2 bytes thanks to @Grimmy. Saved a further byte by finding a better way to choose between 0 or the empty string from a boolean. Saved a further 2 bytes because Base(l, 10) conveniently returns an empty array when l is zero. Explanation:

   N                            Input number
  ↨ φ                           Convert to base 1000 as an array
 E                              Map over elements
        ι                       Current element
       ↨ ¹⁰⁰                    Convert to base 100 as an array
      E                         Map over elements
              λ                 Current element
             ↨ χ                Convert to base 10 as an array
            ⪫                   Join with
                 0              Literal `0`
                …               Truncated to length
                    λ           Current element
                   Π            Digital product
                  ›             Is greater than
                      λ         Current element
                     ﹪          Modulo
                       χ        Predefined variable 10
     ⪫                          Join with
                        100     Literal string `100`
⪫                               Join with
                            φ   Predefined variable 1000
                           I    Cast to string

Example: 67890[67, 890][[67], [8, 90]][[607], [8, 90]][607, 810090]6071000810090.

\$\endgroup\$
2
\$\begingroup\$

JavaScript, 95 93 92 bytes

f=n=>n>999?f(n/1e3|0)+[1e3]+f(n%1e3):n>99?(n/100|0)+'100'+f(n%100):n>20&&(x=n%10)?n-x+''+x:n

Try it online!


  • -2 bytes (@Shaggy): store n%10 in a variable

  • -1 byte (@Arnauld): replace '1000' with [1e3]

\$\endgroup\$
  • 1
    \$\begingroup\$ 93 bytes \$\endgroup\$ – Shaggy Nov 2 at 10:21
  • 2
    \$\begingroup\$ '1000' can be turned into [1e3]. \$\endgroup\$ – Arnauld Nov 2 at 17:20
1
\$\begingroup\$

Python 2, 106 105 100 107 bytes

f=lambda n:n/T and f(n/T)+`T`+f(n%T)or(n>=H)*`n/H*T+H`+'0'[:n%10>0<n%H>19].join(`n%H`)*(n%H>0)
H=100;T=1000

Try it online!

Saved 5 bytes adapting the .join approach of randomdude999's answer; lost 7 bytes fixing a bug :).

\$\endgroup\$
1
\$\begingroup\$

Python 3, 110 115 bytes

def F(n,o=""):
 for i in 1000,100:
  if n>=i:o+=F(n//i)+str(i);n%=i
 return o+'0'[:0<n%10<=n>19].join(str(n))*(n>0)

Try it online!

Pretty simple. Hundreds and thousands are handled recursively.

+5 bytes but fixed a bug with F(100) thanks to @ChasBrown.

\$\endgroup\$
  • 2
    \$\begingroup\$ F(100) gives wrong result. \$\endgroup\$ – JBernardo Nov 1 at 16:46
  • \$\begingroup\$ 107 bytes, also fixes the F(100) issue. \$\endgroup\$ – Chas Brown Nov 1 at 22:49
  • \$\begingroup\$ Which python is it? QtPython 3.6.6 on Android gives me just the digit representation not words. F(55) -> '505' \$\endgroup\$ – Gnudiff Nov 1 at 23:09
  • \$\begingroup\$ @ChasBrown Unfortunately that fails on F(20). \$\endgroup\$ – 79037662 Nov 1 at 23:50
  • \$\begingroup\$ @79037662 : Quite right! 115 bytes . Also was a bug in my answer as well. \$\endgroup\$ – Chas Brown Nov 2 at 1:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.