Numéro de téléphone dans les mots parlés

33

Objectif

Ecrivez un programme ou une fonction qui convertit un numéro de téléphone numérique en texte facilitant la prononciation. Lorsque les chiffres sont répétés, ils doivent être lus comme "double n" ou "triple n".

Exigences

Contribution

Une chaîne de chiffres.

  • Supposons que tous les caractères sont des chiffres de 0 à 9.
  • Supposons que la chaîne contienne au moins un caractère.

Sortie

Des mots, séparés par des espaces, expliquant comment ces chiffres peuvent être lus à voix haute.

  • Traduire les chiffres en mots:

    0 "oh"
    1 "un"
    2 "deux"
    3 "trois"
    4 "quatre"
    5 "cinq"
    6 "six"
    7 "sept"
    8 "huit"
    9 "neuf

  • Lorsque le même chiffre est répété deux fois de suite, écrivez " numéro double ".

  • Lorsque le même chiffre est répété trois fois de suite, écrivez "triple numéro ".
  • Lorsque le même chiffre est répété quatre fois ou plus, écrivez " numéro double " pour les deux premiers chiffres et évaluez le reste de la chaîne.
  • Il y a exactement un espace entre chaque mot. Un seul espace de début ou de fin est acceptable.
  • La sortie n'est pas sensible à la casse.

Notation

Code source avec le moins d'octets.

Cas de test

input        output
-------------------
0123         oh one two three
4554554      four double five four double five four
000          triple oh
00000        double oh triple oh
66667888     double six double six seven triple eight
19999999179  one double nine double nine triple nine one seven nine
Hand-E-Food
la source
38
Toute personne intéressée par "speech golf" devrait noter que "double six" prend plus de temps à dire que "six six". Parmi toutes les possibilités numériques, seul le "triple sept" enregistre les syllabes.
Purple P
13
@Purple P: Et comme vous le savez sûrement, "double-u double-u double-u"> "World Wide Web" ..
Chas Brown
11
Je vote pour changer cette lettre en "dub".
Hand-E-Food
8
Je sais que ce n’est qu’un exercice intellectuel, mais j’ai sous les yeux une facture d’essence portant le numéro 0800 048 1000 et que je lirais comme "oh huit cent oh quatre huit un mille". Le regroupement de chiffres est important pour les lecteurs humains et certains modèles tels que "0800" sont traités de manière spécifique.
Michael Kay
3
@PurpleP Toute personne intéressée par la clarté de la parole, cependant, surtout lorsque vous parlez au téléphone, peut utiliser le "double 6", car il est clair que le locuteur signifie deux six et qu'il n'a pas répété le chiffre 6 par inadvertance. Les gens ne sont pas des robots: P
S'excuser et réintégrer Monica

Réponses:

10

05AB1E , 53 52 51 50 49 octets

γε€T2äθ¬MÊi¨₃1ǝR]˜“Šç€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‹¶½¿“#s踻

Essayez-le en ligne!

Explication:

γ                      # split input in groups of consecutive equal digits
 ε              ]      # for each group
  €T                   #  add a 10 before each digit (66 -> [10, 6, 10, 6])
    2äθ                #  keep only the second half of that list
       ¬MÊi     ]      #  if the first element is not the maximum
           ¨           #   drop the last element
            ₃1ǝ        #   replace the second element with 95
               R       #   reverse the list
˜                      # flatten
 “...“                 # compressed string: "oh one two ... nine double triple"
      #                # split on spaces
       sè              # index (wraps around, so 95 yields "triple")
         ¸»            # join with spaces
Grimmy
la source
1
Oh, Mregarde aussi à l'intérieur des listes lors de la détermination du nombre entier maximal sur la pile? Je ne savais pas ça. Cela ressemble à quelque chose à retenir. :)
Kevin Cruijssen
16

8088 Assembly, IBM PC DOS, 164 159 156 155 octets

Binaire:

