ย้อนกลับสัญกรณ์โปแลนด์


41

คุณต้องประเมินสตริงที่เขียนในรูปแบบReverse Polishและแสดงผลลัพธ์

โปรแกรมต้องยอมรับอินพุตและส่งคืนเอาต์พุต สำหรับภาษาโปรแกรมที่ไม่มีฟังก์ชั่นในการรับอินพุต / เอาต์พุตคุณสามารถใช้ฟังก์ชันเช่น readLine / print

คุณไม่ได้รับอนุญาตให้ใช้ "eval" ใด ๆ ในโปรแกรม

เบอร์และผู้ประกอบการจะถูกแยกออกโดยหนึ่งหรือมากกว่าช่องว่าง

คุณต้องสนับสนุนอย่างน้อย +, -, * และ / โอเปอเรเตอร์

คุณต้องเพิ่มการรองรับกับจำนวนลบ (เช่น-4ไม่ใช่สิ่งเดียวกับ0 4 -) และหมายเลขทศนิยม

คุณสามารถสันนิษฐานได้ว่าอินพุตนั้นถูกต้องและปฏิบัติตามกฎด้านบน


กรณีทดสอบ

การป้อนข้อมูล:

-4 5 +

เอาท์พุท:

1

การป้อนข้อมูล:

5 2 /

เอาท์พุท:

2.5

การป้อนข้อมูล:

5 2.5 /

เอาท์พุท:

2

การป้อนข้อมูล:

5 1 2 + 4 * 3 - +

เอาท์พุท:

14

การป้อนข้อมูล:

4 2 5 * + 1 3 2 * + /

เอาท์พุท:

2

8
มันเป็นความอัปยศไม่มี EVAL ที่ได้รับอนุญาตมิฉะนั้นทางออกที่ GolfScript 1 ~ตัวอักษร: :-P
Chris Jester-Young

5
นั่นเป็นสาเหตุที่ไม่ได้รับอนุญาต :-P คำถามนี้ใน StackOverflow ได้รับคำตอบ 4 ตัวอักษรพร้อม dc

1
@SHiNKiROU: ภาษาใดที่คุณต้องใช้evalในการวิเคราะห์ตัวเลข? มันฟังดูค่อนข้างหัก (GolfScript เป็นหนึ่งในภาษาดังกล่าวเท่าที่ฉันรู้ฉันคิดว่ามันก็หักเช่นกัน)
Chris Jester-Young

3
-4 ไม่เหมือนกับ 0 4 - อย่างไร
Keith Randall

1
ฉันคิดว่า eval น่าจะโอเคถ้ามันแค่แปลงสตริงเป็นตัวเลข เช่น. ในไพ ธ อนeval(s)ดีกว่าfloat(s)
gnibbler

คำตอบ:


15

Ruby - 95 77 ตัวอักษร

a=[]
gets.split.each{|b|a<<(b=~/\d/?b.to_f: (j,k=a.pop 2;j.send b,k))}
p a[0]

ใช้อินพุตบน stdin

รหัสการทดสอบ

[
  "-4 5 +",
  "5 2 /",
  "5 2.5 /",
  "5 1 2 + 4 * 3 - +",
  "4 2 5 * + 1 3 2 * + /",
  "12 8 3 * 6 / - 2 + -20.5 "
].each do |test|
  puts "[#{test}] gives #{`echo '#{test}' | ruby golf-polish.rb`}"
end

จะช่วยให้

[-4 5 +] gives 1.0
[5 2 /] gives 2.5
[5 2.5 /] gives 2.0
[5 1 2 + 4 * 3 - +] gives 14.0
[4 2 5 * + 1 3 2 * + /] gives 2.0
[12 8 3 * 6 / - 2 + -20.5 ] gives 10.0

ซึ่งแตกต่างจากรุ่น C ซึ่งจะส่งกลับผลลัพธ์ที่ถูกต้องล่าสุดหากมีตัวเลขพิเศษผนวกเข้ากับการป้อนข้อมูลดูเหมือนว่า


1
คุณสามารถโกนตัวละครโดยใช้แผนที่แทนตัวละครแต่ละตัว
แอดดิสัน

10

Python - 124 ตัวอักษร

s=[1,1]
for i in raw_input().split():b,a=map(float,s[:2]);s[:2]=[[a+b],[a-b],[a*b],[a/b],[i,b,a]]["+-*/".find(i)]
print s[0]

Python - 133 ตัวอักษร

s=[1,1]
for i in raw_input().split():b,a=map(float,s[:2]);s={'+':[a+b],'-':[a-b],'*':[a*b],'/':[a/b]}.get(i,[i,b,a])+s[2:]
print s[0]

1
ฉันชอบการจัดการกองซ้อน
Alexandru

2
คุณไม่สามารถ0เป็นตัวถูกดำเนินการที่สอง ...
JBernardo

2
[a/b]ควรถูกแทนที่ด้วยb and[a/b]เพื่อให้คุณสามารถมี 0 เป็นตัวถูกดำเนินการที่สอง
flornquake

10

