# Numbers in 2050

It's 2050, and people have decided to write numbers in a new way. They want less to memorize, and number to be able to be written quicker.
For every place value(ones, tens, hundreds, etc.) the number is written with the number in that place, a hyphen, and the place value name. "zero" and it's place value does not need to be written.
The number 0 and negative numbers do not need to be handled, so don't worry about those.

#### Input:

The input will be a positive integer up to 3 digits.

#### Output:

The output should be a string that looks like something below.

Test cases:

56 => five-ten six
11 => ten one
72 => seven-ten two
478 => four-hundred seven-ten eight
754 => seven-hundred five-ten four
750 => seven-hundred five-ten
507 => five-hundred seven


This question would not be a dupe because that one has a bit more requirements.
"One" does not need to be printed unless it is in the ones place value.
This is , so normal golfing rules apply.
Good luck!

###### Imagine if numbers are actually written like this in the future...
• Can 'one' be printed, or are we not allowed? Commented Mar 31, 2022 at 2:31
• This is exactly how numbers in a language some of us in chat designed (katlani) work haha Commented Mar 31, 2022 at 2:34
• Most east Asian languages influenced by the Chinese numerical system read numbers exactly this way. Commented Mar 31, 2022 at 8:58
• As a Vietnamese, this is how you read numbers. Commented Mar 31, 2022 at 14:36
• Suggested test case: 110 (which I think should be hundred ten). Commented Mar 31, 2022 at 21:26

# Perl 5-p, 100 bytes

$a="{,{one,two,three,four,five,six,seven,eight,nine}";$_=(<"$a-hundred }$a-ten }$a}">)[$_];s/one-//g


Try it online!

#!perl -pl
$a="{,{one,two,three,four,five,six,seven,eight,nine}";$_=(<"$a-hundred }$a-ten }$a}">)[$_];
s/one-//g


The idea here is simple: instead of trying to generate the number on the fly, generate a list of all 2050 numbers using a glob expression (which is much easier) and then index into that list. If $n is the list of numbers, we construct the glob {,{$n}-hundred }{,{$n}-ten }{,{$n}}. The only problem is that this glob expression will generate one-ten and one-hundred, which we can simply strip at the end with s/one-//g.

# VyxalS, 25 bytes

ẏṘ↵Z'h;ƛ∆ċ1∆ċ-';\-jȧ1∆ċ$∨  Try it Online! or try a test suite. Thank goodness for built-in number to word support ## Explained ẏṘ↵Z'h;ƛ∆ċ1∆ċ-';\-jȧ1∆ċ$∨ # example input → 701
ẏṘ                        # range(len(input) - 1, -1, -1) → [2, 1, 0]
↵                       # 10 to the power of each item in that range → [100, 10, 1]
Z                      # zip that with the digits of the input → [[7, 100], [0, 10], [1, 1]]
'h;                   # keep only items where the digit of the input isn't 0 → [[7, 100], [1, 1]]
ƛ                  # to each item in the remaining [digit, power10] list:
∆ċ                #   convert both digit and power10 to words → [["seven", "one hundred"], ["one", "one"]]
1∆ċ-            #   remove any occurances of the word "one" from each → [["seven", " hundred"], ["", ""]]
';          #   and remove any empty strings - this makes it so that you have singleton lists for hundreds and tens and an empty list for ones if one is present → [["seven", " hundred"], []]
\-j       #   join the result of that on "-" → ["seven- hundred", ""]
ȧ      #   remove whitespace → ["seven-hundred", ""]
1∆ċ$∨ # get the first truthy item from that and "one" - this works because an empty string means that we want the word "one" → ["seven-hundred", "one"] # The -S joins the result on spaces → "seven-hundred one"  # Python + num2words, 162138 137 bytes lambda N:' '.join([((num2words(n)+'-'*(w>''),'')[n=='1'<w]+w)for n,w in zip('%3s'%N,['hundred','ten',''])if'0'<n]) from num2words import* Attempt This Online! Requires the package num2words to be installed, so won't run in the ATO link. -24 bytes thans to Jonathan Allan -1 byte, replaced '%03s'%N with '%3s'%N • Saved 21 bytes and fixed the fact that you have extra spaces when zeros appear: lambda N:' '.join([((num2words(n)+'-'*(w>''),'')[n=='1'>''<w]+w)for n,w in zip('%03s'%N,['hundred','ten',''])if'0'<n]) Commented Mar 31, 2022 at 12:15 • ...actually since 'hundred' and 'ten' are both greater than '1' while '' is not the n=='1'>''<w above can just be n=='1'<w saving three more bytes. Commented Mar 31, 2022 at 12:19 # Charcoal, 74 bytes ⪫Φ⮌Ｅ⮌Ｓ⪫Φ⟦§⪪”↶⌈↶？#λ<∕CＳＧ∨⮌№¤"~^hφ﹪▶U⊕hU⦄w↷” ∧∨⊖ι¬κＩι§⪪”↶↧WaＫπ⁵1✂” ∧Ｉικ⟧λ-ι  Try it online! Link is to verbose version of code. Explanation:  Ｓ Input as a string ⮌ Reversed Ｅ Map over digits ⟦ ⟧ Tuple of ”...” Compressed digits string ⪪ Split on spaces § Indexed by ι Current digit ⊖ Decremented ∨ Logical Or κ Current power of 10 ¬ Is zero ∧ Logical And ι Current digit Ｉ Cast to integer ”...” Compressed places string ⪪ Split on spaces § Indexed by ι Current digit Ｉ Cast to integer ∧ Logical And κ Current power of 10 Φ Filtered where λ String is not empty ⪫ Joined with - Literal string - ⮌ Reversed Φ Filtered where ι String is not empty ⪫ Joined with spaces Implicitly print  # C (gcc), 193171 169 bytes • -2 thanks to ceilingcat Recursively divides the input number, looking up each digit (except for 1 in non-ones position and 0) and and appending the suffix (except for ones position.) g(v,s,i){v&&g(v/10,s?"hundred":"ten"),(i=v%10)&&printf("%3$.5s%2$s%s "+(i<2&&s)*10,s?:"",!s+"-","one\0 two\0 threefour\0five\0six\0 seveneightnine"+~-i*5);}f(v){g(v,0);}  Try it online! # Factor + math.text.english math.text.utils, 138136 126 bytes [ 1 digit-groups [ 10^ [ number>text ] bi@ "-"glue R/ one[- ]|-one$|zero.*/ ""re-replace ] map-index reverse harvest " "join ]


