Una calcolatrice come un elenco di numeri e operatori


20

Il tuo compito è quello di prendere un elenco di argomenti che sono numeri interi o operatori e analizzarli in questo modo:

  1. C'è un operatore corrente, che inizia come +.

  2. Ogni volta che viene trovato un operatore, l'operatore corrente cambierà in esso.

  3. I possibili operatori sono: "+", "-", "*", "/" e "%", che corrispondono ai loro significati in C e nella maggior parte delle lingue.

  4. È stata mantenuta una soluzione in esecuzione, che inizia da 0.

  5. Ogni volta che viene trovato un numero intero, la soluzione viene modificata dal numero in base all'operatore; ad es. se l'operatore è "/", la soluzione viene divisa per il numero.

  6. Se un'operazione si tradurrebbe in un numero misto (cioè con un decimale), allora deve essere ripristinato a un numero intero (cioè il decimale deve essere troncato).

  7. Invia la soluzione finale.

Per esempio:

Gli argomenti 5 8 25 * 9 6 2 - 104 / 4 7 + 6 % 14comporterebbero:

  5 8  25 * 9   6    2    - 104  / 4    7      + 6 % 14
0 5 13 38   342 2052 4104   4000   1000 142   148    8  -> 8

Gli input saranno come argomenti da riga di comando o funzione, o un equivalente per la tua lingua.

Vince il codice più corto!


quando dici significati in C intendi esattamente come fanno in C, o va bene se il %giro è verso -inf invece di 0?
Maltysen,

@Maltysen: qualunque sia la tua lingua.
Trebuchette,

3
Gli interi dall'input possono essere negativi?
Dennis,

I punti 3 e 6 si contraddicono a vicenda: in C e nella maggior parte delle lingue, la divisione dei numeri interi viene arrotondata a zero anziché a pavimentazione.
Peter Taylor,

Sarebbe interessante vedere un'altra sfida simile a questa, ma includendo la precedenza tra parentesi ...
Joshpbarron,

Risposte:


6

Pyth - 24 23 22 20 byte

2 byte salvati grazie a @issacg e 1 grazie a @orlp!

Gli usi si riducono con il caso base di 0e verifica la 'presenza di repr per rilevare string vs.

u.xsv++GbH&=bHG+\+QZ

Non funziona online perché utilizzo full eval che è disabilitato online per motivi di sicurezza. Prende input da stdin in una lista come ad esempio: 5, 8, 25, "*", 9, 6, 2, "-", 104, "/", 4, 7, "+", 6.


Puoi salvare 2 byte passando da ?a .x, perché solo il blocco else può generare un'eccezione e lo farà ogni volta. Non puoi più usare K, comunque. u.xsv++GbH&=bHG+\+QZ, in particolare.
isaacg,

6

JavaScript (ES6) 53

Una funzione che accetta un array come input.

Esegui lo snippet in Firefox per testare.

f=a=>a.map(t=>t<'0'?o=t:v=eval(v+o+t)|0,v=0,o='+')&&v

// TEST
out=x=>O.innerHTML=x;

input = [5,8,25,"*",9,6,2,"-",104,"/",4,7,"+",6,"%",14];
out(input.join(' ')+' -> '+f(input));

function go() {
  i=I.value.split(/ +/),out(I.value+' -> '+f(i))
}  
<pre id=O></pre>
Your test:<input id=I><button onclick='go()'>GO</button>


4

Julia, 85 83 byte

s->(o=0;p="+";for i=split(s) isdigit(i)?o=eval(parse("ifloor($o$p$i)")):(p=i)end;o)

Ciò crea una funzione senza nome che accetta una stringa come input e restituisce un numero intero.

Ungolfed:

function f(s::String)
    # Assign the starting output value o and operator p
    o = 0
    p = "+"

    # Split the input string into an array on spaces
    for i = split(s)
        if isdigit(i)
            # Assign o using string interpolation
            o = eval(parse("ifloor($o $p $i)"))
        else
            # Assign p to the new operator
            p = i
        end
    end
end

Risolto problema e salvato 2 byte grazie a Glen O.


Julia si lamenta che o is not definedquando si tenta di eseguire la funzione di recente. Cerca di eseguire la funzione "o = ifloor ..." in Main, piuttosto che all'interno della funzione (vedi qui github.com/JuliaLang/julia/issues/2386 ). Potrei suggerire s->(o=0;p="+";for i=split(s) isdigit(i)?o=eval(parse("ifloor($o$p$i)")):p=i;end;o)?
Glen O

@GlenO Non so come non l'ho preso. : / Grazie, risolto.
Alex A.

4

elisp, 101 byte

