Gelişmiş Hesap Makinesi


28

Gelişmiş bir hesap makinesine girilecek bir dizeyi değerlendiren bir program yazmalısınız.

Program, stdin kullanarak girdiyi kabul etmeli ve doğru cevabı vermelidir. Hiçbir fonksiyonları Stdin kabul etmek gerekiyor diller için, işlevlerini üstlenecek edebilir readLineve printbu görevleri işlemek için.

Gereksinimler:

  • Herhangi bir "eval" işlevini kullanmaz
  • Kayan nokta ve negatif sayıları idare edebilir
  • En azından +, -, *, /, ve ^ operatörlerini destekler
  • Normal düzeni geçersiz kılmak için parantez ve parantezleri destekler
  • Operatörler ve sayılar arasında bir veya daha fazla boşluk içeren girişi idare edebilir
  • Standart işlem sırasını kullanarak girişi değerlendirir

Test Kılıfları

Giriş

10 - 3 + 2

Çıktı

9


Giriş

8 + 6 / 3 - 7 + -5 / 2.5

Çıktı

1


Giriş

4 + [ ( -3 + 5 ) * 3.5 ] ^ 2 - 12

Çıktı

41

1
Çıkarılan sayıların .0sonunda tamsayılar varsa izleri varsa sorun olur mu? Ayrıca: hesap makinesinin ne kadar doğru olması gerekiyor (kayan nokta hassasiyetiyle ilgili)?
sepp2k

1
Çıktının .0sonunda bir iz olabilir . Hassasiyet konusunda pek emin değilim, ama daha fazlası daha iyi.
Kevin Brown,

1
Yığın Taşması versiyonu Matematiksel ifade değerlendiricisi (tam PEMDAS) idi . Buna cevabımın çoğu satır sayıyor olsa da (?!?). Yine de, c.
dmckee

PN / RPN hesaplayıcıları için bonus?
Mateen Ulhaq

Yanıtlar:


8

C ++ 640 583

string k="[]()+-*/^";stack<double> m;stack<char> n;
#define C(o,x,y) ('^'==o?x<y:x<=y)
#define Q(a) double a=m.top();m.pop();
#define R(o) {Q(b)Q(a)m.push(o=='+'?a+b:o=='-'?a-b:o=='*'?a*b:o=='/'?a/b:o=='^'?pow(a,b):0);n.pop();}
while(!cin.eof()){string s;getline(cin,s,' ');if(s.empty())continue;if('\n'==*--s.end())s.erase(--s.end());(s.size()==1&&s.npos!=k.find(s[0]))?({char c=s[0]=='['?'(':s[0]==']'?')':s[0];while(!n.empty()&&'('!= c&&C(c,k.find(c),k.find(n.top())))R(n.top());')'==c?n.pop():n.push(c);}):m.push(strtod(s.c_str(),0));}while(!n.empty())R(n.top());cout<<m.top()<<endl;

senetli

string k="[]()+-*/^";
stack<double> m;
stack<char> n;
#define C(o,x,y) ('^'==o?x<y:x<=y)
#define Q(a) double a=m.top();m.pop();
#define R(o) {Q(b)Q(a)m.push(o=='+'?a+b:o=='-'?a-b:o=='*'?a*b:o=='/'?a/b:o=='^'?pow(a,b):0);n.pop();}
while(!cin.eof())
{
    string s;
    getline(cin,s,' ');
    if(s.empty())continue;
    if('\n'==*--s.end())s.erase(--s.end());
    (s.size()==1&&s.npos!=k.find(s[0]))?({
        char c=s[0]=='['?'(':s[0]==']'?')':s[0];
        while(!n.empty()&&'('!= c&&C(c,k.find(c),k.find(n.top())))
            R(n.top());
        ')'==c?n.pop():n.push(c);
    }):m.push(strtod(s.c_str(),0));
}
while(!n.empty())
    R(n.top());
cout<<m.top()<<endl;

Benim ilk kod golf, yorum ve eleştiri bekliyorum!


JB'nin Perl çözümünün görünmediği üs üs işletmecisinin doğru ilişkisini ele alır.
drspod

Ne sorun bildirimi ne de bağlantılı wikipedia sayfası, üstelikten bahseder, hak ilişkisel olmak zorunda değildir. Dahası, wikipedia sayfası açıkça her iki yolun da ticari hesap makinelerinde bulunduğunu söylüyor.
JB

1
+1 güzelce golf oynadı, ama ... sadece düşme içeriyor using namespace stdve bir ana işlev pek iyi değil, değil mi?
saat

2

PHP - 394 354 312 karakter

<?=e(!$s=preg_split('#\s+#',`cat`,-1,1),$s);function e($P,&$s){$S='array_shift';if(($a=$S($s))=='('|$a=='['){$a=e(0,$s);$S($s);}while($s&&($p=strpos(' +-*/^',$o=$s[0]))&&$p>=$P){$b=e($p+($S($s)!='^'),$s);if($o=='+')$a+=$b;if($o=='-')$a-=$b;if($o=='*')$a*=$b;if($o=='/')$a/=$b;if($o=='^')$a=pow($a,$b);}return$a;}

