Converter uma sequência de dígitos de palavras em um número inteiro

19

Converta uma sequência contendo dígitos como palavras em um número inteiro, ignorando os zeros à esquerda.

Exemplos

  • "four two"-> 42.
  • "zero zero zero one"-> 1.

Premissas

As submissões podem assumir que:

  1. A sequência de entrada é composta por palavras com dígitos separados por espaço.
  2. Todas as palavras são válidas (no intervalo "zero" .. "nove") e minúsculas. O comportamento para entrada vazia é indefinido.
  3. A sequência de entrada sempre representa um número não assinado dentro do intervalo inte nunca é uma sequência vazia.

Pontuação

As respostas serão pontuadas em bytes, com menos bytes sendo melhores.

Sparkler
fonte
3
Bem vindo ao site. Há algumas coisas que normalmente esperamos de perguntas que faltam aqui. O mais importante seria um critério de pontuação objetivo que todos os desafios devem ter.
Wheat Wizard
3
Além disso, esta questão é muito esparsa na especificação. Você deve especificar exatamente o que é necessário para envios sem ambiguidade. Uma frase e um exemplo simplesmente não estão de acordo com nossos padrões de clareza para desafios.
Wheat Wizard
3
Além do que já foi dito, temos uma caixa de proteção onde os usuários podem postar seus desafios antes de publicá-los no main. Dessa forma, você perderá menos informações ao fazer postagens. Se você olhar para outras postagens recentes no site com uma recepção razoavelmente positiva, acho que verá que tanto sua pergunta quanto sua solução não estão alinhadas com o que fazemos aqui.
FryAmTheEggman 22/09
3
Correndo o risco de ser pedante, gostaria de salientar que range "zero".."nine"não está totalmente especificado.
String não relacionada
4
Irritantemente, o built-in Interpreter@"SemanticNumber"faz exatamente isso no Mathematica - exceto que falha nas strings começando com zero zero .
Greg Martin

Respostas:

22

PHP , 74 bytes

foreach(explode(' ',$argn)as$w)$n.='793251_8640'[crc32($w)%20%11];echo+$n;

Experimente online!

Tentou obter uma solução que não copia respostas existentes. Eu recebo o polinômio da soma de verificação de redundância cíclica de 32 bits ( crc32 ) para cada palavra e, em seguida, faço um mod 20 e um mod 11 para obter valores exclusivos de 0 a 10 (faltando 6) para cada dígito. Então, usando esse valor único, encontro o dígito real.

| Word  | CRC32      | %20 | %11 | Equivalent digit |
|-------|------------|-----|-----|------------------|
| zero  | 2883514770 | 10  | 10  | 0                |
| one   | 2053932785 | 5   | 5   | 1                |
| two   | 298486374  | 14  | 3   | 2                |
| three | 1187371253 | 13  | 2   | 3                |
| four  | 2428593789 | 9   | 9   | 4                |
| five  | 1018350795 | 15  | 4   | 5                |
| six   | 1125590779 | 19  | 8   | 6                |
| seven | 2522131820 | 0   | 0   | 7                |
| eight | 1711947398 | 18  | 7   | 8                |
| nine  | 2065529981 | 1   | 1   | 9                |

Outra alternativa CRC32 de 74 bytes usando %493%10:Experimente online!

Outra alternativa CRC32 de 74 bytes usando %2326%11: Experimente online!


PHP , 74 bytes

foreach(explode(' ',$argn)as$w)$n.=strpos(d07bfe386c,md5($w)[21]);echo+$n;

Experimente online!

Outra alternativa com o mesmo comprimento, pega o 22º caractere md5da palavra (único caractere que fornece um valor único para cada palavra) e depois usa esse caractere para mapear para um dígito.

Night2
fonte
Esta é uma resposta legal
Juan Sebastian Lozano
9

Python 2 ,  71  70 bytes

-1 graças a ovs (use findno lugar de index)

lambda s:int(''.join(`'rothuvsein'.find((w*3)[6])`for w in s.split()))

Experimente online!

Jonathan Allan
fonte
7

JavaScript (ES6),  70 67 66  62 bytes

Guardado 3 bytes graças a @ovs

s=>+s.replace(/\w+ ?/g,s=>'2839016547'[parseInt(s,36)%204%13])

Experimente online!

Arnauld
fonte
1
'2839016547'[parseInt(s,36)%204%13]é 3 bytes mais curto.
ovs 22/09
6

Geléia ,  19  17 bytes

Ḳµ7ị“*;nÄƲ]³Ṙ»i)Ḍ

Um link monádico que aceita uma lista de caracteres que gera um número inteiro.

Experimente online!

Praticamente uma porta da minha resposta Python 2.


Anterior

ḲŒ¿€i@€“©¥q£½¤MÆÑ‘Ḍ

