Telephone number in spoken words; &050okoDed 592th.tta) th:e ʻ

15
\\$\\begingroup\\$

Goal

Write a program or function that translates a numerical telephone number into text that makes it easy to say. When digits are repeated, they should be read as "double n" or "triple n".

Requirements

Input

A string of digits.

  • Assume all characters are digits from 0 to 9.
  • Assume the string contains at least one character.

Output

Words, separated by spaces, of how these digits can be read out loud.

  • Translate digits to words:

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

  • When the same digit is repeated twice in a row, write "double number".

  • When the same digit is repeated thrice in a row, write "triple number".
  • When the same digit is repeated four or more times, write "double number" for the first two digits and evaluate the rest of the string.
  • There is exactly one space character between each word. A single leading or trailing space is acceptable.
  • Output is not case sensitive.

Scoring

Source code with the least bytes.

Test Cases

input        output
-------------------
0123         oh one two three
4554554      four double five four double five four
000          triple oh
66667888     double six double six seven triple eight
19999999179  one double nine double nine triple nine one seven nine
share|improve this question
\\$\\endgroup\\$
  • 9
    \\$\\begingroup\\$ Anyone interested in "speech golf" should note that "double six" takes longer to say than "six six". Of all the numerical possibilities here, only "triple seven" saves syllables. \\$\\endgroup\\$ – Purple P 9 hours ago
  • 1
    \\$\\begingroup\\$ @Purple P: And as I'm sure you know, 'double-u double-u double-u'>'world wide web'.. \\$\\endgroup\\$ – Chas Brown 9 hours ago
  • 2
    \\$\\begingroup\\$ I vote to change that letter to "dub". \\$\\endgroup\\$ – Hand-E-Food 9 hours ago
  • \\$\\begingroup\\$ @Adám, no. Added to output requirements. Thanks! \\$\\endgroup\\$ – Hand-E-Food 8 hours ago
  • \\$\\begingroup\\$ You should have used non-English/standard digit names for all digits to avoid build-ins… \\$\\endgroup\\$ – Adám 7 hours ago

12 Answers 12

active oldest votes
4
\\$\\begingroup\\$

05AB1E, 61 56 bytes

γεDg;Å2¨3ª£}˜v… ‹¶½¿#yg蓊瀵‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“#yнè})õKðý

-5 bytes thanks to @Grimy.

Try it online or verify all test cases.

Explanation:

γ               # Split the (implicit) input into substrings of equal adjacent characters
 ε              # Map each substring to:
  Dg            #  Get the length of a copy of the substring
    ;           #  Halve this length
     Å2         #  Create a list with that many 2s (truncates .5 decimals to an integer)
       ¨3ª      #  Remove the last 2, and append a 3 instead
          £     #  Split the substring into parts according to this list
                #   i.e. "9999999" (length=7) → [2,2,3] → ["99","99","999"]
 }˜             # After the map: flatten the list
   v            # Loop over each item `y`:
    … ‹¶½¿      #  Push dictionary word: "  double triple"
          #     #  Split it on spaces: ["","","double","triple"]
           yg   #  Get the length of the current item `y`
             è  #  And use it to (0-based) index into the list
    “Šç€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“
                 #  Push dictionary string "oh two three four five six seven eight nine"
      #          #  Split it on spaces: ["oh","two","three",...,"nine"]
       yн        #  Use the first digit of substring `y`
         è       #  To index into this list
   })            # After the loop: wrap all values on the stack into a list
     õK          # Remove empty strings from this list
       ðý        # And join the list on spaces
                 # (after which the result is output implicitly)

See this 05AB1E tip of mine (section How to use the dictionary?) to understand why … ‹¶½¿ is " double triple" and “Šç€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“ is "oh two three four five six seven eight nine".

share|improve this answer
\\$\\endgroup\\$
  • 1
    \\$\\begingroup\\$ @Grimy Ah, of course.. I added the if(length>=4) before adding the rest, but of course it isn't necessary for integers of size 1,2,3, because the ;Å2¨3ª£ will leave the strings intact (merely wrapped in a list we flatten after the map anyway). Thanks for noticing! And looking forward seeing your answer with Åγ. I indeed had the feeling the first part could be done a lot shorter somehow. \\$\\endgroup\\$ – Kevin Cruijssen 2 hours ago
  • \\$\\begingroup\\$ Here's my current best. Åγ didn't turn out as great as I thought; a better score might be possible by golfing your approach instead. \\$\\endgroup\\$ – Grimy 1 hour ago
  • \\$\\begingroup\\$ @Grimy Not as short as I thought, but yours is still shorter than mine, so obvious +1. I like the single string with added 10/12 indices for the double/triple. Out of curiosity though, why the work-around ¸» when a simple ðý suffices? ;) \\$\\endgroup\\$ – Kevin Cruijssen 1 hour ago
  • \\$\\begingroup\\$ It's actually 11 for triple, not 12. Why ðý when ¸» does the job? ðý is a rigid two-byter, while ¸» offers golfing opportunities if you can wrangle the rest of the code such that ¸ is not necessary. \\$\\endgroup\\$ – Grimy 1 hour ago
  • \\$\\begingroup\\$ @Grimy Ah, the 12 was a typo.. And I personally tend to use the most straight-forward approach if byte-counts are the same anyway (unless an equal-bytes but less straight-forward approach is a huge improvement for performance). I personally think using "push space, join by it" is easier to understand for someone reading through the docs than "wrap list in list, join each inner-most list by spaces, and then those strings by newlines (but since there is only a single inner string, no newlines are added)". ;) But feel free to use whatever you'd want; everyone has their own coding style of course. \\$\\endgroup\\$ – Kevin Cruijssen 1 hour ago