Scheme, 162 chars

(เพิ่มตัวแบ่งบรรทัดเพื่อความชัดเจน - ทั้งหมดเป็นตัวเลือก)

(let l((s'()))(let((t(read)))(cond((number? t)(l`(,t,@s)))((assq t
`((+,+)(-,-)(*,*)(/,/)))=>(lambda(a)(l`(,((cadr a)(cadr s)(car s))
,@(cddr s)))))(else(car s)))))

เวอร์ชันที่มีการจัดรูปแบบเต็ม (ไม่ได้บรรจุ):

(let loop ((stack '()))
  (let ((token (read)))
    (cond ((number? token) (loop `(,token ,@stack)))
          ((assq token `((+ ,+) (- ,-) (* ,*) (/ ,/)))
           => (lambda (ass) (loop `(,((cadr ass) (cadr stack) (car stack))
                                    ,@(cddr stack)))))
          (else (car stack)))))

ความเห็นที่เลือก

`(,foo ,@bar)เป็นเช่นเดียวกับ(cons foo bar)(คือมัน (อย่างมีประสิทธิภาพ ) ผลตอบแทนเป็นรายการใหม่ที่มีfooใช้ได้กับbar) ยกเว้นมันเป็นหนึ่งในตัวละครที่สั้นลงถ้าคุณบีบอัดช่องว่างทั้งหมดออก

ดังนั้นคุณสามารถอ่านประโยคการวนซ้ำได้(loop (cons token stack))และ(loop (cons ((cadr ass) (cadr stack) (car stack)) (cddr stack)))ถ้านั่นง่ายต่อสายตาของคุณ

`((+ ,+) (- ,-) (* ,*) (/ ,/))สร้างรายการเชื่อมโยงที่มีสัญลักษณ์ +จับคู่กับขั้นตอน +และเช่นเดียวกันกับตัวดำเนินการอื่น ดังนั้นมันจึงเป็นตารางการค้นหาสัญลักษณ์แบบง่าย ๆ (คำเปล่าอยู่(read)ในฐานะสัญลักษณ์ซึ่งเป็นสาเหตุที่ไม่tokenจำเป็นต้องดำเนินการเพิ่มเติม) รายการเชื่อมโยงมีการค้นหา O (n) ดังนั้นจึงเหมาะสำหรับรายการสั้น ๆ เท่านั้น :-P

†สิ่งนี้ไม่ถูกต้องทางเทคนิค แต่สำหรับโปรแกรมเมอร์ที่ไม่ใช่เสียงกระเพื่อมก็ทำให้เกิดความคิดที่ถูกต้องพอสมควร


คุณอ่านได้ไหม อย่างจริงจัง?

1
@ M28: รุ่นที่ไม่ดีใช่แล้ว ฉันโปรแกรมใน Scheme แบบกึ่งปกติ (สำหรับโปรแกรมจริงและจริงจัง)
Chris Jester-Young

น่าเสียดายที่ Scheme เป็นภาษา verbose และยากที่จะตีกอล์ฟได้ยาก ดังนั้นฉันจะไม่แปลกใจที่จะเห็นการส่ง Perl บางอย่างชนะอันนี้
Chris Jester-Young

7
ฉันชอบสี่รอยยิ้มในเวอร์ชั่นกอล์ฟ
tomsmeding

2
lambda (ass)+1 สำหรับตัวเลือกชื่อตัวแปร: P
Downgoat

7

c - 424 ตัวละครที่จำเป็น

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define O(X) g=o();g=o() X g;u(g);break;
char*p=NULL,*b;size_t a,n=0;float g,s[99];float o(){return s[--n];};
void u(float v){s[n++]=v;};int main(){getdelim(&p,&a,EOF,stdin);for(;;){
b=strsep(&p," \n\t");if(3>p-b){if(*b>='0'&&*b<='9')goto n;switch(*b){case 0:
case EOF:printf("%f\n",o());return 0;case'+':O(+)case'-':O(-)case'*':O(*)
case'/':O(/)}}else n:u(atof(b));}}

สมมติว่าคุณมี libc เพียงพอที่จะรวมgetdelimใน stdio.h วิธีการจะตรงไปข้างหน้าอินพุตทั้งหมดจะถูกอ่านในบัฟเฟอร์จากนั้นเรา tokenize ด้วยstrsepและใช้ความยาวและอักขระเริ่มต้นเพื่อกำหนดคลาสของแต่ละ ไม่มีการป้องกันอินพุตที่ไม่ดี ป้อน "+ - * / + - ... " และมันจะป๊อปอัปหน่วยความจำอย่างมีความสุข "ด้านล่าง" สแต็กจนกว่ามันจะแยกความผิดพลาด ผู้ประกอบการที่ไม่ใช่ทั้งหมดจะถูกตีความว่าเป็นลอยตัวatofซึ่งหมายถึงค่าศูนย์ถ้าพวกเขาดูเหมือนตัวเลข

อ่านและแสดงความคิดเห็น:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *p=NULL,*b;
size_t a,n=0;
float g,s[99];
float o(){        /* pOp */
  //printf("\tpoping '%f'\n",s[n-1]);
  return s[--n];
};
void u(float v){  /* pUsh */
  //printf("\tpushing '%f'\n",v);
  s[n++]=v;
};
int main(){
  getdelim(&p,&a,EOF,stdin); /* get all the input */
  for(;;){
    b=strsep(&p," \n\t"); /* now *b though *(p-1) is a token and p
                 points at the rest of the input */
    if(3>p-b){
      if (*b>='0'&&*b<='9') goto n;
      //printf("Got 1 char token '%c'\n",*b);
      switch (*b) {
      case 0:
      case EOF: printf("%f\n",o()); return 0;
      case '+': g=o(); g=o()+g; u(g); break;
      case '-': g=o(); g=o()-g; u(g); break;
      case '*': g=o(); g=o()*g; u(g); break;
      case '/': g=o(); g=o()/g; u(g); break;
    /* all other cases viciously ignored */
      } 
    } else { n:
      //printf("Got token '%s' (%f)\n",b,atof(b));
      u(atof(b));
    }
  }
}

การตรวจสอบ:

 $ gcc -c99 rpn_golf.c 
 $ wc rpn_golf.c
  9  34 433 rpn_golf.c
 $ echo -4 5 + | ./a.out
1.000000
 $ echo 5 2 / | ./a.out
2.500000
 $ echo 5 2.5 / | ./a.out
2.000000

หึ! ต้องพูดอะไรกับ*มัน ...

 $ echo "5 1 2 + 4 * 3 - +" | ./a.out
14.000000
 $ echo "4 2 5 * + 1 3 2 * + /" | ./a.out
2.000000

และกรณีทดสอบของฉันเอง

 $ echo "12 8 3 * 6 / - 2 + -20.5 " | ./a.out
-20.500000

คุณสามารถเซฟตัวละครบางตัวโดยแทนที่caseด้วย makro
FUZxxl

7

Haskell (155)

f#(a:b:c)=b`f`a:c
(s:_)![]=print s
s!("+":v)=(+)#s!v
s!("-":v)=(-)#s!v
s!("*":v)=(*)#s!v
s!("/":v)=(/)#s!v
s!(n:v)=(read n:s)!v
main=getLine>>=([]!).words

คุณสามารถลบอักขระได้ 9 ตัวโดยเปลี่ยน "(s: _)! [] = s" เป็น "(s: _)! [] = พิมพ์ s" และ "main = getLine >> = putStrLn.show. ([]! ) .words" เป็น "หลัก = getline >> = ([]) คำว่า"!.
Fors

จากนั้นลบอักขระอื่น ๆ ออกไปโดยใช้คำสั่ง case-one-line
Fors

s!(n:v)=case n of{"+"->(+)#s;"-"->(-)#s;"*"->(*)#s;"/"->(/)#s;_->(read n:s)}!vจะบันทึก 14 ตัวอักษร
Fors

7

MATLAB - 158 , 147

C=strsplit(input('','s'));D=str2double(C);q=[];for i=1:numel(D),if isnan(D(i)),f=str2func(C{i});q=[f(q(2),q(1)) q(3:end)];else q=[D(i) q];end,end,q

(อินพุตถูกอ่านจากอินพุตของผู้ใช้เอาต์พุตที่พิมพ์ออกมา)


ด้านล่างนี้เป็นรหัสที่ได้รับการ prettified และแสดงความคิดเห็นมันค่อนข้างใช้อัลกอริทึม postfix ที่อธิบายไว้ (ด้วยการสันนิษฐานว่านิพจน์นั้นใช้ได้):

C = strsplit(input('','s'));         % prompt user for input and split string by spaces
D = str2double(C);                   % convert to numbers, non-numeric are set to NaN
q = [];                              % initialize stack (array)
for i=1:numel(D)                     % for each value
    if isnan(D(i))                   % if it is an operator
        f = str2func(C{i});          % convert op to a function
        q = [f(q(2),q(1)) q(3:end)]; % pop top two values, apply op and push result
    else
        q = [D(i) q];                % else push value on stack
    end
end
q                                    % show result

โบนัส:

ในโค้ดข้างต้นเราจะถือว่าผู้ประกอบการมักจะไบนารี ( +, -, *, /) เราสามารถทำให้เป็นมาตรฐานโดยใช้nargin(f)เพื่อกำหนดจำนวนของอาร์กิวเมนต์ที่ตัวถูกดำเนินการ / ฟังก์ชั่นที่ต้องการและป๊อปอัพจำนวนค่าที่เหมาะสมจากสแต็คตามเช่นใน:

f = str2func(C{i});
n = nargin(f);
args = num2cell(q(n:-1:1));
q = [f(args{:}) q(n+1:end)];

ด้วยวิธีนี้เราสามารถประเมินการแสดงออกเช่น:

str = '6 5 1 2 mean_of_three 1 + 4 * +'

โดยที่mean_of_threeฟังก์ชั่นที่ผู้ใช้กำหนดมีสามอินพุต:

function d = mean_of_three(a,b,c)
    d = (a+b+c)/3;
end

6

Perl (134)

@a=split/\s/,<>;/\d/?push@s,$_:($x=pop@s,$y=pop@s,push@s,('+'eq$_?$x+$y:'-'eq$_?$y-$x:'*'eq$_?$x*$y:'/'eq$_?$y/$x:0))for@a;print pop@s

ครั้งต่อไปฉันจะใช้สิ่งที่ regexp ซ้ำ

Ungolfed:

@a = split /\s/, <>;
for (@a) {
    /\d/
  ? (push @s, $_)
  : ( $x = pop @s,
      $y = pop @s,
      push @s , ( '+' eq $_ ? $x + $y
                : '-' eq $_ ? $y - $x
                : '*' eq $_ ? $x * $y
                : '/' eq $_ ? $y / $x
                : 0 )
      )
}
print(pop @s);

ฉันว่า F # เป็นภาษาการเขียนโปรแกรมในฝันของฉันเท่านั้น ...


ฉันมีการติดตั้ง Perl 5 ที่สั้นกว่า
dolmen

6

Windows PowerShell, 152 181 192

ในรูปแบบที่อ่านได้เพราะตอนนี้มันเป็นเพียงสองบรรทัดโดยไม่มีโอกาสที่จะทำลายพวกเขา:

$s=@()
switch -r(-split$input){
  '\+'        {$s[1]+=$s[0]}
  '-'         {$s[1]-=$s[0]}
  '\*'        {$s[1]*=$s[0]}
  '/'         {$s[1]/=$s[0]}
  '-?[\d.]+'  {$s=0,+$_+$s}
  '.'         {$s=$s[1..($s.count)]}}
$s

2010-01-30 11:07 (192) - ความพยายามครั้งแรก

2010-01-30 11:09 (170) - การเปลี่ยนฟังก์ชั่นเป็น scriptblock แก้ปัญหาขอบเขต เพียงแค่ทำให้แต่ละการเรียกใช้สองไบต์ยาวขึ้น

2010-01-30 11:19 (188) - ไม่ได้แก้ปัญหาขอบเขตกรณีทดสอบเพิ่งปิดบัง ลบดัชนีออกจากผลลัพธ์สุดท้ายและลบเส้นแบ่งที่ไม่จำเป็นออก floatและเปลี่ยนไปเป็นคู่

2010-01-30 11:19 (181) - จำคำแนะนำของฉันไม่ได้ การหล่อเป็นตัวเลขสามารถทำได้ในถ่านเดียว

11:39 2010/01/30 (152) - ลดลงอย่างมากโดยใช้การจับคู่ regex switchใน แก้ปัญหาขอบเขตก่อนหน้าโดยสิ้นเชิงด้วยการเข้าถึงสแต็กเพื่อเปิดออก


5

แร็กเก็ต 131:

(let l((s 0))(define t(read))(cond[(real? t)
(l`(,t,@s))][(memq t'(+ - * /))(l`(,((eval t)(cadr s)
(car s)),@(cddr s)))][0(car s)]))

ตัวแบ่งบรรทัดเป็นตัวเลือก

อ้างอิงจากวิธีแก้ปัญหาของ Chris Jester-Young สำหรับ Scheme


4

Python, 166 อักขระ

import os,operator as o
S=[]
for i in os.read(0,99).split():
 try:S=[float(i)]+S
 except:S=[{'+':o.add,'-':o.sub,'/':o.div,'*':o.mul}[i](S[1],S[0])]+S[2:]
print S[0]

ใช้raw_input()รหัสไม่แยกหลายบรรทัด
JPvdMerwe

จากนั้นคุณสามารถลอง: from operator import*และแทนที่ด้วยo.div div
JPvdMerwe

4

Python 3, 119 ไบต์

s=[]
for x in input().split():
 try:s+=float(x),
 except:o='-*+'.find(x);*s,a,b=s;s+=(a+b*~-o,a*b**o)[o%2],
print(s[0])

การป้อนข้อมูล: 5 1 1 - -7 0 * + - 2 /

เอาท์พุท: 2.5

(คุณสามารถค้นหารุ่น Python 2 ได้ 128 ตัวในประวัติการแก้ไข)


ฉลาดมาก :) ฉันชอบวิธีที่คุณไม่ต้องการ/ในสตริง
Daniel Lubarov


@EriktheOutgolfer ที่ตัดกับZeroDivisionErrorเมื่อตัวถูกดำเนินการตัวที่สองคือ 0 (เช่น5 0 +)
flornquake

คุณสามารถบันทึก 1 ตัวอักษรโดยใช้ord(x) - 42วิธีการ
frederick99

@ frederick99 ฉันไม่เห็นวิธี
flornquake

3

จาวาสคริปต์ (157)

รหัสนี้ถือว่ามีสองฟังก์ชั่นนี้: readLine และการพิมพ์

a=readLine().split(/ +/g);s=[];for(i in a){v=a[i];if(isNaN(+v)){f=s.pop();p=s.pop();s.push([p+f,p-f,p*f,p/f]['+-*/'.indexOf(v)])}else{s.push(+v)}}print(s[0])

สั้นถ้าคุณใช้prompt()แทนreadLine()(และอาจจะalert()แทนprint()จะมีการแข่งขันprompt())
nyuszika7h

3

Perl, 128

นี่ไม่ใช่การแข่งขันที่แท้จริงถัดจากคำตอบ Perl อื่น ๆ แต่สำรวจเส้นทางที่แตกต่าง (suboptimal)

perl -plE '@_=split" ";$_=$_[$i],/\d||
do{($a,$b)=splice@_,$i-=2,2;$_[$i--]=
"+"eq$_?$a+$b:"-"eq$_?$a-$b:"*"eq$_?
$a*$b:$a/$b;}while++$i<@_'

ตัวละครนับว่าแตกต่างกับการperl -e ''เรียกใช้ที่เรียบง่าย


2

Python, 161 ตัวอักษร:

from operator import*;s=[];i=raw_input().split(' ')
q="*+-/";o=[mul,add,0,sub,0,div]
for c in i:
 if c in q:s=[o[ord(c)-42](*s[1::-1])]+s 
 else:s=[float(c)]+s
print(s[0])

2

PHP, 439 265 263 262 244 240 ตัวอักษร

<? $c=fgets(STDIN);$a=array_values(array_filter(explode(" ",$c)));$s[]=0;foreach($a as$b){if(floatval($b)){$s[]=$b;continue;}$d=array_pop($s);$e=array_pop($s);$s[]=$b=="+"?$e+$d:($b=="-"?$e-$d:($b=="*"?$e*$d:($b=="/"?$e/$d:"")));}echo$s[1];

รหัสนี้ควรทำงานกับ stdin แม้ว่าจะไม่ได้ทดสอบด้วย stdin

มันได้รับการทดสอบในทุกกรณีเอาท์พุท (และรหัส) สำหรับคนสุดท้ายอยู่ที่นี่:
http://codepad.viper-7.com/fGbnv6

Ungolfed, 314 330 326 ตัวอักษร

<?php
$c = fgets(STDIN);
$a = array_values(array_filter(explode(" ", $c)));
$s[] = 0;
foreach($a as $b){
    if(floatval($b)){
        $s[] = $b;
        continue;
    }
    $d = array_pop($s);
    $e = array_pop($s);
    $s[] = $b == "+" ? $e + $d : ($b == "-" ? $e - $d : ($b == "*" ? $e * $d : ($b == "/" ? $e / $d :"")));
}
echo $s[1];

อ้างอิงจากคำอธิบายงาน: »สำหรับภาษาการเขียนโปรแกรมที่ไม่มีฟังก์ชั่นในการรับอินพุต / เอาท์พุตคุณสามารถสมมติฟังก์ชั่นเช่น readLine / print « - PHP ที่สาธิตได้มีฟังก์ชั่นการใช้งานดังนั้นสมมติฐานจึงไม่ถูกต้อง
Joey

อัปเดตให้ใช้ stdin และ golfed เพิ่มอีกนิด
Kevin Brown

2

งอ - 157

%{
float b[100],*s=b;
#define O(o) s--;*(s-1)=*(s-1)o*s;
%}
%%
-?[0-9.]+ *s++=strtof(yytext,0);
\+ O(+)
- O(-)
\* O(*)
\/ O(/)
\n printf("%g\n",*--s);
.
%%

หากคุณไม่คุ้นเคยให้คอมไพล์ด้วย flex rpn.l && gcc -lfl lex.yy.c


2

Python 130 ตัว

น่าจะเป็น 124 ตัวอักษรถ้าเราทิ้งb and(ซึ่งคำตอบของ Python บางคำหายไป) และมันรวม 42!

s=[]
for x in raw_input().split():
 try:s=[float(x)]+s
 except:b,a=s[:2];s[:2]=[[a*b,a+b,0,a-b,0,b and a/b][ord(x)-42]]
print s[0]

คำตอบที่ดีจริงๆ แต่ฉันนับ 130 ตัว ;)
flornquake

