Kalkulator jako lista liczb i operatorów


20

Twoim zadaniem jest pobranie listy argumentów, które są liczbami całkowitymi lub operatorami, i parsowanie ich w następujący sposób:

  1. Obecny operator zaczyna się od +.

  2. Za każdym razem, gdy zostanie znaleziony operator, aktualny operator zmieni się na niego.

  3. Możliwe operatory to: „+”, „-”, „*”, „/” i „%”, które odpowiadają ich znaczeniom w języku C i większości języków.

  4. Zachowywane jest działające rozwiązanie, które zaczyna się od 0.

  5. Za każdym razem, gdy zostanie znaleziona liczba całkowita, rozwiązanie jest modyfikowane przez liczbę zależną od operatora; np. jeśli operatorem jest „/”, wówczas rozwiązanie jest dzielone przez liczbę.

  6. Jeśli operacja spowodowałaby powstanie liczby mieszanej (tj. Dziesiętnej), należy ją przenieść z powrotem do liczby całkowitej (tzn. Przecinek dziesiętny należy odciąć).

  7. Wyjście ostatecznego rozwiązania.

Na przykład:

Argumenty 5 8 25 * 9 6 2 - 104 / 4 7 + 6 % 14skutkowałyby:

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

Dane wejściowe będą w postaci argumentów wiersza polecenia lub funkcji lub równoważnych dla twojego języka.

Najkrótszy kod wygrywa!


kiedy %wymawiasz znaczenia w C, masz na myśli dokładnie to samo, co w C, czy też jest w porządku, jeśli zaokrągla się w kierunku -inf zamiast 0?
Maltysen

@Maltysen: Cokolwiek robi Twój język.
Trebuchette,

3
Czy liczby całkowite z wejścia mogą być ujemne?
Dennis

Punkty 3 i 6 są ze sobą sprzeczne: w języku C i większości języków podział liczb całkowitych zaokrągla się w kierunku zera, a nie podłogi.
Peter Taylor

Odpowiedzi:


6

Pyth - 24 23 22 20 bajtów

2 bajty zapisane dzięki @issacg i 1 dzięki @orlp!

Używa zmniejszania z podstawowym przypadkiem 0i sprawdza, czy 'jest w repr, aby wykryć ciąg vs. int.

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

Nie działa online, ponieważ używam pełnej wersji, która jest wyłączona online ze względów bezpieczeństwa. Zajmuje wejście od stdin na liście jako takie: 5, 8, 25, "*", 9, 6, 2, "-", 104, "/", 4, 7, "+", 6.


Możesz zapisać 2 bajty, przełączając się z ?na .x, ponieważ tylko blok else może zgłosić wyjątek, i zrobi to za każdym razem. Nie możesz Kjuż więcej korzystać . u.xsv++GbH&=bHG+\+QZ, konkretnie.
isaacg

6

JavaScript (ES6) 53

Funkcja przyjmująca tablicę jako dane wejściowe.

Uruchom fragment w przeglądarce Firefox, aby go przetestować.

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>


4

Julia, 85 83 bajtów

s->(o=0;p="+";for i=split(s) isdigit(i)?o=eval(parse("ifloor($o$p$i)")):(p=i)end;o)

Tworzy to nienazwaną funkcję, która akceptuje ciąg wejściowy i zwraca liczbę całkowitą.

Nie golfowany:

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

Naprawiono problem i zapisano 2 bajty dzięki Glen O.


Julia narzeka, że o is not definedkiedy próbujesz uruchomić tę funkcję na świeżo. Próbuje uruchomić funkcję „o = ifloor ...” w Main, a nie wewnątrz funkcji (patrz tutaj github.com/JuliaLang/julia/issues/2386 ). Czy mogę zasugerować s->(o=0;p="+";for i=split(s) isdigit(i)?o=eval(parse("ifloor($o$p$i)")):p=i;end;o)?
Glen O

@GlenO Nie wiem, jak tego nie złapałem. : / Dzięki, naprawiono.
Alex A.

4

elisp, 101 bajtów

Po przekazaniu argumentów jako cytowanej listy: np (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))

Wersja z nowymi liniami:

    (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))

4

CJam, 24 bajty

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

Jest to pełny program, który odczytuje dane wejściowe jako argumenty wiersza poleceń.

Aby wypróbować kod online na tłumacza CJam (która nie obsługuje argumenty wiersza poleceń), wymienić eaz lS/odczytu z symulowanym stdin.

Jak to działa

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.

3

JavaScript, 85 bajtów

r=0;o="+";prompt().split(" ").forEach(t=>+t+1?r=parseInt(eval(r+o+ +t)):o=t);alert(r)

