Numero di telefono in parole pronunciate


33

Obbiettivo

Scrivi un programma o una funzione che traduca un numero di telefono numerico in testo che lo rende facile da dire. Quando le cifre vengono ripetute, devono essere lette come "doppia n" o "tripla n".

Requisiti

Ingresso

Una serie di cifre.

  • Supponiamo che tutti i caratteri siano cifre da 0 a 9.
  • Supponiamo che la stringa contenga almeno un carattere.

Produzione

Parole, separate da spazi, di come queste cifre possono essere lette ad alta voce.

  • Traduci le cifre in parole:

    0 "oh"
    1 "uno"
    2 "due"
    3 "tre"
    4 "quattro"
    5 "cinque"
    6 "sei"
    7 "sette"
    8 "otto"
    9 "nove"

  • Quando la stessa cifra viene ripetuta due volte di seguito, scrivi "doppio numero ".

  • Quando la stessa cifra viene ripetuta tre volte di seguito, scrivi " numero triplo ".
  • Quando la stessa cifra viene ripetuta quattro o più volte, scrivere "doppio numero " per le prime due cifre e valutare il resto della stringa.
  • C'è esattamente un carattere spaziale tra ogni parola. È accettabile un singolo spazio iniziale o finale.
  • L'output non fa distinzione tra maiuscole e minuscole.

punteggio

Codice sorgente con il minor numero di byte.

Casi 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

38
Chiunque sia interessato al "golf parlato" dovrebbe notare che "doppio sei" impiega più tempo a dire di "sei sei". Di tutte le possibilità numeriche qui, solo "triple seven" salva sillabe.
Viola P

13
@Purple P: E come sono sicuro che sai, 'double-u double-u double-u'> 'world wide web' ..
Chas Brown

11
Voto per cambiare quella lettera in "doppiaggio".
Hand-E-Food

8
So che questo è solo un esercizio intellettuale, ma ho davanti a me una bolletta del gas con il numero 0800 048 1000, e lo leggerei come "oh ottocento oh quattro ottomila". Il raggruppamento di cifre è significativo per i lettori umani e alcuni modelli come "0800" sono trattati in modo speciale.
Michael Kay,

3
@PurpleP Chiunque sia interessato alla chiarezza del discorso, tuttavia, specialmente quando si parla al telefono, potrebbe voler usare il "doppio 6" poiché è più chiaro che l'altoparlante significa due sei e non ha ripetuto il numero 6 accidentalmente. Le persone non sono robot: P
Scusati e ripristina Monica il

Risposte:


10

05AB1E , 53 52 51 50 49 byte

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

Provalo online!

Spiegazione:

γ                      # 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

1
Oh, Mguarda anche negli elenchi quando si determina il numero intero massimo nello stack? Non lo sapevo. Sembra qualcosa da ricordare. :)
Kevin Cruijssen,

16

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

Binario:

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$

Costruisci e testa l'eseguibile usando xxd -rdall'alto, oppure scarica PHONE.COM .

Elenco non assemblato:

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 stringa di input viene letta da destra a sinistra per facilitare la ricerca di una tripla. L'output viene inserito nello stack x86 per semplificare l'inversione dell'ordine di visualizzazione e facilitare anche la riorganizzazione delle parole "doppia" e "tripla" per precedere il nome della cifra.

Se la cifra successiva è diversa dall'ultima, il nome viene cercato nell'elenco di parole e inserito nello stack. Poiché non esiste un concetto formale di "matrice indicizzata di stringhe a lunghezza variabile" nel codice macchina, l'elenco di parole viene scansionato i(l'indice della parola) numero di volte in cui il delimitatore di stringa ( $) trova la parola corrispondente. Utilmente, x86 ha un paio di brevi istruzioni ( REPNZ SCASBche è simile a memchr()in C), che semplifica questo (grazie CISC !).

Se la cifra è la stessa di quella precedente, il contatore per la lunghezza di una "corsa" viene incrementato e continua a scorrere verso sinistra sull'ingresso. Una volta terminata la corsa, il nome della cifra viene preso dallo stack poiché dovrà essere posizionato dopo il "doppio" o il "triplo" per ciascun raggruppamento. Se la lunghezza della corsa è dispari (e la lunghezza della corsa è > 1), il nome della cifra seguito dalla stringa "triple" viene inserito nello stack e la lunghezza della corsa viene ridotta di 3. Poiché la lunghezza della corsa sarà ora pari, il passaggio viene ripetuto per "double" fino a quando la lunghezza della corsa è 0.