Try it online!

## Explanation

Code                     | Data stack                              | Comment
============================================================================================================
! 478
1 digit-groups           ! { 8 7 4 }
<<inside the map-index quotation now; first iteration>>
! 8 0                                       (digit, index)
10^                      ! 8 1
[ number>text ] bi@      ! "eight" "one"
"-"glue                  ! "eight-one"
R/ one[- ]|-one$|zero.*/ ! "eight-one" R/ one[- ]|-one$|zero.*/      (push a regexp literal on the data stack)
""re-replace             ! "eight"
<<outside the map-index quotation now>>
map-index                ! { "eight" "seven-ten" "four-hundred" }
reverse                  ! { "four-hundred" "seven-ten" "eight" }
harvest                  ! { "four-hundred" "seven-ten" "eight" }    (remove empty strings)
" "join                  ! "four-hundred seven-ten eight"


# JavaScript (V8), 162153151 148 bytes

-3 bytes thanks to Arnauld.
-6 bytes by merging the handling of 10's and 100's.
-2 bytes thanks to Arnauld, again.
-3 bytes by moving the floor operation, thanks to Shaggy.

f=(n,p)=>n>9?f(n/(m=n>99?100:10)|0,m%4?'ten ':'hundred ')+f(n%m):n?--n|!p?'one,two,three,four,five,six,seven,eight,nine'.split,[n]+[p&&'-'+p]:p:''


Try it online!

Ungolfed

f = (n, p) =>
n > 9 ? // check if we should handle 10's or 100's
f(
n / (m = n > 99 ? 100 : 10) | 0, // check what mod to use, then floor divide
m % 4 ? 'ten ' : 'hundred ' // check what place to use
) + f(n % m) :
n ? // if 9 >= n > 0
--n | !p ? // if n > 1 or p ('ten' or 'hundred') is not defined we need to find the name of n
'one,two,three,four,five,six,seven,eight,nine'.split,[n] +
[p && '-' + p] : // add p if we have it
p : // return p if n = 1
'' // return '' if n = 0

• You can use [p&&'-'+p] instead of (p?'-'+p:''). Commented Mar 31, 2022 at 8:36
• You can use --n instead of n-1, which allows to get rid of the leading comma in the lookup string. Commented Mar 31, 2022 at 8:38
• @Arnauld Thank you! That's clever to use [] to remove undefined. There's probably a way to avoid duplicate n>99 but I don't see it. Commented Mar 31, 2022 at 19:47
• You can do m%4?'ten ':'hundred '. Commented Mar 31, 2022 at 19:56
• You can save another byte with (n|=0) instead of (n=~~n). Commented Mar 31, 2022 at 20:56

# Python, 198 188 bytes

lambda m:" ".join([r[int(i)]for i,r in zip('%3s'%m,[[c+s for c in",one,two,three,four,five,six,seven,eight,nine".split(",")]for s in['-hundred','-ten','']])if"0"<i>" "]).replace("one-","")

