Número de telefone em palavras faladas


33

Objetivo

Escreva um programa ou função que traduza um número de telefone numérico em texto que facilite a digitação. Quando os dígitos são repetidos, eles devem ser lidos como "duplo n" ou "triplo n".

Exigências

Entrada

Uma sequência de dígitos.

  • Suponha que todos os caracteres sejam dígitos de 0 a 9.
  • Suponha que a string contenha pelo menos um caractere.

Saída

Palavras, separadas por espaços, de como esses dígitos podem ser lidos em voz alta.

  • Traduzir dígitos para palavras:

    0 "oh"
    1 "um"
    2 "dois"
    3 "três"
    4 "quatro"
    5 "cinco"
    6 "seis"
    7 "sete"
    8 "oito"
    9 "nove"

  • Quando o mesmo dígito for repetido duas vezes seguidas, escreva " número duplo ".

  • Quando o mesmo dígito for repetido três vezes seguidas, escreva " número triplo ".
  • Quando o mesmo dígito for repetido quatro ou mais vezes, escreva " número duplo " para os dois primeiros dígitos e avalie o restante da string.
  • Há exatamente um caractere de espaço entre cada palavra. Um único espaço à esquerda ou à direita é aceitável.
  • A saída não diferencia maiúsculas de minúsculas.

Pontuação

Código fonte com o mínimo de bytes.

Casos de teste

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
Qualquer pessoa interessada em "discurso de golfe" deve observar que "seis em dobro" leva mais tempo para dizer do que "seis seis". De todas as possibilidades numéricas aqui, apenas o "triplo sete" salva sílabas.
Purple P

13
@ Roxo P: E como eu tenho certeza que você sabe, 'double-u double-u double-u'> 'world wide web' ..
Chas Brown

11
Eu voto para mudar essa carta para "dub".
Hand-E-Food

8
Sei que este é apenas um exercício intelectual, mas tenho na minha frente uma conta de gás com o número 0800 048 1000, e leria isso como "oh oitocentos oh quatro oito mil". O agrupamento de dígitos é significativo para os leitores humanos, e alguns padrões como "0800" são tratados especialmente.
Michael Kay

3
@PurpleP Qualquer pessoa interessada em clareza de fala, no entanto, especialmente ao falar por telefone, pode querer usar o "duplo 6", pois é mais claro que o falante significa dois seis e não repetiu o número 6 acidentalmente. As pessoas não são robôs: P
Desculpe

Respostas:


10

05AB1E , 53 52 51 50 49 bytes

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

Experimente online!

Explicação:

γ                      # 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
Ah, Mtambém olha dentro de listas ao determinar o número máximo máximo na pilha? Não sabia disso. Parece algo para lembrar. :)
Kevin Cruijssen

16

Conjunto 8088, IBM PC DOS, 164 159 156 155 bytes

Binário:

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$

Crie e teste o executável usando a xxd -rpartir de cima ou faça o download do PHONE.COM .

Listagem desmontada:

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:

A sequência de entrada é lida da direita para a esquerda para facilitar a localização de um triplo. A saída é enviada para a pilha x86 para simplificar a reversão da ordem de exibição e também facilitar a reorganização das palavras "dupla" e "tripla" para preceder o nome do dígito.

Se o próximo dígito for diferente do último, o nome será procurado na lista de palavras e empurrado para a pilha. Como não existe um conceito formal de uma "matriz indexada de seqüências de comprimento variável" no código da máquina, a lista de palavras é varrida i(o índice da palavra) quantas vezes o delimitador ( $) encontra a palavra correspondente. Felizmente, o x86 possui um par de instruções curtas ( REPNZ SCASBque são semelhantes a memchr()C), que simplificam isso (obrigado CISC !).

Se o dígito for o mesmo que o anterior, o contador para a duração de uma "execução" é incrementado e continua em loop para a esquerda na entrada. Depois que a execução termina, o nome do dígito é retirado da pilha, pois ele deve ser colocado após o "duplo" ou "triplo" para cada agrupamento. Se a duração da execução for ímpar (e a duração da execução for > 1), o nome do dígito seguido pela string "triple" será empurrado para a pilha e a duração da execução será reduzida em 3. Como a duração da execução agora será regular, a etapa é repetido para "double" até que o comprimento da execução seja 0.

