Máy tính cơ bản


20

Bạn phải viết một chương trình để đánh giá một chuỗi sẽ được nhập vào máy tính.

Chương trình phải chấp nhận đầu vào và đầu ra câu trả lời đúng. Đối với các ngôn ngữ không có chức năng đầu vào / đầu ra tiêu chuẩn, bạn có thể đảm nhận các chức năng readLineprint.

Yêu cầu

  • Không sử dụng bất kỳ loại chức năng "eval"
  • Có thể xử lý số dấu phẩy động và số âm
  • Hỗ trợ ít nhất các toán tử +, -, * và /
  • Có thể xử lý đầu vào chứa một hoặc nhiều khoảng trắng giữa các toán tử và số
  • Đánh giá biểu thức từ trái sang phải

Chương trình nào là chiến thắng ngắn nhất. Trong trường hợp hòa, chương trình được gửi trước sẽ thắng.

Bạn có thể giả sử rằng đầu vào là hợp lệ và theo đúng định dạng

Các trường hợp thử nghiệm

Đầu vào

-4 + 5

Đầu ra

1


Đầu vào

-7.5 / 2.5

Đầu ra

-3


Đầu vào

-2 + 6 / 2 * 8 - 1 / 2.5 - 18

Đầu ra

-12

Máy tính của tôi sử dụng postfix . Xem thêm Đánh giá các biểu thức toán học trên Stack Overflow để cạnh tranh (mặc dù tôi chưa kiểm tra xem các quy tắc có giống nhau không).
dmckee

3
Trường hợp thử nghiệm thứ ba là sai - cho dù bạn tuân theo thứ tự hoạt động tiêu chuẩn hoặc thực hiện tất cả các hoạt động từ trái sang phải. Nhìn vào trường hợp thử nghiệm thứ hai, máy tính của bạn có làm tròn kết quả của mỗi thao tác không?
Xin vui lòng

Đã sửa trường hợp kiểm tra thứ hai và thứ ba, kết quả không được làm tròn.
Kevin Brown

Trường hợp thử nghiệm thứ ba không tuân theo thứ tự hoạt động tiêu chuẩn. Là câu trả lời của chúng tôi phải?
Giăng

1
Điều gì về việc sử dụng các đối số dòng lệnh ARGV? bởi vì shell tự động phân tách và liệt kê các đối số.
Ming-Tang

Câu trả lời:


7

Ruby - 74 69 67 65 ký tự

a=0
("+ "+$<.read).split.each_slice 2{|b,c|a=a.send b,c.to_f}
p a

1
Thay vì sử dụng b[0],b[1].to_fbạn có thể thay thế |b|với |b,c|và sử dụngb,c.to_f
Nemo157

\ồ cảm ơn ! :-)
Arnaud Le Blanc

1
Thay vì a.send(b,c.to_f)sử dụng a.send b,c.to_f. Nó tiết kiệm cho một char
nặc danh hèn nhát

1
Bạn có thể sử dụng $<thay vìARGF
Dogbert

9

Befunge - 37 x 5 = 185 38 x 3 = 114 ký tự

Điều này được giới hạn ở số nguyên vì Befunge không hỗ trợ dấu phẩy động.

&v      /& _ #`&# "-"$# -#<          v
 >~:0`!#v_:" "`! #v_:","`#^_"*"`#v_&*>
 ^      ># $ .# @#<              >&+ 

Giải trình

Tính năng phân biệt lớn nhất của Befunge là thay vì là một bộ hướng dẫn tuyến tính như hầu hết các ngôn ngữ; nó là một lưới 2d của các lệnh ký tự đơn, trong đó điều khiển có thể chảy theo bất kỳ hướng nào.

Đầu tiên &chỉ cần nhập số đầu tiên. Các v>sau đó kiểm soát chuyển hướng đến con đường chính vào hàng thứ hai.