00000000: d1ee 8a0c 03f1 53fd ac3a d075 0343 e2f7  ......S..:.u.C..
00000010: 85db 741c 5f8a d043 f6c3 0174 0a57 bd64  ..t._..C...t.W.d
00000020: 0155 83eb 0374 0957 bd5d 0155 4b4b 75f7  .U...t.W.].UKKu.
00000030: 8ad0 2c2f 7213 518a f0b0 24b1 31bf 6a01  ..,/r.Q...$.1.j.
00000040: fcf2 aefe ce75 fa59 57e2 bc5a 85d2 740c  .....u.YW..Z..t.
00000050: b409 cd21 b220 b402 cd21 ebef c364 6f75  ...!. ...!...dou
00000060: 626c 6524 7472 6970 6c65 246f 6824 6f6e  ble$triple$oh$on
00000070: 6524 7477 6f24 7468 7265 6524 666f 7572  e$two$three$four
00000080: 2466 6976 6524 7369 7824 7365 7665 6e24  $five$six$seven$
00000090: 6569 6768 7424 6e69 6e65 24              eight$nine$

Construisez et testez le fichier exécutable à xxd -rpartir d’en haut, ou téléchargez PHONE.COM .

Liste non assemblée:

D1 EE       SHR  SI, 1              ; point SI to DOS PSP (80H) for input string
8A 0C       MOV  CL, BYTE PTR[SI]   ; load input string length into CX
03 F1       ADD  SI, CX             ; move SI to end of input 
53          PUSH BX                 ; push a 0 to signal end of output stack 
        CHAR_LOOP:
FD          STD                     ; set LODS direction to reverse 
AC          LODSB                   ; load next char from [SI] into AL, advance SI 
3A D0       CMP  DL, AL             ; is it same as previous char? 
75 03       JNZ  NEW_CHAR           ; if not, it's a different char 
43          INC  BX                 ; otherwise it's a run, so increment run length
E2 F7       LOOP CHAR_LOOP          ; move on to next char 
        NEW_CHAR: 
85 DB       TEST BX, BX             ; is there a run greater than 0? 
74 1C       JZ   GET_WORD           ; if not, look up digit name 
5F          POP  DI                 ; get name for the current digit 
8A D0       MOV  DL, AL             ; save current char in DL 
43          INC  BX                 ; adjust run count (BX=1 means run of 2, etc)
F6 C3 01    TEST BL, 1              ; is odd? if so, it's a triple
74 0A       JZ   IS_DBL             ; is even, so is a double 
57          PUSH DI                 ; push number string ("one", etc) to stack
BD 0164     MOV  BP, OFFSET T       ; load "triple" string 
55          PUSH BP                 ; push to stack 
83 EB 03    SUB  BX, 3              ; decrement run count by 3 
74 09       JZ   GET_WORD           ; if end of run, move to next input char 
        IS_DBL: 
57          PUSH DI                 ; push number string to stack
BD 015D     MOV  BP, OFFSET D       ; load "double" string 
55          PUSH BP                 ; push to stack 
4B          DEC  BX                 ; decrement by 2
4B          DEC  BX
75 F7       JNZ  IS_DBL             ; if not end of run, loop double again 
        GET_WORD: 
8A D0       MOV  DL, AL             ; save current char into DL
2C 2F       SUB  AL, '0'-1          ; convert ASCII char to 1-based index 
72 13       JB   NOT_FOUND          ; if not a valid char, move to next
51          PUSH CX                 ; save outer loop counter 
8A F0       MOV  DH, AL             ; DH is the index to find, use as scan loop counter
B0 24       MOV  AL, '$'            ; word string is $ delimited
B1 31       MOV  CL, 031H           ; search through length of word data (49 bytes)
BF 016A     MOV  DI, OFFSET W       ; reset word data pointer to beginning
FC          CLD                     ; set DF to scan forward for SCAS 
        SCAN_LOOP: 
