INTERCALの二項演算子を実装する


29

発音可能な頭字語のないコンパイラ言語(略してINTERCAL)は、非常にユニークなプログラミング言語です。その再現性のなさの中には、二項演算子があります。

INTERCALの2つの2項演算子は、インターリーブミングルとも呼ばれます)、およびselectです。インターリーブは変更(¢)で表され、選択は波形(〜)で表されます。

インターリーブは、0〜65535の範囲の2つの数値を取得し、それらのビットを交互に切り替えることで機能します。例えば:

234 ¢ 4321
234   = 0000011101010
4321  = 1000011100001
Result: 01000000001111110010001001
Output: 16841865

Selectは、0〜65535の範囲の2つの数値を取得し、2番目のオペランドの1と同じ位置にある最初のオペランドのビットを取得し、それらのビットを右詰めします。

2345 ~ 7245
2345  = 0100100101001
7245  = 1110001001101
Taken : 010   0  10 1
Result: 0100101
Output: 37

この課題では、インターリーブまたは選択操作のいずれかを使用してバイナリ式が与えられます。可能な限り少ないバイトを使用して、結果を計算する必要があります。

式は、0〜65535の整数、スペース¢または~、スペース、0〜65535の整数で構成されるスペース区切りの文字列として指定されます。

入力および出力は、標準システム(STDIN、関数、コマンドラインなど)を介して行うことができます。標準的な抜け穴は禁止されています。

例:

5 ¢ 6
54

5 ~ 6
2

51234 ¢ 60003
4106492941

51234 ~ 60003
422

これはコードゴルフです-最少バイトが勝ちます。がんばろう。

編集:一部の言語はINTERCALの変更(¢)記号をサポートしていないため、代わりに5バイトのペナルティで大金($)記号を使用できます。


10
それはドル記号の使用に対して人々を罰する少し厳しいです。それは仕方がないことです。
ベータ崩壊

9
CLWNPAがウェールズ語で完全に発音できることに気づきました。Wはスペイン語ではU、英語ではOOと発音されます。
レベルリバーセント

9
5バイトのペナルティは受けません。C-INTERCALはを使用し$ます。
kirbyfan64sos

13
あなたは何について議論していますか?$は、¢よりも明らかに高価です。何、99¢を無料で欲しいですか?
最大

6
INTERCALで10進数の数字を入力できるとは思いませんでした。書く必要はありませんFIVE ONE TWO THREE FOURか?そして、出力はローマ数字であるべきではありませんか?
ネイト・

回答:


9

Pyth、 32の 31 29バイト

isummFdG}\~zCm.[Z16jvd2%2cz)2

オンラインそれを試してみてください:通常の入力/テストスイートを

説明:

                         cz)   split input at spaces
                       %2      only take every second item (the numbers)
             m                 map each number d to:
                    vd           convert d to int
                   j  2          convert to base 2
              .[Z16              pad zeros at the left
            C                  zip
  u     }\~z                   apply the following function ("~" in input) times:
   m   G                         map each pair d to:
    mFd                          convert [x,0] to [] and [x,1] to [x]
 s                             take sum (unfold all lists)
i                           2  convert back from base 2 and print

に変更してhMfeTから3進法の外側にsmmFd複製を移動することにより、1バイトを保存できますs。また、現在のコードは33バイトではなく32バイトです。
isaacg

@isaacgうわー。私はその賢いゴルフを考えたことがなかったでしょう。ありがとう。そして、ええ、説明を書いている最中にゴルフをしましたが、バイト数は更新しませんでした。
ジャクベ

2
本当にPythとCJam答え、ほとんど常に同じバイト数を見るのは興味深いですが、Pythは、多くの場合、少数でCJamを打つ
Kametrixom

13

Python 2、115 112バイト

x,y,z=input().split()
d=y<""
f=lambda a,b:a+b and(b%2+5&4-d)*f(a/2,b/2)+(a%2*2+b%2)/3**d
print f(int(x),int(z))

2行目の文字列には、印刷できない単一の文字\x7d、次の文字が含まれ~ます。