Quando la stringa di input ha raggiunto la fine, lo stack viene scaricato con ciascuna stringa salvata scritta sullo schermo in ordine inverso.

I / O:

Un eseguibile DOS per PC autonomo, input dall'output della riga di comando alla console.

inserisci qui la descrizione dell'immagine

Scarica e prova PHONE.COM .


repne scasbè memchr(o strchrse sai che ci sarà un successo), no strstr.
Peter Cordes,

CH = 0 sulla voce di processo è garantito da uno standard o è proprio quello che succede in qualche versione di DOS? Ho notato che supponi che mov cl, byte[si] sia equivalente a movzx cx, byte [si]. Mi chiedo se usare un reg diverso, come AH, per il conteggio dec ah / jnzinvece di loopsalverebbe qualsiasi cosa dal non dover premere / pop CX. Probabilmente no, e non hai ancora reg a 16 bit che consentirebbe 1 byte dec.
Peter Cordes,

1
@PeterCordes, per il fatto CH=0che vado da fysnet.net/yourhelp.htm , che per ogni ragionevole rilascio di DOS è sempre azzerato, lo stesso con BX. Buona considerazione dell'estensione zero mov, anche se tecnicamente non penso movzxsia disponibile sull'808x (mantenendo la piattaforma di destinazione un PC IBM 5150 e tutti). Ho frugato nel migliore dei modi con tutti i registri per salvare i byte, ma se vedi qualcosa che probabilmente ho perso, per favore fammi sapere!
640 KB

1
È più preciso chiamarlo memchrIMO. La denominazione "istruzione stringa" induce le persone a pensare di lavorare su stringhe C di lunghezza implicita, ma in realtà lavorano su stringhe di lunghezza esplicita come std::stringo buffer. Come memcpy, memset(movs / stos), memchr/ memrchr(repne scas con DF = 0 o 1) e memcmp(repe cmps). L'unico C equivalente repe scasè strspnperché non penso che ci sia una memfunzione per questo. Puoi persino descrivere stoswo stosdcome wmemsetad esempio.
Peter Cordes,

1
movzxcosta un byte di codice operativo aggiuntivo e sì, è stato introdotto solo con 386. È stato più semplice digitare per descrivere il fatto che stai eseguendo un'unione a byte basso e supponendo che sia correttamente zero esteso. Se conosci CX o almeno CH = 0, allora sì per il golf vai sempre mova CL. Ma al di fuori del golf, le istruzioni di caricamento byte di x86 sono movzxe movsx: evitano false dipendenze o altri shenanigans a registro parziale. Sulle CPU moderne con destinazione dword, sono veloci quanto i mov carichi di dword .
Peter Cordes,

9

05AB1E , 61 56 53 52 51 byte

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

-9 byte grazie a @Grimy .

Provalo online o verifica tutti i casi di test .

Spiegazione:

γ               # 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)

Vedi questo mio suggerimento 05AB1E (sezione Come usare il dizionario? ) Per capire perché … ‹¶½¿è " double triple"ed “Šç€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“è "oh two three four five six seven eight nine".


1
@Grimy Ah, certo .. Ho aggiunto il if(length>=4)prima di aggiungere il resto, ma ovviamente non è necessario per numeri interi di dimensioni 1,2,3, perché ;Å2¨3ª£lasceranno intatte le stringhe (semplicemente racchiuse in un elenco che appiattiamo comunque dopo la mappa). Grazie per averlo notato! E non vedo l'ora di vedere la tua risposta Åγ. In effetti ho avuto la sensazione che la prima parte potesse essere fatta molto più breve in qualche modo.
Kevin Cruijssen,

1
Dg;LàäRè ancora un byte più corto di āɨšJõKe molto più simile a quello che avevi originariamente.
Grimmy,

1
@Grimy Ah, questo è davvero chiuso a ciò che inizialmente avevo davvero, mi piace. :) Grazie ancora!
Kevin Cruijssen,

1
@Grimy Sono stato in grado di trovare un altro golf me stesso di cui mi sono dimenticato .. áinvece che õKalla fine. :)
Kevin Cruijssen,

1
Bello trovarlo con á! Ecco un 51 e un altro . 50 sembra possibile.
Grimmy,

7

QuadR , 137 byte SBCS

Caso del titolo con uno spazio iniziale.

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

Provalo online!