F2/ AE      REPNZ SCASB             ; search until delimiter '$' is found in [DI]
FE CE       DEC  DH                 ; delimiter found, decrement counter 
75 FA       JNZ  SCAN_LOOP          ; if counter reached 0, index has been found 
59          POP  CX                 ; restore outer loop position
57          PUSH DI                 ; push string on stack 
        NOT_FOUND:
E2 BC       LOOP CHAR_LOOP          ; move to next char in input 
        OUTPUT_STACK: 
5A          POP  DX                 ; get string from top of stack 
85 D2       TEST DX, DX             ; it is the last? 
74 0C       JZ   EXIT               ; if so, exit 
B4 09       MOV  AH, 09H            ; DOS display string function 
CD 21       INT  21H                ; write string to console 
B2 20       MOV  DL, ' '            ; load space delimiter 
B4 02       MOV  AH, 02H            ; DOS display char function 
CD 21       INT  21H                ; write char to console 
EB EF       JMP  OUTPUT_STACK       ; continue looping 
        EXIT: 
C3          RET                     ; return to DOS 

D   DB "double$" 
T   DB "triple"
W   DB "$oh$","one$","two$","three$","four$","five$","six$","seven$","eight$","nine$" 

TL; DR:

La chaîne d'entrée est lue de droite à gauche pour faciliter la recherche d'un triple. La sortie est poussée sur la pile x86 pour simplifier l'inversion de l'ordre d'affichage et faciliter la réorganisation des mots "double" et "triple" pour précéder le nom du chiffre.

Si le chiffre suivant est différent du dernier, le nom est recherché dans la liste de mots et inséré dans la pile. En l'absence de concept formel de "tableau indexé de chaînes de longueur variable" dans le code machine, la liste de mots est analysée i(l'index du mot) plusieurs fois pour que le délimiteur de chaîne ( $) recherche le mot correspondant. Utilement, x86 a une paire d’instructions courtes ( REPNZ SCASBsimilaires à celles memchr()en C), ce qui simplifie les choses (merci à l’ ICCI !).

Si le chiffre est identique au précédent, le compteur de la longueur d'une "exécution" est incrémenté et continue à boucler vers la gauche sur l'entrée. Une fois la course terminée, le nom du chiffre est extrait de la pile car il devra être placé après le "double" ou le "triple" pour chaque groupe. Si la longueur de la séquence est impaire (et la longueur de la séquence est > 1), le nom du chiffre suivi de la chaîne "triple" est envoyé dans la pile et la longueur de la séquence est réduite de 3. Comme la longueur de la séquence sera désormais paire, le pas est répété pour "double" jusqu'à ce que la longueur de l'analyse soit 0.

Lorsque la chaîne d'entrée a atteint la fin, la pile est vidée avec chaque chaîne enregistrée écrite à l'écran dans l'ordre inverse.

I / O:

Un exécutable PC DOS autonome, entré de la sortie de la ligne de commande vers la console.

enter image description here

Téléchargez et testez PHONE.COM .

