Kalkulator sebagai daftar angka dan operator

20

Tugas Anda adalah mengambil daftar argumen yang merupakan bilangan bulat atau operator, dan menguraikannya seperti:

  1. Ada operator saat ini, yang dimulai dengan +.

  2. Setiap kali ditemukan operator, operator saat ini akan mengubahnya.

  3. Operator yang mungkin adalah: "+", "-", "*", "/", dan "%", yang sesuai dengan artinya dalam C dan sebagian besar bahasa.

  4. Ada solusi yang berjalan disimpan, yang dimulai pada 0.

  5. Setiap kali bilangan bulat ditemukan, solusinya diubah dengan angka tergantung pada operator; mis. jika operator adalah "/" maka solusinya dibagi dengan angka.

  6. Jika suatu operasi akan menghasilkan angka campuran (yaitu dengan desimal) maka itu harus lantai kembali ke bilangan bulat (yaitu desimal harus dipotong).

  7. Keluarkan solusi akhir.

Sebagai contoh:

Argumen 5 8 25 * 9 6 2 - 104 / 4 7 + 6 % 14akan menghasilkan:

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

Input akan berupa argumen baris perintah atau fungsi, atau setara untuk bahasa Anda.

Kode terpendek menang!

Trebuchette
sumber
ketika Anda mengatakan makna dalam C yang Anda maksud persis seperti yang mereka lakukan dalam C, atau tidak apa-apa jika %putaran menuju -inf bukan 0?
Maltysen
@Maltysen: Apapun bahasa Anda.
Trebuchette
3
Bisakah bilangan bulat dari input menjadi negatif?
Dennis
Poin 3 dan 6 saling bertentangan: dalam C dan sebagian besar bahasa, putaran pembagian bilangan bulat mengarah ke nol daripada lantai.
Peter Taylor
Akan menarik untuk melihat tantangan lain yang serupa dengan ini, tetapi termasuk diutamakan kurung ...
Joshpbarron

Jawaban:

6

Pyth - 24 23 22 20 byte

2 byte disimpan berkat @issacg dan 1 terima kasih ke @orlp!

Penggunaan dikurangi dengan kasus dasar 0dan memeriksa 'keberadaan dalam repr untuk mendeteksi string vs. int.

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

Tidak berfungsi online karena saya menggunakan eval penuh yang dinonaktifkan online karena alasan keamanan. Mengambil input dari stdin dalam daftar seperti: 5, 8, 25, "*", 9, 6, 2, "-", 104, "/", 4, 7, "+", 6.

Maltysen
sumber
Anda dapat menyimpan 2 byte dengan beralih dari ?ke .x, karena hanya blok lain yang bisa melempar pengecualian, dan itu akan melakukannya setiap saat. Anda tidak dapat menggunakan Klagi. u.xsv++GbH&=bHG+\+QZkhususnya.
isaacg
6

JavaScript (ES6) 53

Sebuah fungsi yang mengambil array sebagai input.

Jalankan cuplikan di Firefox untuk menguji.

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>

edc65
sumber
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)

Ini menciptakan fungsi tanpa nama yang menerima string sebagai input dan mengembalikan integer.

Tidak Terkumpul:

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

Memperbaiki masalah dan menyimpan 2 byte berkat Glen O.

Alex A.
sumber
Julia mengeluh bahwa o is not definedketika Anda mencoba menjalankan fungsi baru. Ia mencoba menjalankan fungsi "o = ifloor ..." di Main, bukan di dalam fungsi (lihat di sini github.com/JuliaLang/julia/issues/2386 ). Mungkinkah saya menyarankan s->(o=0;p="+";for i=split(s) isdigit(i)?o=eval(parse("ifloor($o$p$i)")):p=i;end;o)?
Glen O
@ GlenO Saya tidak tahu bagaimana saya tidak menangkapnya. : / Terima kasih, sudah diperbaiki.
Alex A.
4

elisp, 101 byte

Dengan argumen yang diteruskan sebagai daftar kutipan: mis (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))

Versi dengan baris baru:

    (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))
Pekat
sumber
4

CJam, 24 byte

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

Ini adalah program lengkap yang membaca input sebagai argumen baris perintah.

Untuk mencoba kode online di juru bahasa CJam (yang tidak mendukung argumen baris perintah), ganti eadengan lS/untuk membaca dari STDIN yang disimulasikan.

Bagaimana itu bekerja

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.
Dennis
sumber
3

JavaScript, 85 byte

