Convierta inglés a un número sin bibliotecas o bibliotecas integradas

14

Este desafío es similar a este otro , sin embargo, hice una restricción (ver texto en negrita a continuación) que creo que lo haría muy diferente y (espero) divertido.

El reto

Escriba un programa o una función en cualquier lenguaje de programación que tome como entrada el nombre en inglés de un entero positivo que nno exceda 100y regrese ncomo un entero.

Las lagunas estándar están prohibidas y no puede utilizar ninguna función integrada, herramienta externa o biblioteca que ya haga este trabajo .

El código fuente más corto en bytes gana.

Prueba

Aquí todos los input->outputcasos:

one              -> 1
two              -> 2
three            -> 3
four             -> 4
five             -> 5
six              -> 6
seven            -> 7
eight            -> 8
nine             -> 9
ten              -> 10
eleven           -> 11
twelve           -> 12
thirteen         -> 13
fourteen         -> 14
fifteen          -> 15
sixteen          -> 16
seventeen        -> 17
eighteen         -> 18
nineteen         -> 19
twenty           -> 20
twenty-one       -> 21
twenty-two       -> 22
twenty-three     -> 23
twenty-four      -> 24
twenty-five      -> 25
twenty-six       -> 26
twenty-seven     -> 27
twenty-eight     -> 28
twenty-nine      -> 29
thirty           -> 30
thirty-one       -> 31
thirty-two       -> 32
thirty-three     -> 33
thirty-four      -> 34
thirty-five      -> 35
thirty-six       -> 36
thirty-seven     -> 37
thirty-eight     -> 38
thirty-nine      -> 39
forty            -> 40
forty-one        -> 41
forty-two        -> 42
forty-three      -> 43
forty-four       -> 44
forty-five       -> 45
forty-six        -> 46
forty-seven      -> 47
forty-eight      -> 48
forty-nine       -> 49
fifty            -> 50
fifty-one        -> 51
fifty-two        -> 52
fifty-three      -> 53
fifty-four       -> 54
fifty-five       -> 55
fifty-six        -> 56
fifty-seven      -> 57
fifty-eight      -> 58
fifty-nine       -> 59
sixty            -> 60
sixty-one        -> 61
sixty-two        -> 62
sixty-three      -> 63
sixty-four       -> 64
sixty-five       -> 65
sixty-six        -> 66
sixty-seven      -> 67
sixty-eight      -> 68
sixty-nine       -> 69
seventy          -> 70
seventy-one      -> 71
seventy-two      -> 72
seventy-three    -> 73
seventy-four     -> 74
seventy-five     -> 75
seventy-six      -> 76
seventy-seven    -> 77
seventy-eight    -> 78
seventy-nine     -> 79
eighty           -> 80
eighty-one       -> 81
eighty-two       -> 82
eighty-three     -> 83
eighty-four      -> 84
eighty-five      -> 85
eighty-six       -> 86
eighty-seven     -> 87
eighty-eight     -> 88
eighty-nine      -> 89
ninety           -> 90
ninety-one       -> 91
ninety-two       -> 92
ninety-three     -> 93
ninety-four      -> 94
ninety-five      -> 95
ninety-six       -> 96
ninety-seven     -> 97
ninety-eight     -> 98
ninety-nine      -> 99
one hundred      -> 100
Beto
fuente
1
¿Qué pasa con un incorporado que hace la mitad del trabajo, por ejemplo, encontrar el nombre unicode de un punto de código?
Brad Gilbert b2gills
@ BradGilbertb2gills No, no está bien.
Bob

Respuestas:

22

C, 160 bytes

g(char*s){char i=1,r=0,*p="k^[#>Pcx.yI<7CZpVgmH:o]sYK$2";for(;*s^'-'&&*s;r+=*s++|9);r=r%45+77;for(;*p!=r;p++,i++);return((*s^'-')?0:g(s+1))+(i<21?i:10*(i-18));}

Pruébalo