素敵な単一のラムダのすべての期待は、入力形式によって押しつぶされます。おそらく入力を読み込むより良い方法があります。"51234 ¢ 60003"STDIN経由で入力します。

この関数fは、次の2つの再帰関数を組み合わせます。

g=lambda a,b:a+b and 4*g(a/2,b/2)+a%2*2+b%2    # ¢
h=lambda a,b:a+b and(b%2+1)*h(a/2,b/2)+a*b%2   # ~

(@xnorの助けを借りて3バイト)


1
+1は、非常に競争力のあるPythonの最初の回答です。私はなぜラムダに悩まされ、式を使用しなかったのか疑問に思っていましたが、そこにいくつかの再帰があるように見えますか?Pythonを知らないので、説明を楽しみにしています。
レベルリバーセント

いくつかの素晴らしいバッシング!定数項式の圧縮を検討しています。式(a%2*2+b%2)/3**dは3文字を節約しますが、補数を使用しd=1-cます。あなたは-~(3*c|b%2)補数に関係する方法がありますか?最悪の場合、で2文字を失い3-3*dます。また、形式and-~x+yは、記号または数字で始まるandy-~x限り可能yです。
xnor

@xnorわかった(b%2+5&4-d)。ありがとう!
-Sp3000

11

CJam、31バイト

rrc\r]{i2bF0e[}%(7=\zf{_)*?~}2b

CJamインタープリターでオンラインで試してください。

使い方

rr                              e# Read two tokens from STDIN.
  c\                            e# Cast the second to char and swap with the first.
    r                           e# Read a third token from STDIN.
     ]                          e# Wrap everything in an array.
      {       }%                e# For all three elements:
       i2b                      e#   Cast to int and convert to base 2.
          F0e[                  e#   Left-pad with zeroes to complete 15 digits.
                (               e# Shift out the first base 2 array.
                 7=             e# Select its eighth MSB (1 for '¢', 0 for '~').
                   \            e# Swap with the array of base 2 arrays.
                    z           e# Zip to transpose rows with columns.
                     f{     }   e# For each pair of base 2 digits:
                                e#   Push the bit, then the pair.
                       _        e#   Copy the pair.
                        )       e#   Pop the second digit.
                         *      e#   Repeat the first digit that many times.
                          ?     e#   Ternary if. Select the pair if the bit is
                                e#    truthy, the repeated first bit if it's falsy.
                           ~    e#   Dump the selected array on the stack.
                             2b e# Convert from base 2 to integer.

8

JavaScript(ES6)、103 117 119 124

編集文字列ではなく数字でようになりました

(先頭のスペース、改行、コメントはカウントしません)

EcmaScript 6に準拠したブラウザーでスニペットを実行してテストします(MSIEではなくChromeが顕著です。Firefoxでテストしたところ、Safari 9でも可能です)

I=s=>
  (i=>{
    for(m=r=0,[a,o,b]=s.split` `;i>0;i<<=1) // loop until bit 31 of i is set
      o>'~'?r+=(b&i)*i+(a&i)*2*i:b&i?r+=(a&i)>>m:++m
  })(1)||r


// TEST
out=x=>O.innerHTML+=x+'\n\n';

[ ['234 ¢ 4321', 16841865], ['2345 ~ 7245', 37]
, ['5 ¢ 6', 54], ['5 ~ 6', 2]
, ['51234 ¢ 60003',4106492941], ['51234 ~ 60003', 422]]
.forEach(([i,o,r=I(i)])=>{
  out('Test '+ (o==r?'OK':'Fail')+'\nInput:    '+ i+'\nResult:   '+r+'\nExpected: '+o)})
<pre id=O></pre>


5

Matlab、119 113バイト

function f(s)
t=dec2bin(str2double(strsplit(s,{'¢' '~'}))');u=any(s>'~');[~u u]*bin2dec({t(1,t(2,:)==49) t(:)'})

ゴルフをしていない:

function f(s)                                     % input s is a string
t = dec2bin(str2double(strsplit(s,{'¢' '~'}))');  % get the two numbers and convert to
                                                  % two-row char array of zeros of ones
u = any(s>'~');                                   % 1 indicates '¢'; 0 indicates '~'
[~u u]*bin2dec({t(1,t(2,:)==49) t(:)'})           % compute both results and display
                                                  % that indicated by u

例:

>> f('234 ¢ 4321')
ans =
    16841865

>> f('2345 ~ 7245')
ans =
    37

5

R、145バイト

s=scan(,"");a=as.double(c(s[1],s[3]));i=intToBits;cat(packBits(if(s[2]=="~")c(i(a[1])[i(a[2])>0],i(0))[1:32] else c(rbind(i(a[2]),i(a[1]))),"i"))

Ungolfed +説明:

# Read a string from STDIN and split it on spaces
s <- scan(, "")

# Convert the operands to numeric
a <- as.double(c(s[1], s[3]))

o <- if (s[2] == "~") {
    # Get the bits of the first operand corresponding to ones in
    # the second, right pad with zeros, and truncate to 32 bits
    c(intToBits(a[1])[intToBits(a[2]) == 1], intToBits(0))[1:32]
} else {
    # Interleave the arrays of bits of the operands
    c(rbind(intToBits(a[2]), intToBits(a[1])))
}

# Make an integer from the raw bits and print  it to STDOUT
cat(packBits(o, "integer"))

5

Python 3、174 166 148 126

非常に簡単な文字列操作、そして整数への変換。

2進数で99桁の数字に制限されます(最大2 ^ 99-1 = 633825300114114700748351602687)。

ありがとう、Sp3000とVioz!

a,o,b=input().split()
print(int(''.join([(i+j,i[:j>'0'])[o>'~']for i,j in zip(*[bin(int(j))[2:].zfill(99)for j in(a,b)])]),2))

または165文字、制限なし:

a,o,b=input().split()
a,b=[bin(int(j))[2:]for j in(a,b)]
print(int(''.join([(i if j=='1'else'')if o=='~'else i+j for i,j in zip(a.zfill(len(b)),b.zfill(len(a)))]),2))

ゴルフをしていない:

a, op, b = input().split()
a, b = [bin(int(j))[2:] for j in(a,b)] #convert to int (base 10), then to binary, remove leading '0b'
m = max(len(a), len(b))
a = a.zfill(m) #fill with leading zeroes
b = b.zfill(m)
if op == '~':
    ret = [i if j=='1' else'' for i, j in zip(a, b)]
else:
    ret = [i + j for i, j in zip(a, b)]
ret = ''.join(ret) #convert to string
ret = int(ret, 2) #convert to integer from base 2
print(ret)

2
ゼロでパディングするzfill代わりに使用できますrjust
-Sp3000

入力は16ビットで最大出力、32ビットで出力。99ビットで十分です。
isaacg

私は知っていますが、「99」は「16」と同じ文字を使用するため、制限するメリットはありません。
トランオウル

1
さらにいくつか:1)あなたが保存する必要はありませんa,bだけでそれを置く、zip*スプラット、2)(i if j=='1'else'') -> i[:j>'0']3)あなたが使用することができ、この先端部を他に保存するif/else
SP3000

1
私の解決策は最終的にあなたのものに近づきすぎたので、ここにあなたが得ることができる限り短いものがあります(126バイト)。
カーデ

4

Pyth、43バイト

私の一部は、isaacgの質問にこのような長いPythの回答を投稿するのを緊張しています...:oP

J.(Kczd1Am.BvdKiu?qJ\~u+G?qeH\1hHk+VGHk.iGH2

説明:

                                               Implicit: z=input(), k='', d=' '
   Kczd                                        Split z on spaces, store in K
J.(    1                                       Remove centre element from K, store in J
         m    K                                For each d in K
          .Bvd                                 Evaluate as int, convert to binary string
        A                                      Store pair in G and H
                                               ~ processing:
                                 +VGH          Create vectorised pairs ([101, 110] -> [11, 01, 10])
                     u               k         Reduce this series, starting with empty string
                        ?qeH\1                 If 2nd digit == 1...
                              hHk              ... take the 1st digit, otherwise take ''
                      +G                       Concatenate
                                      .iGH     ¢ processing: interleave G with H
                ?qJ\~                          If J == ~, take ~ processing, otherwise take ¢
               i                          2    Convert from binary to decimal

4
あなたのプロフィール写真が大好きです!:)
kirbyfan64sos

2
@ kirbyfan64sosブルーカービーは最高のカービーです:o)
ソク