@ flornquake คุณพูดถูกต้องขอบคุณสำหรับการแก้ไข
Daniel Lubarov

2

Python 3, 126 132 ตัวอักษร

s=[2,2]
for c in input().split():
    a,b=s[:2]
    try:s[:2]=[[a+b,b-a,a*b,a and b/a]["+-*/".index(c)]]
    except:s=[float(c)]+s
print(s[0])

มีวิธีแก้ไขปัญหาที่ดีกว่าอยู่แล้ว แต่ตอนนี้ฉันเขียนมัน (โดยไม่ต้องอ่านบทความก่อนหน้านี้แน่นอน - แม้ว่าฉันต้องยอมรับว่ารหัสของฉันดูเหมือนว่าฉันได้คัดลอกมันด้วยกัน) ฉันต้องการแบ่งปัน เกินไป.


b/aควรแทนที่ด้วยa and b/aมิฉะนั้นโซลูชันนี้จะไม่ทำงานหากตัวถูกดำเนินการตัวที่สองเป็น 0 (เช่น4 0 -)
flornquake

@flornquake แก้ไขให้เขา
mbomb007

2

c99 gcc 235

สิ่งนี้ใช้ได้กับฉัน (พร้อมคำเตือน):

#include <stdlib.h>
#define O(x):--d;s[d]=s[d]x s[d+1];break;
float s[99];main(c,v)char**v;{for(int i=1,d=0;i<c;i++)switch(!v[i][1]?*v[i]:' '){case'+'O(+)case'-'O(-)case'*'O(*)case'/'O(/)default:s[++d]=atof(v[i]);}printf("%f\n",s[1]);}

