単純な整数演算計算機


28

単純な整数演算のスクリプト可能な計算機を実装します。

概念

アキュムレータは0から始まり、操作が実行されます。プログラムの最後に、アキュムレーターの値が出力されます。

操作:

  • +1アキュムレータに追加します
  • -1アキュムレータから減算します
  • * アキュムレータに乗算します 2
  • / アキュムレータを除算します 2

サンプルスクリプト

入力++**--/は出力を与えるべき3です。

実装例

def calc(s)
    i = 0
    s.chars.each do |o|
        case o
            when '+'
                i += 1
            when '-'
                i -= 1
            when '*'
                i *= 2
            when '/'
                i /= 2
        end
    end
    return i
end

ルール

  • これはであるため、バイト単位の最小の回答が優先されますが、選択されません。
  • 創造的な実装が奨励されます。
  • 標準的な抜け穴は禁止されています。
  • プログラムは標準入力または引数で取得し、戻り値または標準出力で回答を出力できます。
  • 楽しむ。
  • 整数除算のため、除算は切り捨てられます。
  • プログラム-/はを返します-1

テストケース

*///*-*+-+
-1
/*+/*+++/*///*/+-+//*+-+-/----*-*-+++*+**+/*--///+*-/+//*//-+++--++/-**--/+--/*-/+*//*+-*-*/*+*+/+*-
-17 
+++-+--/-*/---++/-+*-//+/++-*--+*+/*/*/++--++-+//++--*/***-*+++--+-*//-*/+*/+-*++**+--*/*//-*--**-/-*+**-/*-**/*+*-*/--+/+/+//-+*/---///+**////-*//+-+-/+--/**///*+//+++/+*++**++//**+**+-*/+/*/*++-/+**+--+*++++/-*-/*+--/++*/-++/-**++++/-/+/--*/-/+---**//*///-//*+-*----+//--/-/+*/-+++-+*-*+*+-/-//*-//+/*-+//+/+/*-/-/+//+**/-****/-**-//+/+-+/*-+*++*/-/++*/-//*--+*--/-+-+/+/**/-***+/-/++-++*+*-+*+*-+-//+/-++*+/*//*-+/+*/-+/-/*/-/-+*+**/*//*+/+---+*+++*+/+-**/-+-/+*---/-*+/-++*//*/-+-*+--**/-////*/--/*--//-**/*++*+/*+/-+/--**/*-+*+/+-*+*+--*///+-++/+//+*/-+/**--//*/+++/*+*////+-*-//--*+/*/-+**/*//+*+-//+--+*-+/-**-*/+//*+---*+//*/+**/*--/--+/*-*+*++--*+//+*+-++--+-*-*-+--**+/+*-/+*+-/---+-*+-+-/++/+*///*/*-+-*//-+-++/++/*/-++/**--+-////-//+/*//+**/*+-+/+/+///*+*///*-/+/*/-//-*-**//-/-+--+/-*--+-++**++//*--/*++--*-/-///-+/+//--+*//-**-/*-*/+*/-*-*//--++*//-*/++//+/-++-+-*/*-+++**-/-*++++**+-+++-+-***-+//+-/**-+/*+****-*+++*/-*-/***/-/*+/*****++*+/-/-**-+-*-*-++**/*+-/*-+*++-/+/-++*-/*-****-*
18773342

2
したがって...整数ではないため、厳密に整数ではありません/
コナーオブライエン

2
次に、これを明示的に指定する必要があります。
コナーオブライエン

5
何を-/返す必要がありますか?
デニス

4
rust-langのホームページに掲載されているコードスニペットがこの課題を解決していることに気づかずにはいられません。
ツヴァイ

4
さらにテストケースを追加してください。
マーティンエンダー

回答:


28

Python 2、48バイト

i=0
for c in input():exec"i=i%s2&-2"%c
print i/2

DOES +2-2*2、または/2+2and -2ではなく+1andを実行することにより-1、2倍の単位で作業するため、最終出力を半分にする必要があります。例外として、フロア分割/は2の倍数に切り捨てる必要があります&-2


