Калькулятор як список номерів та операторів


20

Ваше завдання - взяти список аргументів, які є або цілими числами, або операторами, і проаналізувати їх так:

  1. Є поточний оператор, який починається як +.

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

  3. Можливі оператори: "+", "-", "*", "/" та "%", які відповідають їх значенню на C та більшості мов.

  4. Є збережене рішення, яке починається з 0.

  5. Щоразу, коли знайдено ціле число, рішення змінюється на число залежно від оператора; наприклад, якщо оператор "/", тоді рішення ділиться на число.

  6. Якщо операція призведе до змішаного числа (тобто з десятковою), то вона повинна бути повернута до цілого числа (тобто десяткові повинні бути відсічені).

  7. Виведіть остаточне рішення.

Наприклад:

Аргументи 5 8 25 * 9 6 2 - 104 / 4 7 + 6 % 14призведуть до:

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

Вхідні дані будуть аргументами командного рядка або функції, або еквівалентом для вашої мови.

Найкоротший код виграє!


коли ви говорите значення C, ви маєте на увазі точно так, як вони роблять у C, чи це нормально, якщо %круги до -inf замість 0?
Мальтісен

@Maltysen: Що б не робила твоя мова.
Trebuchette

3
Чи можуть цілі числа введення бути від’ємними?
Денніс

Пункти 3 та 6 суперечать один одному: у мові C та більшості мов ціле ділення округляється до нуля, а не до підлоги.
Пітер Тейлор

Було б цікаво побачити ще один виклик, подібний до цього, але включаючи пріоритет дужок ...
Joshpbarron

Відповіді:


6

Pyth - 24 23 22 20 байт

2 байти збережено завдяки @issacg та 1 подяку @orlp!

Використання зменшується з базовим регістром 0та перевіряє наявність 'у repr для виявлення рядка проти int.

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

Не працює в Інтернеті, оскільки я використовую повний eval, який відключений в Інтернеті з міркувань безпеки. Приймає вхідний сигнал від стандартного введення в списку , як , наприклад: 5, 8, 25, "*", 9, 6, 2, "-", 104, "/", 4, 7, "+", 6.


Ви можете зберегти 2 байти, переключившись ?на .x, тому що лише інший блок може викинути виняток, і це буде робити кожен раз. Ти вже не можеш користуватися K. u.xsv++GbH&=bHG+\+QZконкретно.
isaacg

6

JavaScript (ES6) 53

Функція, що приймає масив як вхідний.

Запустіть фрагмент у Firefox для тестування.

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

Джулія, 85 83 байти

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

Це створює неназвану функцію, яка приймає рядок як вхідний і повертає ціле число.

Безголівки:

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

Виправлена ​​проблема та збережено 2 байти завдяки Глен О.


Юлія скаржиться, що o is not definedколи ви намагаєтеся виконувати функцію свіжо. Він намагається запустити функцію "o = ifloor ..." в Main, а не всередині функції (див. Тут github.com/JuliaLang/julia/isissue/2386 ). Чи можу я запропонувати s->(o=0;p="+";for i=split(s) isdigit(i)?o=eval(parse("ifloor($o$p$i)")):p=i;end;o)?
Глен О

@GlenO Я не знаю, як я цього не зрозумів. : / Дякую, виправлено.
Олексій А.

4

елісп, 101 байт

З аргументами, поданими як список цитованих: напр (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))

Версія з новими рядками:

    (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 байти

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

Це повна програма, яка читає введення як аргументи командного рядка.

Щоб спробувати код онлайн в інтерпретаторі CJam (який не підтримує аргументи командного рядка), замінітьea з lS/читанням з моделируемого STDIN.

Як це працює

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 байт

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

чому o+ +t? ви все одно будуєте рядок, не потрібно перетворювати на число. Більше того, .forEachу Code Golf немає місця: use.map
edc65

... і ~~ замість 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 байт.
Ісмаїл Мігель

3

Луа, 142 байти

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

Безголівки:

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 байт

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

неозорий;

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

Якщо непряма змінна в for-every є оператором, а не числом, Invoke-Expression (POSH's eval()) не вдасться, а стан виконання $?буде хибним.

Підлога в POSH є непростим - $foo=[math]::floor($foo)і це $foo-=$foo%1була найкраща альтернатива, яку я міг придумати.


Приємно. Я читаю його трохи більш буквально, припускаючи введення рядка та розбираючи його на пробіли, потім ifрозміщуючи цифри, але по суті те саме. 89 байт $o="+";$r=0;$args-split'\s+'|%{if($_-match'^\d+$'){$r=iex $r$o$_;$r-=$r%1}Else{$o=$_}};$r
AdmBorkBork

3

GNU Sed (з розширенням eval, + dc), 102

(Оцінка включає +1 для опції -r до сед.)

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

Перетворює вхідний вираз у зворотну польську нотацію, а потім використовує dc для його оцінки.

Тестовий вихід:

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

2

CJam, 34 байти

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

Спробуйте в Інтернеті

Я вважав, що це буде досить розумним. Але я не був достатньо швидким, щоб розмістити його, щоб бути хоча б на мить найкоротшою відповіддю CJam. :(


2

Python 3 - 131 байт 129 байт 121 байт 116 байт

Дякуємо Малтісену за бриття двох байтів, Beta Decay за гоління 8, та Стівена Румбальського за гоління 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

Я намагаюся знайти спосіб зменшити довжину твердження if, але наразі це здається настільки гольовим, як я можу його отримати. Вводиться як список.


Ви можете зберегти кілька байт на відступи і заміна intз//1
Maltysen

Крім того, чому паролі в `якщо?
Мальтісен

@ Maltysen озвучує, я забув, що мені не потрібні дужки в операторі if. Спасибі. Я не думаю, що використання // 1 буде дозволено, хоча я не думав використовувати його, оскільки, здається, він залишає пробіл 0 (наприклад, 10.0), що, на мою думку, не дозволено.
Коул

я не думаю, що вам потрібен простір між inцитатою.
Мальтісен

Ви можете зберегти деякі байти, припустивши, що список переданий в аргументах функції та позбутися .split().
Бета-розпад

2

Баш, 69

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

Це працює лише з невід’ємними цілими числами - це не ясно в питанні, це нормально чи ні.


2

Groovy, 79 байт

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}

Демонстрація:

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

Безголівки:

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 (з попередженнями) 165 (якщо закінчення рядка рахується як 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);}

Але якщо ви компілюєте його з mingw32, вам потрібно вимкнути глобулінг (див. Https://www.cygwin.com/ml/cygwin/1999-11/msg00052.html ), компілюючи так:

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

1

Perl 5,10+, 52 байти

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

Демонстрація:

$ 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

(Зауважте, що * потрібно уникати моєї оболонки, щоб вона не інтерпретувалася як глобальний зразок.)

Безголівки:

$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 байт

Ця функція передбачає, що введення є дійсним. Це важко для C #, якщо немаєeval еквівалента.

Дякую edc65 за збереження 33 байтів!

Відступ для наочності.

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

Можна вивести більшість нових рядків.
Trebuchette

Я не порахував жодних нових рядків або незначного пробілу.
Hand-E-Food

1
132, використовуючи ?:->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

Рубін, 59 байт

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

Пробіг:

$ ruby calc.rb <<< "5 8 25 * 9 6 2 - 104 / 4 7 + 6 % 14"
8
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.