Convertir une chaîne de chiffres de mots en un entier

19

Convertissez une chaîne contenant des chiffres sous forme de mots en un entier, en ignorant les zéros de tête.

Exemples

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

Hypothèses

Les soumissions peuvent supposer que:

  1. La chaîne d'entrée est composée de mots numériques séparés par des espaces.
  2. Tous les mots sont valides (dans la plage "zéro" .. "neuf") et en minuscules. Le comportement pour une entrée vide n'est pas défini.
  3. La chaîne d'entrée représente toujours un nombre non signé dans la plage de intet n'est jamais une chaîne vide.

Notation

Les réponses seront notées en octets avec moins d'octets étant mieux.

Cierge magique
la source
3
Bienvenue sur le site. Il y a deux ou trois choses que nous attendons habituellement des questions qui manquent ici. Le plus important serait un critère de notation objectif que tous les défis doivent avoir.
Post Rock Garf Hunter
3
En dehors de cela, cette question est très rare sur les spécifications. Vous devez spécifier exactement ce qui est requis pour les soumissions sans ambiguïté. Une phrase et un exemple ne sont tout simplement pas à la hauteur de nos normes de clarté pour les défis.
Post Rock Garf Hunter
3
En plus de ce qui a déjà été dit, nous avons un bac à sable où les utilisateurs peuvent publier leurs défis avant de les publier sur main. De cette façon, vous manquerez moins d'informations lors de la publication de messages. Si vous regardez d'autres articles récents sur le site avec un accueil raisonnablement positif, je pense que vous verrez que votre question et votre solution ne correspondent pas tout à fait à ce que nous faisons ici.
FryAmTheEggman
3
Au risque d'être pédant, je voudrais souligner que le range "zero".."nine"n'est pas entièrement spécifié.
Unrelated String
4
Chose ennuyeuse, la fonction intégrée Interpreter@"SemanticNumber"fait exactement cela dans Mathematica, sauf qu'elle échoue sur les chaînes commençant par zero zero .
Greg Martin

Réponses:

22

PHP , 74 octets

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

Essayez-le en ligne!

J'ai essayé d'obtenir une solution qui ne copie pas les réponses existantes. J'obtiens un polynôme de somme de contrôle de redondance cyclique de longueurs 32 bits ( crc32 ) pour chaque mot, puis je fais un mod 20 et un mod 11 dessus pour obtenir des valeurs uniques mélangées de 0 à 10 (6 manquantes) pour chaque chiffre. Ensuite, en utilisant cette valeur unique, je trouve le chiffre réel.

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

Une autre alternative CRC32 de 74 octets utilisant %493%10: Essayez-le en ligne!

Une autre alternative CRC32 de 74 octets utilisant %2326%11: Essayez-le en ligne!


PHP , 74 octets

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

Essayez-le en ligne!

Une autre alternative avec la même longueur, prend le 22ème caractère dans le md5mot (seul caractère qui donne une valeur unique pour chaque mot) et utilise ensuite ce caractère pour mapper à un chiffre.

Nuit2
la source
C'est une bonne réponse
Juan Sebastian Lozano
9

Python 2 ,  71  70 octets

-1 grâce aux ovs (utilisation findà la place de index)

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

Essayez-le en ligne!

Jonathan Allan
la source
7

JavaScript (ES6),  70 67 66  62 octets

Sauvegardé 3 octets grâce à @ovs

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

Essayez-le en ligne!

Arnauld
la source
1
'2839016547'[parseInt(s,36)%204%13]est de 3 octets plus court.
OVS
6

Gelée ,  19  17 octets

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

Un lien monadique acceptant une liste de caractères qui donne un entier.

Essayez-le en ligne!

À peu près un portage de ma réponse Python 2.


précédent

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

Essayez-le en ligne!

Il existe peut - être un moyen plus court, mais c'est un moyen qui m'est venu à l'esprit.

Jonathan Allan
la source
Supprimer zéro de la chaîne enklact pour éviter toute décrémentation, car non trouvé est de toute façon nul ... intelligent!
Unrelated String
1
Ah je vois que tu as fait la même méthode, sympa.
Jonathan Allan
5

Python 3 , 107 , 91 , 77 , 90 octets

-16 octets par Sriotchilism O'Zaic

+13 octets pour supprimer les zéros non significatifs

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

Essayez-le en ligne!

movatica
la source
Joli! De cette façon, je peux même supprimer complètement le délimiteur :)
movatica
1
Avec les mises à jour du défi, cela n'est plus valable car il inclut des zéros non significatifs. :(
Post Rock Garf Hunter
1
@movatica Votre correction est incorrecte. La lstripméthode supprime chaque caractère de la chaîne qui est donnée comme argument, donc "huit deux" devient "ight deux", car "e" est supprimé. De plus, "zéro zéro zéro" devrait imprimer "0", et non pas donner une erreur.
NemPlayer
5