r=0;o="+";prompt().split(" ").forEach(t=>+t+1?r=parseInt(eval(r+o+ +t)):o=t);alert(r)
Ypnypn
sumber
mengapa o+ +t? Anda sedang membangun string, tidak perlu mengkonversi ke nomor. Selain itu, .forEachtidak memiliki tempat di Code Golf: use.map
edc65
... dan ~~ bukannya 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

Tidak Terkumpul:

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
Nikolai97
sumber
3

Powershell, 57 byte

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

tidak diserang;

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

Jika variabel implisit dalam-masing-masing adalah operator dan bukan angka, Invoke-Expression (POSH eval()) akan gagal dan status eksekusi $?akan salah.

Lantai di POSH berat - $foo=[math]::floor($foo)dan $foo-=$foo%1merupakan alternatif golf yang bisa saya pikirkan.

Tomkandy
sumber
Bagus. Saya membacanya sedikit lebih harfiah dengan mengasumsikan input string dan menguraikannya pada spasi, kemudian ifpada digit, tetapi pada dasarnya sama. 89 Bytes $o="+";$r=0;$args-split'\s+'|%{if($_-match'^\d+$'){$r=iex $r$o$_;$r-=$r%1}Else{$o=$_}};$r
AdmBorkBork
3

GNU Sed (dengan ekstensi eval, + dc), 102

(Skor termasuk +1 untuk opsi -r untuk sed.)

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

Mengubah ekspresi input untuk membalikkan notasi polish, dan kemudian gunakan dcuntuk mengevaluasinya.

Output tes:

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

CJam, 34 byte

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

Cobalah online

Saya pikir ini akan cukup masuk akal. Tapi saya tidak cukup cepat mempostingnya untuk menjadi jawaban CJam terpendek setidaknya untuk sesaat. :(

Reto Koradi
sumber
2

Python 3 - 131 byte 129 byte 121 byte 116 Bytes

Terima kasih kepada Maltysen karena mencukur dua byte, Beta Decay untuk mencukur 8, dan Steven Rumbalski untuk mencukur 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

Saya mencoba mencari cara untuk mengurangi panjang pernyataan if, tapi untuk saat ini sepertinya sama golfnya dengan yang saya bisa. Mengambil input sebagai daftar.

cole
sumber
Anda dapat menyimpan beberapa byte pada indentasi dan menggantinya intdengan//1
Maltysen
juga, mengapa parens di `if?
Maltysen
@ Maltysen ups, saya lupa saya tidak perlu tanda kurung di pernyataan if. Terima kasih. Saya tidak berpikir bahwa menggunakan // 1 akan diizinkan, meskipun saya tidak berpikir untuk menggunakannya, karena tampaknya meninggalkan 0 (misalnya 10.0) yang menurut saya tidak diperbolehkan.
cole
Saya tidak berpikir Anda membutuhkan ruang antara indan kutipan.
Maltysen
Anda dapat menyimpan beberapa byte dengan mengasumsikan bahwa daftar dilewatkan dalam argumen fungsi dan menghilangkannya .split().
Beta Decay
2

Bash, 69

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

Ini hanya bekerja dengan bilangan bulat non-negatif - tidak jelas dalam pertanyaan apakah ini ok atau tidak.

Trauma Digital
sumber
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

Tidak Terkumpul:

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
}
egyb2h9
sumber
1

gcc (dengan peringatan) 165 (jika akhiran baris dihitung sebagai 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);}

Tetapi jika Anda mengompilasinya dengan mingw32 Anda harus mematikan globbing (lihat https://www.cygwin.com/ml/cygwin/1999-11/msg00052.html ) dengan mengkompilasi seperti ini:

gcc x.c C:\Applications\mingw32\i686-w64-mingw32\lib\CRT_noglob.o
Jerry Jeremiah
sumber
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

(Catat itu * harus dilepaskan di shell saya sehingga tidak ditafsirkan sebagai pola gumpalan.)

Tidak Terkumpul:

$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
IniSuitIsBlackNot
sumber
1

C #, 132 165 168 byte

Fungsi ini menganggap input tersebut valid. Ini sulit untuk C # mengingat tidak adaeval setara.

Terima kasih edc65 untuk menghemat 33 byte!

Diindentasi untuk kejelasan.

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;
}
Makanan Tangan
sumber
Anda dapat mengambil sebagian besar baris baru.
Trebuchette
Saya belum menghitung baris baru atau spasi kosong apa pun.
Hand-E-Food
1
132 menggunakan ?:->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
1

Ruby, 59 byte

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

Uji coba:

$ ruby calc.rb <<< "5 8 25 * 9 6 2 - 104 / 4 7 + 6 % 14"
8
daniero
sumber