Convierte una cadena de dígitos de palabras a un entero

19

Convierta una cadena que contenga dígitos como palabras en un número entero, ignorando los ceros iniciales.

Ejemplos

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

Supuestos

Las presentaciones pueden suponer que:

  1. La cadena de entrada se compone de palabras de dígitos separados por espacios.
  2. Todas las palabras son válidas (en el rango "cero" .. "nueve") y en minúsculas. El comportamiento de la entrada vacía no está definido.
  3. La cadena de entrada siempre representa un número sin signo dentro del rango de inty nunca es una cadena vacía.

Puntuación

Las respuestas se puntuarán en bytes, siendo menos bytes mejores.

Bengala
fuente
3
Bienvenido al sitio. Hay un par de cosas que generalmente esperamos de las preguntas que faltan aquí. Lo más importante sería un criterio de puntuación objetivo que todos los desafíos deben tener.
Wheat Wizard
3
Aparte de eso, esta pregunta es muy escasa en cuanto a especificaciones. Debe especificar exactamente lo que se requiere de las presentaciones sin ambigüedad. Una oración y un ejemplo no están a la altura de nuestros estándares de claridad para los desafíos.
Wheat Wizard
3
Además de lo que ya se ha dicho, tenemos un sandbox donde los usuarios pueden publicar sus desafíos antes de publicarlos en main. De esa manera, perderá menos información al hacer publicaciones. Si mira otras publicaciones recientes en el sitio con una recepción razonablemente positiva, creo que verá que tanto su pregunta como su solución no coinciden con lo que hacemos aquí.
FryAmTheEggman
3
A riesgo de ser pedante, me gustaría señalar que range "zero".."nine"no está completamente especificado.
Cadena no relacionada
44
Molesto, el incorporado Interpreter@"SemanticNumber"hace exactamente esto en Mathematica, excepto que falla en cadenas que comienzan con zero zero .
Greg Martin el

Respuestas:

22

PHP , 74 bytes

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

Pruébalo en línea!

Intenté obtener una solución que no copie las respuestas existentes. Obtengo un polinomio de suma de verificación de redundancia cíclica de 32 bits de longitud ( crc32 ) para cada palabra y luego hago un mod 20 y un mod 11 para mezclar valores únicos de 0 a 10 (faltan 6) para cada dígito. Luego, usando ese valor único, encuentro el 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                |

Otra alternativa de 74 bytes CRC32 usando %493%10: ¡ Pruébelo en línea!

Otra alternativa de 74 bytes CRC32 usando %2326%11: ¡ Pruébelo en línea!


PHP , 74 bytes

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

Pruébalo en línea!

Otra alternativa con la misma longitud, toma el carácter 22 en la md5palabra (único carácter que le da un valor único para cada palabra) y luego usa ese carácter para mapear a un dígito.

Noche2
fuente
Esta es una respuesta genial
Juan Sebastian Lozano
9

Python 2 ,  71  70 bytes

-1 gracias a ovs (uso finden lugar de index)

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

Pruébalo en línea!

Jonathan Allan
fuente
7

JavaScript (ES6),  70 67 66  62 bytes

Guardado 3 bytes gracias a @ovs

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

Pruébalo en línea!

Arnauld
fuente
1
'2839016547'[parseInt(s,36)%204%13]es 3 bytes más corto.
ovs
6

Jalea ,  19  17 bytes

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

Un enlace monádico que acepta una lista de caracteres que produce un número entero.

Pruébalo en línea!

Más o menos un puerto de mi respuesta Python 2.


Anterior

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

Pruébalo en línea!

Hay muy posiblemente un camino más corto, pero esta es una manera de que primero vino a la mente.

Jonathan Allan
fuente
Eliminar cero de la cadena de enklact para evitar la disminución, porque de todos modos no se encuentra cero ... ¡listo!
Cadena no relacionada
1
Ah, veo que hiciste el mismo método, bien.
Jonathan Allan
5

Python 3 , 107 , 91 , 77 , 90 bytes

-16 bytes por Sriotchilism O'Zaic

+13 bytes para eliminar los ceros a la izquierda

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

Pruébalo en línea!

movatica
fuente
¡Buena esa! De esa manera, incluso puedo soltar el delimitador por completo :)
movatica
1
Con las actualizaciones del desafío, esto ya no es válido, ya que incluye ceros a la izquierda. :(
Wheat Wizard
1
@movatica Su corrección es incorrecta. El lstripmétodo quita todos los caracteres de la cadena que se da como argumento, por lo que "ocho dos" se convierte en "ight two", ya que "e" se elimina. Además, "cero cero cero" debería imprimir "0", no dar un error.
NemPlayer
5

Perl 6 , 35 32 bytes

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

Pruébalo en línea!

Explicación

{                              }  # 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
fuente
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++;);}

Pruébalo en línea!

Gracias a los trucos más inteligentes de @Ceilingcat:

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

05AB1E , 18 16 bytes

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

Pruébalo en línea.

Explicación:

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

Ver este consejo 05AB1E mío (sección Cómo comprimir cadenas que no forman parte del diccionario? ) Para entender por qué .•ƒ/ÿßÇf•es "rothuvsein".

Kevin Cruijssen
fuente
3

05AB1E , 17 16 bytes

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

Pruébalo en línea!

Empate perfecto con la otra respuesta 05AB1E , pero con un enfoque 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
Mugriento
fuente
3

Retina 0.8.2 , 46 45 bytes

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

^0+\B

Pruébalo en línea! El enlace incluye casos de prueba. Explicación:

\w+
¶$&$&$&

Pon cada palabra en su propia línea y triplicala.

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

Translitera el séptimo carácter de cada línea usando la cadena de @ UnrelatedString.