แต่ถ้าคุณกำลังคอมไพล์ด้วย mingw32 คุณต้องปิด globbing (ดูhttps://www.cygwin.com/ml/cygwin/1999-11/msg00052.html ) โดยการคอมไพล์ดังนี้:

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

หากคุณไม่ * ถูกขยายโดย mingw32 CRT โดยอัตโนมัติ

ไม่มีใครรู้วิธีเปลี่ยนbreak;case'*':s[--d]*=s[d+1];เป็นมาโครที่ยอมรับอักขระ + เป็นพารามิเตอร์ได้เพราะทั้งสี่กรณีจะเป็นเช่นนั้นO(+)O(-)O(*)O(/)

H:\Desktop>gcc -std=c99 x.c C:\Applications\mingw32\i686-w64-mingw32\lib\CRT_noglob.o
x.c:3:13: warning: return type defaults to 'int'
 float s[99];main(c,v)char**v;{for(int i=1,d=0;i<c;i++)switch(!v[i][1]?*v[i]:' '){case'+'O(+)case'-'O(-)case'*'O(*)case'/'O(/)default:s[++d]=atof(v[i]);}printf("%f\n",s[1]);}
x.c: In function 'main':
x.c:3:13: warning: type of 'c' defaults to 'int'
x.c:3:1: warning: implicit declaration of function 'atof' [-Wimplicit-function-declaration]
 float s[99];main(c,v)char**v;{for(int i=1,d=0;i<c;i++)switch(!v[i][1]?*v[i]:' '){case'+'O(+)case'-'O(-)case'*'O(*)case'/'O(/)default:s[++d]=atof(v[i]);}printf("%f\n",s[1]);}
x.c:3:1: warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration]
x.c:3:153: warning: incompatible implicit declaration of built-in function 'printf'
 float s[99];main(c,v)char**v;{for(int i=1,d=0;i<c;i++)switch(!v[i][1]?*v[i]:' '){case'+'O(+)case'-'O(-)case'*'O(*)case'/'O(/)default:s[++d]=atof(v[i]);}printf("%f\n",s[1]);}