これは素晴らしいです!あなたはそれを投稿したい場合は自分でこのCJamポートは、現在の課題をリードすることになります0q{2\~-2&}/2/2\~第二オペランドとの試用版とその演算子2-2&ビット単位でAND、2/。2による最終部門ですがq{...}/、入力に対するforeachで、0ちょうど初期であります値。)
マーティンエンダー

あなたはそれを投稿することができます、私はCJamを知りません。
-xnor

本当に賢い!ES6に移植され、これは簡単に私の答えを上回るだろう
edc65

Pythonの見事な使用。これから何か新しいことを学びました。
-Jacobr365

12

Haskell、51バイト

x#'+'=x+1
x#'-'=x-1
x#'*'=x*2
x#_=div x 2 
foldl(#)0

使用例:foldl(#)0 $ "++**--/"-> 3


12

ゼリー18 17 バイト

‘

’

:2
Ḥ
O0;ṛĿ/

オンラインでお試しください!

使い方

第6行は、の範囲のインデックスを持つヘルパーリンク定義16。インクリメント、何もしない、デクリメント、何もしない、半分(床)、そしてダブル。

メインリンク– O0;ṛĿ/–入力文字をコードポイント(O)に変換し、コードポイントの配列の先頭に0(初期値)を0;追加し、生成された配列を次のように縮小します。

初期値は、配列の最初の要素、つまり先頭に0が追加されます。クイックリンクṛĿは、最後の戻り値を左の引数として、現在の要素を右の引数として、配列内のすべての後続要素に対して呼び出されます。正しい引数()を検査し、そのインデックスを持つリンクを一元的に評価し(Ŀ)、目的の操作を適用します。


10
これは、最も改行の多いゼリーの回答のように見えます
コナーオブライエン

10

Python 2、54バイト

i=0
for c in input():exec"i=i"+c+`~ord(c)%5%3`
print i

入力は文字列リテラルとして取得されます。~ord(c)%5%3演算子を対応する右オペランドにマップします。

以前は、hash(c)%55%3Pythonの異なるバージョン間で一貫した結果が得られなかったものを使用しました。これは私に他の式を探求することを奨励しました。


...動作するようには思えない
破壊可能なレモン

55,3と65,4は、python 2のハッシュの二重modの2つの最短です
ジョナサンアラン

@DestructibleWatermelonは私のために:イデオン
ジョナサンアラン

hashPythonバージョンに固有だと思います-ideoneは2.7.10を使用[1, 1, 2, 2]して4つのマッピングを提供しますが、ローカルでは2.7.12になります[2, 0, 1, 0]
-Sp3000

1
それはideoneで動作しますが、私のコンピュータのpythonでは動作しません。おそらくバージョンに依存します。この場合、バージョンに注意する必要があります編集:ninja'd:/
破壊可能なレモン

10

SILOS133 211バイト

:s
def : lbl G GOTO
readIO
i-46
if i a
i+2
if i b
i+2
if i c
i+1
if i d
G e
:a
G v
:p
a-1
a/2
G o
:v
a+1
if a p
a-1
j=a
j/2
k=j
k*2
k-a
a/2
if k t
G o
:t
a-1
:o
G s
:b
a-1
G s
:c
a+1
G s
:d
a*2
G s
:e
printInt a

演算子のASCIIコードを取得します。

テストケースでオンラインで試してください。
-/
++**--/
*///*-*+-+


loadLine golfierは何ですか?
ローハンジュンジュンワラ

OPが明確になりました。0ではなく-1-/を返す必要があります
デニス

@デニス修正。しかし、多くのバイトを追加しました:/
betseg

9

チューリングマシン-23の状態(684バイト)

ここで試してください- パーマリンク

0 * * r 0
0 _ . l 1
1 * * l 1
1 _ * l 2
2 * 0 r 3
3 _ * r 3
3 + _ l +
3 - _ l -
3 x _ l x
3 / _ l /
+ _ * l +
+ * * * 4
4 - * l 5
4 _ 1 r 6
4 0 1 l 7
4 1 0 l 4
- _ * l -
- * * * 5
5 - * l 4
5 _ * r 8
5 0 1 l 5
5 1 0 l 7
x * * l x
x 1 0 l 9
x 0 0 l a
9 _ 1 r 6
9 1 1 l 9
9 0 1 l a
a _ _ r 6
a 1 0 l 9
a 0 0 l a
/ _ * l /
/ * * l b
b * * l b
b _ * r c
c 0 0 r d
c 1 0 r e
d * * l 7 
d 0 0 r d
d 1 0 r e
e _ * l 7
e - * l 4
e 0 1 r d
e 1 1 r e
8 * * r 8
8 - _ r 3
8 _ - r 3
7 * * l 7
7 _ * r f
f 0 _ r f
f 1 * r 6
f * _ l g
g * 0 r 6
6 * * r 6
6 _ * r 3
3 . _ l h
h _ * l h
h - _ l i
h * * l halt
i * * l i
i _ - r halt

入力はチューリングマシンコードの特殊文字であるため、「*」を含めないでください。代わりに「x」を使用してください。回答をバイナリで出力します。

難読化されていないコード

init2 * * r init2
init2 _ . l init0
init0 * * l init0
init0 _ * l init1
init1 * 0 r readop
readop _ * r readop
readop + _ l +
readop - _ l -
readop x _ l x
readop / _ l /
+ _ * l +
+ * * * inc
inc - * l dec
inc _ 1 r return
inc 0 1 l zero
inc 1 0 l inc
- _ * l -
- * * * dec
dec - * l inc
dec _ * r neg
dec 0 1 l dec
dec 1 0 l zero
x * * l x
x 1 0 l x1
x 0 0 l x0
x1 _ 1 r return
x1 1 1 l x1
x1 0 1 l x0
x0 _ _ r return
x0 1 0 l x1
x0 0 0 l x0
/ _ * l /
/ * * l //
// * * l //
// _ * r div
div 0 0 r div0
div 1 0 r div1
div0 * * l zero 
div0 0 0 r div0
div0 1 0 r div1
div1 _ * l zero
div1 - * l inc
div1 0 1 r div0
div1 1 1 r div1
neg * * r neg
neg - _ r readop
neg _ - r readop
zero * * l zero
zero _ * r zero1
zero1 0 _ r zero1
zero1 1 * r return
zero1 * _ l zero2
zero2 * 0 r return
return * * r return
return _ * r readop
readop . _ l fin
fin _ * l fin
fin - _ l min
fin * * l halt
min * * l min
min _ - r halt

状態の説明:

初期化:
これらの状態は、init2で始まる各実行の開始時に1回アクセスされます。

  • init2:右端まで移動して「。」を入力します。これにより、TMはいつ停止するかを認識します。「init0」に変更します。
  • init0:頭がスペースを読み取るまで、すべてを左に移動します。次に、1つのセルを左に移動します。「init1」に変更します。
  • init1:ゼロを入力して、1つのセルを右に移動し、「readop」に変更します。

指示を読む:
これらの州は、プログラム全体で複数回訪問されます

  • readop:演算子または「。」を読み取るまで、右端まで移動します。演算子にヒットした場合、対応する状態(+、-、x、/)に変更します。「。」がヒットした場合は、「fin」状態に変更します。

  • return:積算合計と演算子の間の空のスペースに頭を返します。次に、「readop」に変更します。

操作:
これらの操作は実際の汚い仕事をします

  • +:ヘッドが非空白文字を読み取るまで左に移動します。この文字が「-」の場合、左に移動して「dec」に変更します。それ以外の場合は、「inc」に変更します。

  • -:「+」に似ていますが、「-」があれば「inc」に、そうでなければ「dec」に変更されます。

  • inc:頭の下の数字が0(または空白)の場合、それを1に変更し、「ゼロ」に変更します。数字が1の場合、0に変更し、次の数字で繰り返します。

  • dec:incと似ていますが、1が0になり、0が1になり、頭が空白を読み取る場合は「neg」に変更します。

  • x、x0、x1:数値1を左にビットシフトします。「戻る」に変更します。

  • /、//、div、div0、div1:数値の右にずっと移動してから、1つ右にビットシフトします。「-」がある場合は、「inc」に変更します。これは、負数の切り捨てをシミュレートします。それ以外の場合は、「ゼロ」に変更します

  • neg:番号の後に「-」を付けてから「readop」に変更します

  • zero、zero1、zero2:先行ゼロを削除し、「readop」に変更します

クリーンアップ: 出力を表示可能にします

  • fin、min:必要に応じて、数字の前に「-」を移動します。停止します。

1
このコードを読むのはとてもクールだと思った。一日を明るくしてくれてありがとう。
-Jacobr365

8

Perl 6の53の  52バイト

{([Ro] %(<+ - * />Z=>*+1,*-1,* *2,*div 2){.comb})(0)}

{[Ro](%(<+ - * />Z=>*+1,*-1,*×2,*div 2){.comb})(0)}

説明:

# bare block lambda that has one implicit parameter 「$_」
{
  (
    # reduce the code refs using ring operator 「∘」 in reverse 「R」
    [R[o]]

      # produce a hash from:
      %(

        # list of pairs of "operator" to code ref
        # ( similar to 「'+' => { $^a + 1 }」 )

          # keys
          < + - * / >

        # keys and values joined using infix zip operator 「Z」
        # combined with the infix Pair constructor operator 「=>」
        Z[=>]

          # values (Whatever lambdas)
          * + 1,
          * - 1,
          * × 2, # same as 「* * 2」
          * div 2,

      ){

        # split the block's argument into chars
        # and use them as keys to the hash
        # which will result in a list of code refs
        .comb

      }

  # call composed code ref with 0
  )(0)
}

使用法:

my $input = '++**--/'
my $output = {[Ro](%(<+ - * />Z=>*+1,*-1,*×2,*div 2){.comb})(0)}.( $input );
say $output; # 3
say $output.^name; # Int


6

05AB1E、20バイト

修正してくれたエニグマに感謝-/-bugます!

整数除算ではなかった場合の16バイトの場合:Î"+-*/""><·;"‡.V

Î…+-*"><·"‡'/"2÷":.V

説明:

Î                      # Push 0, which is our starting variable, and input
 …+-*                  # Push the string "+-*"
     "><·"             # Push the string "><·"
          ‡            # Transliterate. The following changes:
                           "+" -> ">"
                           "-" -> "<"
                           "*" -> "·"
           '/"2÷":     # Replace "/" by "2÷"
                  .V   # Evaluate the code as 05AB1E code...
                           '>' is increment by 1
                           '<' is decrement by 1
                           '·' is multiply by 2
                           '2÷' is integer divide by two
                       # Implicitly output the result

CP-1252エンコードを使用します。オンラインでお試しください!


OPが明確になりました。0ではなく-1-/を返す必要があります
デニス

Î…+-*"><·"‡'/"2÷":.V同じバイトカウントで負の数値除算の問題を修正できます。
エミグナ

@Dennis問題を修正しました。
アドナン

@Emignaありがとう:)
アドナン

5

JavaScriptのES6、80の 68バイト

k=>[...k].reduce((c,o)=>+{"+":c+1,"-":c-1,"*":c*2,"/":c/2|0}‌​[o],0)

ニールのおかげでなんと12バイト節約できました!


を削除し"c"+て書いた場合、2番目の答えは読みやすくなります"c+1 c-1 c*2 c/2|0".split
ニール・

最初の答えとして、なぜ書かo=>c=[c+1,c-1,c*2,c/2|0]["+-*/".indexOf(o)]ないのですか、またはを使用してさらにバイトを保存することができると思いますo=>c={"+":c+1,"-":c-1,"*":c*2,"/":c/2|0}[o]
ニール

k=>[...k].reduce((c,o)=>+{"+":c+1,"-":c-1,"*":c*2,"/":c/2|0}[o],0)さらに短くなるかもしれませんが、私は数を失いました...
ニール

@ニールああ、はい、私はこれを忘れていました
コナー・オブライエン

1
どういうわけか、}との間の幅がゼロの文字[o]になったので、これは実際にはたった66バイトの長さです。また、OPが明確になりました。0ではなく-1-/を返す必要があります
デニス