Con gli argomenti passati come un elenco citato: ad es (c '(5 5 * 10))

    (defun c(a)(let((f 0)(o '+))(dolist(x a)(if(not(integerp x))(setf o x)(setq f (eval(list o f x)))))f))

Versione con nuove linee:

    (defun c (a)
      (let ((f 0)
            (o '+))
        (dolist (x a)
          (if (not (integerp x))
              (setf o x) 
            (setq f (eval (list o f x)))))
        f))

4

CJam, 24 byte

0'+ea+{_A,s&O{:O;}?S}%s~

Questo è un programma completo che legge l'input come argomenti della riga di comando.

Per provare il codice online nell'interprete CJam (che non supporta gli argomenti della riga di comando), sostituirlo eacon lS/per leggere da STDIN simulato.

Come funziona

0'+                       Push a 0 and the character '+'.
   ea                     Push the array of command-line arguments.
     +                    Prepend the character to the array.
      {             }%    For each element:
       _                    Push a copy.
        A,s                 Push "0123456789".
           &                Intersect the copy with the string of digits.
             {   }?         If the intersection is non-empty:
            O                 The element is a number. Push O.
              :O;             The element is an operator. Save it in O.
                   S        Push a space.
                      s~  Flatten the array of strings and evaluate it.

3

JavaScript, 85 byte

r=0;o="+";prompt().split(" ").forEach(t=>+t+1?r=parseInt(eval(r+o+ +t)):o=t);alert(r)

perchè o+ +t? stai comunque costruendo una stringa, non è necessario convertirla in numero. Inoltre, .forEachnon ha spazio in Code Golf: use.map
edc65,

... e ~~ invece di parseInt ( codegolf.stackexchange.com/a/2788/21348 )
edc65

prompt(o="+",r=0).split(" ").forEach(t=>+t+1?r=+eval(r+o+ +t):o=t);alert(r)-> 75 byte.
Ismael Miguel,

3

Lua, 142 byte

function f(s)o="+"r=0 for c in s:gmatch"%S+" do if tonumber(c)~=nil then loadstring("r=r"..o..c)() else o=c end r=math.floor(r)end print(r)end

Ungolfed:

function f(s)
    o="+" --original operator
    r=0 --return value
    for c in s:gmatch"%S+" do --split by spaces
        if tonumber(c)~=nil then --check if the current character is a number
            loadstring("r=r"..o..c)() --appends the current operator and current character ex "r=r+5" and then evaluates as another Lua script 
        else 
            o=c --if the character is not a number, it is the new operator
        end
        r=math.floor(r) --floor after each operation
    end 
    print(r) --print the result
end

3

Powershell, 57 byte

$o="+"
$args|%{$r=iex "$r$o$_"
if(!$?){$o=$_}$r-=$r%1}
$r

ungolfed;

$operator="+"
$args | ForEach-Object
{
    $result = Invoke-Expression "$result $operator $_"
    if(!$?)
    {
        $operator=$_
    }
    $result -= $result % 1
}
$result

Se la variabile implicita nel for-each è un operatore anziché un numero, Invoke-Expression (POSH eval()) fallirà e lo stato di esecuzione $?sarà falso.

Il pavimento in POSH è ingombrante - $foo=[math]::floor($foo)ed è $foo-=$foo%1stata l'alternativa più golfosa che mi sia venuta in mente.


Bello. L'ho letto un po 'più letteralmente assumendo un input di stringa e analizzandolo sugli spazi, quindi utilizzando le ifcifre, ma essenzialmente lo stesso. 89 byte $o="+";$r=0;$args-split'\s+'|%{if($_-match'^\d+$'){$r=iex $r$o$_;$r-=$r%1}Else{$o=$_}};$r
AdmBorkBork,

3

GNU Sed (con estensione eval, + dc), 102

(Il punteggio include +1 per l'opzione -r a sed.)

s/.*/0 + &p/
s/([-+/*%]) ([0-9]+)/\2 \1/g
:
s/([-+/*%] )([0-9]+ )([0-9]+)/\1\2\1\3/
t
s/.*/dc<<<'&'/e

Trasforma l'espressione di input in inversione della notazione polacca, quindi la utilizza dcper valutarla.

Uscita di prova:

$ sed -rf calclist.sed <<< '5 8 25 * 9 6 2 - 104 / 4 7 + 6 % 14'
8
$ 

2

CJam, 34 byte

'+0lS/{"+-*/%"1$#){@;\}{i2$~}?}/\;

Provalo online

Ho pensato che sarebbe stato abbastanza ragionevole. Ma non sono stato abbastanza veloce pubblicandolo per essere la risposta CJam più breve almeno per un momento. :(


2

Python 3 - 131 byte 129 byte 121 byte 116 byte

Grazie a Maltysen per la rasatura di due byte, Beta Decay per la rasatura di 8 e Steven Rumbalski per la rasatura di 5.

def f(x):
    a,b="+",0
    for i in x:
        if i in"+-*/%":a=i
        else:b=int(eval(str(b)+a+i))
    return b

Sto cercando di trovare un modo per ridurre la lunghezza dell'istruzione if, ma per ora questo sembra il più golfato possibile. Accetta input come elenco.


puoi salvare alcuni byte sul rientro e sostituirli intcon//1
Maltysen,

inoltre, perché i genitori nel `se?
Maltysen,

@ Maltysen, ho dimenticato che non avevo bisogno delle parentesi nell'istruzione if. Grazie. Non penso che l'uso di // 1 sarà consentito, anche se non pensavo di usarlo, in quanto sembra lasciare uno 0 finale (es. 10.0) che non credo sia permesso.
Cole

non penso che tu abbia bisogno di quello spazio tra ine la citazione.
Maltysen,

È possibile salvare alcuni byte supponendo che l'elenco venga passato negli argomenti della funzione e eliminarlo .split().
Decadimento beta

2

Bash, 69

set -f
for t in $*
do
((1${t}1>2))&&((r${o-+}=$t))||o=$t
done
echo $r

Funziona solo con numeri interi non negativi - non è chiaro nella domanda se va bene o no.


2

Groovy, 79 byte

def f(x,a=0,b='+'){x.each{z->a=z=~/\d/?Eval.me(a+b+z)as int:a;b=z=~/\d/?b:z};a}

demo:

groovy> f([5,8,25,'*',9,6,2,'-',104,'/',4,7,'+',6,'%', 14])
Result: 8

Ungolfed:

def f(x, a=0, b='+') {                                   
    x.each {z->
        a = z =~ /\d/ ? Eval.me(a+b+z) as int : a
        b = z =~ /\d/ ? b : z
    }
    a
}

1

gcc (con avvertenze) 165 (se la fine della riga conta come 1)

#define A atoi(*a);break;case
o='+',s=0;main(c,a)char**a;{while(*++a)if(**a<48)o=**a;else switch(o){case'+':s+=A'-':s-=A'*':s*=A'/':s/=A'%':s%=A 0:;}printf("%d",s);}

Ma se lo stai compilando con mingw32 devi disattivare il globbing (vedi https://www.cygwin.com/ml/cygwin/1999-11/msg00052.html ) compilando in questo modo:

gcc x.c C:\Applications\mingw32\i686-w64-mingw32\lib\CRT_noglob.o

1

Perl 5.10+, 52 byte

perl -E '$o="+";/\D/?$o=$_:eval"\$x=int\$x$o$_"for@ARGV;say$x'

demo:

$ perl -E '$o="+";/\D/?$o=$_:eval"\x=int\$x$o$_"for@ARGV;say$x' 5 8 25 \* 9 6 2 - 104 / 4 7 + 6 % 14
8

(Nota che *deve essere evaso nella mia shell, quindi non è interpretato come un modello glob.)

Ungolfed:

$o="+";                      # Start with addition
/\D/ ? $o=$_                 # If not a number, update the current operator
     : eval"\$x=int\$x$o$_"  # Otherwise, make a string like '$x=int$x+1' and eval it
for@ARGV;                    # Repeat for each item in the argument list
say$x                        # Print the result

1

C #, 132 165 168 byte

Questa funzione presuppone che l'ingresso sia valido. Questo è difficile per C # dato che non esiste un evalequivalente.

Grazie edc65 per aver salvato 33 byte!

Rientrato per chiarezza.

int C(string[]a){
    int o=1,r=0,n;
    foreach(var b in a)
        n=int.TryParse(b,out n)
            ?r=o<0?r%n
              :o<1?r*n
              :o<2?r+n
              :o<4?r-n
                  :r/n
            :o=b[0]-42;
    return r;
}

Puoi eliminare la maggior parte delle nuove linee.
Trebuchette,

Non ho contato nessuna nuova riga o spazio bianco insignificante.
Hand-E-Food

1
132 utilizzando ?:->int C(string[]a){int o=1,r=0,n;foreach(var b in a)n=int.TryParse(b,out n)?r=o<0?r%n:o<1?r*n:o<3?r+n:o<5?r-n:r/n:o=b[0]-42;return r;}
edc65 il

1

Rubino, 59 byte

a=0
o=?+
gets.split.map{|s|s=~/\d/?a=eval([a,s]*o):o=s}
p a

Prova:

$ ruby calc.rb <<< "5 8 25 * 9 6 2 - 104 / 4 7 + 6 % 14"
8
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.