Girintili'ye:

<?
preg_match_all('#\d+(\.\d+)?|\S#',`cat`,$m);
$s=$m[0];
function e($P) {
        global $s;
        if (strpos(" ([",$s[0])){
                array_shift($s);
                $a=e(0);
                array_shift($s);
        } else {
                $a=array_shift($s);
                if ($a=='-')$a.=array_shift($s);
        }
        while ($s && ($p=strpos(' +-*/^',$o=$s[0])) && $p >= $P) {
                array_shift($s);
                $b = e($p+($o!='^'));
                switch($o){
                case'+':$a+=$b;break;
                case'-':$a-=$b;break;
                case'*':$a*=$b;break;
                case'/':$a/=$b;break;
                case'^':$a=pow($a,$b);
                }
        }
        return $a;
}
echo e(0);

2

Postscript, 446

Bu, şönt bahçe algoritmasını kullanır.

[/*[/p
2/e{mul}>>/d[/p
2/e{div}>>/+[/p
1/e{add}>>/-[/p
1/e{sub}>>/o[/p
9/e{}>>/c[/p
-1/e{}>>/^[/p
3/e{exp}>>/p
0>>begin/s(%stdin)(r)file 999 string readline pop def
0 1 s length 1 sub{s exch[0 1 255{}for]dup[(\(o)([o)(\)c)(]c)(/d)]{{}forall
put dup}forall
pop
3 copy pop
get
get
put}for{s token not{exit}if
exch/s exch store{cvr}stopped{load
dup/p get
p
le{currentdict end
exch begin/e get exec}{begin}ifelse}if}loop{{e end}stopped{exit}if}loop
=

Golfsüz ve yorum yaptı:

% We associate the operators with their precedence /p and the executed commend /e
[
  (*)[/p  2 /e{mul}>>
  (d)[/p  2 /e{div}>> % This is division
  (+)[/p  1 /e{add}>>
  (-)[/p  1 /e{sub}>>
  (o)[/p  9 /e{   }>> % This is open bracket
  (c)[/p -1 /e{   }>> % This is close bracket
  (^)[/p  3 /e{exp}>>
  /p 0
>>begin

% Let's read the input string
/s(%stdin)(r)file 999 string readline pop def

% If we want to use the token operator, we have to replace (, [, ), ] and / to get meaningful results
% We use kind of an encoding array (familiar to PostScripters) to map those codes to o, c, and d.
0 1 s length 1 sub{        % index
  s exch                   % string index
  [0 1 255{}for] dup       % string index translationArray translationArray
  [(\(o)  ([o)  (\)c)  (]c)  (/d)] % string index translationArray translationArray reencodeArray
  {                        % string index translationArray translationArray translationString
    {}forall               % string index translationArray translationArray charCode newCharCode
    put dup                % string index translationArray translationArray
  }forall                  % string index translationArray translationArray
  pop                      % string index translationArray
  3 copy pop               % string index translationArray string index
  get                      % string index translationArray charCode
  get                      % string index translatedCharCode
  put                      % -/-
}for

% Now we can actually start interpreting the string
% We use the stack for storing numbers we read and the dictionary stack for operators that are "waiting"
{                          % number*
  s token not{exit}if      % number* string token
  exch /s exch store       % number* token
  % We try to interpret the token as a number
  {cvr}stopped{            % number* token
    % If interpretation as number fails, we have an operator
    load                   % number* opDict
    % Compare operator precedence with last operator on dictstack
    dup /p get             % number* opDict opPrec
    p                      % number* opDict opPrec prevOpPrec
    le {                   % number* opDict
      % If the last operator on the stack has at least the same precedence, execute it
      currentdict end      % number* opDict prevOpDict
      exch begin           % number* prevOpDict
      /e get exec          % number*
    }{                     % number* opDict
      % If last operator doesn't have higher precedence, put the new operator on the dictstack as well
      begin
    }ifelse
  }if
}loop
% If we're finished with interpreting the string, execute all operators that are left on the dictstack
{{e end}stopped{exit}if}loop
=

TODO : Üstelik doğru ilişkilendirme


Ah ... dictstack: muhteşem!
luser droog 17:12

Stackoverflow hakkında yorum yapmama izin verildi, bu yüzden biraz kafam karıştı. İtibarın ayrı ayrı yönetilmesi normal midir, yoksa girişlerimi mahvetmiş miyim?
Thomas W.

Size, çözümünüzle ilgili bir sorun olması gerektiğini söylemek istedim, çünkü yukarıda verilen üç test durumunun tümü başarısız oldu. Ancak, henüz ne yaptığınızı anlamaya çalışmadım (bazı yorumlar iyi olurdu ;-)).
Thomas W.

1) Herhangi bir sitede 200'e bastığınızda, her sitede 101'den başlayacaksınız. Veya burada 50'ye basın. 2) AUGHH! Temel Hesap Makinesinin hızlı bir uzantısı olduğunu düşündüm. Desteklerin gerekli olduğunu bile görmedim! Ve çok iyi test etmedim. Oh iyi; aşağı pantolon, en azından iç çamaşırlarım temiz!
luser droog

@luserdroog: "@ThomasW" beni yorum yapmaya davet etmiyor.
Thomas W.

1

Piton 2 , 339 335 bayt

import re
x,s=input(),re.sub
def f(y):
 y,r=s('- ','+ -',y).split(),['^','*','/','+','-']
 for c in r:
  while c in y:d=y.index(c)-1;a,b=map(float,[y[d],y[d+2]]);y=y[:d]+[((a,-a)[a<0]**b,a*b,a/b,a+b,a-b)[r.index(c)]]+y[d+3:]
 return`y[0]`
w=lambda b:s("[([]+[\d+\-*/^ .]*[)\]]",lambda m:f(m.group()[1:]),s(' +',' ',b))
print f(w(w(x)))