ϵ nlist (appiattisci)
¯2↑¨ prende gli ultimi due caratteri (imbottitura a sinistra con uno spazio) di ogni carattere
@ nelle posizioni in cui i
(∊∘⎕A) caratteri sono membri dell'alfabeto A maiuscolo
 nel risultato dell'operazione PCRE Sostituisci di seguito ...

(.) qualsiasi carattere
\1 seguito da se stesso
* zero o più volte, viene sostituito dal risultato del seguente ...

{…}⍵M "DFN"; è il M atch del modello sopra

('OhOneTwoThreeFourFiveSixSevenEightNine'(... )⎕A) applica la seguente funzione tacita anonima con la stringa lunga e l' alfabeto A maiuscolo come argomenti a sinistra:

 appartenenza (di lettere nella stringa lunga dell'alfabeto maiuscolo)

 partizioni (con una nuova partizione che inizia ogni volta che è un membro

 l'argomento sinistro (ovvero la stringa lunga)

(... )⎕R PCRE R eplace i seguenti modelli con queste parole:

⎕D le cifre da 0 a 9

 trattare ciascuno come un modello separato

⍺← assegnare questa funzione di sostituzione a (per un alfabeto)

poi,

⊃⍵ il primo personaggio della partita

, come una stringa

 applicare ad esso

w← assegnare questo a w(per parola )

' '∊... : se lo spazio è un suo membro (ovvero se la corrispondenza era vuota):

 non restituisce nulla (diventa la stringa vuota)

 altro,

1=≢⍵: se si eguaglia il conteggio dei personaggi nella partita (cioè la sua lunghezza):

⍺⍵ alfabetizzare quella cifra

 altro,

3=≢⍵: se tre è uguale al conteggio dei personaggi nella partita (cioè la sua lunghezza):

'Triple',w anteporre "Triple" al w ord

 altro,

2↓⍵ passa alle cifre della partita

 fare affidamento su questo

w, anteporre la parola

'Double', anteponi "Double"


6

JavaScript (ES6),  161 160 152  144 byte

L'output include un unico spazio iniziale.

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

Provalo online!

oppure Vedi il codice sorgente formattato

Come?

La conversione viene elaborata in tre passaggi:

  1. sostituire ogni cifra con la parola inglese corrispondente, preceduta da uno spazio
  2. sostituire ogni motivo "X X"con"double X"
  3. sostituire ogni motivo "double X X"con"triple X"

Per salvare i byte, utilizziamo la stessa espressione regolare per tutti i passaggi:

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

che funziona come segue:

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

Al passaggio 1, utilizziamo una funzione di callback che seleziona la parola corretta da una tabella di ricerca:

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

Al passaggio 2, sostituiamo con "$1 double$2":

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

Al passaggio 3, sostituiamo con "triple$2":

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



3

Python 2 , 171 169 168 byte

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

Provalo online!

-1 byte, grazie a Jitse


Batti di nuovo! Salva 1 byte in questo modo
Jitse il

@Jitse, per cui non funziona 1312;)
TFeld

Ah, hai ragione!
Jitse il

Che ne dici di questo allora: ['','double ','triple '][n]a ' eellpbiurotd'[-n:0:-2]per 168 byte: provalo online!
Jitse il

In alternativa, anche 168 byte
Jitse

3

Perl 5 -p , 111 byte

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

Provalo online!

Spiegazione:

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

1
Rasato alcuni byte: 106
Xcali

3

Scala , 213 byte

Fatto. In qualche modo la versione ricorsiva che stavo cercando di costruire era decisamente più dettagliata di questa (comunque comunque ricorsiva, ma solo in un caso). La funzione fprende come stringa di input il numero di telefono e genera la sua fonetica con uno spazio bianco finale.

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)}})

Provalo online!
modificare : -8b grazie a DrY Wit!

Scala , 215 byte

Ed ecco che arriva la principale versione degli spazi bianchi, due byte in più per qualche motivo (anche con un massiccio 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)-48)
" , double , triple ".split(",")(if(o.length>3){k+=f(o drop 2);1}else o.length-1)+k})

Provalo online!


2
È possibile salvare 8 byte sostituendo (o(0)+"").toIntcon o(0)-48.
Dr Y Wit,

Oof ben fatto @DrYWit grazie!
V. Courtois,

3

PHP , 174 169 166 159 byte

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].' ');

Provalo online!