H:\Desktop>a -4 5 +
1.000000
H:\Desktop>a 5 2 /
2.500000
H:\Desktop>a 5 2.5 /
2.000000
H:\Desktop>a 5 1 2 + 4 * 3 - +
14.000000
H:\Desktop>a 4 2 5 * + 1 3 2 * + /
2.000000

2

C, 232 229 ไบต์

สนุกกับการเรียกซ้ำ

#include <stdlib.h>
#define b *p>47|*(p+1)>47
char*p;float a(float m){float n=strtof(p,&p);b?n=a(n):0;for(;*++p==32;);m=*p%43?*p%45?*p%42?m/n:m*n:m-n:m+n;return*++p&&b?a(m):m;}main(c,v)char**v;{printf("%f\n",a(strtof(v[1],&p)));}

Ungolfed:

#include <stdlib.h>

/* Detect if next char in buffer is a number */
#define b *p > 47 | *(p+1) > 47

char*p; /* the buffer */

float a(float m)
{
    float n = strtof(p, &p); /* parse the next number */

    /* if the next thing is another number, recursively evaluate */
    b ? n = a(n) : 0;

    for(;*++p==32;); /* skip spaces */

    /* Perform the arithmetic operation */
    m = *p%'+' ? *p%'-' ? *p%'*' ? m/n : m*n : m-n : m+n;

    /* If there's more stuff, recursively parse that, otherwise return the current computed value */
    return *++p && b ? a(m) : m;
}