~:0`!#v_

Điều này nhập một ký tự ( ~), sao chép nó ( :), đẩy số 0 lên ngăn xếp ( 0), bật hai phần tử trên cùng và xác định xem phần tử thứ hai có lớn hơn phần tử thứ nhất không ( ` tôi ngạc nhiên bạn không thể sử dụng `` `để có được mã backticks. ), đảo ngược tính trung thực của phần tử trên cùng ( !), sau đó đi đúng nếu nó bằng 0, ngược lại ( #v_).

Về cơ bản, nó kiểm tra xem đầu vào có -1đại diện cho đầu vào không nữa.

># $ .# @

Nếu đầu vào là -1giá trị đầu vào trùng lặp bị loại bỏ ( $), đỉnh của ngăn xếp là đầu ra dưới dạng một số nguyên ( .) và chương trình được tạm dừng ( @).

:" "`! #v_

Mặt khác, một quá trình tương tự được lặp lại để xác định xem đầu vào nhỏ hơn hoặc bằng một khoảng trắng. Nếu đó là một khoảng trắng thì điều khiển đi xuống, nếu không thì điều khiển đầu phải.

^      ># $ .# @#<

Nếu đó là một khoảng trắng thì nó được chuyển hướng trái ( <); chương trình tạm dừng ( @), đầu ra ( .) và chuyển hướng phải ( >) đều được bỏ qua bằng cách sử dụng #; nhưng loại bỏ được thực hiện để loại bỏ không gian từ ngăn xếp. Cuối cùng, nó được chuyển hướng lên để bắt đầu thực hiện tiếp theo ( ^).

:","`#^_

Nếu đó không phải là một không gian, quá trình tương tự được sử dụng để phân chia nếu nó ở trong [+, *]hoặc [-, \]đi đúng và lên tương ứng.

 >~                         "*"`#v_&*>
 ^                               >&+

Đối với [+, *]nó một lần nữa được phân chia để xác định xem nó là a +hay a *. Nếu +nó được hướng xuống thì số tiếp theo là input ( &) và chúng được thêm vào ( +), điều khiển sau đó bao bọc xung quanh và được chuyển hướng đến đường dẫn chính cho ký tự tiếp theo. Nếu *sau đó, nó nhập ( &) và nhân ( *) thì trực tiếp kết thúc.

/& _ #`&# "-"$# -#<

Đối với [-, \]nó bắt đầu trên tiêu đề bên trái. Các #'s bỏ qua nhân vật sau khi họ để con đường ban đầu là "-"`_mà chỉ đơn giản xác định nếu nó là -hay /. Nếu có /thì nó tiếp tục sang trái để nhập ( &) và chia ( /). Nếu -đúng, nó sẽ đi đúng, một lần nữa bỏ qua các ký tự để nó thực thi &"-"$-dẫn đến số được nhập ( &) -ký tự được đẩy lên ngăn xếp sau đó loại bỏ ( "-"$) và sau đó phép trừ được tính ( -). Kiểm soát sau đó được chuyển hướng trở lại đường dẫn chính.


6

Python 3, 105 byte

Quản lý bốn thao tác cơ bản, nhưng chỉ tốn 5 ký tự để thêm ^hoặc %.

f=float
x,*l=input().split()
while l:o,y,*l=l;x,y=f(x),f(y);x=[x+y,x-y,x*y,x/y]['+-*/'.find(o)]
print(x)

Ưu tiên của hoạt động là trái sang phải.


5

Con trăn (156)

from operator import*
while 1:
 l=raw_input().split();f=float
 while len(l)>2:l[:3]=({'*':mul,'/':div,'+':add,'-':sub}[l[1]](f(l[0]),f(l[2])),)
 print l[0]

1
Việc sử dụng Python 3 trở nên dễ dàng hơn
jamylak

5

C - 168 126 ký tự

main(c){float a,b;scanf("%f",&a);while(scanf("%s%f",&c,&b)!=-1)c=='+'?a+=b:c=='-'?(a-=b):c=='*'?(a*=b):(a/=b);printf("%f",a);}

5

Tcl 8.6, 57 48 ký tự.

  • Đầu vào từ các đối số:

    lm o\ b [las $argv a] {set a [exp $a$o$b]};pu $a
    
  • Từ Stdin ( 64 53 )

    lm o\ b [las [ge stdin] a] {set a [exp $a$o$b]};pu $a
    

Bạn phải sử dụng vỏ tương tác cho cả hai giải pháp.

