Converti una stringa di cifre dalle parole in un numero intero


19

Converti una stringa contenente cifre come parole in un numero intero, ignorando gli zeri iniziali.

Esempi

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

ipotesi

I contributi possono presumere che:

  1. La stringa di input è composta da parole numeriche separate da spazio.
  2. Tutte le parole sono valide (nell'intervallo "zero" .. "nove") e minuscole. Il comportamento per input vuoto non è definito.
  3. La stringa di input rappresenta sempre un numero senza segno all'interno dell'intervallo di inte non è mai una stringa vuota.

punteggio

Le risposte verranno classificate in byte con un numero inferiore di byte migliori.


3
Benvenuti nel sito. Ci sono un paio di cose che di solito ci aspettiamo da domande che mancano qui. Il più importante sarebbe un criterio obiettivo di punteggio che tutte le sfide devono avere.
Mago del grano,

3
A parte questo, questa domanda è molto scarsa sulle specifiche. È necessario specificare esattamente ciò che è richiesto per l'invio senza ambiguità. Una frase e un esempio non sono all'altezza dei nostri standard di chiarezza per le sfide.
Wheat Wizard

3
Oltre a quanto già detto, abbiamo una sandbox in cui gli utenti possono pubblicare le loro sfide prima di pubblicarle in main. In questo modo perderai meno informazioni durante la pubblicazione dei post. Se guardi altri post recenti sul sito con un'accoglienza ragionevolmente positiva, penso che vedrai che sia la tua domanda che la tua soluzione non sono del tutto in linea con ciò che facciamo qui.
FryAmTheEggman,

3
A rischio di essere pedante, vorrei sottolineare che range "zero".."nine"non è completamente specificato.
Unrelated String

4
In modo fastidioso, il builtin Interpreter@"SemanticNumber"fa esattamente questo in Mathematica, tranne per il fatto che non ha esito positivo sulle stringhe zero zero .
Greg Martin,

Risposte:


22

PHP , 74 byte

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

Provalo online!

Ho cercato di ottenere una soluzione che non copiasse le risposte esistenti. Ricevo un polinomio di checksum di ridondanza ciclico di lunghezze a 32 bit ( crc32 ) per ogni parola e quindi faccio una mod 20 e una mod 11 su di essa per ottenere valori univoci univoci da 0 a 10 (6 mancanti) per ogni cifra. Quindi usando quel valore univoco trovo la cifra reale.

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

Un'altra alternativa CRC32 da 74 byte che utilizza %493%10: Provalo online!

Un'altra alternativa CRC32 da 74 byte che utilizza %2326%11: Provalo online!


PHP , 74 byte

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

Provalo online!

Un'altra alternativa con la stessa lunghezza, prende il 22 ° carattere in md5 parola (solo carattere che dà un valore univoco per ogni parola) e quindi usa quel carattere per mappare una cifra.


Questa è una bella risposta
Juan Sebastian Lozano il



6

Gelatina ,  19  17 byte

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

Un collegamento monadico che accetta un elenco di caratteri che produce un numero intero.

Provalo online!

Praticamente una porta della mia risposta Python 2.


Precedente

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

Provalo online!

C'è probabilmente un modo più breve, ma questo è un modo che è venuto in mente per la prima volta.


Rimuovere zero dalla stringa enklact per evitare il decremento, perché comunque non trovato è zero ... intelligente!
Unrelated String

1
Ah, vedo che hai fatto lo stesso metodo, carino.
Jonathan Allan,

5

Python 3 , 107 , 91 , 77 , 90 byte

-16 byte di Sriotchilism O'Zaic

+13 byte per rimuovere gli zeri iniziali

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

Provalo online!



Ben fatto! In questo modo, posso anche eliminare completamente il delimitatore :)
movatica,