Quando a sequência de entrada chega ao fim, a pilha é despejada com cada sequência salva gravada na tela em ordem inversa.

E / S:

Um executável autônomo do PC DOS, entrada da saída da linha de comando para o console.

insira a descrição da imagem aqui

Faça o download e teste o PHONE.COM .


repne scasbé memchr(ou strchrse você sabe que haverá um sucesso), não strstr.
Peter Cordes

CH = 0 na entrada do processo é garantido por um padrão ou é exatamente isso que uma versão do DOS faz? Percebo que você assume que isso mov cl, byte[si] é equivalente a movzx cx, byte [si]. Gostaria de saber se usando um reg diferente, como AH, para a contagem com em dec ah / jnzvez de loopsalvar qualquer coisa de não ter que pressionar / pop CX. Provavelmente não, e você não tem nenhum registro de 16 bits que permita 1 byte dec.
Peter Cordes

1
@ PeterCordes, pelo que CH=0eu vou em fysnet.net/yourhelp.htm , que para qualquer versão razoável do DOS é sempre zerado, o mesmo com BX. Bom pensamento sobre a extensão zero mov, embora tecnicamente eu não ache que movzxesteja disponível no 808x (mantendo a plataforma de destino um IBM PC 5150 e tudo mais). Eu brinquei com todos os registros da melhor maneira possível para salvar os bytes, mas se você vir algo que provavelmente perdi, por favor me avise!
640KB 16/08

1
É mais preciso chamá-lo de memchrIMO. O nome da "instrução de string" leva as pessoas a pensarem que trabalham em strings C de comprimento implícito, mas na verdade elas trabalham em strings de comprimento explícito, como std::stringbuffers. Como memcpy, memset(movs / stos), memchr/ memrchr(repne scas com DF = 0 ou 1) e memcmp(reppe cmps). O único equivalente em C repe scasé strspnporque eu não acho que exista uma memfunção para isso. Você pode até descrever stoswou stosdcomo wmemsetpor exemplo.
Peter Cordes

1
movzxcusta um byte extra de opcode e, sim, foi introduzido apenas com 386. Era mais fácil digitar para descrever o fato de que você está fazendo uma mesclagem de baixo byte e assumindo que ele é estendido corretamente a zero. Se você conhece CX ou pelo menos CH = 0, então sim para o golfe sempre vá movpara CL. Mas, fora do golfe, as instruções de carregamento de bytes do x86 são movzxe movsx: evitam dependências falsas ou outras travessuras de registro parcial. Em CPUs modernas com um destino dword, elas são tão rápidas quanto as mov cargas dword .
Peter Cordes

9

05AB1E , 61 56 53 52 51 bytes

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

-9 bytes graças a @Grimy .

Experimente online ou verifique todos os casos de teste .

Explicação:

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

Veja esta dica 05AB1E (seção Como usar o dicionário? ) Para entender por que … ‹¶½¿é " double triple"e “Šç€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š“é "oh two three four five six seven eight nine".


1
@ Grimy Ah, é claro ... eu adicionei o if(length>=4)antes de adicionar o restante, mas é claro que não é necessário números inteiros de tamanho 1,2,3, porque ;Å2¨3ª£isso deixará as cordas intactas (apenas envoltas em uma lista que nivelamos após o mapa). Obrigado por perceber! E ansioso para ver sua resposta com Åγ. Eu realmente tive a sensação de que a primeira parte poderia ser feita muito mais curta de alguma forma.
Kevin Cruijssen 13/08

1
Dg;LàäRainda é um byte menor āɨšJõKe muito mais parecido com o que você tinha originalmente.
Grimmy

1
@ Grimy Ah, isso é realmente fechado para o que eu realmente tinha de fato, eu gosto. :) Obrigado novamente!
Kevin Cruijssen 13/08

1
@ Grimy Consegui encontrar mais um golfe que eu esqueci .. em ávez de õKno final. :)
Kevin Cruijssen 13/08

1
Nice encontrar com á! Aqui está um 51 e outro . 50 parece possível.
Grimmy