3
\\$\\begingroup\\$

QuadR, 137 bytesSBCS

Title case with a leading space.

∊¯2↑¨@(∊∘⎕A)⍵
(.)\\1*
{⍺←(,¨⎕D)⎕R('OhOneTwoThreeFourFiveSixSevenEightNine'(∊⊂⊣)⎕A)⋄' '∊w←⍺,⊃⍵:⍬⋄1=≢⍵:⍺⍵⋄3=≢⍵:'Triple',w⋄'Double',w,∇2↓⍵}⍵M

Try it online!

ϵnlist (flatten)
¯2↑¨ take the last two characters (padding on left with a space) of each characters
@ at positions where
(∊∘⎕A) characters are members of the uppercase Alphabet
 in the result of the below PCRE Replace operation…

(.) any character
\\1 followed by itself
* zero or more times, is replaced by the result of the following…

{…}⍵M "dfn"; is the Match of the above pattern

('OhOneTwoThreeFourFiveSixSevenEightNine'()⎕A) apply the following anonymous tacit function with the long string and the uppercase Alphabet as left arguments:

 membership (of letters in the long string in the uppercase alphabet)

 partitions (with a new partition beginning whenever is-a-member

 the left argument (i.e. the long string)

()⎕R PCRE Replace the following patterns with those words:

⎕D the digits 0 through 9

 treat each as a separate pattern

⍺← assign this replacement function to (for alphabetise)

then,

⊃⍵ the first character of the match

, as a string

 apply to it

w← assign this to w (for word)

' '∊: if space is a member thereof (i.e. if the match was empty):

 return nothing (becomes the empty string)

 else,

1=≢⍵: if one equals the tally of characters in the match (i.e. its length):

⍺⍵ alphabetise that digit

 else,

3=≢⍵: if three equals the tally of characters in the match (i.e. its length):

'Triple',w prepend "Triple" to the word

 else,

2↓⍵ drop to digits from the match

 recurse on that

w, prepend the word

'Double', prepend "Double"

share|improve this answer
\\$\\endgroup\\$
3
\\$\\begingroup\\$

05AB1E, 53 52 51 bytes

γεεT‚Nè}D¤›ài¨₃1ǝ]혓Šç€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‹¶½¿“#s踻

Try it online!

Explanation:

γ                      # split input in groups of consecutive equal digits
 ε               ]     # for each group
  ε    }               #  for each digit in the group
   T‚Nè                #   if the 0-based index is odd, replace the digit with 10
        D¤›ài    ]     #  if the last element is not the maximum
             ¨         #   drop the last element
              ₃1ǝ      #   replace the second element with 95
í                      # reverse each group
 ˜                     # flatten
  “...“                # compressed string: "oh one two ... nine double triple"
       #               # split on spaces
        sè             # index (wraps around, so 95 yields "triple")
          ¸»           # join with spaces
share|improve this answer
\\$\\endgroup\\$
2
\\$\\begingroup\\$

Wolfram Language (Mathematica), 115 bytes