Perl 6 , 35 32 octets

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

Essayez-le en ligne!

Explication

{                              }  # 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
la source
5

C (gcc) , 89 octets

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

Essayez-le en ligne!

Grâce aux astuces les plus intelligentes de @Ceilingcat:

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

05AB1E , 18 16 octets

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

Essayez-le en ligne.

Explication:

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

Voir cette astuce de mes 05AB1E (section Comment chaînes Compresser ne font pas partie du dictionnaire? ) Pour comprendre pourquoi .•ƒ/ÿßÇf•est "rothuvsein".

Kevin Cruijssen
la source
3

05AB1E , 17 16 octets

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

Essayez-le en ligne!

Lien parfait avec l'autre réponse 05AB1E , mais en utilisant une approche complètement différente.

•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
la source
3

Retina 0.8.2 , 46 45 octets

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

^0+\B

Essayez-le en ligne! Le lien inclut des cas de test. Explication:

\w+
¶$&$&$&

Mettez chaque mot sur sa propre ligne et tripliquez-le.

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

Translittérer le 7e caractère de chaque ligne en utilisant la chaîne de @ UnrelatedString.

\D

Supprimez tous les caractères non numériques restants.

^0+\B

Supprimez les zéros non significatifs (mais laissez au moins un chiffre).

Solution plus traditionnelle de 46 octets:

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

^0+\B

Essayez-le en ligne! Le lien inclut des cas de test. Explication:

T`z\wuxg`E

Les mots zero, two, four, sixet eightcontiennent uniquement les lettres zwuxg. Translittérez-les aux chiffres pairs.

on
1
th
3
fi
5
se
7
ni
9

Pour les chiffres impairs, faites correspondre les deux premières lettres de chaque mot individuellement.

\D

Supprimez tous les caractères non numériques restants.

^0+\B

Supprimez les zéros non significatifs (mais laissez au moins un chiffre).

Neil
la source
2

Gelée , 20 18 17 octets

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

Essayez-le en ligne!

-2 octets de l'exécution de "rothuvsein" via le compresseur de cordes de user202729 .

-1 octet pour avoir volé la chaîne d'enklact zéro-libre de Jonathan Allan et l'avoir placée dans un programme légèrement différent.

Ḳ                    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.
Chaîne indépendante
la source
2

C ++ (gcc) , 478 218 142 octets

- (beaucoup) merci à 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;}

Essayez-le en ligne!

Cierge magique
la source
1
127 octets
Plafond
2

Japt , 13 octets

