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


20

Ваша задача - взять список аргументов, которые являются целыми числами или операторами, и проанализировать их следующим образом:

  1. Существует текущий оператор, который начинается с +.

  2. Каждый раз, когда оператор найден, текущий оператор изменится на него.

  3. Возможные операторы: «+», «-», «*», «/» и «%» соответствуют их значениям в Си и большинстве языков.

  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

@Maltysen: что бы ни делал ваш язык.
Требушетт

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, потому что только блок else может вызвать исключение, и это будет происходить каждый раз. Вы больше не можете использовать K, хотя. u.xsv++GbH&=bHG+\+QZконкретно.
Исаак

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)

Это создает безымянную функцию, которая принимает строку в качестве входных данных и возвращает целое число.

Ungolfed:

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 байта благодаря Glen O.


Юля жалуется, что o is not definedпри попытке запустить функцию заново. Он пытается запустить функцию «o = ifloor ...» в Main, а не внутри функции (см. Здесь github.com/JuliaLang/julia/issues/2386 ). Могу я предложить s->(o=0;p="+";for i=split(s) isdigit(i)?o=eval(parse("ifloor($o$p$i)")):p=i;end;o)?
Глен O

@GlenO Я не знаю, как я не уловил это. : / Спасибо, исправлено.
Алекс А.

4

elisp, 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

Ungolfed:

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

ungolfed;

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

Если неявная переменная в for-each является оператором, а не числом, Invoke-Expression (POSH 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 для sed.)

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

Спасибо Мальтисену за то, что он сбрил два байта, Бета Деку за то, что он сбрил 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

Кроме того, почему Parens в `если?
Maltysen

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

Я не думаю, что вам нужно это пространство между inцитатой.
Maltysen

Вы можете сохранить несколько байтов, предполагая, что список передан в аргументах функции и избавившись от них .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

Ungolfed:

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

(Обратите внимание, что *в моей оболочке нужно экранировать, чтобы она не интерпретировалась как шаблон глобуса.)

Ungolfed:

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

Вы можете убрать большинство новых строк.
Требушетт

Я не насчитал ни одной новой строки или незначительных пробелов.
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.