Çevrimiçi deneyin!

  • -4 byte'ları str (x) değiştirerek backticks ile ``!

0

Postscript, 1000 695 665 494

ThomasW'tan fikir çaldı. Eklenen özellik: işleçlerin etrafında boşluklu veya boşluksuz dizeleri kabul eder.[özellik kaldırıldı]


Kullanımı ARGUMENTS, %stdinönyüklemekten daha kısa ve test etmesi daha kolay!


Sadece parantezle parantez değiştirmek için değiştirme basitleştirildi.

575(1)10:36 PM:ps 0> gsnd -q -- calc2bg.ps '10 - 3 + 2'
9
576(1)10:37 PM:ps 0> gsnd -q -- calc2bg.ps '8 + 6 / 3 - 7 + -5 / 2.5'
1.0
577(1)10:37 PM:ps 0> gsnd -q -- calc2bg.ps '4 + [ ( -3 + 5 ) * 3.5 ] ^ 2 - 12'
41.0

Kod:

/T[/^[/C{exp}/P 4/X{le}>>/*[/C{mul}/P 3/X{lt}>>/[/C{div}/P
3/X{lt}>>/+[/C{add}/P 2/X{lt}>>/-[/C{sub}/P
2/X{lt}>>>>def[/integertype{}/realtype{}/stringtype{V}/nametype{cvlit/N
exch store{P T N get dup/P get exch/X get exec{exit}if C end}loop T N get
begin}91 40 93 41>>begin/V{0 1 2 index length 1 sub{2 copy get
dup where{exch get}if 3 copy put pop pop}for[/N 0/R 0/P 0/C{}>>begin{token
not{exit}if exch/R exch store dup type exec R}loop{P 0 eq{end exit}if C
end}loop}def ARGUMENTS{V ==}forall

Ungolfed ve yorumladı:

%!
%Shunting-Yard Algorithm using dictstack for operators
%invoke with %gsnd -q -- calc2bg.ps [ 'expr1' ]*

%The operator table. C:code P:precedence X:test(implements associativity)
/T[
    /^[/C{exp}/P 4/X{le}>>
    /*[/C{mul}/P 3/X{lt}>>
    /[/C{div}/P 3/X{lt}>>
    /+[/C{add}/P 2/X{lt}>>
    /-[/C{sub}/P 2/X{lt}>>
>>def

%The type-dispatch dictionary
%numbers: do nothing
%string: recurse
%name: process op
[%/integertype{}/realtype{} %now uses `where` below
/stringtype{V}/nametype{
pstack()=
    cvlit/N exch store %stash cur-op
    {
        P %prec(tos)
        T N get %prec(tos) cur-op-dict
        dup/P get %prec(tos) cur-op-dict prec(cur-op)
        exch/X get %prec(tos) prec(cur-op) test(cur-op)
        exec{exit}if %exit if prec(tos) < || <= prec(cur-op)
/C load ==
        C %pop-and-apply
        end
pstack()=
    } loop
    T N get begin %push cur-op
}>>begin

%substitutions
[91 40 93 41>>begin %replace brackets with parens
/V {
    %pre-process
    0 1 2 index length 1 sub {
        2 copy get
        dup where { exch get } if
        3 copy put pop pop
    } for
dup ==

    [/N 0/R 0/P 0/C{}>>begin %dummy base operator and storage
    { token not{exit}if exch /R exch store %extract token, stash Remainder
pstack(>)=
        %dispatch type procedure
        dup type dup where { pop exec }{ pop } ifelse
    R }loop
pstack()=
    {
        P 0 eq{end exit}if %hit dummy op: exit
/C load ==
        C end %pop and apply
    } loop
} def

ARGUMENTS{V ==}forall %iterate through the command-line arguments

@ThomasW Bunun sizi yorum yapmaya davet etmek işe yarayıp yaramadığını merak ediyorum . (?)
luser droog

Aynı fikrin daha eksiksiz bir uygulamasını comp.lang.postscript'te yayınladım .
luser droog
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.