Tôi đối xử với các đầu vào dạng danh sách (Tcl sử dụng không gian như delimiter) lấy phần tử đầu tiên và gán nó vào a, sau đó tôi đi qua phần còn lại, lấy 2 yếu tố mỗi lần, các nhà điều hành và một số thứ hai, áp dụng các toán tử trên $a$bvà giao cho dẫn đến a. Cuối cùng kết quả là trong a.


Ideone hỗ trợ ít nhất stdin.
Julian Kuhn

Cuối cùng, tôi đã đánh bại Ruby. Thật không may, Idone không hỗ trợ Tcl 8.6, nhưng tôi không cần kết quả lmapnhư vậy foreachlà một sự thay thế tốt.
Julian Kuhn

4

Haskell: 124 114 ký tự

j[o]=o
j(u:m:b:o)=j$show((case m of{"+"->(+);"-"->(-);"*"->(*);"/"->(/)})(read u)(read b)):o
main=interact$j.words

Một câu trả lời khá đơn giản, sử dụng khớp mẫu và một tuyên bố trường hợp đơn giản cho việc nâng vật nặng. Sử dụng:

> ./calc <<< "123 - 12 + -12 / 12.124 * 9.99 - 1"
80.57456285054437

1
Thay vì ((case m of{..})(read u)(read b))bạn có thể viết ((case m of{..}$read u)$read b), 2 ký tự ít hơn.
swish

4

C: 111 108 ký tự

main(c){float a,b;for(scanf("%f ",&a);~scanf("%c%f ",&c,&b);a=c^43?c%5?c%2?a/b:a*b:a-b:a+b);printf("%f",a);}

Nó đáp ứng tất cả các yêu cầu, cách sử dụng:

> ./calc <<< "-43 - 56 + 14.123 / -13.22"
6.420348

1
~scanfCó thể thay thế +1. Ngoài ra, c^45-> c%5c^42-> c%2nên hoạt động.
ugoren

@MDXF không có trên máy của tôi, nó vượt qua mọi trường hợp thử nghiệm ở đây. Tôi đang biên dịch với Clang trên một chiếc Macbook Intel khá hiện đại và nó hoạt động rất tốt (tôi đã kiểm tra lại nó ngay bây giờ, tôi đã sao chép mã từ đây và chỉ biên dịch nó mà không có bất kỳ cờ nào). Trình biên dịch, kiến ​​trúc bộ xử lý và hệ điều hành nào bạn đang sử dụng?
Dành cho

@Fors Tôi tin rằng tôi đã có một số cờ kỳ lạ gây ra hành vi lạ; lỗi của tôi, nó làm việc cho tôi bây giờ Xin lỗi đã làm phiền bạn.
MD XF

3

C ++ 0x 205 203 198 194 ký tự

#include<iostream>
#define P [](F l,F r){return l
int main(){typedef float F;F r,v,(*a[])(F,F)={P*r;},P+r;},0,P-r;},0,P/r;}};std::cin>>r;for(char o;std::cin>>o>>v;)r=a[o-42](r,v);std::cout<<r;}

Định dạng độc đáo:

#include<iostream>

int main()
{
    float r,v;
    float (*a[])(float,float)   ={  [](float l,float r){return l*r;},
                                    [](float l,float r){return l+r;},
                                    0,
                                    [](float l,float r){return l-r;},
                                    0,
                                    [](float l,float r){return l/r;}
                                 };

    std::cin>>r;
    for(char o;std::cin>>o>>v;)
        r=a[o-42](r,v);

    std::cout<<r;
}

3

Perl (97)

$b=shift;eval"\$b$r=$s"while($r=shift,$s=shift);print$b

đọc từ tranh luận

$b=shift;$b=($r eq'+'?$b+$s:$r eq'-'?$b-$s:$r eq'*'?$b*$s:$b/$s)while($r=shift,$s=shift);print$b;

đọc từ đầu vào

@_=split/ /,<>;$b=shift@_;$b=($r eq'+'?$b+$s:$r eq'-'?$b-$s:$r eq'*'?$b*$s:$b/$s)while($r=shift@_,$s=shift@_);print$b

3

PostScript (145)