3

C、127 123バイト+ 5ペナルティ= 128

scanf ユニコード記号を複数の文字としてカウントするため、物事が非常に複雑になるため、使用するために5バイトのペナルティを適用しています $ます。

a,b,q,x,i;main(){scanf("%d %c %d",&a,&q,&b);for(i=65536;i/=2;)q%7?x=x*4|a/i*2&2|b/i&1:b/i&1&&(x=x*2|a/i&1);printf("%u",x);}

元のバージョンからの変更は次のとおりです。

-$または〜のテストはからに改訂されq&2ましたq%7。これにより、true / false値が逆になり、$演算子のコードが :できるようになります。つまり、括弧のセットを削除できます。

- iループは2の累乗でカウントダウンするようになりましたが、より長いですが>>/括弧を節約できます。

オリジナルバージョン127バイト

a,b,q,x,i;
main(){
  scanf("%d %c %d",&a,&q,&b);
  for(i=16;i--;)
    q&2?
      b>>i&1&&(x=x*2|a>>i&1):    // ~ operator. && used as conditional: code after it is executed only if code before returns truthy.
      (x=x*4|(a>>i&1)*2|b>>i&1); // $ operator
  printf("%u",x);
}

2つのループのオーバーヘッドを回避するために、条件付きの単一ループを使用しました。どちらの場合も、オペランドのビットを1のビットに右シフトし、最上位ビットから最下位ビットの結果を作成し、結果を左シフト(2または4倍)します。


私はあなたのためにそれをゴルフしました:main(a、b、q、x、i){scanf( "%d%c%d"、&a、&q、&b); for(i = 16; i-;)q&2? b >> i&1 &&(x = x * 2 | a >> i&1):( x = x * 4 |(a >> i&1)* 2 | b >> i&1); printf( "%u"、x);} >> i&1パーツをゴルフで削ってみましたが、費用対効果の高い方法が見つかりませんでした。しかし、変数定義をmainに入れることで、1文字を節約できました。注:未テスト。
ラムダベータ

@LamdaBetaありがとう、>> i&1のマクロは見つかりませんでしたが、別の方法でゴルフをすることができました。私のマシンでは、変数をmain原因の引数としてq破損させるのは奇妙です。本当の問題はにあるとscanf思いますが、そのため通常の宣言として残しています。
レベルリバーセント

私はそれを考えていませんでした。あなたは正しい、qが破損します。その理由は、mainがコマンドライン引数の数と引数自体の配列という2つの引数を取ることを学習する一方で、ほとんどのシステムは実際にコードの環境を記述する3番目の引数(通常char * envp []と呼ばれる)を提供するためですで実行されます(EGへのアクセスを許可する:環境変数)。したがって、mainの3番目の値にもシステムによって値が割り当てられる場合がありますが、今回はscanfが無害です。
ラムダベータ

@steveverill 5バイトのペナルティも削除できると思います。コードをテストして(ALTを使用して¢を作成)、正常に機能しているようです。:)
LambdaBeta

@LambdaBetaは実際に実験により、それが両方の組み合わせであることを示しています。通常の宣言でqはゼロになることが保証されていますが、関数パラメーターとしての宣言でqは32ビットのガベージが含まれています。それは私があれば問題ではない割り当ての値をq、しかしscanf"%c"のみ定義されていない他の24を残して、ごみの最下位8ビットを上書きします。私は別のコンパイラで幸運になるかもしれません!
レベルリバーセント

3

K5、53の 52バイト