7

QuadR , 137 bytes SBCS

Título com um espaço à esquerda.

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

Experimente online!

ε nlist (flatten)
¯2↑¨ tomar os dois últimos caracteres (preenchimento à esquerda com um espaço) de cada caracteres
@ em posições onde
(∊∘⎕A) personagens são membros da maiúscula A lphabet
 no resultado da operação abaixo PCRE Substituir ...

(.) qualquer caractere
\1 seguido por si mesmo
* zero ou mais vezes, é substituído pelo resultado da seguinte…

{…}⍵M "dfn"; é o M atch do padrão acima

('OhOneTwoThreeFourFiveSixSevenEightNine'(... )⎕A) aplicar a seguinte função tácita anônimo com a cadeia longa ea maiúscula A lphabet como argumentos de esquerda:

 associação (de letras na cadeia longa no alfabeto maiúsculo)

 partições (com uma nova partição começando sempre que um membro

 o argumento esquerdo (ou seja, a cadeia longa)

(... )⎕R PCRE R EColoque os seguintes padrões com essas palavras:

⎕D os dígitos de 0 a 9

 tratar cada um como um padrão separado

⍺← atribuir esta função de substituição a (para um lphabetise)

então,

⊃⍵ o primeiro caractere da partida

, como uma corda

 aplicar a ele

w← atribuir isso a w(por palavra )

' '∊: Se o espaço for um membro do mesmo (ou seja, se a partida estiver vazia):

 retornar nada (torna-se a string vazia)

 outro,

1=≢⍵: se alguém igualar a contagem de caracteres na partida (ou seja, seu comprimento):

⍺⍵ alfabetize esse dígito

 outro,

3=≢⍵: se três for igual à contagem de caracteres na partida (ou seja, seu comprimento):

'Triple',w prepend "Triple" ao w ord

 outro,

2↓⍵ cair para dígitos da partida

 recuar sobre isso

w, preceda a palavra

'Double', preceder "Duplo"


6

JavaScript (ES6),  161 160 152  144 144 bytes

A saída inclui um único espaço à esquerda.

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

Experimente online!

ou Veja o código fonte formatado

Quão?

A conversão é processada em três etapas:

  1. substitua cada dígito pela palavra correspondente em inglês, precedida por um espaço
  2. substitua cada padrão "X X"por"double X"
  3. substitua cada padrão "double X X"por"triple X"

Para salvar bytes, usamos a mesma expressão regular para todas as etapas:

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

que funciona da seguinte maneira:

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

Na etapa 1, usamos uma função de retorno de chamada que seleciona a palavra correta em uma tabela de pesquisa:

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

Na etapa 2, substituímos por "$1 double$2":

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

Na etapa 3, substituímos por "triple$2":

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



3

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

Experimente online!

-1 byte, graças ao Jitse


Me bata de novo! Salvar 1 byte como assim
Jitse

@Jitse, isso não funciona para 1312;)
TFeld 13/08

Ah, você está certo!
Jitse 13/08

Que tal um presente, então: ['','double ','triple '][n]a ' eellpbiurotd'[-n:0:-2]de 168 bytes: Experimente online!
Jitse 13/08

Como alternativa, também 168 bytes
Jitse

3

Perl 5 -p , 111 bytes

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

Experimente online!

Explicação:

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


3

Scala , 213 bytes

Consegui. De alguma forma, a versão recursiva que eu estava tentando criar era muito mais detalhada do que esta (ainda que recursiva, mas apenas em um caso). A função fpega como string de entrada o número de telefone e gera sua fonética com um espaço em branco à direita.

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

Experimente online!
Edit : -8b graças a DrY Wit!

Scala , 215 bytes

E aqui vem a versão líder em espaço em branco, dois bytes a mais por algum motivo (mesmo com refatoração massiva).

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

Experimente online!


2
Você pode salvar 8 bytes substituindo (o(0)+"").toIntpor o(0)-48.
Dr Y Wit

Oof bem feito @DrYWit obrigado!
V. Courtois

3

PHP , 174 169 166 159 bytes

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

Experimente online!

