Зворотне польське позначення


41

Ви повинні оцінити рядок, написаний у зворотному польському позначенні та вивести результат.

Програма повинна прийняти вхід і повернути результат. Для мов програмування, які не мають функцій прийому вводу / виводу, ви можете взяти на себе функції, такі як 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
Кріс Єстер-Янг

5
Ось чому це не дозволено :-P, на це запитання в StackOverflow надійшла відповідь на 4 знаки з dc.

1
@SHiNKiROU: Яку мову потрібно використовувати evalдля розбору чисел? Це звучить досить ламано. (Наскільки я знаю, GolfScript є однією з таких мов. Я думаю, що це теж порушено.)
Кріс Jester-Young

3
Як -4 не такий, як 0 4 -?
Кіт Рендалл

1
Я думаю, що eval має бути нормальним, якби просто перетворити рядки в числа. напр. у python eval(s)краще, ніжfloat(s)
gnibbler

Відповіді:


15

Рубі - 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
Ви можете поголити персонажа, використовуючи мапу замість кожної
addison

10

Пітон - 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]

Пітон - 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
Мені подобається маніпуляція зі стеком.
Олександру

2
Ви не можете бути 0другим операндом ...
JBernardo

2
[a/b]слід замінити на b and[a/b]так, щоб у вас був 0 як другий операнд.
flornquake

10

Схема, 162 символів

(Для чіткості додаються розриви рядків - усі необов’язкові.)

(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

† Це технічно не є точним, але для програмістів, які не є Lisp, він отримує достатньо правильну ідею.


Ви можете це прочитати? Серйозно?

1
@ M28: Версія, що не перебуває у віці, так. Я програмую в Схемі на пів регулярній основі (для реальних, серйозних програм).
Кріс Єстер-Янг

На жаль, схема - це багатослівна мова, і, як відомо, важко добре пограти в гольф. Тож я не був би здивований, побачивши, як деякі подання Perl перемогли цю.
Кріс Єстер-Янг

7
Мені подобаються чотири смайлики у версії для гольфу.
tomsmeding

2
lambda (ass)+1 для вибору змінної назви: P
Пуховик

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. Підхід прямо попереду, весь вхід зчитується в буфер, потім ми токенізуємо 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на макро.
FUZxxl

7

Хаскелл (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: _)! [] = Print s" та "main = getLine >> = putStrLn.show. ([]! ) .words "to" main = getLine >> = ([]!). words "
Fors

А потім видаліть ще декілька символів, використовуючи однорядковий випадок з регістру.
Форс

s!(n:v)=case n of{"+"->(+)#s;"-"->(-)#s;"*"->(*)#s;"/"->(/)#s;_->(read n:s)}!vврятувало б 14 символів.
Форс

7

МАТЛАБ - 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

(введення зчитується з введення користувача, вихід друкується).


Нижче наведений код, який попередньо уточнений та прокоментований, він в значній мірі реалізує описаний алгоритм постфікса (з припущенням, що вирази дійсні):

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

Наступного разу я збираюся використовувати рекурсивну рігекс-ріп.

Безголовки:

@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.
долмен

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) - Перша спроба.

30.01.2010 11:09 (170) - Перетворення функції в сценарій блоку вирішує проблеми сфери. Просто збільшує кожне виклик на два байти довше.

2010-01-30 11:19 (188) - Не вирішили проблему із сферою застосування, тестовий випадок просто замаскував її. Однак вилучено індекс з кінцевого виводу та усунув зайвий розрив рядка. І змінився вдвічі на float.

2010-01-30 11:19 (181) - Не можу навіть пригадати власну пораду. Кастинг на числовий тип можна здійснити в одній таблиці.

2010-01-30 11:39 (152) - Значно зменшено за допомогою відповідності регулярних виразів у 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)]))

Розриви рядків необов’язкові.

На основі рішення Кріса Єстер-Янга для схеми.


4

Пітон, 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

(Ви можете знайти 128-символьну версію Python 2 в історії редагування.)


Досить розумно :) Мені подобається, як вам не потрібно /в рядку.
Даніель Лубаров


@EriktheOutgolfer, що розривається з a, ZeroDivisionErrorколи другий операнд дорівнює 0 (наприклад 5 0 +).
flornquake

Ви можете зберегти 1 символ за допомогою ord(x) - 42методу.
frederick99

@ frederick99 Я не бачу як.
flornquake

3

JavaScript (157)

Цей код передбачає, що існують ці дві функції: readLine та print

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

Перл, 128

Це насправді не є конкурентоспроможним поряд з іншою відповіддю Perl, але досліджує інший (неоптимальний) шлях.

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

Пітон, 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

Унгольф, 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 має функції для цього, тому припущення неправильне.
Джой

Оновили його на використання stdin і трохи більше гольфували його.
Кевін Браун

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

Пітон, 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 ви праві, дякую за виправлення.
Даніель Любаров

2

Пітон 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, вам потрібно вимкнути глобулінг (див. 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

Якщо цього не зробити *, автоматично розширюється CRT mingw32.

Хтось знає, як перетворитись 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)));}

Безголовки:

#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 i .


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. видаліть трюк простору імен, чітко визначте два типи, які потребують цього. Ви зберігаєте ключове слово "простір імен" та відповідні дужки. 2. Видаліть пробіли між рядками [] та i, ключовими словами та мітками, перемкніть та його паролі. 3. Позбавтеся від float o і просто використовуйте математику, щоб отримати правильні результати (тобто -k.Pop () + k.Pop () за мінусом, а 1 / k.Pop () * k.Pop () для ділення .
MikeP

1

Scala 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

Пітон - 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]);}}

Редагувати: Заміна стека масивом набагато коротше

Edit2: замінив ifs на потрійний вираз


string[] i=> string[]i.
Zacharý

1

Пітон 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

Матлаб, 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}

Безголовки:

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 Я використовую лише нові рядки, коли не порушувати лінію потрібно буде ;. Тож я думаю, що кількість байтів однакова
Луїс Мендо

не точно, більшість редакторів віконних текстів використовують cr+lfдля нового рядка, який становить 2 символи. Мій блокнот ++ налічував 230 символів у вашій версії з 3 рядками, але лише 128, якщо я вставлю все в один рядок (видалено 2 * 2 = 4 символи з двох нових рядків, і додав два ;). Спробуйте самі;)
Хокі

@Hoki Ви маєте рацію. Насправді, якщо я вставляю три рядкову версію на mothereff.in/byte-counter (що я використовував для підрахунку текстових байтів), він дає 228. І звичайно, це теж те, що я отримую від того, щоб це все було в одному рядок. Я не знаю, звідки я взяв номер 230. Дякую! Виправлено
Луїс Мендо

1

К5, 70 байт

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

Я не впевнений, коли K5 був випущений, так що це може не рахувати. Ще дивовижно!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.