5

ルビー、48 44 42 + 1 = 43バイト

-nフラグ用に+1バイト。STDINで入力を受け取ります。

i=0
gsub(/./){i=i.send$&,"+-"[$&]?1:2}
p i

ideoneでご覧ください($_ideoneはコマンドラインフラグを使用しないため、使用します):http ://ideone.com/3udQ3H



4

パイソン2、58の 56バイト

@Lynnのおかげで-2バイト

r=0
for c in input():exec'r=r'+c+`2-ord(c)%11%3`
print r

文字の序数が+-*/ある43,45,42,47これらはモジュロ11 10,1,9,3たものであるモジュロ3 1,1,0,0、2より少ないものをしている1,1,2,2:私たちは、各操作のために必要な量を与えr=r+1r=r-1r=r*2、およびr=r/2


前:

r=0
for c in input():exec'r=r'+c+`(ord(c)%5==2)+1`
print r

どう2-ord(c)%11%3
リン

@Lynnまあ私はそれでいいならそれを取るでしょう?(しかし、それを投稿することができる変更の十分だと本当に思う)
ジョナサンアラン

2
どうぞ:) ----
リン

4

Mathematica、83 73 70バイト

@MartinEnderにより10バイト節約

(#/*##2&@@#/.Thread[{"+","-","*","/"}->{#+1&,#-1&,2#&,⌊#/2⌋&}])@0&

匿名関数。入力として文字のリストを受け取り、出力として数値を返します。ゴルフの提案を歓迎します。



4

C#、87 81バイト

int f(string s){int i=0;foreach(var c in s)i=c<43?i*2:c<46?i+44-c:i>>1;return i;}

ゴルフをしていない:

int f(string s)
{
    int i = 0;

    foreach (var c in s)
        i = c < 43 ? i * 2
          : c < 46 ? i + 44 - c
          : i >> 1;

    return i;
}

入力は有効であると想定されます。通常の除算は常にゼロに丸められ、ビットシフトは常に切り捨てられるため、2による除算は右に1ビットシフトすることによって行われます。インクリメントとデクリメントはのためのASCIIコード間の1つの距離の便利な使用を作る+-


Linqの新しいC#6構文と集約メソッドが好きですか?int f(string s)=>s.Aggregate(0,(i,c)=>c<43?i*2:c<46?i+44-c:i>>1);(65バイト)
シリルガンドン

@CyrilGandonは、 "using System.Linq;"を含める必要があり、19バイト長くして84バイトにする必要があることを知っています。それが私がやらなかった理由です。
Scepheo

4

Javascript(ES6)、57バイト(配列)/ 60バイト(整数)

すべての中間結果の配列を返す:

o=>[...o].map(c=>x=[x>>1,x+1,x*2,x-1][eval(2+c+3)&3],x=0)

たとえば、の出力はに"++**--/"なります[1, 2, 4, 8, 7, 6, 3]

最終結果のみを返す:

o=>[...o].reduce((x,c)=>[x>>1,x+1,x*2,x-1][eval(2+c+3)&3],0)

使い方

どちらのソリューションも同じ考え方に基づいています。完全なハッシュ関数eval(2+c+3)&3を使用して、異なる演算子文字をにマップc[0, 3]ます。

 operator | eval(2+c+3)  | eval(2+c+3)&3
----------+--------------+---------------
    +     |  2+3 = 5     |    5 & 3 = 1
    -     |  2-3 = -1    |   -1 & 3 = 3
    *     |  2*3 = 6     |    6 & 3 = 2
    /     |  2/3 ~= 0.67 | 0.67 & 3 = 0

3

JavaScript(ES6)、57

a=>[...a].map(c=>a=c<'+'?a<<1:c<'-'?-~a:c<'/'?~-a:a>>1)|a

注:アキュムレーターの初期値はプログラム文字列で、ビット操作(〜、>>、<<、|)を使用して、最初の使用時に0に変換されます。

サイドノートとして、@ xnorの賢い答えは、javascriptに移植された40を獲得します。

a=>[...a].map(c=>a=eval(~~a+c+2))&&a>>1

(これが好きなら、彼に投票してください)

テスト

f=a=>[...a].map(c=>a=c<'+'?a<<1:c<'-'?-~a:c<'/'?~-a:a>>1)|a

function update() {
  O.textContent = f(I.value);
}

update()
<input value='++**--/' id=I oninput='update()'><pre id=O></pre>


3

Java、77バイト

int f(String s){return s.chars().reduce(0,(r,c)->c<43?r*2:c<46?r+44-c:r>>1);}

Java 8ストリームを使用します。


1
いい答えです。サイトへようこそ!Javaについては何も知りませんが、2バイトに変更r >> 1r>>1て保存できますか?
DJMcMayhem

あなたは絶対に正しいです、ありがとう@DJMcMayhem
primodemus

1
素晴らしい、助けてくれてうれしい!もう1つの注意点として、77バイトをカウントしています。バイトカウントに改行を含めましたか?必要ないので、もう1バイト削除できます。
DJMcMayhem

Correct again @DJMcMayhem , aparently wc counts the null-terminanting byte or something...
primodemus

1
as you are using java8, why don't define function by using lambda, s->s.chars().reduce(0,(r,c)->c<43?r*2:c<46?r+44-c:r>>1); that will give you 56 bytes
user902383

3

GNU sed, 65 59 57 bytes

Edit: 2 bytes shorter thanks to Toby Speight's comments

s/[+-]/1&/g
s/*/2&/g
s:/:d0>@2&:g
s/.*/dc -e"0[1-]s@&p"/e

Run:

sed -f simple_calculator.sed <<< "*///*-*+-+"

Output:

-1

The sed script prepares the input for the dc shell call at the end, the latter accepting the input in Reverse Polish notation. On division, if the number is negative (d0>), the [1-] decrement command stored in register @ is called. Conversion example: + - * / --> 1+ 1- 2* d0>@2/.


You don't need the quotes around the argument to dc, if there's no spaces, and no files matching the [1-] pattern...
Toby Speight

@TobySpeight In my mind I switched the meaning of s with S. I forgot that it doesn't replace the registry's stack, it pushes onto it, having the contrary effect of what I wanted (since I used it for every /). The quotes are still needed because you have / symbols in it making the string interpreted as a file path :) I shaved 1 byte more by removing the space after the -e.
seshoumara