Per ogni cifra all'indice di $ipartenza da 0:

  • Se l'intervallo della stessa cifra a partire dalla posizione di $iè uguale a 3, stampa 'triple 'e aggiunge 2 a$i sì che l'iterazione successiva salti 2 cifre.
  • Se l'intervallo della stessa cifra a partire dalla posizione di $iè uguale o superiore a 2 ma non è 3, stampa 'double 'e aggiunge 1 a$i successiva iterazione successiva verrà saltata 1 cifra.
  • Stampa la parola per la cifra e uno spazio.
  • $i++.

2

Retina 0.8.2 , 105 byte

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

Provalo online! Emette uno spazio iniziale. Spiegazione: Inizialmente ho provato un regex che corrisponde automaticamente a 2 o 3 cifre, ma l'approccio di @ Arnauld si è rivelato più golfista. Spiegazione:

+`(.)\1
=$1

Abbina coppie di cifre identiche e sostituisci la prima con a =. Quindi ripetere, in modo che per un numero dispari anche la seconda ultima cifra sia sostituita da a =.

.
 $&

Spazio le cifre (e = ).

= =
triple

Gestire il caso di tre cifre identiche.

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

Sostituisci tutti i caratteri rimanenti con le parole.


2

Gelatina , 59 byte

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

Provalo online!

Un collegamento monadico che accetta una stringa di caratteri numerici come argomento e restituisce una stringa Jelly di parole separate da spazio. Se chiamato come programma completo, genera implicitamente.


2

T-SQL 2017, 238 byte

Aggiunti alcuni punti di interruzione per renderlo leggibile

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 @

Provalo online


2

C ++, 382 byte

Non è un superclever, ma qualcuno doveva scrivere una versione C ++. La funzione ricorsiva R passa attraverso la stringa di input e conta i valori ripetuti. Se ci sono più di 3 ripetizioni, finge che ci fossero 2 ripetizioni, quindi riavvolge e riprova.

Qualche altro carattere alla fonte potrebbe probabilmente essere spremuto con i #definemaggiori, ma sono sicuro che un algo migliore potrebbe spremere di più.

#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;
    }
}

e verifica dei casi di 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

1
La parte del golf ha davvero bisogno #include <sstream>? Oppure potresti spostarlo verso il basso dopo la parte golfata per la funzione test? Penso che scriverebbe std::ostream&soccuperebbe meno spazio di using namespace std;, a meno che non ci siano altri posti in cui avresti bisogno di un std::.
Peter Cordes,


2

Perl 6 , 96 93 byte

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

Provalo online!

Questo è un blocco di codice anonimo che accetta un numero e restituisce una stringa con i numeri in maiuscolo, ad es 0123 => oh ONE TWO THREE Con un singolo spazio finale.

Questo è stato cancellato per un po 'fino a quando ho scoperto come utilizzare le acquisizioni in un lookahead, ma ora dovrebbe essere risolto.


1

Rosso , 242 byte

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

Provalo online!


1

Scala , 253 byte

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

Provalo online!


1

Oracle SQL, 578 byte (in formato formattato)

La soluzione non è affatto concisa, quindi pubblicala in modo formattato.

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

Il trucco principale è che le cifre convertite in parole usando i modelli in formato Oracle invece dei letterali hardcoded "uno" ... "nove".


qualche possibilità che questo venga giocato a golf? sembra che puoi rimuovere un mucchio di spazi. Immagino anche che tu possa riscrivere WHERE s non è nullo su WHERE s> ''
t-clausen.dk

1
Puoi salvare alcuni caratteri sostituendo ciò che è dopo union allcon select regexp_replace(s,case when length(regexp_substr(s, '(.)(\1)+')) = 3 then '^...' else '^(.)\1|^.' end) from r.
Steve Kass,

1

JavaScript, 142 byte

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

Provalo online!


1

(Roblox) Lua 5.1 , 166 byte

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

Assicurarsi che ssia un valore di stringa predefinito popolato solo con cifre; quella sarà la variabile da modificare. Il risultato includerà un carattere spazio principale [\u20] .


Benvenuti nel sito! Poiché Lua può accettare input tramite metodi standard , è contro le regole richiedere sdi disporre già dell'input. A parte questo, hai un buon primo post! Ti consiglio di includere un link a un sito di test online, ad esempio tio.run/#lua, in modo che altri possano testare la tua soluzione
caird coinheringaahing

Ciao. La variante di Lua su cui stavo testando (Rbx.Lua) non contiene metodi di input, sebbene il sandbox abbia metodi di output di stampa, avviso ed errore.
VisualPlugin Rōblox il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.