int main ()
{
    char* w[] = {"", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", "twenty-one", "twenty-two", "twenty-three", "twenty-four", "twenty-five", "twenty-six", "twenty-seven", "twenty-eight", "twenty-nine", "thirty", "thirty-one", "thirty-two", "thirty-three", "thirty-four", "thirty-five", "thirty-six", "thirty-seven", "thirty-eight", "thirty-nine", "forty", "forty-one", "forty-two", "forty-three", "forty-four", "forty-five", "forty-six", "forty-seven", "forty-eight", "forty-nine", "fifty", "fifty-one", "fifty-two", "fifty-three", "fifty-four", "fifty-five", "fifty-six", "fifty-seven", "fifty-eight", "fifty-nine", "sixty", "sixty-one", "sixty-two", "sixty-three", "sixty-four", "sixty-five", "sixty-six", "sixty-seven", "sixty-eight", "sixty-nine", "seventy", "seventy-one", "seventy-two", "seventy-three", "seventy-four", "seventy-five", "seventy-six", "seventy-seven", "seventy-eight", "seventy-nine", "eighty", "eighty-one", "eighty-two", "eighty-three", "eighty-four", "eighty-five", "eighty-six", "eighty-seven", "eighty-eight", "eighty-nine", "ninety", "ninety-one", "ninety-two", "ninety-three", "ninety-four", "ninety-five", "ninety-six", "ninety-seven", "ninety-eight", "ninety-nine", "one hundred"};

    int n;
    for (n = 1; n <= 100; n++)
    {
        printf ("%s -> %d\n", w[n], g(w[n]));
        if (n != g(w[n]))
        {
            printf ("Error at n = %d", n);
            return 1;
        }
    }
    return 0;
}

Cómo funciona

Después de algunos intentos, me encontré con una función que asigna los números de "excepcionales" one, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve, thirteen, fourteen, fifteen, sixteen, seventeen, eighteen, nineteen, twenty, thirty, forty, fifty, sixty, seventy, eighty, ninety, one hundred, a los caracteres ASCII imprimibles k, ., [, <, *, , c, K, w, y, e, (, S, _, -, C, ), 7, =, 4, &,o, ], s, Y, g, m, N, Respectivamente.

Esta función es:

char hash (char* s)
{
    char r = 0;

    while (*s)
    {
        r += *s|9;
        s++;
    }

    return r%45+77;
}

El programa de golf calcula la hashfunción de la entrada hasta que alcanza el final de la cadena o el carácter -. Luego busca el hash en la cadena k.[<* cKwye(S_-C)7=4&o]sYgmNy determina el número correspondiente. Si se alcanzó el final de la cadena de entrada, se devuelve el número, si en su lugar -se alcanzó a, se devuelve el número más el resultado del programa de golf aplicado al resto de la cadena de entrada.

Beto
fuente
Estoy pensando, si había una versión de golf de C, en realidad podría vencer a idiomas como el Cjam Pyth Japt etc ...
busukxuan
11

JavaScript (ES6), 175 166 163 156 153 147 bytes

Guardado 7 bytes gracias a @Neil

a=>+a.replace(/.+te|.*el|y$/,x=>x[1]?'on-'+x:'-d').split(/ |-|dr/).map(x=>"un|d,on|le,w,th,fo,f,x,s,h,i,".split`,`.findIndex(y=>x.match(y))).join``

Verifíquelo aquí:

Cómo funciona

La idea básica es dividir cada número en sus palabras de dígitos, luego asignar cada palabra al dígito correspondiente. Casi todas las palabras están configuradas para que coincidan correctamente con una expresión regular simple, pero hay algunas anomalías:

  • eleventhrough nineteen: si la palabra contiene un el, o a teen el medio (para evitar ten), agregamos un on-al principio, cambiándolos a on-eleventravés on-nineteen.
  • twenty, thirty, Etc .: la sustitución de un arrastre ycon -dcambios estos a twent-d, thirt-d, etc.

Ahora nos dividimos en guiones, espacios y drs. Esto divide todo de 11 a 99 en sus correspondientes palabras de dígitos, y "one hundred"en [one,hun,ed]. Luego mapeamos cada una de estas palabras a través de una matriz de expresiones regulares, y mantenemos el índice de la que coincide primero.

0: /un|d/ - This matches the "hun" and "ed" in 100, as well as the "d" we placed on the end of 20, 30, etc.
1: /on|le/ - Matches "one" and the "on" we placed on the beginning of 11 through 19, along with "eleven".
2: /w/ - Matches "two", "twelve", and "twenty".
3: /th/ - Matches "three" and "thirty".
4: /fo/ - Matches "four" and "forty".
5: /f/ - "five" and "fifty" are the only words by now that contain an "f".
6: /x/ - "six" and "sixty" are the only words that contain an "x".
7: /s/ - "seven" and "seventy" are the only words by now that contain an "s".
8: /h/ - "eight" and "eighty" are the only words by now that contain an "h".
9: /i/ - "nine" and "ninety" are the only words by now that contain an "i".
10: /<empty>/ - "ten" is the only word left, but it still has to be matched.

Por ahora, cada entrada será la matriz de los dígitos adecuados. Todo lo que tenemos que hacer es unirnos a ellos join``, convertirlos en un número con unario +y listo.

ETHproductions
fuente
Por favor explique.
Bob
@Bob Claro, explicación añadida.
ETHproductions
No .findIndex(y=>x.match(y))funciona
Neil
@Neil No me di cuenta de que lo haría, pero lo hace, ¡gracias!
ETHproductions
Estoy bastante seguro de que puedes alias replace.
Mama Fun Roll
6

sh + coreutils, 112 bytes

Se puede ejecutar en todos los casos de prueba a la vez, uno por línea.

sed -r "`awk '$0="s/"$0"/+"NR"/g"'<<<"on
tw
th
fo
fi
si
se
ei
ni
te|lv
el"`
s/ /y0/
s/y/*10/
s/^\+|[a-z-]//g"|bc

Explicación

El backticked awkevalúa el sedguión

s/on/+1/g       # one, one hundred
s/tw/+2/g       # two, twelve, twenty
s/th/+3/g       # three, thirteen, thirty
s/fo/+4/g       # ...
s/fi/+5/g
s/si/+6/g
s/se/+7/g
s/ei/+8/g
s/ni/+9/g
s/te|lv/+10/g   # ten, -teen, twelve
s/el/+11/g      # eleven

que transforma partes de números en su representación numérica.

fife            ->    +5ve
ten             ->    +10n
eleven          ->    +11even
twelve          ->    +2e+10e
sixteen         ->    +6x+10en
thirty-seven    ->    +3irty-+7ven
forty-four      ->    +4rty-+4ur
eighty          ->    +8ghty
one hundred     ->    +1e hundred

Las líneas adicionales del script sed

s/ /y0/
s/y/*10/

cuidar de -tys y one hundred.

+3irty-+7ven    ->    +3irt*10-+7ven
+4rty-+4ur      ->    +4rt*10-+4ur
+8ghty          ->    +8ght*10
+1e hundred     ->    +1ey0hundred      ->    +1e*100hundred

Finalmente, elimine los +s iniciales y todo lo que no sea +, *o un dígito.

s/^\+|[a-z-]//g"

Solo quedan expresiones matemáticas

fife            ->    5
sixteen         ->    6+10
forty-four      ->    4*10+4
eighty          ->    8*10
one hundred     ->    1*100

y se pueden verter en bc.

Rainer P.
fuente
4

Pyth, 79 76 75 68 bytes

Gracias a @ETHproductions por 7 bytes.

?}"hu"z100sm*+hxc."ewEСBu­["2<d2?|}"een"d}"lv"dTZ?}"ty"dT1cz\-

Básicamente, primero verifica el caso de la esquina de 100, luego usa una matriz de las dos primeras letras de los números del 0 al 11 para determinar la semántica de la entrada y modificar el valor de acuerdo con el sufijo ("-ty" y "-teen"; " lv "en 12 es otro caso de esquina). Primero divide la entrada en una lista de palabras, luego asigna cada una a un valor y las resume.

En pseudocódigo pitónico:

                           z = input()    # raw, unevaluated
                           Z = 0
                           T = 10
?}"hu"z                    if "hu" in z:  # checks if input is 100
  100                        print(100)
                           else:
sm                           sum(map( lambda d: # evaluates each word, then sum
  *                            multiply(
   +hxc."ewEСBu­["2<d2           plusOne(chop("ontwth...niteel",2).index(d[:2])) + \
                                 # chops string into ["on","tw",..."el"]
                                 # ."ewEСBu­[" is a packed string
     ?|}"een"d}"lv"dTZ               (T if "een" in d or "lv" in d else Z),
                                     # add 10 for numbers from 12 to 19
   ?}"ty"dT1                     T if "ty" in d else 1),  # times 10 if "-ty"
  cz\-                         z.split("-"))  # splits input into words

Banco de pruebas


Python 3, 218 bytes

z=input()
if "hu" in z:print(100);exit()
print(sum(map(lambda d:([0,"on","tw","th","fo","fi","si","se","ei","ni","te","el"].index(d[:2])+(10 if "een" in d or "lv" in d else 0))*(10 if "ty" in d else 1),z.split("-"))))

Básicamente idéntico a la respuesta de Pyth.


Sin relación:

Acabo de descubrir una versión significativa de la respuesta a la vida, el universo y todo: son ramitas sedientas de té. ¡Guau, ramitas que anhelan el té! No estoy seguro de cuántas otras respuestas hacen esto, pero para mi respuesta si la entrada es "ramitas sedientas de té", la salida es 42.

busukxuan
fuente
Creo que puede guardar siete bytes utilizando una cadena empaquetada . Copie la salida y colóquela "ontwthfofisiseeiniteel"en este programa.
ETHproductions
@ETHproductions ¡Guau, gracias! La última vez que lo revisé, todavía había "ze" en la cabeza de la cuerda, y el embalaje no podía funcionar. No revisé una vez más después de jugarlo. Nuevamente, gracias xD
busukxuan
@ETHproductions sí, en realidad lo hice, está bajo el pseudocódigo.
busukxuan
2

Python 3, 365 361 310 303 caracteres

Golfed

def f(a):
 y=0
 for i in a.split("-"):
  x="one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir;four;fif;six;seven;eigh;nine;twenty,thirty,forty,fifty,sixty,seventy,eighty,ninety,one hundred".replace(";","teen,").split(",").index(i)
  y+=x+1 if x<20 else range(30,110,10)[x-20]
 return y

Sin golf

 def nameToNumber (numberName):
    names = ["one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen",
             "fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","twenty","thirty","forty","fifty",
             "sixty","seventy","eighty","ninety","one hundred"]
    numbers = range(30, 110, 10)
    number = 0
    for n in numberName.split("-"):
        x = names.index(n)
        number += x + 1 if x < 20 else numbers[x - 20]
    return number
Argenis García
fuente
45 caracteres más cortos: n="one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thirteen,fourteen,fifteen,sixteen,seventeen,eighteen,nineteen,twenty,thirty,forty,fifty,sixty,seventy,eighty,ninety,one hundred".split(",")pero como veo, debería funcionar sin asignarlo a la variable n, solo invoca .index()directamente.
manatwork
7 caracteres más cortos: "one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir;four;fif;six;seven;eigh;nine;twenty,thirty,forty,fifty,sixty,seventy,eighty,ninety,one hundred".replace(";","teen,").split(",").
manatwork
El motor del sitio StackExchange tiene un hábito irritante: inserta caracteres invisibles (U200C Zero Width Non-Joiner y U200B Zero Width Space) en el código publicado en los comentarios. Tú también los pegaste. Edité tu publicación para eliminarlos.
manatwork
2

Haskell 252 231 bytes

let l=words;k=l"six seven eight nine";w=l"one two three four five"++k++l"ten eleven twelve"++((++"teen")<$>l"thir four fif"++k)++[n++"ty"++s|n<-l"twen thir for fif"++k,s<-"":['-':x|x<-take 9w]]in maybe 100id.flip lookup(zip w[1..])

Esto crea una lista de todos los nombres de números en inglés desde "uno" hasta "noventa y nueve" y luego busca el índice de la entrada. Si no existe, estamos en el caso límite "cien", por lo que devuelve 100, de lo contrario, devolverá el índice.

Sin golf

-- k in the golfed variant
common = words "six seven eight nine" 

-- w in the golfed variant
numbers = words "one two three four five" ++ common
       ++ words "ten eleven twelve" ++ [p ++ "teen" | p <- words "thir four fif" ++ common]
       ++ [p ++ "ty" ++ s| p <- words "twen thir for fif" ++ common
                         , s <- "" : map ('-':) (take 9 numbers)]

-- part of the expression in the golfed variant
convert :: String -> Int
convert s = maybe 100 id $ lookup s $ zip numbers [1..]
Zeta
fuente
2

Python 2, 275 caracteres

def x(n):a='one two three four five six seven eight nine ten eleven twelve'.split();t='twen thir four fif six seven eigh nine'.split();b=[i+'teen'for i in t[1:]];c=[i+'ty'for i in t];return(a+b+[i+j for i in c for j in ['']+['-'+k for k in a[:9]]]+['one hundred']).index(n)+1

Simplemente construye una lista de cada número y encuentra el índice.

Peter
fuente
1

Japt, 82 bytes

+Ur`(.+)¿``¿-$1` r"y$""-d" q$/ |-|dr/$ £`un|Üaiwo|ØÏ¿ifoifix¿iÊ¿¿e¿iv`qi b_XfZ}Ãq

Cada uno ¿representa un carácter no imprimible. ¡Pruébalo en línea!

Basado en mi respuesta JS. Reste un byte si la salida no necesita ser un número entero, ya que aparecería exactamente igual que una cadena.

Cómo funciona

+Ur`(.+)¿` `¿-$1`  r"y$""-d" q/ |-|dr/ £  `un|Üaiwo|ØÏ¿ifoifix¿iÊ¿¿e¿iv`          qi b_ XfZ}à q
+Ur"(.+)te""on-$1" r"y$""-d" q/ |-|dr/ mX{"un|dioniwo|wenithifoifixisihineiteiniv"qi bZ{XfZ}} q

Ur"(.+)te""on-$1" // Replace "thirteen", "fourteen", etc. with "on-thiren", "on-fouren", etc.
r"y$""-d"         // Replace "twenty", "thirty", etc. with "twent-d", "thirt-d", etc.
q/ |-|dr/         // Split at occurances of a space, hyphen, or "dr". By now,
                  // "one", "thirteen", "twenty", "sixty-six", "one hundred" will have become:
                  // "one", "on" "thiren", "twent" "d", "sixty" "six", "one" "hun" "ed"
mX         }      // Map each item X in the resulting array to:
"..."qi           //  Take this string, split at "i"s,
b_XfZ}            //  and find the first item Z where X.match(RegExp(Z)) is not null.
                  //  See my JS answer to learn exactly how this works.
                  // Our previous example is now
                  // "1", "1" "3", "2" "0", "6" "6", "1" "0" "0"
+              q  // Join and convert to integer.
                  // 1, 13, 20, 66, 100
ETHproductions
fuente
1

JavaScript, 214 199 bytes

Como siempre: resulta que esto es demasiado largo para competir, pero ahora que he terminado, sería un desperdicio no publicar esto.

¿Quizás hay una manera obvia de jugar golf más allá que he pasado por alto?

e=s=>s.slice(-1)=='d'?100:'  ontwthfofisiseeinite'.indexOf(s.slice(0,2))/2;f=s=>([t,u]=s.split('-'),~s.indexOf`le`?11:~s.indexOf`lv`?12:e(t)+(t.slice(-3)=='een')*10+''+(u?e(u):t.slice(-1)=='y'?0:''))

JSFiddle para casos de prueba

vvye
fuente
1
¿Qué tal cambiar fa f=s=>([t,u]=s.split('-'),~s.indexOf('le')?11:~s.indexOf('lv')?12:e(t)+(t.slice(-3)=='een')*10+''+(u?e(u):t.slice(-1)=='y'?0:''))? Además, un argumento de cadena simple se puede pasar a una función como esta:s.indexOf`lv`
ETHproductions
@ETHproductions Eso es genial, ¡gracias! No sabía que JS tenía un operador de coma, y ​​la abreviatura para pasar cadenas también es realmente útil.
vvye
1

Perl, 158 bytes

@s=split/(\d+)/,'te1ten0l1le1on1tw2th3fo4fi5si6se7ei8ni9d00';foreach(split'-',$n=$ARGV[0]){for($i=0;$i<$#s;$i+=2){m/$s[$i]/&&print$s[$i+1]}}$n=~/ty$/&&print 0

Se ejecuta desde la línea de comando. one hundreddebe ingresarse como "one hundred"para evitar que se interprete como dos entradas.

CJ Dennis
fuente