1
Con gli aggiornamenti della sfida questo non è più valido poiché include zeri iniziali. :(
Wheat Wizard


1
@movatica La tua correzione non è corretta. Il lstripmetodo elimina ogni carattere nella stringa che viene dato come argomento, quindi "otto due" diventa "due", quando "e" viene rimosso. Inoltre, "zero zero zero" dovrebbe stampare "0", non dare un errore.
NemPlayer

5

Perl 6 , 35 32 byte

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

Provalo online!

Spiegazione

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

5

C (gcc) , 89 byte

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

Provalo online!

Grazie ai trucchi più intelligenti di @Ceilingcat:

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

3

05AB1E , 18 16 byte

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

Provalo online.

Spiegazione:

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

Vedere questo 05AB1E punta del mio (sezione Come stringhe di comprimere che non fanno parte del dizionario? ) Per capire il motivo per cui .•ƒ/ÿßÇf•è "rothuvsein".



3

05AB1E , 17 16 byte

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

Provalo online!

Legame perfetto con l'altra risposta 05AB1E , ma con un approccio completamente diverso.

•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

3

Retina 0.8.2 , 46 45 byte

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

^0+\B

Provalo online! Il link include casi di test. Spiegazione:

\w+
¶$&$&$&

Metti ogni parola sulla sua riga e triplicala.

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

Traslitterare il settimo carattere di ogni riga usando la stringa di @ UnrelatedString.

\D

Elimina tutti i caratteri non numerici rimanenti.

^0+\B

Elimina gli zeri iniziali (ma lascia almeno una cifra).

Precedente soluzione più tradizionale a 46 byte:

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

^0+\B

Provalo online! Il link include casi di test. Spiegazione:

T`z\wuxg`E

Le parole zero, two, four, sixe eightcontengono unicamente le lettere zwuxg. Traslitterli in cifre pari.

on
1
th
3
fi
5
se
7
ni
9

Per le cifre dispari, basta abbinare le prime due lettere di ogni parola singolarmente.

\D

Elimina tutti i caratteri non numerici rimanenti.

^0+\B

Elimina gli zeri iniziali (ma lascia almeno una cifra).


2

Gelatina , 20 18 17 byte

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

Provalo online!

-2 byte dall'esecuzione di "rothuvsein" attraverso il compressore di stringhe dell'utente202729 .

-1 byte dal rubare la stringa enklact zero-free di Jonathan Allan e inserirla in un programma strutturato in modo leggermente diverso.

Ḳ                    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.


2

Japt , 13 byte

¸mg6 ì`Ψuv 

Provalo

Sembra che tutti gli altri mi abbiano battuto alla stessa idea: avrei potuto risparmiarmi il fastidio di scrivere una sceneggiatura per forzare la stringa ottimale per la compressione, solo per scoprire che, fino all'indice 1,000,000(era presto, non avevo avuto il mio caffeina ancora!), "rothuvsein" è l' unica stringa possibile!

¸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 stringa compressa contiene i caratteri a codepoints 206, 168, 117, 118, 160e 136.


1
... hai davvero provato fino a 1000000? L'lcm delle lunghezze dei nomi delle cifre è 60, quindi non ha senso provare oltre (60 equivale a 0, 61 a 1, ecc.).
Grimmy,

1
@Grimy, era presto, non avevo ancora preso la mia caffeina! Collegare un milione alla sceneggiatura che ho scritto per generare tutte le possibilità è stato facile come qualsiasi altro numero e mi ha salvato facendo matematica sull'LCM.
Shaggy,


2

T-SQL, 110 byte

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

L'interruzione di riga è solo per leggibilità.

io secondo le nostre regole IO . Avrei potuto salvare 14 byte pre-popolando una variabile stringa, ma ciò è consentito solo se la lingua non ha altri metodi di input.

Spiegazione:

  1. STRING_SPLIT prende la stringa di input e la separa negli spazi
  2. CHARINDEX accetta i primi 2 caratteri e restituisce la posizione (in base 1) nella stringa '_ontwthfofisiseeini' .'ze'per zero non è nella stringa e restituisce 0 per "non trovato". Il carattere di sottolineatura ci assicura di ottenere solo multipli di due.
  3. Dividi per 2 per ottenere il numero finale
  4. STRING_AGG rompe le cifre insieme senza separatore
  5. 0+forza una conversione implicita in INT e elimina eventuali zeri iniziali. 1*funzionerebbe anche.

2

codice macchina x86, 46 byte

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

È una fastcallfunzione: riceve un puntatore alla stringa ecxe restituisce il risultato eax.

La funzione di hashing si moltiplica per un numero magico 1856645926, fa un XORbyte di input e si sposta a destra di 2 bit.

Salvataggio e ripristino dei registri dei noclobber (edi e ebx) ha richiesto 4 byte, ma non ho trovato un modo più efficiente per implementarlo. Memorizzare la costante 10 polliciebx stato particolarmente fastidioso!

Disassemblaggio con byte di codice corrispondenti:

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

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

Come hai trovato i numeri magici?
Sparkler

Ho fatto una ricerca usando il mio codice C - ho provato tutti i numeri a 32 bit e tutti i turni. Ci sono solo poche possibilità: il codice ne ha trovato solo uno nell'intervallo fino a 2000000000.
Anatolyg

puoi usare edx invece di edi (premi edx prima dell'idiv, fai pop eax dopo di esso, imul con ebx, aggiungi eax a edx) per salvare un byte.
Peter Ferrie,



1

Carbone , 19 byte

I⍘⭆⪪S §ι⁶rothuvsein

Provalo online! Il collegamento è alla versione dettagliata del codice. Porta della risposta 05AB1E di @ KevinCruijssen. Spiegazione:

    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

1

PowerShell , 48 byte

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

Provalo online!

Usa lo stesso rothuvseintrucco degli altri, grazie a Jonathan Allan. Si aspetta argomenti di input tramite splatting, che su TIO si manifesta come argomenti della riga di comando separati.


1

Kotlin, 83 byte

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

+1 byte se si desidera supportare longs con toLong()

Lo stesso trucco di rothuvsein degli altri, salvando alcuni byte preziosi grazie al simpatico toInt()e fold(). Non riesco proprio a scrollarmi di dosso la sensazione che alcuni più byte possano essere eliminati però ...



1

Lotto di Windows, 169 byte

@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%


0

VBA, 160 byte

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

Corrisponde ai primi due caratteri in una stringa, zero escluso.


0

BaCon , 83 72 byte

Supponendo che la stringa sia fornita in w $, questo codice cerca l'indice in "zeontwthfofisiseeini" usando un'espressione regolare basata sui primi 2 caratteri univoci di ogni parola. L'indice viene quindi diviso per 2 fornendo il risultato corretto.

FOR x$ IN w$:r=r*10+REGEX("zeontwthfofisiseeini",LEFT$(x$,2))/2:NEXT:?r
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.