Calculadora numeral inglesa

16

Desafío

Escriba una calculadora que tome la entrada en forma verbal (como se podría decir una ecuación) y que también salga en forma verbal (como se podría decir un número).

Reglas

La calculadora debería poder:

  • sumar, restar, multiplicar y dividir
  • manejar operandos entre un millón y un millón negativos
  • manejar salidas entre mil millones y mil millones negativos
  • manejar puntos decimales en su entrada y colocarlos correctamente en su salida
  • manejar la salida decimal al lugar de las centésimas, redondeando donde sea necesario

Todas las operaciones que arrojen resultados fraccionales deben redondearse al centésimo más cercano (de forma idéntica al formato de salida).

Informe con la salida "E" (por error) cuando la entrada haga que el programa falle debido a un formato incorrecto o dividido por 0; Básicamente, el programa no debería bloquearse con una entrada incorrecta, porque sería una calculadora pésima.

Se permite la calculadora , pero no se requiere que informe errores cuando los operandos o la salida escapan de sus límites. Esto está destinado a simplificar el problema, pero si no está de acuerdo conmigo, no dude en hacer una calculadora capaz de manejar correctamente mayores operandos y salidas sin informar errores.

Salida "E" en el caso de que un operando para una operación exceda los límites definidos para los operandos.

Salida "E" en caso de que la salida exceda los límites descritos para las salidas

La forma en que el programa maneja la distinción entre mayúsculas y minúsculas y el espacio en blanco se deja al golfista, como es la elección del inglés británico o estadounidense. 1

Los programas que omiten la implementación de la calculadora mediante el uso de un idioma o biblioteca que ya haya implementado la funcionalidad descrita anteriormente no serán elegibles para la victoria.

Ganador

El programa con el menor número de caracteres gana.

Ejemplos

Entrada: dos más dos
Salida: cuatro

Entrada: veintiuno punto cinco menos un punto cinco
Salida: veinte

Entrada: uno menos dos
Salida: uno negativo

Entrada: cinco veces cinco
Salida: veinticinco

Entrada: veinticinco dividido por cinco
Salida: cinco

Entrada: dos más dos menos cinco por cinco dividido por cero cero negativo cinco
Salida: diez

Entrada un millón de veces mil
Salida: mil millones

Entrada: un millón de veces mil más uno
Salida: E

Entrada: dos millones más un millón
Salida: E

Entrada: un millón más un millón más un millón
Salida: E

invitado
fuente
2
¿Cuál es el orden de evaluación que está utilizando? Normalmente, two plus two minus five times five divided by negative zero point five-> 2 + 2 - 5 * 5 / -0.5-> 54.
marinus
1
@marinus parece estrictamente de izquierda a derecha. Gracias por tomar nota
John Dvorak
1
es lo que tenemos a fallar por one million onela entrada o one billion oneen la salida? Además, ¿el límite 1e6 o el límite 1e9 se aplica también a los resultados intermedios?
John Dvorak
2
@ JanDvorak Voy a decir que no es necesario fallar en nada (entrada, salida, resultados intermedios) siempre que pueda entregar la salida correcta; El propósito del fracaso fue facilitar a las personas la honestidad.
invitado el
1
Usted habla sobre el soporte de decimales, pero no especifica correctamente cómo se deben manejar. ¿Para qué sería la salida correcta one hundred divided by three point nought? (Además, ¿por qué es la salida del ejemplo final en Elugar de hacerlo three million?)
Peter Taylor

Respuestas:

6

En primer lugar, esto es totalmente engañoso y no está completo según las especificaciones.

requiere la --disable-web-securitybandera en cromo, +22

Javascript 509 + 22 = 531

x=new XMLHttpRequest;y=Object.keys(x);b=alert;q="querySelectorAll";s="send";x[y[3]]="document";x.open("GET","http://www.wolframalpha.com/input/?i="+escape(prompt()));x[y[10]]=function(c){4===x.readyState&&(w=[].filter.call(x.response[q](".pod h2"),function(a){return"ame:"==a.innerText.slice(-4)})[0].parentElement,(k=w[q]("a")[0])&&"Words only"==k.innerText?(x.open("GET",k.href),x.send()):alert(JSON.parse([].pop.call(x[y[2]][q]("script")).innerHTML.match(/d_0.00\.push\((.+?)\)/)[1]).stringified))};x[s]()