int main(int c, char **v)
{
    printf("%f\n", a(strtof(v[1], &p)));
}

กรณีทดสอบ:

$ ./a.out "-4 5 +"
1.000000
$ ./a.out "5 2 /"
2.500000
$ ./a.out "5 2.5 /"
2.000000
$ ./a.out "5 1 2 + 4 * 3 - +"
14.000000
$ ./a.out "4 2 5 * + 1 3 2 * + /"
2.000000

2

JavaScript ES7, 119 ไบต์

ฉันได้รับบั๊กที่มีความเข้าใจในอาร์เรย์ดังนั้นฉันจึงใช้ .map

(s,t=[])=>(s.split` `.map(i=>+i?t.unshift(+i):t.unshift((r=t.pop(),o=t.pop(),[r+o,r-o,r*o,r/o]['+-*/'.indexOf(i)]))),t)

ลองออนไลน์ได้ที่ ESFiddle


มีล่าม ES7 หรือไม่?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴสิ่งนี้น่าจะใช้ได้กับ Firefox คุณสามารถลองbabeljs.io/repl
Downgoat

อ้อเข้าใจแล้ว. ^ _ ^ ขอบคุณ!
Conor O'Brien

1

PHP - 259 ตัวอักษร

$n=explode(" ",$_POST["i"]);$s=array();for($i=0;$i<count($n);$s=$d-->0?array_merge($s,!$p?array($b,$a,$c):array($p)):$s){if($c=$n[$i++]){$d=1;$a=array_pop($s);$b=array_pop($s);$p=$c=="+"?$b+$a:($c=="-"?$b-$a:($c=="*"?$b*$a:($c=="/"?$b/$a:false)));}}echo$s[2];