{Switch[L=Tr[1^{##}],1," ",3," triple ",_," double "],If[#<1,"oh",IntegerName@#],If[L>3,#0@##3,""]}&@@@Split@#<>""&

Try it online!

Takes a list of digits as input. Output includes a leading space.

share|improve this answer
\\$\\endgroup\\$
2
\\$\\begingroup\\$

JavaScript (ES6),  161 160 152  144 bytes

The output includes a single leading space.

s=>[n=>' '+'oh/one/two/three/four/five/six/seven/eight/nine'.split`/`[n],'$1 double$2','triple$2'].map(r=>s=s.replace(/(\\S*)( \\S+)\\2|\\d/g,r))&&s

Try it online!

How?

The conversion is processed in three steps:

  1. replace each digit with the corresponding English word, preceded with a space
  2. replace each pattern "X X" with "double X"
  3. replace each pattern "double X X" with "triple X"

To save bytes, we use the same regular expression for all steps:

/(\\S*)( \\S+)\\2|\\d/g     (\\S*)  -> 1st capturing group: any word, or nothing at all
                        ( \\S+) -> 2nd capturing group: a space, followed by a word
                        \\2     -> a copy of the 2nd capturing group
                        |\\d    -> or try to capture a digit instead (for step 1)

For step 1, we use a callback function that picks the correct word from a lookup table:

  • "799999"" seven nine nine nine nine nine"

For step 2, we replace with "$1 double$2":

  • " (seven)( nine)( nine)"" seven double nine"
  • "( nine)( nine) nine"" double nine nine"

For step 3, we replace with "triple$2":

  • " (double)( nine)( nine)"" triple nine"

Formatted source code

share|improve this answer
\\$\\endgroup\\$
2
\\$\\begingroup\\$

Scala, 221 bytes

Got it. Somehow the recursive version I was trying to build was strongly more verbose-y than this one (still recursive though, but only in one case). Function f takes as an input string the phone number and outputs its phonetics with a trailing whitespace.

var u="oh one two three four five six seven eight nine" split " "
"(.)\\\\1*".r.replaceAllIn(s,x=>{var o=x.matched
var k=u((o(0)+"").toInt)+" "
o.length match{case 3=>"triple "+k
case 1=>k
case _=>"double "+k+f(o drop 2)}})

Try it online!
Edit : it does not link to the version using ..." split " " but to the version with ...".split(" ") which is one byte longer.

Scala, 223 bytes

And here comes the leading whitespace version, two bytes longer for some reason (even with massive refactoring).

var u="oh one two three four five six seven eight nine" split " "
"(.)\\\\1*".r.replaceAllIn(s,x=>{var o=x.matched
var k=u((o(0)+"").toInt)
" , double , triple ".split(",")(if(o.length>3){k+=f(o drop 2);1}else o.length-1)+k})

Try it online!

share|improve this answer
\\$\\endgroup\\$
2
\\$\\begingroup\\$

Python 2, 171 169 168 bytes

s=input()
while s:c=s[0];n=(s[1:2]==c)+(s[:3]==c*3!=s[1:4]);print'   eellpbiurotd'[-n:0:-2]+'oh one two three four five six seven eight nine'.split()[int(c)],;s=s[1+n:]

Try it online!

-1 byte, thanks to Jitse

share|improve this answer
\\$\\endgroup\\$
  • \\$\\begingroup\\$ Beat me again! Save 1 byte like so \\$\\endgroup\\$ – Jitse 4 hours ago
  • \\$\\begingroup\\$ @Jitse, that doesn't work for 1312 ;) \\$\\endgroup\\$ – TFeld 4 hours ago
  • \\$\\begingroup\\$ Ah, you're right! \\$\\endgroup\\$ – Jitse 4 hours ago
  • \\$\\begingroup\\$ How about this one then: ['','double ','triple '][n] to ' eellpbiurotd'[-n:0:-2] for 168 bytes: Try it online! \\$\\endgroup\\$ – Jitse 4 hours ago
  • \\$\\begingroup\\$ Alternatively, also 168 bytes \\$\\endgroup\\$ – Jitse 3 hours ago
1
\\$\\begingroup\\$

Lua 5.1, 166 bytes

for I,N in('111 triple 11 double 1 '):gmatch'(%d+)(%D+)'do for i,n in('0oh1one2two3three4four5five6six7seven8eight9nine'):gmatch'(.)(%l+)'do s=s:gsub(i*I,N..n)end end

Ensure s is a predefined string value populated only with digits; that will be the variable to be modified. The result will include a leading space [\\u20] character.

share|improve this answer
New contributor
VisualPlugin Rōblox is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\\$\\endgroup\\$
  • \\$\\begingroup\\$ Welcome to the site! As Lua can take input via standard methods, it's against the rules to require s to already have the input. Aside from that, you've got a good first post! I would recommend you include a link to an online testing site e.g. tio.run/#lua so that others can test your solution \\$\\endgroup\\$ – caird coinheringaahing 4 hours ago
0
\\$\\begingroup\\$

PHP, 174 169 166 bytes

for(;$s=strspn($argn,$d=$argn[$i],$i++);$s==3?($i+=2)&&print'triple ':$s<2?:++$i&&$a[]=print'double ',print[oh,one,two,three,four,five,six,seven,eight,nine][$d].' ');

Try it online!

For each digit at index of $i starting from 0:

  • If span of the same digit starting from location of $i is equal to 3, prints 'triple ' and adds 2 to $i so next iteration will have 2 digits jumped over.
  • If span of the same digit starting from location of $i is equal to or more than 2 but is not 3, prints 'double ' and adds 1 to $i so next iteration will have 1 digit jumped over.
  • Prints word for the digit and a space.
  • $i++.
share|improve this answer
\\$\\endgroup\\$
0
\\$\\begingroup\\$

Red, 242 bytes

func[s][b:[copy t skip t]parse s[any[change[b t ahead not t](rejoin["triple "t])|
change b(rejoin["double "t])| skip]]foreach c s[prin either i:
find"0123456789"c[rejoin[pick[:oh:one:two:three:four:five:six:seven:eight:nine]index? i" "]][c]]]

Try it online!

share|improve this answer
\\$\\endgroup\\$
0
\\$\\begingroup\\$

Retina 0.8.2, 105 bytes

+`(.)\\1
=$1
.
 $&
= =
triple
=
double
9
nine
8
eight
7
seven
6
six
5
five
4
four
3
three
2
two
1
one
0
oh

Try it online! Outputs a leading space. Explanation: I originally tried a regex that automatically matches 2 or 3 digits but @Arnauld's approach of turned out to be golfier. Explanation:

+`(.)\\1
=$1

Match pairs of identical digits and replace the first with a =. Then repeat, so that for an odd number the second last digit is also replaced with a =.

.
 $&

Space the digits (and =s) out.

= =
triple

Handle the case of three identical digits.

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

Replace all remaining characters with words.

share|improve this answer
\\$\\endgroup\\$
0
\\$\\begingroup\\$

T-SQL 2017, 234 bytes

Added some linebreaks to make it readable

WHILE''<left(@,1)SELECT @=stuff(@,1,iif(p<4,p,2),'')+
iif(p=1,' ',iif(p=3,' triple ',' double '))
+trim(substring('oh  one  two  threefour five six  seveneightnine',left(@,1)*5,5))
FROM(SELECT~-patindex('%[^'+left(@,1)+']%',@)p)z
PRINT @

Try it online

share|improve this answer
\\$\\endgroup\\$

Your Answer

If this is an answer to a challenge…

  • …Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.

  • …Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one. Explanations of your answer make it more interesting to read and are very much encouraged.

  • …Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.

More generally…

  • …Please make sure to answer the question and provide sufficient detail.

  • …Avoid asking for help, clarification or responding to other answers (use comments instead).

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 code-golf kolmogorov-complexity or ask your own question.

Popular posts from this blog

ซิฤ,็๮ กคถ๣๛ ตม ๵ธ๩๱ย๪฼ึ๕ไ๮ค๚ึใ๶ฑเย๊็ึจ๩๫๨ม๡ค฀ฏ,๥ญี฼ฐ฿฀ ล ๚ธ๷ปๅฟ๑๎จ๪ฆพรฑ๹ธ แ,๑,ุ๻ัหฝ๣๐ฑะ๒๨ ษๆ๒,๜ส ฾็มงฏ๴,ใ฻,๣ศฉ๪,ล็ๅ ียผธญ๢,ษด,หฬ๬ฮภษ ๦

ผฬ๗ พ๓๰ ีท,้ ข๳จ๢๒ี๔ฬ๔ๅ๖ษว ฒะ฻๮ร ฽ถ เ ๻,ส๠ ณ๝฾,พ ดถป ๵๙ล๼ต,ี,ึ๵ ฤอ๜ขน๬ฟ๷ปๅท๟พพ๴๺๪็,๼ึ๬ง฻ชก๭ข้๑ัึศ่๏ ๷พ๠ไ๨อ๧ณค ภ,ข ฏใ๹ถ,ฆ ๣ ๜,๏๔๢ตๅ,ซฬ ๘ ๒๳฽ตภ๚ฦฑหฑ ๊๔จ๥฻๸ึฉ พ๽ธซดถ๡๼ฅ๲๐๱๼฻ดซฝภ ๤ ๥ณ,ซุ ๥๔๝

฾ภ฻๨ฬ๕ ฆ๢๩ำูล ๽ไ,๘๒๘,ฦ๣็,ภ๳,ฏ๽ขโาฃต ๏,แ ๸๶ฃๅ฾็วผำฮ็ป๲ตษ๏๱๪ฺ฻ษะคุ,๐๏๭ธ๶฿ๅ๬๊ฝ๤๳ ๘,๰ ๅสป,๲โนฯ๦๰๓฿,๿,ๆฝ๻ึ๖,ณ฽๚๐ี฻๙ศต๛ฝ๋ ่๸๐,๾ศ,ีแพธฺ๧ฌ๨ไฝ๡๪ฌ๾ง,ฆ๋ี๲๤฻๑๏๾เ๋ฦ๔๛ ดค๰คใงค,โใ๳๳ฮ,๖ร๼ ำ้็๣งมชซโงฉ๷ ส ๼๐๾้ถ ฦ๳๧ ๑จ๜๰