El primero de la especificación es también la salida de ejemplo
Las two plus two minus five times five divided by negative zero point fivesalidas de entrada

ingrese la descripción de la imagen aquí

Cualquier otro caso debe manejarse bien (ahora), esto todavía es bastante sencillo, solo quería que se arreglara.

input: two plus two
output: four

input: twenty-one point five minus one point five
output: twenty

input: one minus two
output: negative one

input: five times five
output: twenty-five

input: twenty-five divided by five
output: five

input: two plus two minus five times five divided by negative zero point five
output: fifty-four

input: one million times one thousand
output: one billion

input: one million times one thousand plus one
output: one billion, one

input: two million plus one million:
output: three million

input: one million plus one million plus one million
output: three million

Ah, y si realmente va a probarlo, puede tomar unos segundos, ya que carga la página completa de Wolfram Alpha hasta dos veces.

Bueno, sin embargo, podría haber mucho que mejorar.

C5H8NNaO4
fuente
No puedo negar que esta es una respuesta divertida, aunque es una lástima que no proporcione resultados en el formato correcto. Tenga en cuenta que los dos últimos ejemplos también tienen resultados incorrectos. Por supuesto, también está la cuestión de cuán legítima es esta respuesta ... aunque no dije explícitamente que no se podía consultar algún otro programa preexistente, tenía la intención de transmitir la idea de que la traducción del inglés al número , el golfista debe implementar el cálculo y la traducción del número al inglés. Sin embargo, pasa la interpretación literal de las reglas, lo daré. :)
invitado
@guest =) Estoy totalmente de acuerdo con usted en eso =) Es más una respuesta divertida, teniendo en cuenta las reglas, que un verdadero codegolf ment. Estoy en el proceso de arreglar los resultados y publicar una nueva versión. Wolfram Alpha solo usa imágenes, me tomó un tiempo descubrir que está almacenado como un atributo de datos, codificado en b64.
C5H8NNaO4
@guest, lo actualizó. Espero que las salidas ahora estén bien =)
C5H8NNaO4
Si hace esto en Mathematica, puede controlar la salida para dar el número correcto de decimales y así sucesivamente (que es lo que N haría para las fracciones): captura de pantalla
+1 por ser realmente creativo con trampas, a pesar de que este no es un concurso de popularidad .
nyuszika7h
4

Python, 982

from re import*
S=split
U=sub
a=S(' ',U('_','teen ','zero one two three four five six seven eight nine ten eleven twelve thir_four_fif_six_seven_eigh_nine_')+U('_','ty ','twen_thir_for_fif_six_seven_eigh_nine_'))
b=range(20)+range(20,99,10)
d=dict(zip(a,b))
D=dict(zip(b,a))
p='point'
v='negative'
def f(s):
 s=S('[ -]',s);n=0.;m=10**(p in s and(s.index(p)-len(s)))
 for x in s[::-1]:m*=10*(m<1)+100*('hu'in x)+1e3*('ho'in x)+1e6*('m'in x)or 1;n+=(x in d)and m*d[x]
 return n-2*n*(v in s)
def F(n):
 l=[v]*(n<0);x=abs(n)
 for i in(9,6,3,0):z=int(x/10**i);h=z%100;g=(z>99)*[D[z/100],'hundred']+(h>0)*[h in D and D[h]or D[h-z%10]+'-'+D[z%10]];l+=g and g+[[],['thousand'],['million'],['billion']][i/3];x%=10**i
 l+=[c=='.'and p or D[int(c)]for c in'%.2g'%x][n**2>=1:];return' '.join(l)
c=lambda n,l:c(eval(`n`+l[0]+`f(l[1])`),l[2:])if l else n
i=S(' (?=. )|(?<= .) ',U('di.*?y','/',U('times','*',U('minus','-',U('plus','+',raw_input())))))
try:print F(c(f(i[0]),i[1:]))
except:print'E'

Creo que funciona como debería de acuerdo con las especificaciones, pero probablemente haya algunos errores más. Podría actuar de manera extraña para la entrada> = mil millones o cualquier palabra inesperada que interprete incorrectamente.