สมมติว่าการป้อนข้อมูลในตัวแปร POST ฉัน


2
ยกมาจากคำอธิบายดั้งเดิม»สำหรับภาษาการเขียนโปรแกรมที่ไม่มีฟังก์ชั่นในการรับอินพุต / เอาต์พุตคุณสามารถสมมติฟังก์ชั่นเช่น readLine / print « PHP มีวิธีรับ stdin ผ่านสตรีม
เควินบราวน์

1

C # - 392 ตัวอักษร

namespace System.Collections.Generic{class P{static void Main(){var i=Console.ReadLine().Split(' ');var k=new Stack<float>();float o;foreach(var s in i)switch (s){case "+":k.Push(k.Pop()+k.Pop());break;case "-":o=k.Pop();k.Push(k.Pop()-o);break;case "*":k.Push(k.Pop()*k.Pop());break;case "/":o=k.Pop();k.Push(k.Pop()/o);break;default:k.Push(float.Parse(s));break;}Console.Write(k.Pop());}}}

อย่างไรก็ตามหากสามารถใช้อาร์กิวเมนต์แทนอินพุตมาตรฐานเราสามารถนำมาใช้กับ

C # - 366 ตัวอักษร

namespace System.Collections.Generic{class P{static void Main(string[] i){var k=new Stack<float>();float o;foreach(var s in i)switch (s){case "+":k.Push(k.Pop()+k.Pop());break;case "-":o=k.Pop();k.Push(k.Pop()-o);break;case "*":k.Push(k.Pop()*k.Pop());break;case "/":o=k.Pop();k.Push(k.Pop()/o);break;default:k.Push(float.Parse(s));break;}Console.Write(k.Pop());}}}

คุณสามารถบันทึก 23 ตัวอักษรด้วยการปรับให้เหมาะสมเล็กน้อย: 1. ลบเคล็ดลับเนมสเปซออกคุณสมบัติสองประเภทที่ต้องการอย่างชัดเจน คุณบันทึกคำสำคัญ "namespace" และวงเล็บที่เกี่ยวข้อง 2. ลบช่องว่างระหว่างสตริง [] และ i คำหลักและตัวพิมพ์เล็กและตัวพิมพ์สลับและการเว้นวรรค 3. กำจัด float o และใช้คณิตศาสตร์เพื่อให้ได้ผลลัพธ์ที่ถูกต้อง (เช่น -k.Pop () + k.Pop () สำหรับลบและ 1 / k.Pop () * k.Pop () เพื่อหาร .
MikeP

1

สกาล่า412 376 349 335 312:

object P extends App{
def p(t:List[String],u:List[Double]):Double={
def a=u drop 2
t match{
case Nil=>u.head
case x::y=>x match{
case"+"=>p(y,u(1)+u(0)::a)
case"-"=>p(y,u(1)-u(0)::a)
case"*"=>p(y,u(1)*u(0)::a)
case"/"=>p(y,u(1)/u(0)::a)
case d=>p(y,d.toDouble::u)}}}
println(p((readLine()split " ").toList,Nil))}

1

Python - 206

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

เวอร์ชันที่ไม่ถูกปรับแต่ง:

# RPN

import sys

input = sys.argv[1].split()
stack = []

# Eval postfix notation
for tkn in input:
    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())

อินพุตจากอาร์กิวเมนต์บรรทัดคำสั่ง เอาต์พุตบนเอาต์พุตมาตรฐาน


1

ECMAScript 6 (131)

เพียงพิมพ์ด้วยกันในไม่กี่วินาทีดังนั้นมันอาจจะสามารถตีกอล์ฟได้ไกลขึ้นหรืออาจจะดีขึ้นก็ได้ พรุ่งนี้ฉันจะกลับมาทบทวนอีกครั้ง:

f=s=>(p=[],s.split(/\s+/).forEach(t=>+t==t?p.push(t):(b=+p.pop(),a=+p.pop(),p.push(t=='+'?a+b:t=='-'?a-b:t=='*'?a*b:a/b))),p.pop())

1

C # - 323 284 241