{b/({,/x,'y};{x@&y})[*"~"=y][b\.x;(b:20#2)\.z]}." "\

53バイトバージョン:

{b/({,/x,'y};{x@&y})[*"¢~"?y][b\.x;(b:20#2)\.z]}." "\

まだもう少しゴルフが必要です。



3

ハスケル、77

g=(`mod`2)
h=(`div`2)
0¢0=0
a¢b=g a+2*b¢h a
a?0=0
a?b=g a*g b+(1+g b)*h a?h b

入力は、関数/演算子に入力を適用することで与えられ、コードで定義されます(Haskellは演算子?¢定義できません~技術的な理由のために)。

基本的には古い再帰的アプローチで動作します。


2

J、173

f=:|."1@(>@(|.&.>)@(#:@{:;#:@{.))
m=:2&#.@:,@:|:@:|.@:f
s=:2&#.@#/@:f
a=:{&a.@-.
(1!:2)&2(s@".@:a&126)^:(126 e.i)((m@".@:a&194 162)^:(1 e.194 162 E.i)i=._1}.(a.i.((1!:1)3)))

1行の入力が必要です

EOFを使用した改行後に入力が終了すると予想されます


2

ジャバスクリプトES6(3つの引数)141の 138 136 121 119バイト

b=x=>(65536|x).toString`2`
f=(x,o,y)=>+eval(`'0b'+(b(y)+b(x)).replace(/^1|${o=='~'?1:'(.)'}(?=.{16}(.)())|./g,'$2$1')`)

テスト:

;[f(234,'¢',4321),f(2345,'~',7245)]=="16841865,37"

ジャバスクリプトES6(1つの引数)135の 133バイト

b=x=>(65536|x).toString`2`
f=s=>([x,o,y]=s.split` `)|eval(`'0b'+(b(y)+b(x)).replace(/^1|${o=='~'?1:'(.)'}(?=.{16}(.)())|./g,'$2$1')`)

テスト:

;[f('234 ¢ 4321'),f('2345 ~ 7245')]=="16841865,37"

PS:新しい行はで置き換えることができるため、1バイトとしてカウントされ;ます。


1
0x10000 == 65536(2文字を保存)
-edc65

@ edc65、答えを更新しました。
Qwertiy

2
65536 | x回避するため~~
-edc65

2番目のバージョンのみが許可されます-入力はスペースで区切られた文字列の形式である必要があります。
isaacg

@isaacg、わかりました。しかし、歴史的な理由で最初のものを削除したくありません。
Qwertiy

2

Python 3、157バイト

a,x,y=input().split()
i=int
b=bin
print(i(''.join(([c for c,d in zip(b(i(a)),b(i(y)))if d=='1'],[c+d for c,d in zip(b(i(a))[2:],b(i(y))[2:])])['¢'==x]),2))

完全な説明バージョンは、pastebinにあります。


「if」の前の「==」演算子の前後のスペースを削除し、位置引数として「base」を渡すことで、いくつかの文字を同じにすることができます。
トランオウル

ありがとう、そして他の何人かは15文字を保存しました!しかし、戻り値を2倍にフォーマットする方法はまだまだあります。
オリバーフリードリッヒ

また、インデントごとに4つのスペースを使用しますか?1つ(またはタブ)で十分です。
トランオウル

2
@BeowulfOF特に指定がない限り、完全なプログラムまたは関数を送信できます。一般に、どちらが短いかは、言語がチャレンジの特定の入力を解析する方法に依存します(たとえば、ルビは、stdinからの数字で驚くほど不器用です)。また、2つの出力方法があります。stdoutまたは戻り値。両方に適用できます(ただし、プログラムからの戻り値はまれです。)
Level River St

1
e一度しか使用していないように見えますが、インライン化することはできませんか?
ケビンブラウン

0

Mathematica、155バイト

f=IntegerDigits[#,2,16]&;
g=#~FromDigits~2&;
¢=g[f@#~Riffle~f@#2]&;
s=g@Cases[Thread@{f@#,f@#2},{x_,1}->x]&;
ToExpression@StringReplace[#,{" "->"~","~"->"s"}]&

入力として文字列を受け取る匿名関数に評価されます。明確にするために改行が追加されました。

fそしてg、ベース2へ/から変換します。インターリーブが想定されているRiffleとおりに動作します。selectに使用したかったのですが、残念ながら良いです。最後の行はちょっとしたトリックです。スペースがMathematicaの挿入演算子であるスペースに変更された後、文字列が評価されます。SelectCases~

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.