Aquí hay una versión ligeramente más legible con algunos cambios:

import re
words = re.split(' ', re.sub('_', 'teen ', 'zero one two three four five six seven eight nine ten eleven twelve thir_four_fif_six_seven_eigh_nine_') + re.sub('_', 'ty ', 'twen_thir_for_fif_six_seven_eigh_nine_'))
values = range(20) + range(20, 99, 10)
d = dict(zip(words, values))
D = dict(zip(values, words))

def str_to_num(s):
    s = re.split('[ -]', s)
    n = 0.0
    multiplier = 10 ** ('point' in s and (s.index('point') - len(s)))

    for word in s[::-1]:
        multiplier *= 10 * (multiplier < 1) + 100 * ('hundred' == word) + 1e3 * ('thousand' == word) + 1e6 * ('million' == word) or 1
        n += (word in d) and multiplier * d[word]

    return n - 2 * n * ('negative' in s)


three_digit_num_to_str = lambda n: (n > 99) * [D[n / 100], 'hundred'] + (n % 100 > 0) * [n % 100 in D and D[n % 100] or D[n % 100 - n % 10] + '-' + D[n % 10]]

def num_to_str(n):
    word_list = ['negative'] * (n < 0)
    x = abs(n)

    for i in (9, 6, 3, 0):
        three_digit_str = three_digit_num_to_str(int(x / 10 ** i))
        if three_digit_str:
            word_list += three_digit_str + [[], ['thousand'], ['million'], ['billion']][i / 3]

        x %= 10 ** i

    word_list += [char == '.' and 'point' or D[int(char)] for char in '%.2g' % x][n ** 2 >= 1:]
    return ' '.join(word_list)

calculate = lambda n, l: calculate(eval(str(n) + l[0] + str(str_to_num(l[1]))), l[2:]) if l else n

i = re.split(' (?=. )|(?<= .) ', re.sub('di.*?y', '/', re.sub('times', '*', re.sub('minus', '-', re.sub('plus', '+', raw_input())))))

try:
    print num_to_str(calculate(str_to_num(i[0]), i[1:]))
except:
    print 'E'
grc
fuente
1

Aquí vamos. Jugar al golf antes de la versión la rompió, pero ahora estamos de vuelta en línea. Estoy seguro de que se puede jugar más golf. Trabajaré más en eso mañana. Sin embargo, fue bastante difícil hacerlo funcionar correctamente sin jugar al golf, y mis ojos están cansados ​​de mirarlo. Jaja

Java - 3220