class P{static void Main(string[] i){int x=0;var a=new float[i.Length];foreach(var s in i){var o="+-*/".IndexOf(s);if(o>-1){float y=a[--x],z=a[--x];a[x++]=o>3?z/y:o>2?z*y:o>1?z-y:y+z;}else a[x++]=float.Parse(s);}System.Console.Write(a[0]);}}

แก้ไข: การแทนที่สแต็กด้วยอาเรย์นั้นสั้นกว่า

แก้ไข 2: แทนที่ ifs ด้วยนิพจน์ประกอบไปด้วย


string[] istring[]i=>
Zacharý

1

Python 2

ฉันได้ลองใช้แนวทางที่แตกต่างกับวิธีที่เผยแพร่ไปแล้ว สิ่งเหล่านี้ไม่ได้ค่อนข้างสั้นเท่าโซลูชั่น Python ที่ดีที่สุด แต่ก็อาจจะน่าสนใจสำหรับคุณบางคน

ใช้การเรียกซ้ำ, 146

def f(s):
 try:x=s.pop();r=float(x)
 except:b,s=f(s);a,s=f(s);r=[a+b,a-b,a*b,b and a/b]['+-*'.find(x)]
 return r,s
print f(raw_input().split())[0]

ใช้การจัดการรายการ 149

s=raw_input().split()
i=0
while s[1:]:
 o='+-*/'.find(s[i])
 if~o:i-=2;a,b=map(float,s[i:i+2]);s[i:i+3]=[[a+b,a-b,a*b,b and a/b][o]]
 i+=1
print s[0]

ใช้reduce(), 145

print reduce(lambda s,x:x in'+-*/'and[(lambda b,a:[a+b,a-b,a*b,b and a/b])(*s[:2])['+-*'.find(x)]]+s[2:]or[float(x)]+s,raw_input().split(),[])[0]

1

Matlab, 228

F='+-/*';f={@plus,@minus,@rdivide,@times};t=strsplit(input('','s'),' ');i=str2double(t);j=~isnan(i);t(j)=num2cell(i(j));while numel(t)>1
n=find(cellfun(@(x)isstr(x),t),1);t{n}=bsxfun(f{t{n}==F},t{n-2:n-1});t(n-2:n-1)=[];end
t{1}

Ungolfed:

F = '+-/*'; %// possible operators
f = {@plus,@minus,@rdivide,@times}; %// to be used with bsxfun
t = strsplit(input('','s'),' '); %// input string and split by one or multiple spaces
i = str2double(t); %// convert each split string to number
j =~ isnan(i); %// these were operators, not numbers ...
t(j) = num2cell(i(j)); %// ... so restore them
while numel(t)>1
    n = find(cellfun(@(x)isstr(x),t),1); %// find left-most operator
    t{n} = bsxfun(f{t{n}==F}, t{n-2:n-1}); %// apply it to preceding numbers and replace
    t(n-2:n-1)=[]; %// remove used numbers
end
t{1} %// display result

คุณสามารถบันทึก 2 ไบต์ได้มากขึ้นโดยใส่ทุกอย่างไว้ในบรรทัดเดียว (หรือใช้โปรแกรมแก้ไขข้อความซึ่งใช้อักขระเพียงตัวเดียวในการขึ้นบรรทัดใหม่)
Hoki

@Hoki ;ฉันเพียงแค่ใช้สายใหม่เมื่อไม่หมดเส้นจะต้องมี ดังนั้นฉันคิดว่าการนับไบต์เหมือนกัน
Luis Mendo

ไม่แน่นอนตัวแก้ไขข้อความหน้าต่างส่วนใหญ่ใช้cr+lfสำหรับการขึ้นบรรทัดใหม่ซึ่งเป็น 2 อักขระ แผ่นจดบันทึกของฉัน ++ นับ 230 ตัวอักษรในรุ่น 3 บรรทัดของคุณ แต่เพียง 128 ถ้าฉันติดทุกอย่างในบรรทัดเดียว (ลบ 2 * 2 = 4 ตัวอักษรจาก 2 บรรทัดใหม่และเพิ่มอีกสอง;) ลองด้วยตัวเอง;)
Hoki

@Hoki คุณพูดถูก ในความเป็นจริงถ้าฉันวางเวอร์ชันสามบรรทัดลงบนmothereff.in/byte-counter (ซึ่งเป็นสิ่งที่ฉันใช้ในการนับไบต์ข้อความ) จะให้ 228 และแน่นอนว่านั่นคือสิ่งที่ฉันได้รับจากการใส่ไว้ในที่เดียว เส้น ฉันไม่รู้ว่าฉันได้เบอร์จาก 230 มาจากไหน ขอบคุณ! แก้ไขแล้ว
Luis Mendo

1

K5, 70 ไบต์

`0:*{$[-9=@*x;((*(+;-;*;%)@"+-*/"?y).-2#x;x,.y)@47<y;(.x;.y)]}/" "\0:`

ฉันไม่แน่ใจว่าเมื่อ K5 เปิดตัวดังนั้นอาจไม่นับ ยังยอดเยี่ยม!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.