Experimente online!

muito possivelmente um caminho mais curto, mas esta é uma maneira que primeiro me veio à mente.

Jonathan Allan
fonte
Remover zero da string enklact para evitar decrementar, porque não encontrado é zero de qualquer maneira ... inteligente!
String não relacionada
1
Ah, eu vejo que você fez o mesmo método, legal.
Jonathan Allan
5

Python 3 , 107 , 91 , 77 , 90 bytes

-16 bytes por Sriotchilism O'Zaic

+13 bytes para remover os zeros iniciais

lambda s:int(''.join(map(lambda w:str('zeontwthfofisiseeini'.index(w[:2])//2),s.split())))

Experimente online!

movatica
fonte
Agradável! Dessa forma, posso até eliminar completamente o delimitador :)
movatica 22/09
1
Com as atualizações para o desafio, isso não é mais válido, pois inclui zeros à esquerda. :(
Wheat Wizard
1
@movatica Sua correção está incorreta. O lstripmétodo retira todos os caracteres da string que são dados como argumento, portanto, "oito dois" se torna "dois dois", à medida que "e" é retirado. Além disso, "zero zero zero" deve imprimir "0", não cometer um erro.
NemPlayer 22/09
5

Perl 6 , 35 32 bytes

{+uniparse 'SP'~S:g/<</,DIGIT /}

Experimente online!

Explicação

{                              }  # Anonymous block
                S:g/<</,DIGIT /   # Insert ",DIGIT " at
                                  # left word boundaries
           'SP'~  # Prepend 'SP' for space
  uniparse  # Parse list of Unicode names into string
 +  # Convert to integer
Nwellnhof
fonte
5

C (gcc) , 89 bytes

i,n;f(char*w){for(i=n=0;n=*w%32?n^*w:(i+=n-2)&&!printf(L"8 0  72 3  59641"+n%17),*w++;);}

Experimente online!

Graças aos truques mais inteligentes do @Ceilingcat:

- printf instead of putchar.   
- !printf instead of printf()&0. 
- And wide char !
AZTECCO
fonte
3

05AB1E , 18 16 bytes

#ε6è}.•ƒ/ÿßÇf•Åβ

Experimente online.

Explicação:

#                 # Split the (implicit) input-string on spaces
 ε  }             # Map each string to:
  6è              #  Get the character at 0-based index 6 (with automatic wraparound)
     .•ƒ/ÿßÇf    # Push compressed string "rothuvsein"
              Åβ  # Convert the characters from custom base-"rothuvsein" to an integer
                  # (after which the top of the stack is output implicitly as result)

Veja este 05AB1E ponta do meu (seção Como cordas compressa não fazem parte do dicionário? ) Para entender por que .•ƒ/ÿßÇf•é "rothuvsein".

Kevin Cruijssen
fonte
3

05AB1E , 17 16 bytes

•D±¾©xWÄ0•I#HèTβ

Experimente online!

Laço perfeito com a outra resposta 05AB1E , mas usando uma abordagem completamente diferente.

•D±¾©xWÄ0•               # compressed integer 960027003010580400
          I#             # split the input on spaces
            H            # convert each word from hex (eg "one" => 6526)
             è           # index (with wrap-around) into the digits of the large integer
              Tβ         # convert from base 10 to integer
Grimmy
fonte
3

Retina 0.8.2 , 46 45 bytes

\w+
¶$&$&$&
%7=T`r\ot\huvs\ein`d`.
\D

^0+\B

Experimente online! O link inclui casos de teste. Explicação:

\w+
¶$&$&$&

Coloque cada palavra em sua própria linha e triplique-a.

%7=T`r\ot\huvs\ein`d`.

Transliterar o sétimo caractere de cada linha usando a string de @ UnrelatedString.

\D

Exclua todos os caracteres restantes que não são dígitos.

^0+\B

Exclua zeros à esquerda (mas deixe pelo menos um dígito).

Solução tradicional de 46 bytes anterior:

T`z\wuxg`E
on
1
th
3
fi
5
se
7
ni
9
\D

^0+\B

Experimente online! O link inclui casos de teste. Explicação:

T`z\wuxg`E

As palavras zero, two, four, sixe eightconter unicamente as letras zwuxg. Transliterar para os dígitos pares.

on
1
th
3
fi
5
se
7
ni
9

Para os dígitos ímpares, basta combinar as duas primeiras letras de cada palavra individualmente.

\D

Exclua todos os caracteres restantes que não são dígitos.

^0+\B

Exclua zeros à esquerda (mas deixe pelo menos um dígito).

Neil
fonte
2

Geléia , 20 18 17 bytes

Ḳ7ị“*;nÄƲ]³Ṙ»iƲ€Ḍ

Experimente online!

-2 bytes da execução de "rothuvsein" através do compressor de string do user202729 .

-1 byte de roubar a sequência de enklact livre de zero de Jonathan Allan e colocá-la em um programa de estrutura marginalmente diferente.

Ḳ                    Split the input on spaces,
              Ʋ€     for each word
             i       find the 1-based index (defaulting to 0)
   “*;nÄƲ]³Ṙ»        in "othuvsein"
 7ị                  of the element at modular index 7,
                Ḍ    and convert from decimal digits to integer.
String não relacionada
fonte
2

C ++ (gcc) , 478 218 142 bytes

- (muito) graças a Jo King

int f(string s){char c[]="N02K8>IE;6";int i=0,n=0;while(s[i]){n=n*10-1;while((s[i]^s[i+1])+47!=c[++n%10]);while(s[i++]!=' '&&s[i]);}return n;}

Experimente online!

Sparkler
fonte
1
127 bytes
ceilingcat 23/09
2

Japonês , 13 bytes

¸mg6 ì`Ψuv 

Tente

Parece que todo mundo me seguiu com a mesma idéia - poderia ter me poupado do trabalho de escrever um script para forçar a corda ideal para a compressão, apenas para descobrir que, até o índice 1,000,000(era cedo, eu não tinha o meu cafeína ainda!), "rothuvsein" é a única sequência possível!

¸mg6 ì`...     :Implicit input of string
¸              :Split on spaces
 m             :Map
  g6           :  Character at index 6 (0-based, with wrapping)
     ì         :Convert from digit array in base
      `...     :  Compressed string "rothuvsein"

A seqüência de comprimido contém os caracteres de codepoints 206, 168, 117, 118, 160e 136.

Shaggy
fonte
1
... você realmente tentou até 1000000? O lcm dos comprimentos dos nomes dos dígitos é 60, então não há sentido em tentar além disso (60 é equivalente a 0, 61 a 1, etc).
Grimmy 23/09
1
@ Grimy, era cedo, eu não tinha tomado minha cafeína ainda! Conectar um milhão ao script que escrevi para gerar todas as possibilidades foi tão fácil quanto qualquer outro número e me salvou na matemática no LCM.
Shaggy
2

Ruby , 63 bytes , 52 bytes , 50 bytes

p $*.map{|d|'rothuvsein'.index (d*3)[6]}.join.to_i

-2 graças ao valor da ponta da tinta

Harrowed
fonte
Bem-vindo ao Code Golf! No Ruby, $*é um apelido para ARGV, então fique à vontade para usá-lo para salvar bytes extras.
Value Ink
2

T-SQL, 110 bytes

SELECT 0+STRING_AGG(CHARINDEX(LEFT(value,2),'_ontwthfofisiseeini')/2,'')
FROM STRING_SPLIT((SELECT*FROM i),' ')

A quebra de linha é apenas para legibilidade.

A entrada é obtida via tabela Eu, de acordo com nossas regras de IO . Eu poderia ter economizado 14 bytes preenchendo previamente uma variável de string, mas isso só é permitido se o idioma não tiver outros métodos de entrada.

Explicação:

  1. STRING_SPLIT pega a string de entrada e a separa nos espaços
  2. CHARINDEXpega os 2 primeiros caracteres e retorna a posição (com base em 1) na string '_ontwthfofisiseeini'.'ze'para zero não está na cadeia e retorna 0 para "não encontrado". O sublinhado garante que obtemos apenas múltiplos de dois.
  3. Divida por 2 para obter o número final
  4. STRING_AGG esmaga os dígitos novamente sem separador
  5. 0+força uma conversão implícita em INT e elimina quaisquer zeros à esquerda. 1*também funcionaria.
BradC
fonte
2

código de máquina x86, 46 bytes

Hexdump:

57 53 33 c0 33 ff f6 01 0f 75 15 6a 0a 5b 99 f7
f3 6b ff 0a 03 fa 33 c0 38 01 75 0f 97 5b 5f c3
69 c0 26 2b aa 6e 32 01 c1 e8 02 41 eb d8

É uma fastcallfunção - recebe um ponteiro para a string ecxe retorna o resultado eax.

A função hash se multiplica por um número mágico 1856645926, faz umXOR com byte de entrada e muda para a direita em 2 bits.

Salvar e restaurar registros noclobber ( edie ebx) levou 4 bytes, mas não encontrei uma maneira mais eficiente de implementar isso. Armazenando a constante 10 emebx foi particularmente irritante!

Desmontagem com os bytes de código correspondentes:

57                   push        edi  ; edi = result
53                   push        ebx  ; we use ebx to store the constant 10
33 C0                xor         eax,eax  
33 FF                xor         edi,edi  
    myloop:
F6 01 0F             test        byte ptr [ecx],0Fh  ; check for end of word
75 15                jne         myhash
6A 0A                push        0Ah  
5B                   pop         ebx  
99                   cdq              ; prepare 64-bit dividend in edx:eax
F7 F3                div         eax,ebx  ; find the remainder of division by 10
6B FF 0A             imul        edi,edi,0Ah
03 FA                add         edi,edx  ; update the result
33 C0                xor         eax,eax  ; reset the hash temporary variable
38 01                cmp         byte ptr [ecx],al  ; check for end of input (here al=0)
75 0F                jne         mycontinue
97                   xchg        eax,edi  ; set the return register
5B                   pop         ebx  ; restore registers
5F                   pop         edi  ; restore registers
C3                   ret  
    myhash:
69 C0 26 2B AA 6E    imul        eax,eax,6EAA2B26h  ; hashing...
32 01                xor         al,byte ptr [ecx]  ; hashing...
C1 E8 02             shr         eax,2  ; hashing...
    mycontinue:
41                   inc         ecx  ; next input byte
EB D8                jmp         myloop

Código C equivalente:

int doit(const char* s)
{
    int result = 0;
    unsigned temp = 0;
    while (true)
    {
        int c = *s++;
        if ((c & 15) == 0)
        {
            temp %= 10;
            result = result * 10 + temp;
            temp = 0;
            if (c == 0)
                break;
            else
                continue;
        }
        temp *= 1856645926;
        temp ^= c;
        temp >>= 2;
    }
    return result;
}
anatolyg
fonte
Como você encontrou os números mágicos?
Sparkler em
Fiz uma pesquisa usando meu código C - tentei todos os números de 32 bits e todos os turnos. Existem apenas algumas possibilidades - o código encontrou apenas uma no intervalo até 2000000000.
anatolyg
você pode usar edx em vez de edi (pressione edx antes do idiv, pop eax depois dele, imul com ebx, adicione eax ao edx) para salvar um byte.
peter ferrie 28/09
1

J , 38 bytes

('b\e~mjPxw['i.[:u:70+1#.15|3&u:)&>@;:

Experimente online!

Jonah
fonte
1

Carvão , 19 bytes

I⍘⭆⪪S §ι⁶rothuvsein

Experimente online! Link é a versão detalhada do código. Porto da resposta 05AB1E de @ KevinCruijssen. Explicação:

    S               Input string
   ⪪                Split on spaces
  ⭆                 Map over words and join
       ι            Current word
      §             Cyclically indexed
        ⁶           Literal `6`
 ⍘       rothuvsein Custom base conversion
I                   Cast to string for implicit print
Neil
fonte
1

PowerShell , 48 bytes

+-join($args|%{'rothuvsein'.indexof(($_*3)[6])})

Experimente online!

Usa o mesmo rothuvseintruque que outros, graças a Jonathan Allan. Espera argumentos de entrada via splatting, que no TIO se manifesta como argumentos separados da linha de comandos.

AdmBorkBork
fonte
1

Kotlin, 83 bytes

fun String.d()=split(' ').fold(""){a,b->a+"rothuvsein".indexOf((b+b+b)[6])}.toInt()

+1 byte, se você deseja oferecer suporte a longos toLong()

O mesmo truque rothuvsein que os outros, economizando alguns bytes preciosos graças ao agradável toInt()e kotlin fold(). Eu simplesmente não consigo abalar a sensação de que mais alguns bytes podem ser removidos ...

Alex Papageorgiou
fonte
1

sed -re , 78 bytes

s/three/3/g;s/five/5/g;s/\w\w(\w)\w*/\1/g;s/ //g;y/eouxvgnr/12467890/;s/^0*//
Herzausrufezeichen
fonte
1

Lote do Windows, 169 bytes

@setlocal enabledelayedexpansion
@set z=zeontwthfofisiseeini
:a
@set b=%1
@for /l %%c in (0,2,18)do @if "!b:~0,2!"=="!z:~%%c,2!" set/aa=a*10+%%c/2&shift&goto a
@echo %a%
Peter Ferrie
fonte
0

VBA, 160 bytes

Function e(s)
s = Split(s, " ")
For i = LBound(s) To UBound(s)
s(i) = Int((InStr("ontwthfofisiseeini", Left(s(i), 2)) + 1) / 2)
Next
e = Val(Join(s, ""))
End Function

Corresponde aos dois primeiros caracteres de uma sequência, zero excluído.

user3819867
fonte
0

BaCon , 83 72 bytes

Supondo que a string seja fornecida em w $, esse código consulta o índice em "zeontwthfisiseeini" usando uma expressão regular com base nos 2 primeiros caracteres exclusivos de cada palavra. O índice é então dividido por 2, fornecendo o resultado correto.

FOR x$ IN w$:r=r*10+REGEX("zeontwthfofisiseeini",LEFT$(x$,2))/2:NEXT:?r
Pedro
fonte