\D

Eliminar todos los caracteres que no sean dígitos restantes.

^0+\B

Elimine los ceros a la izquierda (pero deje al menos un dígito).

Solución anterior más tradicional de 46 bytes:

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

^0+\B

Pruébalo en línea! El enlace incluye casos de prueba. Explicación:

T`z\wuxg`E

Las palabras zero, two, four, sixy eightcontienen únicamente las letras zwuxg. Translítelos a los dígitos pares.

on
1
th
3
fi
5
se
7
ni
9

Para los dígitos impares, solo combine las dos primeras letras de cada palabra individualmente.

\D

Eliminar todos los caracteres que no sean dígitos restantes.

^0+\B

Elimine los ceros a la izquierda (pero deje al menos un dígito).

Neil
fuente
2

Jalea , 20 18 17 bytes

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

Pruébalo en línea!

-2 bytes desde la ejecución de "rothuvsein" a través del compresor de cadenas de user202729 .

-1 byte por robar la cadena de enklact libre de cero de Jonathan Allan y ponerla en un programa marginalmente diferente estructurado.

Ḳ                    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.
Cadena no relacionada
fuente
2

C ++ (gcc) , 478 218 142 bytes

- (mucho) gracias 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;}

Pruébalo en línea!

Bengala
fuente
1
127 bytes
ceilingcat
2

Japt , 13 bytes

¸mg6 ì`Ψuv 

Intentalo

Parece que todos los demás me convencieron con la misma idea: podría haberme ahorrado la molestia de escribir un guión para forzar a la fuerza bruta a la secuencia óptima para la compresión, solo para descubrir que, hasta el índice 1,000,000(era temprano, no había tenido mi cafeína todavía!), "rothuvsein" es la única secuencia posible!

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

La cadena comprimida contiene los caracteres en los puntos de código 206, 168, 117, 118, 160y 136.

Lanudo
fuente
1
... ¿realmente probaste hasta 1000000? El mcm de las longitudes de los nombres de los dígitos es 60, por lo que no tiene sentido intentar más allá de eso (60 es equivalente a 0, 61 a 1, etc.).
Grimmy
1
@ Grimy, era temprano, ¡todavía no había tomado mi cafeína! Conectar un millón en el guión que escribí para generar todas las posibilidades fue tan fácil como cualquier otro número y me ahorró hacer los cálculos en el LCM.
Shaggy
2

Ruby , 63 bytes , 52 bytes , 50 bytes

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

-2 gracias al valor de la punta de tinta

Angustiado
fuente
¡Bienvenido a Code Golf! En rubí$* es un alias para ARGV, así que siéntase libre de usarlo para guardar bytes adicionales.
Value Ink el
2

T-SQL, 110 bytes

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

El salto de línea es solo para legibilidad.

yo

Explicación:

  1. STRING_SPLIT toma la cadena de entrada y la separa en los espacios
  2. CHARINDEXtoma los primeros 2 caracteres y devuelve la posición (basada en 1) en la cadena '_ontwthfofisiseeini'. 'ze'para cero no está en la cadena y devuelve 0 para "no encontrado". El guión bajo asegura que solo obtengamos múltiplos de dos.
  3. Divide entre 2 para obtener el número final
  4. STRING_AGG vuelve a juntar los dígitos sin separador
  5. 0+fuerza una conversión implícita a INT y elimina los ceros iniciales. 1*También funcionaría.
BradC
fuente
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

Es una fastcallfunción: recibe un puntero a la cadena enecx y devuelve el resultado eax.

La función hash se multiplica por un número mágico. 1856645926 , hace un XORbyte de entrada y se desplaza a la derecha por 2 bits.

Guardar y restaurar registros de noclobber ( ediyebx ) tomó 4 bytes, pero no encontré una forma más eficiente de implementar esto. ¡Almacenar la constante 10 en ebxfue particularmente molesto!

Desmontaje con los bytes de código correspondientes:

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
fuente
¿Cómo encontraste los números mágicos?
Bengala
Hice una búsqueda con mi código C: probé todos los números de 32 bits y todos los cambios. Solo hay unas pocas posibilidades: el código encontró solo una en el rango de hasta 2000000000.
anatolyg
puede usar edx en lugar de edi (presione edx antes del idiv, pop eax después de él, imul con ebx, agregue eax a edx) para guardar un byte.
Peter Ferrie
1

Carbón , 19 bytes

I⍘⭆⪪S §ι⁶rothuvsein

Pruébalo en línea! El enlace es a la versión detallada del código. Puerto de la respuesta 05AB1E de @ KevinCruijssen. Explicación:

    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
fuente
1

PowerShell , 48 bytes

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

Pruébalo en línea!

Utiliza el mismo rothuvseintruco que otros, gracias a Jonathan Allan. Espera argumentos de entrada mediante splatting, que en TIO se manifiesta como argumentos de línea de comandos separados.

AdmBorkBork
fuente
1

Kotlin, 83 bytes

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

+1 byte si quieres soportar largos con toLong()

El mismo truco de rothuvsein que los demás, ahorrando algunos bytes preciosos gracias a Kotlin's nice toInt()and fold(). Sin embargo, no puedo evitar la sensación de que se pueden eliminar algunos bytes más ...

Alex Papageorgiou
fuente
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
fuente
1

Lote de 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
fuente
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

Coincide con los dos primeros caracteres de una cadena, cero excluido.

usuario3819867
fuente
0

BaCon , 83 72 bytes

Suponiendo que la cadena se proporciona en w $, este código busca el índice en "zeontwthfofisiseeini" utilizando una expresión regular basada en los primeros 2 caracteres únicos de cada palabra. El índice se divide entre 2 para obtener el resultado correcto.

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