640 Ko
la source
repne scasbest memchr(ou strchrsi vous savez qu'il va y avoir un coup), pas strstr.
Peter Cordes
Est-ce que CH = 0 à l'entrée du processus est garanti par un standard, ou est-ce juste ce que certaines versions de DOS font? Je remarque que vous supposez que cela mov cl, byte[si] équivaut à movzx cx, byte [si]. Je me demande si utiliser un registre différent, comme AH, pour le compte avec dec ah / jnzau lieu de loopsauver quelque chose de ne pas avoir à pousser / pop CX. Probablement pas, et vous n'avez plus de registre 16 bits autorisant un octet dec.
Peter Cordes
1
@PeterCordes, CH=0par exemple , allez sur fysnet.net/yourhelp.htm , qui, pour toute version raisonnable de DOS, est toujours à zéro, comme avec BX. Bonne idée de l'extension à zéro mov, bien que, techniquement, je ne pense pas qu'elle movzxsoit disponible sur le 808x (conserver la plate-forme cible sous IBM PC 5150 et tous). J'ai manipulé tous les registres du mieux que j'ai pu pour sauver les octets, mais si vous voyez quelque chose que j'ai probablement manqué, faites-le-moi savoir!
640KB
1
Il est plus précis de l'appeler memchrIMO. L '"instruction de chaîne" qui donne un nom trompe les gens en leur faisant croire qu'ils travaillent sur des chaînes C de longueur implicite, mais qu'ils travaillent en réalité sur des chaînes de longueur explicite telles que des std::stringtampons. Comme memcpy, memset(movs / stos), memchr/ memrchr(repne scas avec DF = 0 ou 1) et memcmp(repe cmps). Le seul équivalent en C repe scasest strspnparce que je ne pense pas qu’il existe une memfonction pour cela. Vous pouvez même décrire stoswou stosdcomme wmemsetpar exemple.
Peter Cordes
1
movzxcoûte un octet supplémentaire en opcode, et oui, il n'a été introduit qu'avec 386. Il était simplement plus facile de taper pour décrire le fait que vous effectuez une fusion à octets inférieurs et en supposant qu'elle est correctement étendue à zéro. Si vous connaissez CX ou au moins CH = 0, alors oui pour le golf, allez toujours avec movCL. Mais en dehors du golf, les instructions de chargement d'octets de x86 sont movzxet movsx: elles évitent toutes fausses dépendances ou autres manigances à registre partiel. Sur les processeurs modernes avec une destination dword, ils sont aussi rapides que le mov chargement de dword .
Peter Cordes
9

05AB1E , 61 56 53 52 51 octets

γvyDg;LàäRv… ‹¶½¿#yg蓊瀵‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“#yè])áðý

-9 octets grâce à @Grimy .

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

γ               # Split the (implicit) input into substrings of equal adjacent characters
                #  i.e. "199999991779" → ["1","9999999","1","77","9"]
 v              # Loop over each substring `y`:
   Dg           #  Get the length of a copy of the substring
     ;          #  Halve it
      L         #  Create a list in the range [1, length/2], where odd lengths are
                #  automatically truncated/floored
                #   i.e. "1" (length=1) → 0.5 → [1,0]
                #   i.e. "9999999" (length=7) → 3.5 → [1,2,3]
       à        #  Pop and push the maximum of this list
  y     ä       #  Divide the string into that many parts
                #   → ["1"]
                #   → ["999","99","99"]
         R      #  Reverse the list
                #   → ["99","99","999"]
  v             # Inner 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 `y` to index into the string-list (with automatic wrap-around,
                #  so since there are 10 words, it basically indexes with a single digit
                #  due to an implicit modulo-10)
                #   i.e. "77" → "seven"
 ]              # Close both loops
  )             # Wrap all values on the stack into a list
   á            # Only keep letters, which removes the empty strings from the list
    ðý          # And join the list on spaces
                # (after which the result is output implicitly)

Voir ce conseil 05AB1E (section Comment utiliser le dictionnaire? ) Pour comprendre pourquoi … ‹¶½¿est " double triple"et “Šç€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“est "oh two three four five six seven eight nine".

Kevin Cruijssen
la source
1
@ Grimy Ah, bien sûr .. J'ai ajouté le if(length>=4)avant d'ajouter le reste, mais bien sûr ce n'est pas nécessaire pour les entiers de taille 1,2,3, car ;Å2¨3ª£cela laissera les chaînes intactes (simplement enveloppées dans une liste que nous avons aplaties après la carte). Merci d'avoir remarqué! Et impatient de voir votre réponse avec Åγ. J'avais en effet le sentiment que la première partie pourrait être beaucoup plus courte.
Kevin Cruijssen
1
Dg;LàäRest toujours un octet plus court que āɨšJõK, et beaucoup plus semblable à ce que vous aviez à l’origine.
Grimmy
1
@ Grimy Ah, c'est en effet fermé à ce que j'avais initialement, je l'aime bien. :) Merci encore!
Kevin Cruijssen
1
@Grimy J'ai été capable de trouver un autre golf moi-même que j'ai oublié de .. áau lieu de õKà la fin. :)
Kevin Cruijssen
1
Belle trouvaille avec á! Voici un 51 et un autre . 50 se sent possible.
Grimmy
7