import java.util.*;class a{int D=0,i,l,j;static boolean T=true,F=false;enum O{A("plus"),S("minus"),M("times"),D(""),P("point");String t;O(String u){t=u;}double p(double f,double s){if(this==A)f+=s;if(this==S)f-=s;if(this==M)f*=s;if(this==D)f/=s;return f;}static O f(String s){O r=null;for(O o:values())if(s.equals(o.t))r=o;return r;}}enum N{A("zero",0,F),B("one",1,F),C("two",2,F),D("three",3,F),E("four",4,F),AG("five",5,F),G("six",6,F),H("seven",7,F),I("eight",8,F),J("nine",9,F),K("ten",10,F),L("eleven",11,F),M("twelve",12,F),N("thirteen",13,F),O("fourteen",14,F),P("fifteen",15,F),Q("sixteen",16,F),R("seventeen",17,F),S("eighteen",18,F),AH("nineteen",19,F),U("twenty",20,F),V("thirty",30,F),W("forty",40,F),X("fifty",50,F),Y("sixty",60,F),Z("seventy",70,F),AA("eighty",80,F),AB("ninety",90,F),AC("hundred",100,T),AD("thousand",1000,T),AE("million",1000000,T),AF("billion",1000000000,T);String t;double v;boolean q;N(String u,int w,boolean r){t=u;v=w;q=r;}static N f(String s){N r=null;for(N n:values())if(s.equals(n.t))r=n;return r;}static N f(char s){return d(q(""+s));}static N d(double v){N r=null;for(N n:values())if(v==n.v)r=n;return r;}static String c(double n){return d(n).t;}}public static void main(String[]a){new a();}a(){while(T){try{List p=p(new Scanner(System.in).nextLine()),t=new ArrayList();double d=0;for(j=0;j<p.size();j++){Object o=p.get(j);if(o(o)){if((O)o==O.P){t.add((d(t.get(t.size()-1))+((d=d(p.get(j+1)))<10?d*=100:d<100?d*=10:d)/1000));t.remove(t.size()-2);j++;}else t.add(o);}else {N n=N.d(d(o));if(n!=null&&n.q){t.add((d(o))*d(t.get(t.size()-1)));t.remove(t.size()-2);}else t.add(o);}}double r=d(t.get(0));for(j=1;j<t.size();j++){Object c=t.get(j),l=t.get(j-1);if(o(c))continue;if(c instanceof Double&&l instanceof Double)r+=d(c);else r=((O)t.get(j-1)).p(r,d(t.get(j)));}System.out.println(p(r));}catch(Exception e){System.out.println("E");}}}List p(String s) {List r=new ArrayList();Scanner i=new Scanner(s);while(i.hasNext()){String c=i.next();if(c.equals("divided")){r.add(O.D);i.next();}else if(c.indexOf("-")!=-1){String[] num=c.split("-");r.add(N.f(num[0]).v+N.f(num[1]).v);}else{Object o=N.f(c);r.add(o!=null?((N)o).v:O.f(c));}}return r;}String p(double n){String a=String.valueOf(n),w,d=null,b="";l=a.indexOf(".");if(l!=-1){w=a.substring(0,l);d=a.substring(l+1);}else w=a;if(d.equals("0"))d=null;D=0;while(w.length()%3!=0)w=" "+w;for(i=w.length();i>0;i-=3,D++)b=w(w.substring(i-3,i))+b;return b+d(d);}String w(String w) {if(w==null)return "";w=w.trim();String b="";l=w.length();if(l>1&&w.charAt(l-2)!='0'){if(w.charAt(l-2)=='1')b=N.d(q(w.substring(l-2))).t;else b+=N.d(q(w.charAt(l-2)+"0")).t+"-"+N.f(w.charAt(l-1)).t;}for(j=(b.equals("")?l-1:l-3);j>-1;j--){N n=N.f(w.charAt(j));if(n==N.A)continue;if(j==l-1)b=n.t;else if(j==l-2)b=N.f(n.t+"0")+"-"+b;else if(j==l-3)b=n.t+" hundred "+b;}if(!b.trim().equals("")){if(D==1)b+=" thousand ";if(D==2)b+=" million ";if(D==3)b+=" billion ";}return b;}String d(String d) {if(d==null)return"";if(d.length()>3)d=d.substring(0,3);String b = " point ";for(char n:d.toCharArray())b+=N.f(n).t+" ";return b;}boolean o(Object o){return o instanceof O;}Double d(Object o){return (Double)o;}static double q(String s){return Double.parseDouble(s);}}

Con saltos de línea y pestañas

import java.util.*;

class a{

    int D=0,i,l,j;
    static boolean T=true,F=false;

    enum O{
        A("plus"),
        S("minus"),
        M("times"),
        D(""),
        P("point");

        String t;       
        O(String u){
            t=u;
        }

        double p(double f,double s){
            if(this==A)f+=s;
            if(this==S)f-=s;
            if(this==M)f*=s;
            if(this==D)f/=s;
            return f;
        }

        static O f(String s){
            O r=null;
            for(O o:values())if(s.equals(o.t))r=o;
            return r;
        }
    }

    enum N{
        A("zero",0,F),
        B("one",1,F),
        C("two",2,F),
        D("three",3,F),
        E("four",4,F),
        AG("five",5,F),
        G("six",6,F),
        H("seven",7,F),
        I("eight",8,F),
        J("nine",9,F),
        K("ten",10,F),
        L("eleven",11,F),
        M("twelve",12,F),
        N("thirteen",13,F),
        O("fourteen",14,F),
        P("fifteen",15,F),
        Q("sixteen",16,F),
        R("seventeen",17,F),
        S("eighteen",18,F),
        AH("nineteen",19,F),
        U("twenty",20,F),
        V("thirty",30,F),
        W("forty",40,F),
        X("fifty",50,F),
        Y("sixty",60,F),
        Z("seventy",70,F),
        AA("eighty",80,F),
        AB("ninety",90,F),
        AC("hundred",100,T),
        AD("thousand",1000,T),
        AE("million",1000000,T),
        AF("billion",1000000000,T);