1
dc won't intepret argument of -e as a filename, so you don't need quotes for the / - try it! I think it's a reasonable for a code-golf to require that the current working directory not contain any files beginning with 01s@ or 0-s@.
Toby Speight

@TobySpeight you were right about -e regarding /, however the quotes are still required as I just saw now. The > is interpreted directly by the shell as a redirect operator I think, since I got this error: cannot create @2/d0: Directory nonexistent
seshoumara

Ah, yes, I didn't consider the >. You do need quotes, after all. Apologies for (attempting to) mislead! And, although adding a backslash looks like one character, it needs to be doubled in a s/// replacement, so no benefit there...
Toby Speight

3

PHP, 75 bytes

This uses a modified version of Jörg Hülsermann's answer.

eval(preg_replace('~.~','$s=($s\0(2-ord("\0")%11%3))|0;',$argv[1]));echo$s;

It heavily relies on string substitution, using a simple regular expression (~.~).

The variable $s is re-assigned with the new value for each character. At the end, it outputs the result.


Note: This is meant to be executed using the -r flag.


Try it here:

Or try on: http://sandbox.onlinephpfunctions.com/code/7d2adc2a500268c011222d8d953d9b837f2312aa

Differences:

  • Instead of echo$s, I'm using sprintf($s). Both perform the same action on numbers. Since this is just for testing, it is fine.
  • In case there's no passed argument, it will run as if you passed ++*+ as the first argument, which should show 5.