Attempt This Online!

Inspired by Sisyphus's answer. Generates three lists of the number string for each of the hundreds, tens and ones. Indexes each list by it's respective value in the input, then gets rid of one-

# JavaScript (Node.js), 147 bytes

n=>['hundred','ten',''].flatMap(t=>(c=',,two,three,four,five,six,seven,eight,nine'.split,[p=(n*=10)/1e3%10|0])?t?c+'-'+t:c:p?t||'one':[]).join


Try it online!

# C (gcc), 223 bytes

o,i,z;main(a,c)char**c;{for(o=strlen(c[1]);z=c[1][i]-49,printf("%s%s%s ",z|o-i==1?"zero\0one\0two\0three\0four\0five\0six\0seven\0eight\0nine"+"059=CHMQW]"[z+1]-48:"",z&&o+~i?"-":"",o-i-2?o-i-3?"":"hundred":"ten"),++i-o;);}


Try it online!

Thanks to Mukul Kumar for basis, fixed what I perceived to be incorrect output, and shaved down by switching to C and embracing the sketchiness of golf C.

Updates based on issues found and golf contributed by Arnauld

Thanks to ceilingcat for some more C golf sketchiness.

• 11 should be ten one and I think 512 should be five-hundred ten two . Commented Mar 31, 2022 at 21:11
• Here is a slightly shorter version based on your original answer. (But still wrong.) Commented Mar 31, 2022 at 21:13
• That's a truly clever edit. But yea, need to work around that one rule. Commented Mar 31, 2022 at 21:15
• (Heck. Looks like I added two extra spaces at the end of the code while fighting with my defective keyboard.) Commented Mar 31, 2022 at 21:17
• @MukulKumar It seems most submissions adopt "number-place" as shown in the testcases rather than the confusing phrasing of the question. Also as Arnauld later pointed out the code didn't handle the one case. Commented Mar 31, 2022 at 22:19

# Python 3.8, no library, 184 bytes

Late to the party, but here's my answer. jezza_99 answer using library is unbeatable!

n=input()
for i,o in zip([' one two three four five six seven eight nine'.split(' ')[int(d)]for d in n],['-hundred','-ten',''][-len(n):]):
if i:print((i+o).replace('one-',''),end=' ')


Try it online!

Commented code

# input: get number to be rewritten in words
# n will be a string
n = input('Input number n to be translated into words (0 < n < 1000): ')

# list of literal digit
# specify split(' ') to have empty string corresponding to 0
literal_digit = ' one two three four five six seven eight nine'.split(' ')
# we will get
# ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']

# list of literal digit corresponding to the input number
# expanded list comprehension [literal_digit[int(d)] for d in n]
literal_number = []
for d in n:
literal_number.append(literal_digit[int(d)])
# for example '438' -> ['four', 'three', 'eight']

# list of literal orders of magnitude
# we have to consider only the elements according to the length of the number
ord_mag = ['-hundred', '-ten', ''][-len(n):]
# for example '43' -> len = 2 -> start at -2
# we will get only ['-ten', '']

# build the number string translated into words
# loop over the literal number and the corresponding order of magnitude
for i, o in zip(literal_number, ord_mag):

# check if digit is 0 -> '': don't print
if i:

# not 0

# we must print the literal digit and its order of magnitude
string = i + o

# if digit is one
# we must print only the order of magnitude,
# otherwise only 'one' if the magnitude is unit
string = string.replace('one-', '')
# this can be done because the '-' is defined in the order of magnitude

# print the string, concatenating the digit on the same line
print(string, end=' ')


# 05AB1E, 53 bytes

“0€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“#ISèāR… —¿°¡#sèøʒнa}€á'-ýðý„€µ-K


Explanation:

“0€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“
# Push dictionary string "0 one two ... eight nine"
#             # Split it on spaces
I            # Push the input-integer
S           # Convert it to a list of digits
è          # Index those into the list
ā              # Push a list in the range [1,length] (without popping)
R             # Reverse it to range [length,1]
… —¿°¡       # Push dictionary string "  ten hundred"
#      # Split it on spaces: ["","","ten","hundred"]
s     # Swap so the [length,1] integer-list is at the top
è    # 0-based index into the ["","","ten","hundred"]
ø              # Create pairs of the two lists
ʒ             # Filter, to only keep the pairs where:
н            #  the first item
a           #  only contains letters
#  (this removes ["0","hundred"], ["0","ten"], and ["0",""] pairs)
}€            # After the filter: map over each remaining pair:
á           #  Only keep strings consisting solely of letters
# (this removes the "" from the last pair)
'-ý       '# Join each inner pair with "-" delimiter
ðý      # Then join these strings with " " delimiter
„€µ-  # Push dictionary string "one-"
K # Remove all those substrings
# (after which the result is output implicitly)