        String t;
        double v;
        boolean q;

        N(String u,int w,boolean r){
            t=u;
            v=w;
            q=r;
        }

        static N f(String s){
            N r=null;
            for(N n:values())if(s.equals(n.t))r=n;
            return r;
        }

        static N f(char s){
            return d(q(""+s));
        }

        static N d(double v){
            N r=null;
            for(N n:values())if(v==n.v)r=n;
            return r;
        }

        static String c(double n){
            return d(n).t;
        }

    }


    public static void main(String[]a){
        new a();
    }


    a(){
        while(T){
            try{
                List p=p(new Scanner(System.in).nextLine()),t=new ArrayList();
                double d=0;
                for(j=0;j<p.size();j++){
                    Object o=p.get(j);
                    if(o(o)){
                        if((O)o==O.P){
                            t.add((d(t.get(t.size()-1))+((d=d(p.get(j+1)))<10?d*=100:d<100?d*=10:d)/1000));
                            t.remove(t.size()-2);
                            j++;
                        }
                        else t.add(o);
                    }
                    else {
                        N n=N.d(d(o));
                        if(n!=null&&n.q){
                            t.add((d(o))*d(t.get(t.size()-1)));
                            t.remove(t.size()-2);
                        }
                        else t.add(o);
                    }
                }

                double r=d(t.get(0));
                for(j=1;j<t.size();j++){
                    Object c=t.get(j),l=t.get(j-1);
                    if(o(c))continue;
                    if(c instanceof Double&&l instanceof Double)r+=d(c);
                    else r=((O)t.get(j-1)).p(r,d(t.get(j)));
                }

                System.out.println(p(r));
            }
            catch(Exception e){
                System.out.println("E");
            }
        }
    }

    List p(String s) {
        List r=new ArrayList();
        Scanner i=new Scanner(s);
        while(i.hasNext()){
            String c=i.next();
            if(c.equals("divided")){
                r.add(O.D);
                i.next();
            }
            else if(c.indexOf("-")!=-1){
                String[] num=c.split("-");
                r.add(N.f(num[0]).v+N.f(num[1]).v);
            }
            else{
                Object o=N.f(c);
                r.add(o!=null?((N)o).v:O.f(c));
            }
        }
        return r;
    }

    String p(double n){

        String a=String.valueOf(n),w,d=null,b="";

        l=a.indexOf(".");
        if(l!=-1){
            w=a.substring(0,l);
            d=a.substring(l+1);
        }
        else w=a;

        if(d.equals("0"))d=null;

        D=0;
        while(w.length()%3!=0)w=" "+w;

        for(i=w.length();i>0;i-=3,D++)b=w(w.substring(i-3,i))+b;

        return b+d(d);
    }


    String w(String w) {
        if(w==null)return "";
        w=w.trim();

        String b="";
        l=w.length();

        if(l>1&&w.charAt(l-2)!='0'){
            if(w.charAt(l-2)=='1')b=N.d(q(w.substring(l-2))).t;
            else b+=N.d(q(w.charAt(l-2)+"0")).t+"-"+N.f(w.charAt(l-1)).t;
        }

        for(j=(b.equals("")?l-1:l-3);j>-1;j--){
            N n=N.f(w.charAt(j));
            if(n==N.A)continue;
            if(j==l-1)b=n.t;
            else if(j==l-2)b=N.f(n.t+"0")+"-"+b;
            else if(j==l-3)b=n.t+" hundred "+b;
        }

        if(!b.trim().equals("")){
            if(D==1)b+=" thousand ";
            if(D==2)b+=" million ";
            if(D==3)b+=" billion ";
        }

        return b;
    }


    String d(String d) {
        if(d==null)return"";
        if(d.length()>3)d=d.substring(0,3);

        String b = " point ";
        for(char n:d.toCharArray())b+=N.f(n).t+" ";

        return b;
    }

    boolean o(Object o){
        return o instanceof O;
    }

    Double d(Object o){
        return (Double)o;
    }

    static double q(String s){
        return Double.parseDouble(s);
    }

}
asteri
fuente