Yay! The e modifier is back! :D
Titus

@Titus I don't get it. Can you elaborate a little?
Ismael Miguel

PHP before version 7 had a pattern modifier e, which was replaced by preg_replace_callback and could be abused to ... but this isn´t quite that.
Titus

@Titus That patern modifier was used to tell that the output would be actual PHP code, and to try to keep the syntax correct. This here, doesn't use it, but replace every single character with a piece of code to execute, regardless of it's syntax. Bad inputs will cause severe security issues.
Ismael Miguel

I know. But it resembles.
Titus

2

Batch, 61 bytes

@set n=
@for %%a in (%*)do @set/an=n%%a2^&-2
@cmd/cset/an/2

Translation of @xnor's xcellent Python answer.


2

Pyke, 24 22 bytes

\*\}:\/\e:\+\h:\-\t:0E

Try it here!

Or 12 bytes (noncompetitive)

~:"ht}e".:0E

Try it here!

Add translate node - basically multiple find and replace.

~:           -   "+-*/"
        .:   -  input.translate(^, V)
  "ht}e"     -   "ht}e"
          0E - eval(^, stack=0)

2

PHP, 104 102 82 bytes

First version with eval:

$i=0;while($c<9999)eval('$i'.['+'=>'++','-'=>'--','*'=>'*=2','/'=>'>>=1'][$argv[1]{$c++}].';');echo$i;