See this 05AB1E tip of mine (section How to use the dictionary?) to understand why “0€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“ is "0 one two three four five six seven eight nine"; … —¿°¡ is " ten hundred"; and „€µ- is "one-".

• I think you mean 48 bytes. 53 is the test suite byte count lol Commented Mar 31, 2022 at 6:48
• @lyxal No, it's 53 bytes. I simply forgot to update the TIO when I added the trailing "one-" removal. Thanks for noticing, I've updated the single TIO. Commented Mar 31, 2022 at 6:49

# Retina 0.8.2, 102 bytes

\B
-ten¶
ten(¶..)
hundred$1 A0 ¶ 1- 1 one 2 two 3 three 4 four 5 five 6 six 7 seven 8 eight 9 nine  Try it online! Link includes test cases. Explanation: \B -ten¶  If there is more than one digit then assume the leading digit is a ten. Also split the digits onto their own line. ten(¶..) hundred$1


If there's a second digit then correct it to a hundred.

A0


Delete any lines containing a 0.

¶



Join the lines together again.

1-



10 and 100 should just be ten and hundred.

1
one
2
two
3
three
4
four
5
five
6
six
7
seven
8
eight
9
nine


Turn the remaining digits into words.

Bonus: Here's a version that works up to 9999 for 116 bytes: Try it online! Link includes test cases. (Sadly the three digit version is 103 bytes.)

# Python 2, 209 bytes

i=input();t,n="0 one two three four five six seven eight nine".split(),map(int,"00"+i)[-3:]
print ("",t[n[0]]+"-hundred ")[n[0]and i>99]+("",(t[n[1]]+"-","")[n[1]<2]+"ten ")[n[1]and i>9]+("",t[n[2]])[n[2]>0]


Try it online!

Python 2 because:

1. Accepts integers directly as input

2.  converts integer to string

3. Can directly index the result of map without converting to a list

4. No () required by the print

# PHP, 195 bytes

<?php foreach(str_split(substr("00".fgets(STDIN),-3))as$i=>$c)echo trim($c>0?[0,$i>1?"one":"","two","three","four","five","six","seven","eight","nine"][$c].["-hundred","-ten",""][$i]." ":"","-");


Input via STDIN, output via echo

Try it online!

De-golf:

<?php
$inp = substr("00".fgets(STDIN),-3); // here I take input and append leading zeros, so as the total lengh is 3 // (for example, 13 becomes 013)$arr = str_split($inp); // string to array of chars foreach($arr as $index =>$digit){
$num_array = [0,$index > 1 ? "one":"","two","three","four","five","six","seven","eight","nine"]; // here one is hidden unless it's on the last position
$name_array = ["-hundred","-ten",""];$chunk = $num_array[$digit].$name_array[$index]." ";
$chunk =$digit > 0 ? $chunk : ""; // empty string if it's zero$trimmed = trim($chunk, "-"); // to dispose of "-" at the beginning of the string (this could happen if we drop "one" in "one-ten", so just "-ten" left) echo$trimmed;
}
?>


Fun note - I didn't expect PHP doesn't complain here:

# C++, 277 bytes

#include <iostream>
main(int a,char*c[]){char s[9];int q[]={0,4,7,10,15,19,23,26,31,36,40},n,m,o=strlen(c[1]),i=0;do{m=c[1][i]-48;n=q[m];strcpy_s(s,"zeroonetwothreefourfivesixseveneightnine"+n,q[m+1]-n);std::cout<<((o-i==2)?"ten-":(o-i==3)?"hundred-":"")<<s<<' ';}while(++i<o);}


## Ungolfed

#include <iostream>

int main(int a, char* c[]) {
char s[9];
int q[] = { 0,4,7,10,15,19,23,26,31,36,40 }, n, m, o = strlen(c[1]), i = 0;
do {
m = c[1][i] - 48;
n = q[m];
strncpy_s(s, 9, "zeroonetwothreefourfivesixseveneightnine" + n, q[m + 1] - n);
std::cout << ((o - i == 2) ? "ten-" : (o - i == 3) ? "hundred-" : "") << s << ' ';
} while (++i < o);
}


Input comes from command-line arguments

Reason for using C++ over C

• apparantly some compilers include string.h header in iostream

• 248 bytes Commented Feb 4, 2023 at 17:29

# Julia, 185 158 bytes

n+m+s=!(n÷m)*"-\$s "*!(n%m)
!n=replace(n<10 ? split(" one two three four five six seven eight nine"," ")[-~n] :
n<100 ? n+10+:ten : n+100+:hundred,"one-"=>"")

Attempt This Online!