Para cada dígito no índice a $ipartir de 0:

  • Se o intervalo do mesmo dígito começar na localização de $i for igual a 3, imprime 'triple 'e adiciona 2 à $ipróxima iteração, com 2 dígitos saltados.
  • Se o intervalo do mesmo dígito, começando na localização de, $ifor igual ou superior a 2, mas não 3, imprime'double ' e adiciona 1 à $ipróxima iteração, com 1 dígito saltado.
  • Imprime a palavra para o dígito e um espaço.
  • $i++.

2

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

Experimente online! Gera um espaço à esquerda. Explicação: Eu tentei originalmente um regex que corresponde automaticamente a 2 ou 3 dígitos, mas a abordagem de @ Arnauld acabou por ser mais golfista. Explicação:

+`(.)\1
=$1

Combine pares de dígitos idênticos e substitua o primeiro por a =. Em seguida, repita para que, para um número ímpar, o segundo último dígito também seja substituído por um= .

.
 $&

Espace os dígitos =.

= =
triple

Manuseie a caixa de três dígitos idênticos.

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

Substitua todos os caracteres restantes por palavras.


2

Geléia , 59 bytes

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

Experimente online!

Um link monádico que usa uma sequência de caracteres de dígitos como argumento e retorna uma sequência Jelly de palavras separadas por espaço. Quando chamado como um programa completo, gera implicitamente.


2

T-SQL 2017, 238 bytes

Adicionadas algumas quebras de linha para torná-lo legível

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 @

Experimente online


2

C ++, 382 bytes

Não é super inteligente, mas alguém precisava escrever uma versão em C ++. A função recursiva R passa pela string de entrada e conta valores repetidos. Se houver mais de 3 repetições, ele fingirá que houve 2 repetições, depois retrocederá e tentará novamente.

Mais alguns caracteres de origem provavelmente poderiam ser extraídos com #definemajor, mas tenho certeza de que algo melhor poderia extrair mais.

#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ção de casos de teste:

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
A parte golfada realmente precisa #include <sstream>? Ou você poderia movê-lo para baixo após a parte do golfe para a função de teste? Eu acho que digitar std::ostream&slevaria menos espaço do que using namespace std;, a menos que haja outros lugares onde você precisaria std::.
Peter Cordes


2

Perl 6 , 96 93 bytes

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

Experimente online!

Este é um bloco de código anônimo que pega um número e retorna uma string com os números em maiúsculas, por exemplo 0123 => oh ONE TWO THREE com um único espaço à direita.

Isso foi excluído por um tempo até eu descobrir como usar capturas em um lookahead, mas deve ser corrigido agora.


1

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

Experimente online!


1

Scala , 253 bytes

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

Experimente online!


1

Oracle SQL, 578 bytes (em formato formatado)

A solução não é concisa de forma alguma, portanto, publique-a de maneira formatada.

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

Teste no 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

O principal truque é que os dígitos são convertidos em palavras usando modelos no formato Oracle, em vez de literais codificados "um" ... "nove".


alguma chance de isso ser jogado golfe? parece que você pode remover vários espaços. Eu também imagino que você pode reescrever WHERE s não é nulo para WHERE s> ''
t-clausen.dk

1
Você pode salvar alguns caracteres substituindo o que está depois union allpor select regexp_replace(s,case when length(regexp_substr(s, '(.)(\1)+')) = 3 then '^...' else '^(.)\1|^.' end) from r.
Steve Kass

1

JavaScript, 142 bytes

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

Experimente online!


1

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

Garantir sé um valor de sequência predefinido preenchido apenas com dígitos; essa será a variável a ser modificada. O resultado incluirá um caractere de espaço inicial [\u20] .


Bem vindo ao site! Como Lua pode receber informações por métodos padrão , é contra as regras exigir sque você já tenha as informações. Além disso, você tem um bom primeiro post! Eu recomendaria que você incluísse um link para um site de testes on-line, por exemplo, tio.run/#lua, para que outros possam testar sua solução
caird coinheringaahing

Oi. A variante de Lua em que eu estava testando (Rbx.Lua) não contém métodos de entrada, embora a sandbox tenha métodos de impressão, aviso e erro.
VisualPlugin Rōblox
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.