Second version with ternary operators:

while($o=ord($argv[1]{$c++}))$i=$o<43?$i*2:($o<44?$i+1:($o<46?$i-1:$i>>1));echo$i;

Takes the input string as first argument from the command line.

This "only" works for input strings shorter than 10,000 characters - which should be plenty. Tested with all the test cases, unfortunately can't save on the initialization in the beginning. Second version works with strings of any length and without initialization. :-)

The main element is the eval function which manipulates $i based on a map of arithmetic operations, which are pretty straightforward except for the division. PHP returns a float when using / and intdiv is too many bytes, so we do a right-shift.

Updates

  1. Saved 2 bytes by shortening $i=$i>>1 to $i>>=1 for integer division.
  2. Threw out eval in favor of ternary operators.

2

Python 3, 98 66 60 bytes

Thanks Tukkax!

Not as golfy as the other answer, but I can't compete with them without plagiarism.

i=0
for c in input():i+=[1,-i//2,-1,i][ord(c)%23%4]
print(i)

Also, I have a recursive lambda solution as well

73 67 bytes (improved!)

s=lambda x,z=0:s(x[1:],z+[1,-z//2,-1,z][ord(x[0])%23%4])if x else z

By applying part of your recursive solution to the procedural version: 60 bytes: i=0 for c in input():i+=[1,-i//2,-1,i][ord(c)%23%4] print(i). (not formatted properly of course). Also I think you should mention that you're using Python3. In Python2, input() would evaluate to int(raw_input()).
Yytsi

@TuukkaX doesn't work for z=0 (+- does 1)
Destructible Lemon

oh yes, my mistake.
Yytsi

1
Add the title Python3 please.
Yytsi

2

R, 201 bytes

Golfed

p=.Primitive;"-"="+"=function(x)p("+")(x,1);body(`-`)[[1]]=p("-");"*"="/"=function(x)p("*")(x,2);body(`/`)[[1]]=p("%/%");Reduce(function(f, ...)f(...),rev(mget(strsplit(scan(stdin(),""),"")[[1]])),0,T)

Commented

p = .Primitive                       # Redefine
"-" = "+" = function(x)p("+")(x,1)   # Define - and +
body(`-`)[[1]] = p("-")              # Change the body, what we do to save a byte
"*" = "/" = function(x)p("*")(x,2)   # Same as above
body(`/`)[[1]] = p("%/%")            # Same as above
Reduce(function(f, ...)f(...),       # Function wrapper to evaluate list of func.  
  rev(mget(strsplit(scan(stdin(),""),"")[[1]])), # Strsplit input into list of functions
  init = 0,                                      # Starting Arg = 1
  right = T)                                     # Right to left = True 

Strategy is to refine the +, -, % operators. Split the string then parse the string into a long list of functions, to be fed into Reduce()'s accumulator.

Couldn't golf it anymore. If someone can get b=body<- to work, there could be a few bytes of savings (refine every function with b after "-"="+"="/"="*"). Initially tried to substitute and parse eval, but the order of operations and parentheses were terrifying.


This is a year later, but I managed to get it down 10 bytes by swapping your approach a bit -- you can drop 8 bytes by removing the space between f, ... in the definition of the Reduce function and getting rid of stdin() in scan but I just tried a naive approach that dropped two more bytes by defining the functions a little differently. tio.run/##XcvLCsMgEAXQrwnO6Gge29B/…
Giuseppe

1

Lex + C, 78, 74, 73 bytes

The first character is a space.

 c;F(){yylex(c=0);return c;}
%%
\+ c++;
- c--;
\* c*=2;
\/ c=floor(c/2.);

Reads from stdin, returns result.

Compile with lex golfed.l && cc lex.yy.c main.c -lm -lfl, test main:

int main() { printf("%d\n", F()); }

1

Javascript (ES5), 127 bytes

function(b){for(a=c=0;a<b.length;++a)switch(b[a]){case"+":++c;break;case"-":--c;break;case"*":c*=2;break;case"/":c/=2}return c}

Ungolfed:

function c(a){
  c=0;
  for(var i=0;i<a.length;++i){
    switch(a[i]){
      case "+":++c;break;
      case "-":--c;break;
      case "*":c*=2;break;
      case "/":c/=2;break;
    }
  }
  return c;
}

1

Pyth, 23 bytes

FNQ=Z.v%".&%sZ2_2"N;/Z2

A full program that takes input as a string and prints the result.

This is a port of @xnor's Python answer.

Try it online

How it works

FNQ=Z.v%".&%sZ2_2"N;/Z2   Program. Input: Q. Z initialised as 0
FNQ                       For. For N in Q:
        ".&%sZ2_2"         String. Literal string ".&%sZ2_2"
       %          N        String format. Replace %s with the current operator N
           %sZ2            Operator. Yield Z*2, Z//2, Z+2, Z-2 as appropriate
         .&    _2          Bitwise and. Result of above & -2
     .v                    Evaluate. Yield the result of the expression
   =Z                      Assignment. Assign result of above to Z
                   ;      End. End for loop
                    /Z2   Integer division. Yield Z//2
                          Print. Print the above implicitly 

1
Converting Python to Pyth is mostly a bad idea. u@[yGhG0tG0/G2)CHQ0 19 bytes
Jakube

@Jakube Thanks - I am very new to Pyth, so any advice is appreciated. Feel free to post that as a separate answer, since it is a different approach.
TheBikingViking

1

PHP, 79 bytes

<?$i=0;switch($_POST['a']){case"+":$i+1;case"-":$i-1;case"/":$i/2;case"*":$i*2}

2
Include the bytecount in your header, remove uneccesary spaces and use 1-letter variable names.
TuxCrafting

Is this even golfed?! :-D
YetiCGN

@TùxCräftîñg I did it.
Winnie The Pooh

You divide and multiply by 1; you need to divide and multiply by 2
TuxCrafting

@TùxCräftîñg I did it.
Winnie The Pooh
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.