QuadR , 137 octets SBCS

Casse de titre avec un espace principal.

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

Essayez-le en ligne!

ε nlist (aplatir)
¯2↑¨ prendre les deux derniers caractères (rembourrage sur la gauche avec un espace) de chacun des caractères
@  à des positions où les
(∊∘⎕A) caractères sont membres de la majuscule A lphabet
 dans le résultat de l'opération ci - dessous PCRE Remplacer ...

(.) tout caractère
\1 suivi par lui-même
* zéro ou plusieurs fois, est remplacé par le résultat de ce qui suit…

{…}⍵M "dfn"; est le M atch du motif ci - dessus

('OhOneTwoThreeFourFiveSixSevenEightNine'()⎕A) Applique la fonction tacite anonyme suivante avec la chaîne longue et l' alphabet majuscule Un alphabet de gauche:

 appartenance (de lettres dans la longue chaîne dans l'alphabet majuscule)

 partitions (avec une nouvelle partition commençant chaque fois que is-a-member

 l'argument de gauche (c'est-à-dire la longue chaîne)

()⎕R PCRE R eplace les motifs suivants avec des ces mots:

⎕D les chiffres 0 à 9

 traiter chacun comme un motif séparé

⍺← assigner cette fonction de remplacement à (pour une alphabétisation)

puis,

⊃⍵ le premier personnage du match

, comme une chaîne

 appliquer à elle

w← assigner ceci à w(pour mot )

' '∊: Si l'espace en est un membre (c'est-à-dire si la correspondance était vide):

 ne renvoie rien (devient la chaîne vide)

 autre,

1=≢⍵: si on égal le décompte des caractères dans la correspondance (c'est-à-dire sa longueur):

⍺⍵ alphabetiser ce chiffre

 autre,

3=≢⍵: si trois est égal au total des caractères de la correspondance (c'est-à-dire sa longueur):

'Triple',w préfixer « Triple » du w ord

 autre,

2↓⍵ déposer aux chiffres du match

 récidive à ce sujet

w, ajouter le mot

'Double', prepend "Double"

Adam
la source
6

JavaScript (ES6),  161 160 152  144 octets

La sortie comprend un seul espace de début.

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

Essayez-le en ligne!

ou Voir le code source formaté

Comment?

La conversion est traitée en trois étapes:

  1. remplace chaque chiffre par le mot anglais correspondant, précédé d'un espace
  2. remplacez chaque motif "X X"par"double X"
  3. remplacez chaque motif "double X X"par"triple X"

Pour économiser des octets, nous utilisons la même expression régulière pour toutes les étapes:

/(\S*)( \S+)\2|\d/g

qui fonctionne comme suit:

(\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)

À l'étape 1, nous utilisons une fonction de rappel qui sélectionne le mot correct dans une table de recherche:

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

A l'étape 2, nous remplaçons par "$1 double$2":

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

A l'étape 3, nous remplaçons par "triple$2" :

  • " (double)( nine)( nine)"" triple nine"
Arnauld
la source
4

Wolfram Language (Mathematica) , 115 octets

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

Essayez-le en ligne!

Prend une liste de chiffres en entrée. La sortie comprend un espace principal.

attinat
la source
3

Python 2 , 171 169 168 octets

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:]

Essayez-le en ligne!

-1 octet, merci à Jitse

TFeld
la source
Battez-moi encore! Économisez 1 octet comme ça
Jitse
@Jitse, ça ne marche pas pour 1312;)
TFeld
Ah tu as raison!
Jitse
Que diriez - vous alors celui - ci: ['','double ','triple '][n]à ' eellpbiurotd'[-n:0:-2]pour 168 octets: Essayez en ligne!
Jitse
Alternativement, aussi 168 octets
Jitse
3