dlaczego o+ +t? i tak budujesz ciąg, nie musisz konwertować na liczbę. Co więcej, .forEachnie ma miejsca w Code Golf: use.map
edc65

... i ~~ zamiast 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 bajtów.
Ismael Miguel

3

Lua, 142 bajty

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

Nie golfowany:

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

3

PowerShell, 57 bajtów

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

bez golfa;

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

Jeśli zmienna niejawna w for-each jest operatorem, a nie liczbą, Wywołanie wyrażenia (POSH eval()) zakończy się niepowodzeniem, a status wykonania $?będzie fałszywy.

Podłoga w POSH jest nieporęczna - $foo=[math]::floor($foo)i $foo-=$foo%1była najbardziej golfową alternatywą, jaką mogłem wymyślić.


Ładny. Przeczytałem to trochę bardziej dosłownie, zakładając ciąg znaków i parsując go na spacjach, a następnie wpisując ifcyfry, ale zasadniczo tak samo. 89 bajtów $o="+";$r=0;$args-split'\s+'|%{if($_-match'^\d+$'){$r=iex $r$o$_;$r-=$r%1}Else{$o=$_}};$r
AdmBorkBork

3

GNU Sed (z rozszerzeniem eval, + dc), 102

(Wynik obejmuje +1 za opcję -r sed.)

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

Przekształca wyrażenie wejściowe w odwrotną notację polską, a następnie używa go dcdo oceny.

Wyjście testowe:

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

2

CJam, 34 bajty

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

Wypróbuj online

Myślałem, że to będzie całkiem rozsądne. Ale nie byłem wystarczająco szybki, aby opublikować to, co najmniej na chwilę, jako najkrótszą odpowiedź CJam. :(


2

Python 3 - 131 bajtów 129 bajtów 121 bajtów 116 bajtów

Dzięki Maltysen za wygolenie dwóch bajtów, Beta Decay za wygolenie 8 i Steven Rumbalski za zgolenie 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

Próbuję wymyślić sposób na skrócenie długości instrukcji if, ale na razie wydaje się, że jestem tak golfistą, jak tylko mogę. Pobiera dane wejściowe jako listę.


można zaoszczędzić kilka bajtów na wgniecenia i zastępowanie intz//1
Maltysen

także, dlaczego parens w `if?
Maltysen

@ Maltysen ups, zapomniałem, że nie potrzebowałem nawiasów w instrukcji if. Dzięki. Nie sądzę, aby użycie // 1 było dozwolone, chociaż nie pomyślałem, aby go użyć, ponieważ wydaje się, że pozostawia końcowe 0 (np. 10,0), co nie wydaje mi się dozwolone.
cole

nie sądzę, żebyś potrzebował tej przestrzeni między ini cytatu.
Maltysen

Możesz zapisać niektóre bajty, zakładając, że lista jest przekazywana w argumentach funkcji i pozbywana się .split().
Beta Decay

2

Bash, 69

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

Działa to tylko z nieujemnymi liczbami całkowitymi - nie jest jasne w pytaniu, czy jest to w porządku, czy nie.


2

Groovy, 79 bajtów

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}

Próbny:

groovy> f([5,8,25,'*',9,6,2,'-',104,'/',4,7,'+',6,'%', 14])
Result: 8

Nie golfowany:

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
}

1

gcc (z ostrzeżeniami) 165 (jeśli koniec linii liczy się jako 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);}

Ale jeśli kompilujesz go za pomocą mingw32, musisz wyłączyć globbing (patrz https://www.cygwin.com/ml/cygwin/1999-11/msg00052.html ), kompilując w ten sposób:

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

1

Perl 5.10+, 52 bajty

perl -E '$o="+";/\D/?$o=$_:eval"\$x=int\$x$o$_"for@ARGV;say$x'

Próbny:

$ 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

(Pamiętaj, że *należy uciec z mojej powłoki, aby nie była interpretowana jako wzorzec globalny).

Nie golfowany:

$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

1

C #, 132 165 168 bajtów

Ta funkcja zakłada, że ​​dane wejściowe są prawidłowe. Jest to trudne dla C #, ponieważ nie ma evalodpowiednika.

Dzięki edc65 za oszczędność 33 bajtów!

Wcięty dla przejrzystości.

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;
}

Możesz usunąć większość nowych linii.
Trebuchette,

Nie policzyłem żadnych nowych linii ani nieznacznych białych znaków.
Hand-E-Food,

1
132 using ?:->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 bajtów

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

Testowe uruchomienie:

$ ruby calc.rb <<< "5 8 25 * 9 6 2 - 104 / 4 7 + 6 % 14"
8
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.