Một mục nhập khác của PostScript (nhờ trình điều khiển luser để đào golf thú vị cho PostScript!):

[/+{add}/-{sub}/*{mul}/{div}>>begin(%stdin)(r)file
999 string readline
pop{token not{exit}if
count 4 eq{3 1 roll
4 1 roll
cvx exec}if
exch}loop
=

Chưa chơi gôn:

[/+{add}/-{sub}/*{mul}/ {div}>>begin
% Read the input
(%stdin)(r)file 999 string readline pop
{                        % .. string
  token not{exit}if      % .. string token
  % If we have 4 objects on the stack, we have two operands, one operator
  % and the input string. This means, we can calculate now.
  count 4 eq{            % a op string b
    % perform operation a op b = c (where op can be +,-,*,/)
    3 1 roll             % a b op string
    4 1 roll             % string a b op 
    cvx exec             % string c
  }if                    % string token (or c)
  exch                   % token string
}loop
=

Anh cứ đánh em đi! +1 Điều này rất thú vị.
luser droog

Nếu bạn có thể đánh bại ô chữ của tôi , tôi sẽ cho bạn một tiền thưởng! NB Bạn chỉ có thể chỉnh sửa 10 lần trước khi bài đăng trở thành CW và phiếu bầu không kiếm được điểm đại diện cho bạn.
luser droog

Tôi tiếp tục đánh bạn vì tôi chỉ chọn những người mà tôi có thể đánh bại bạn ;-). Tôi không chắc liệu tôi có thể với lưới ô chữ không. Tôi có thể sẽ thử, nhưng chỉ trong một vài tuần.
Thomas W.

1
Wiki cộng đồng. Nó có nghĩa là bài viết đã được chỉnh sửa rất nhiều lần bây giờ nó thuộc về cộng đồng. Bất kỳ người dùng nào cũng có thể chỉnh sửa nó (bỏ qua sự chấp thuận của người điều hành đối với các chỉnh sửa được đề xuất thông thường ) và không có thêm điểm. Vì vậy, bất cứ điều gì bạn làm, dừng lại trên Rev 9. Tôi gần như đã thổi nó trên tab guitar một.
kẻ lừa đảo người lái xe

1
Bỏ qua tất cả những gì CW bám. Họ đã sửa nó!
luser droog

3

Con trăn - 308

import sys;i=sys.argv[1].split();o=[];s=[];a=o.append;b=s.pop;c=s.append
for t in i:
 if t in"+-*/":
  if s!=[]:a(b())
  c(t)
 else:a(t)
if s!=[]:a(b())
for t in o:
 if t=="+":c(b()+b())
 elif t=="-":m=b();c(b()-m)
 elif t=="*":c(b()*b())
 elif t=="/":m=b();c(b()/m)
 else:c(float(t))
print(b())

Phiên bản dễ đọc:

# Infix expression calc

import sys

# Shunting-yard algorithm
input = sys.argv[1].split()
output = []
stack = []

for tkn in input:
    if tkn in "+-*/":
        while stack != []:
            output.append(stack.pop())
        stack.append(tkn)
    else:
        output.append(tkn)

while stack != []:
    output.append(stack.pop())

# Eval postfix notation
for tkn in output:
    if tkn == "+":
        stack.append(stack.pop() + stack.pop())
    elif tkn == "-":
        tmp = stack.pop()
        stack.append(stack.pop() - tmp)
    elif tkn == "*":
        stack.append(stack.pop() * stack.pop())
    elif tkn == "/":
        tmp = stack.pop()
        stack.append(stack.pop()/tmp)
    else:
        stack.append(float(tkn))

print(stack.pop())

Lấy biểu thức làm đối số dòng lệnh, đầu ra trên đầu ra tiêu chuẩn.


2

Bản thảo (340)

/D<</+{add}/-{sub}/*{mul}/ {div}>>def/eval{/P null def{token not{exit}if exch/rem exch def
dup D exch known{/P load null ne{D/P load get exch/P exch def exec}{/P exch def}ifelse}if
rem}loop/P load null ne{D/P load get exec}if}def {(> )print flush{(%lineedit)(r)file
dup bytesavailable string readline pop eval == flush}stopped{quit}if}loop

Và dễ đọc hơn một chút:

%!
/oper<</+{add}/-{sub}/*{mul}/ {div}>>def

/eval{
    /op null def
    {
        token not {exit} if
        exch /rem exch def
        dup oper exch known {
            /op load null ne {
                oper /op load get
                exch /op exch def
                exec
            }{
                /op exch def
            } ifelse
        } if
        rem
    } loop
    /op load null ne { oper /op load get exec } if
} def

{
    (> )print flush
    {
    (%lineedit)(r)file
    dup bytesavailable string readline pop
    eval == flush
    } stopped { quit } if
} loop

2

JavaScript (được nén 208 ký tự)

Để rõ ràng, đây là mã trước khi tôi nén nó xuống ( JS-Fiddle của nó ):

function math(match, leftDigit, operator, rightDigit, offset, string) {
    var L = parseFloat(leftDigit)
    var R = parseFloat(rightDigit)
    switch (operator)
    {
        case '*': return L*R;
        case '/': return L/R;
        case '+': return L+R;
        case '-': return L-R;
    }
};

str = prompt("Enter some math:", "-2 + 6 / 2 * 8 - 1 / 2.5 - 18").replace(/ /g, "");
var mathRegex = /(\-?\d+\.?\d*)([\*\/\+\-])(\-?\d+\.?\d*)/;
while(mathRegex.test(str)) {
    str = str.replace(mathRegex, math);
}
alert(str)

Ở đây, nó được nén xuống còn 208 ký tự ( JS-Fiddle của nó ):

function m(x,l,o,r){
    L=(f=parseFloat)(l);
    R=f(r);
    return o=='*'?L*R:o=='/'?L/R:o=='+'?L+R:L-R;
};

M=/(\-?\d+\.?\d*)([\*\/\+\-])(\-?\d+\.?\d*)/;
for(s=prompt().replace(/ /g, "");M.test(s);s=s.replace(M,m)){};
alert(s)

Vì tôi kết thúc dòng bằng dấu chấm phẩy, tất cả các khoảng trắng có thể tháo rời đã bị bỏ qua để đếm ký tự, nhưng để lại cho rõ ràng.


2

Haskell - 124

let p=let f[x]=Just$read x;f(x:o:r)=lookup o[("-",(-)),("+",(+)),("*",(*)),("/",(/))]<*>f r<*>Just(read x)in f.reverse.words

Kết quả sẽ được bọc trong Maybeđơn nguyên

λ: p"-2 + 6 / 2 * 8 - 1 / 2.5 - 18"
Just (-12.0)

Ngoài ra, nó yêu cầu nhập <*>từ Control.Applicative, nhưng nhập có thể được thực hiện bên ngoài mã, vì vậy tôi hy vọng nó được cho phép.


2

C # (234) (231) (229) (223) (214)

class A{void Main(string[]s){var n=1;var o="";var r=0F;foreach(var t in s){if(n>0){var v=float.Parse(t);if(o=="")r=v;if(o=="+")r+=v;if(o=="-")r-=v;if(o=="*")r*=v;if(o=="/")r/=v;}o=t;n=-n;}System.Console.Write(r);}}

class A{
    void Main(string[] s)
    {
      var n = 1;
      var o = "";
      var r = 0F;

      foreach (var t in s)
      {
        if (n > 0)
        {
          var v = float.Parse(t);
          if (o == "") r = v;
          if (o == "+") r += v;
          if (o == "-") r -= v;
          if (o == "*") r *= v;
          if (o == "/") r /= v;
        }
        o = t;
        n = -n;
      }
      System.Console.Write(r);
    }
}

Tôi nhận được '0' cho '1 + 1'. IDEONE
Rob

@Mike Nhập làm đối số, không phải stdin.
Julian Kuhn

1

JavaScript (87 ký tự)

alert(prompt().split(/ +/).reduce((a,b,i)=>i%2?(o=b,a):o+1-0?a-b*-(o+1):o<'/'?a*b:a/b))

1

Java 11, 151 (dưới dạng hàm lambda)

s->{float r=0,t;int o=43,q;for(var x:s.split(" ")){if(x.length()>1|(q=x.charAt(0))>47){t=new Float(x);r=o<43?r*t:o<44?r+t:o<46?r-t:r/t;}o=q;}return r;}

Hàm Lambda lấy đầu vào Chuỗi và xuất ra một dấu phẩy.

Hãy thử trực tuyến.

Java 11, 241 byte (dưới dạng chương trình đầy đủ với I / O được hỏi)

interface M{static void main(String[]a){float r=0,t;int o=43,q;for(var x:new java.util.Scanner(System.in).nextLine().split(" ")){if(x.length()>1|(q=x.charAt(0))>47){t=new Float(x);r=o<43?r*t:o<44?r+t:o<46?r-t:r/t;}o=q;}System.out.print(r);}}

Toàn bộ chương trình lấy một chuỗi String thông qua STDIN và xuất ra STDOUT.

Hãy thử trực tuyến.

Giải trình:

interface M{                  // Class
  static void main(String[]a){//  Mandatory main-method
    float r=0,                //   Result float, starting at 0
          t;                  //   Temp float
    int o=43,                 //   Operator flag, starting at '+'
        q;                    //   Temp operator flag
    for(var x:new java.util.Scanner(System.in)
                              //   Create an STDIN-reader
               .nextLine()    //   Get the user input
               .split(" ")){  //   Split it on spaces, and loop over it:
      if(x.length()>1         //    If the current String length is larger than 1
                              //    (work-around for negative values)
         |(q=x.charAt(0))>47){//    Or the first character is an operator
                              //    (and set `q` to this first character at the same time)
        t=new Float(x);       //     Convert the String to a float, and set it to `t`
        r=                    //     Change `r` to:
          o<43?               //      If `o` is a '*':
            r*t               //       Multiply `r` by `t`
          :o<44?              //      Else-if `o` is a '+':
            r+t               //       Add `r` and `t` together
          :o<46?              //      Else-if `o` is a '-':
            r-t               //       Subtract `t` from `r`
          :                   //      Else (`o` is a '/'):
            r/t;}             //       Divide `r` by `t`
      o=q;}                   //    And at the end of every iteration: set `o` to `q`
    System.out.print(r);}}    //    Print the result `r` to STDOUT

1

05AB1E , 30 byte

#ćs2ôívy`…+-*sk©i-ë®>i+ë®<i*ë/

Hãy thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

#           # Split the (implicit) input-string by spaces
 ć          # Pop the list, and push the remainder and first item separated to the stack
  s         # Swap so the remainder is at the top of the stack
   2ô       # Split it into parts of size 2 (operator + number pairs)
     í      # Reverse each pair so the numbers are before the operators
v           # Loop over each of the pairs:
 y`         #  Push the number and operator separated to the stack
   …+-*     #  Push a string "+-*"
       sk   #  Get the index of the operator in this string
         ©  #  Store this index in the register (without popping)
   i        #  If the index is 1 (the "-"):
    -       #   Subtract the numbers from each other
   ë®>i     #  Else-if the index is 0 (the "+"):
       +    #   Add the numbers together
   ë®<i     #  Else-if the index is 2 (the "*"):
       *    #   Multiply the numbers with each other
   ë        #  Else (the index is -1, so "/"):
    /       #   Divide the numbers from each other
            # (and output the result implicitly)

Nếu một evalnội dung được cho phép, đây có thể là một cách tiếp cận khác ( 16 byte ):

#ćs2ôJv…(ÿ)y«}.E

Hãy thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

#ćs2ô    # Same as above
     J   # Join each operator+number pair together to a single string
v        # Loop over the operator+number strings:
 …(ÿ)    #  Surround the top of the stack in parenthesis
     y«  #  And append the operator+number string
}.E      # After the loop: evaluate the string using a Python-eval

Điều này sẽ thay đổi "-2 + 6 / 2 * 8 - 1 / 2.5 - 18"thành "((((((-2)+6)/2)*8)-1)/2.5)-18"trước khi sử dụng evalnội dung (sử dụng .Etrực tiếp sẽ ưu tiên cho toán tử */hơn +-, do đó chuyển đổi với dấu ngoặc đơn trước).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.