Perl 5 -p , 111 octets

s/(\d)\1/ double$1/g;s/\w+(\d)\1/triple$1/g;s/\d/' '.qw(oh one two three four five six seven eigth nine)[$&]/ge

Essayez-le en ligne!

Explication:

s/(\d)\1/ double$1/g; # Replace non-overlapping double digits with " double<digit>"
s/\w+(\d)\1/triple$1/g; # Replace remaining double digits preceded by "double" with "triple<digit>"
s/\d/' '.qw(oh one two three four five six seven eigth nine)[$&]/ge # Replace digits with " <word>"
wastl
la source
1
Rasé quelques octets: 106
Xcali
3

Scala , 213 octets

Je l'ai. D'une manière ou d'une autre, la version récursive que j'essayais de construire était fortement plus prolixe que celle-ci (toujours récursive, mais dans un cas seulement). Function fprend comme chaîne d'entrée le numéro de téléphone et sort sa phonétique avec un espace de fin.

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)-48)+" "
o.length match{case 3=>"triple "+k
case 1=>k
case _=>"double "+k+f(o drop 2)}})

Essayez-le en ligne!
modifier : -8b grâce à DrY Wit!

Scala , 215 octets

Et voici la version la plus avancée des espaces, deux octets de plus pour une raison quelconque (même avec un refactoring massif).

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)-48)
" , double , triple ".split(",")(if(o.length>3){k+=f(o drop 2);1}else o.length-1)+k})

Essayez-le en ligne!

V. Courtois
la source
2
Vous pouvez économiser 8 octets en remplaçant (o(0)+"").toIntpar o(0)-48.
Dr Y Wit
Bravo @DrYWit, merci!
V. Courtois
3

PHP , 174 169 166 159 octets

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

Essayez-le en ligne!

Pour chaque chiffre à l'indice de à $ipartir de 0:

  • Si l'intervalle du même chiffre commence à partir de l'emplacement de $i est égal à 3, imprime 'triple 'et ajoute 2 à $il'itération suivante pour permettre à 2 chiffres de sauter.
  • Si l'intervalle du même chiffre à partir de l'emplacement de $iest égal ou supérieur à 2 mais non égal à 3, imprime 'double 'et ajoute 1 à $il'itération suivante, ce qui signifie qu'un chiffre est sauté.
  • Mot d'impression pour le chiffre et un espace.
  • $i++.
Nuit2
la source
2

Retina 0.8.2 , 105 octets

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

Essayez-le en ligne! Sort un espace de premier plan. Explication: À l’origine, j’ai essayé une expression régulière qui correspond automatiquement à 2 ou 3 chiffres, mais l’approche de @ Arnauld s’est révélée être plus golfeuse. Explication:

+`(.)\1
=$1

Faites correspondre les paires de chiffres identiques et remplacez le premier par un =. Répétez ensuite l'opération, de sorte que pour un nombre impair, l'avant-dernier chiffre soit également remplacé par un =.

.
 $&

Espacez les chiffres (et =s).

= =
triple

Traitez le cas de trois chiffres identiques.

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

Remplacez tous les caractères restants par des mots.

Neil
la source
2

Gelée , 59 octets

⁵;`,0;$Ɗ€Ẏ;`Ø0ṭ;-œṣjƭƒV€‘$ị“¡ıc⁴Ṛ⁽]@ɱ2¦Ż©Ẉḷ$Æ!)ɗ[ı8ɱḃ%ċ»Ḳ¤K

Essayez-le en ligne!

Un lien monadique qui prend une chaîne de caractères numériques comme argument et renvoie une chaîne Jelly de mots séparés par des espaces. Appelé en tant que programme complet, génère implicitement.

Nick Kennedy
la source
2

T-SQL 2017, 238 octets

Ajout de quelques sauts de ligne pour le rendre lisible

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 @

Essayez-le en ligne

t-clausen.dk
la source
2

C ++, 382 octets

Ce n'est pas super, mais quelqu'un a besoin d'écrire une version C ++. La fonction récursive R parcourt la chaîne en entrée et compte les valeurs répétées. S'il y a plus de 3 répétitions, il prétend qu'il y en a 2, puis rembobine et tente à nouveau.

Quelques caractères de source supplémentaires pourraient probablement être supprimés avec #definemajor, mais je suis sûr qu'un meilleur algo pourrait en extraire davantage.

#include <iostream>
#include <sstream>
using namespace std;
char*n[]={"oh","one","two","three","four","five","six","seven","eight","nine"};
void R(ostream& s,const char*r,char p='x',int c=0){if(*r==p)R(s,r+1,p,c+1);else
{if(c>1){if(c>= 4){s<<"double ";r-=(c-2);}else if(c==3)s<< "triple ";else if(c==2)s<< "double ";
}if(c >0)s<<n[p-'0']<<" ";if(!*r)return;R(s,r+1,*r,1);}}

void check(const char* in, const char* out)
{
    std::stringstream ss;
    R(ss,in);
    if (out == ss.str()) std::cout << "PASS: "; else std::cout << "FAIL! ";
    std::cout << in << "\n< " << out << "\n> " << ss.str() << std::endl;
}

int main(int c,char**argv)
{
    if (argv[1] == std::string("test"))
    {
        check("0123"         ,"oh one two three ");
        check("4554554"      ,"four double five four double five four ");
        check("000"          ,"triple oh ");
        check("00000"        ,"double oh triple oh ");
        check("66667888"     ,"double six double six seven triple eight ");
        check("19999999179"  ,"one double nine double nine triple nine one seven nine ");
    }
    else
    {
        char* v = argv[1];
        R(std::cout,v);
        std::cout << std::endl;
    }
}

et vérification des cas de test:

pa-dev01$ ./a.out test
PASS: 0123
< oh one two three
> oh one two three
PASS: 4554554
< four double five four double five four
> four double five four double five four
PASS: 000
< triple oh
> triple oh
PASS: 00000
< double oh triple oh
> double oh triple oh
PASS: 66667888
< double six double six seven triple eight
> double six double six seven triple eight
PASS: 19999999179
< one double nine double nine triple nine one seven nine
> one double nine double nine triple nine one seven nine
Mark Lakata
la source
1
La partie golfée a-t-elle réellement besoin #include <sstream>? Ou pourriez-vous déplacer cela après la partie golfée pour la fonction de test? Je pense que la saisie std::ostream&sprendrait moins de place que using namespace std;, sauf s’il existe d’autres endroits où vous auriez besoin d’un std::.
Peter Cordes
253 octets
ceilingcat le
2

Perl 6 , 96 93 octets

{S:g/(.)$0?[$0{}<!$0>]?/{(<triple double>X$)[3-$/.comb]}{+$/??uniname(~$0).words[1]!!'oh'} /}

Essayez-le en ligne!

Ceci est un bloc de code anonyme qui prend un nombre et retourne une chaîne avec les nombres en majuscules, par exemple 0123 => oh ONE TWO THREE avec un seul espace de fin.

Cela a été supprimé pendant un certain temps jusqu'à ce que je découvre comment utiliser les captures dans un aperçu, mais cela devrait être corrigé maintenant.

Jo King
la source
1

Rouge , 242 octets

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]]]

Essayez-le en ligne!

Galen Ivanov
la source
1

Scala , 253 octets

def g(s:String):String={val t="oh one two three four five six seven eight nine".split(" ")(s(0)-48)
s.length match{case 3=>"triple "+t;case 2=>"double "+t;case 1=>t;case _=>"double "+t+" "+g(s drop 2)}}
s=>"(.)\\1*".r.findAllIn(s).map(g(_)) mkString " "

Essayez-le en ligne!

Dr Y Wit
la source
1

Oracle SQL, 578 octets (sous forme formatée)

La solution n’est en aucun cas concise, vous devez donc l’afficher sous forme formatée.

with r(s) as
(select x from t
  union all
 select case
           when length(regexp_substr(s, '(.)(\1)+')) = 3 
           then regexp_replace(s, '^...')
           else regexp_replace(s, '^(.)\1|^.')
        end
   from r
  where s is not null)
select listagg(decode(length(r),  2, 'double ',  3, 'triple ') ||
               decode(substr(r, 1, 1), 0, 'oh', to_char(to_date(substr(r, 1, 1), 'j'), 'jsp')), ' ')
               within group (order by rownum)
  from (select regexp_replace(s, lag(s) over (order by length(s)) || '$') r
          from r order by length(s) desc);

Test en SQL * Plus

SQL> create table t(x) as select /*'45547777777774'*/ '1999999910079' from dual;

Table created.

SQL> set pages 0
SQL> with r(s) as
  2  (select x from t
  3    union all
  4   select case
  5             when length(regexp_substr(s, '(.)(\1)+')) = 3
  6             then regexp_replace(s, '^...')
  7             else regexp_replace(s, '^(.)\1|^.')
  8          end
  9     from r
 10    where s is not null)
 11  select listagg(decode(length(r),  2, 'double ',  3, 'triple ') ||
 12                 decode(substr(r, 1, 1), 0, 'oh', to_char(to_date(substr(r, 1, 1), 'j'), 'jsp')), ' ')
 13                 within group (order by rownum)
 14    from (select regexp_replace(s, lag(s) over (order by length(s)) || '$') r
 15            from r order by length(s) desc);
one double nine double nine triple nine one double oh seven nine

L'astuce principale est que les chiffres convertis en mots à l'aide de modèles au format Oracle au lieu de littéraux codés en dur "un" ... ... neuf ".

Dr Y Wit
la source
une chance de jouer au golf? il semble que vous pouvez supprimer un tas d'espaces. J'imagine aussi que vous pouvez réécrire WHERE s n'est pas nul en WHERE s '' '
t-clausen.dk
1
Vous pouvez enregistrer quelques caractères en remplaçant ce qui suit union allpar select regexp_replace(s,case when length(regexp_substr(s, '(.)(\1)+')) = 3 then '^...' else '^(.)\1|^.' end) from r.
Steve Kass
1

JavaScript, 142 octets

s=>s.replace(/(.)(\1\1(?!\1)|\1|)/g,t=>(t[2]?' triple ':t[1]?' double ':' ')+'oh one two three four five six seven eight nine'.split` `[t[0]])

Essayez-le en ligne!

tsh
la source
1

(Roblox) Lua 5.1 , 166 octets

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 sest une valeur de chaîne prédéfinie remplie uniquement de chiffres; ce sera la variable à modifier. Le résultat comprendra un caractère d' espacement [\u20] .

VisualPlugin Rōblox
la source
Bienvenue sur le site! Comme Lua peut prendre des entrées via des méthodes standard , il est contraire aux règles d’exiger sd’avoir déjà l’entrée. En dehors de cela, vous avez un bon premier post! Je vous recommanderais d'inclure un lien vers un site de test en ligne, par exemple tio.run/#lua, afin que d'autres personnes puissent tester votre solution
caird coinheringaahing
Salut. La variante de Lua sur laquelle je testais (Rbx.Lua) ne contient pas de méthodes d'entrée, bien que le bac à sable dispose des méthodes d'impression, d'avertissement et de sortie d'erreur.
VisualPlugin Rōblox