¸mg6 ì`Ψuv 

Essayez-le

On dirait que tout le monde m'a battu à la même idée - j'aurais pu me épargner les tracas de l'écriture d'un script pour forcer brutalement la chaîne optimale pour la compression, seulement pour trouver cela, jusqu'à l'index 1,000,000 (c'était tôt, je n'avais pas eu mon caféine encore!), "rothuvsein" est la seule chaîne possible!

¸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 chaîne compressée contient les caractères à codepoints 206, 168, 117, 118, 160et 136.

Hirsute
la source
1
... avez-vous vraiment essayé jusqu'à 1000000? La longueur en cm des noms de chiffres est de 60, il est donc inutile d'essayer au-delà (60 équivaut à 0, 61 à 1, etc.).
Grimmy
1
@Grimy, c'était tôt, je n'avais pas encore pris ma caféine! Brancher un million dans le script que j'ai écrit pour générer toutes les possibilités était aussi simple que n'importe quel autre nombre et m'a évité de faire les calculs sur le LCM.
Shaggy
2

Ruby , 63 octets , 52 octets , 50 octets

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

-2 grâce à la pointe de l'encre de valeur

Harrowed
la source
Bienvenue chez Code Golf! Dans Ruby, $*est un alias pour ARGV, alors n'hésitez pas à l'utiliser pour économiser des octets supplémentaires.
Value Ink
2

T-SQL, 110 octets

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

Le saut de ligne est uniquement pour la lisibilité.

L'entrée est prise via la table je, selon nos règles IO . J'aurais pu économiser 14 octets en préremplissant une variable de chaîne, mais cela n'est autorisé que si la langue n'a pas d'autres méthodes d'entrée.

Explication:

  1. STRING_SPLIT prend la chaîne d'entrée et la sépare dans les espaces
  2. CHARINDEXprend les 2 premiers caractères et renvoie la position (basée sur 1) dans la chaîne '_ontwthfofisiseeini'. 'ze'pour zéro n'est pas dans la chaîne et renvoie 0 pour "non trouvé". Le trait de soulignement garantit que nous n'obtenons que des multiples de deux.
  3. Divisez par 2 pour obtenir le chiffre final
  4. STRING_AGG écrase les chiffres sans séparateur
  5. 0+force une conversion implicite en INT et supprime tous les zéros non significatifs. 1*fonctionnerait également.
BradC
la source
2

code machine x86, 46 octets

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

C'est un fastcall fonction - reçoit un pointeur sur la chaîne ecxet retourne le résultat danseax .

La fonction de hachage se multiplie par un nombre magique 1856645926 , fait unXOR octet d'entrée et se décale de 2 bits vers la droite.

Sauvegarde et restauration des registres noclobber (edi et ebx) ont pris 4 octets, mais je n'ai pas trouvé de moyen plus efficace de l'implémenter. Stockage de la constante 10 poucesebx était particulièrement ennuyeux!

Démontage avec octets de code correspondants:

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

Code C équivalent:

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
la source
Comment avez-vous trouvé les nombres magiques?
Sparkler
J'ai fait une recherche en utilisant mon code C - j'ai essayé tous les nombres 32 bits et tous les changements. Il n'y a que quelques possibilités - le code n'en a trouvé qu'un dans la plage allant jusqu'à 2000000000.
anatolyg
vous pouvez utiliser edx au lieu de edi (pousser edx avant l'idiv, pop eax après, imul avec ebx, ajouter eax à edx) pour enregistrer un octet.
peter ferrie
1

VBA, 160 octets

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

Correspond aux deux premiers caractères d'une chaîne, zéro exclu.

user3819867
la source
(1/3) Excellente approche ici, mais il semble que vous n'ayez pas compté les sauts de ligne comme octets, et que vous pouvez obtenir le nombre de bytecount si vous utilisez quelques astuces. À savoir, il n'est pas nécessaire de détartrer le " "dans Splitcar c'est la valeur par défaut, Lbound(s)sera toujours zéro et vous pouvez supprimer (...)+1si vous ajoutez un espace au début des InStrdonnées. En plus de cela, il vaut mieux utiliser une chaîne ou une variante pour gérer la conservation des données provenant de l' InStrinstruction car vous n'avez pas besoin d'utiliser (i)ou Join(s,""). Oh et Int(a/b)c'est la même chose que a\b.
Taylor Scott Il y a
(2/3) En utilisant ceux-ci, et une for eachboucle, vous pouvez réduire votre fonction à 101 octets en tant que Function G(x):For Each c In Split(x):G=10*G+InStr(" ontwthfofisiseeini",Left(c,2))\2:Next:End Functionou 101 octets en tant que sous-ensemble imprime implicitement la sortie dans la fenêtre de débogage en tant que Sub F(x):For Each c In Split(x):v=10*v+InStr(" ontwthfofisiseeini",Left(c,2))\2:Next:Debug.?v:End Sub. Si vous limitez votre réponse, vous pouvez même l'obtenir à 81 octets en tant que fonction de fenêtre immédiate Excel VBA For Each c In Split([A1]):v=10*v+InStr(" ontwthfofisiseeini",Left(c,2))\2:Next:?v.
Taylor Scott Il y a
(3/3) Je vous recommande fortement d'aller jeter un œil à notre page Conseils pour jouer au golf dans VBA pour plus d'informations sur ces approches. Cheers
Taylor Scott Il y a
1

Fusain , 19 octets

I⍘⭆⪪S §ι⁶rothuvsein

Essayez-le en ligne! Le lien est vers la version détaillée du code. Port de la réponse 05AB1E de @ KevinCruijssen. Explication:

    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
la source
1

PowerShell , 48 octets

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

Essayez-le en ligne!

Utilise la même rothuvseinastuce que les autres, grâce à Jonathan Allan. Attend les arguments d'entrée via l'éclatement, qui sur TIO se manifeste sous forme d'arguments de ligne de commande distincts.

AdmBorkBork
la source
1

Kotlin, 83 octets

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

+1 octet si vous voulez prendre en charge les longs avec toLong()

Même astuce rothuvsein que les autres, économisant de précieux octets grâce à nice toInt()et kotlin fold(). Je ne peux tout simplement pas me débarrasser du sentiment que certains octets supplémentaires peuvent être rasés, bien que ...

Alex Papageorgiou
la source
1

sed -re , 78 octets

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

Windows Batch, 169 octets

@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
la source
0

BaCon , 83 72 octets

En supposant que la chaîne est fournie en w $, ce code recherche l'index dans "zeontwthfofisiseeini" en utilisant une expression régulière basée sur les 2 premiers caractères uniques de chaque mot. L'index est ensuite divisé par 2 fournissant le résultat correct.

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