複素数2進数


36

正整数からガウス整数への単純な全射マッピングを作成してみましょう。ガウス整数は、実数部と虚数部が整数である複素数です。

たとえば4538、正の整数が与えられた場合、先頭に0'を付けずにバイナリで表現します。

4538 base 10 = 1000110111010 base 2

後続0のを削除します。

100011011101

1つ以上0のすべての実行を単一のものに置き換えます+

1+11+111+1

すべて1のをで置き換えますi

i+ii+iii+i

結果の複雑な式を評価し、単純化されたガウス整数を出力します。

i+ii+iii+i = i+i*i+i*i*i+i = 2i+i^2+i^3 = 2i+(-1)+(-i) = -1+i

出力は、従来の数学的な方法で表現することも、実数部と複素数部に2つの個別の整数として与えることもできます。この4538例では、次のいずれでも問題ありません。

-1+i
i-1
-1+1i
(-1, 1)
-1 1
-1\n1

以下のような入力の場合29、Mathyさんは、次のような出力フォーマットされた00iまたは0+0iすべての罰金です。

それがあなたの言語にとってより自然であれば、j代わりに(または他の何か)を使用しても問題ありませんi

バイト単位の最短コードが優先されます。


タイトルから、挑戦は2進数の複素数に関するものになると考えました。たとえば、4+2j-> 100+10j...
Erik the Outgolfer

回答:


22

MATL、7バイト

BJ*Y'^s

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

使い方

4538たとえば、入力を検討してください。

B     % Implicit input. Convert to binary
      % STACK: [1 0 0 0 1 1 0 1 1 1 0 1 0]
J*    % Multiply by 1i
      % STACK: [1i 0 0 0 1i 1i 0 1i 1i 1i 0 1i 0]
Y'    % Run-length encoding
      % STACK: [1i 0 1i 0 1i 0 1i 0], [1 3 2 1 3 1 1 1]
^     % Power, element-wise
      % STACK: [1i 0 -1 0 -1i 0 1i 0]
s     % Sum of array. Implicit display
      % STACK: -1+1i

2
MATLで7バイト、MATLAB58バイトが最高です...素敵な小さな言語を作成しました!=)
Stewie Griffin

1
@StewieGriffinは、グラフやプロットに関してはショーで最高のパフォーマンスを発揮します。また、おそらく彼が投稿した素晴らしい回答から得られる行列演算についても同様です。
魔法のタコUr

13

ゼリー、8バイト

BŒgaıP€S

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

使い方

BŒgaıP€S  Main link. Argument: n (integer)

B         Convert to binary.
          If n = 4538, this yields [1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0].
 Œg       Group equal elements.
          This yields [[1], [0, 0, 0], [1, 1], [0], [1, 1, 1], [0], [1], [0]].
   aı     Logical AND with the imaginary unit.
          This yields [[ı], [0, 0, 0], [ı, ı], [0], [ı, ı, ı], [0], [ı], [0]].
     P€   Product each.
          This yields [ı, 0, -1, 0, -ı, 0, ı, 0].
       S  Sum.
          This yields -1+ı.

10

Python 2、53バイト

f=lambda n,k=0:(n and f(n/2,n%2*(k or 1)*1j))+~n%2*k

これをゴルフしようとしていて、ゴルフができるように思えますが、私はアイデアの雰囲気がありません...


1
これは、(k or 1)最適ないないようですが、私は考えることができる唯一の他の事はある(k+0**k)...
ETHproductions

@ETHproductions私の考えは正確ですが、残念ながら0**k複雑なものには機能しませんk...
Sp3000

6

Mathematica、44 38バイト

Tr[1##&@@@Split[I*#~IntegerDigits~2]]&

説明

#~IntegerDigits~2

入力を基数2に変換します(に4538なります{1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0}

I*

乗算I(に{1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0}なる{I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0}

Split

実行ごとに分割(に{I, 0, 0, 0, I, I, 0, I, I, I, 0, I, 0}なります{{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}}

1##&@@@ ...

レベル2の製品を検索します(に{{I}, {0, 0, 0}, {I, I}, {0}, {I, I, I}, {0}, {I}, {0}}なります{I, 0, -1, 0, -I, 0, I, 0}

Tr

結果を合計します。(に{I, 0, -1, 0, -I, 0, I, 0}なります-1 + I


マイナス1バイト:Tr[Times@@@(I*Split@RealDigits[#,2][[1]])]&
マーティン

1
@martinまあ、I最初に掛け算のアイデアを使いましたが、IntegerDigits結局短くなりました。
ジョンファンミン

はい-はるかに良い:)
マーティン


5

JavaScript(ES6)、67 64バイト

f=(n,q=0,a=[0,0])=>q|n?f(n/2,n&1?q+1:q&&0*(a[q&1]+=1-(q&2)),a):a
<input oninput="O.innerHTML=f(this.value)" type="number" step=1 min=0 value="4538">
<pre id=O></pre>

2要素配列として出力します。

説明

JavaScriptには虚数がないため、実部と虚部を別々の変数で追跡する必要があります。これを行う最も簡単な方法は、実際の部分を最初にして、単一の配列にすることです。i[0,1]i 2(または-1)は[-1,0]i 3(または-i)は[0、-1]i 4(または1)は[1 、0]

まず、数値を2で繰り返し除算し、1の各実行をバイナリ表現で収集します。n個の各実行はi nに対応します。これは、2項目配列のインデックスn&1の項目に1-(n&2)を追加することに対応します。それが私たちの仕事です。

おそらくもっと説明を追加する必要がありますが、他に説明が必要なものは考えられません。質問がある場合は、気軽にコメントしてください。


5

パイソン、199 129 124 116 94 90 71 63 61バイト

print sum(1j**len(s)for s in bin(input())[2:].split('0')if s)

入力は単なる数値そのものです。
出力はの形式(a+bj)で、jは虚数単位です。0jの代わりに出力されます(0+0j)

最初にバイナリに変換します。'0b'オフを切り捨てます。末尾のゼロを削除します。区切り文字としてゼロのブロックを使用して分割します。各ブロックをにマップし1j ** lenます。次に、全体の合計を取ります。

-70バイトはプラスに変換されません。
-5バイトの正規表現は短くなります。一度だけ呼び出された2つの不要な変数を取り除くことにより、
-8バイト。私の奇妙なものの代わりに複素数を使用して
-22バイト。複素数を通知してくれた@Dennisの回答に感謝します!
-4バイトそれが実現することにより、map長い除き、リストの内包表記をしているだけの空想の方法です。エラーを回避し、正規表現を回避する少し難解な方法に切り替えることにより、
-19バイトj ** 0。@Griffinのコメントに触発されました。ありがとう!:) パートを最後に移動して
-8バイトif
-2バイト 代わりに角括弧を削除してジェネレータ式にしたことで2バイトを節約してくれた@Griffinに感謝します!


私は非常に似たものを手に入れたので、個別の回答を投稿しませんが、少し短くなりますsum(1j**x.count('1')for x in bin(input()).split('0')if x)
グリフィン

@グリフィンニース。1ブロックをカウントする別の方法を使用し、私のように正規表現を使用しないため、別の回答を投稿できるほど十分に異なると思います。また、私のバージョンよりもはるかに優れているため、コードを盗みたくありません。:)
HyperNeutrino 16

@Griffin私はあなたのソリューションと同じ長さの別のソリューションを見つけました。ただし1、長さではなくs をカウントする代わりに、0x最初にフロントから部分を取ります。if最後に移動するアイデアをありがとう。そうでなければ機能することを私は決して知らなかったでしょう!
ハイパーニュートリノ16

リストを理解する必要はありません。角括弧を削除してジェネレータ式にします
グリフィン

@グリフィンああ。わかった、ありがとう!私は、将来のゴルフのためにそれを覚えているだろう
HyperNeutrino

4

MATLAB、58バイト

@(x)eval([strrep(strrep(dec2bin(x),48,43),49,'i*1'),'.0'])

dec2bin(x) % converts the decimal value to a binary string of 1s and 0s.
strrep(dec2bin(x),48,43) % Substitutes ASCII character 48 with 43 (0s become +)
strrep(___,49,'i*1')     % Substitutes ASCII character 49 with 'i*1'
                         % 1s become 'i*1' (this is the gem)
eval([___,'.0']          % Appends .0 in the end and evaluates the expression.   

285プロセスを説明するために使用しましょう:

temp1 = dec2bin(285)
      = 100011101

temp2 = strrep(temp1,48,43)
      = 1+++111+1

幸いなことに、MATLABと1+++1同じよう1+1に動作するため、上記の評価結果は次のとおり1+111+1です。

temp3 = strrep(temp2,49,'i*1')
      = i*1+++i*1i*1i*1+i*1

今、このstrrep-callは本当の宝石です!挿入することでi*11本当に素晴らしいものが得られます。1つしかない場合は、どちらか1を取得i*1しますi。複数ある場合i*1は、繰り返され、連結されてシーケンスになりますi*1i*1i*1i*1。以来i==1iMATLAB内と1i*1==iこれは単純です:i*i*i*i

temp4 = [temp3,'.0']
      = i*1+++i*1i*1i*1+i*1.0

.0ここでは追加する必要はないようですが、の最後の文字がtemp3である場合に必要です+。ゼロを追加することはできません。ゼロを追加すると、i*10上記の場合に結果が返されるためです。

そして最後に:

eval(temp4)
0.0000 + 1.0000i

これは、いくつかの理由でOctaveで機能しません。strrep入力としてASCII値を取ることはできません。実際の文字('0'ではなく48)が必要です。また、インクリメント/デクリメントのショートカットとを壊してしまうため、Octave +++だけ+では評価されません。x++x--


1
eval使用する場合は常に+1 :-Pの1i代わりに使用できません1*iか?
ルイスメンドー

1
ああ、あなたはそれを異なって使用しています。非常に賢い!
ルイスメンドー

おかげで:-)私は認めなければならない、私は非常に満足したi*1部分...
Stewieグリフィン


2

Mathematica、84バイト

ToExpression[#~IntegerString~2~StringTrim~"0"~StringReplace~{"0"..->"+","1"->"I "}]&

匿名関数。入力として数値を受け取り、出力として複素数を返します。


6
Mathematicaにこの機能が組み込まれていないことに驚きました!
HyperNeutrino 16

2

Mathematica、75バイト

ToExpression[#~IntegerString~2~StringReplace~{"1"->"I ","0"..->"+"}<>"-0"]&

LegionMammal978が23分前に投稿したものとほぼ同じソリューションを独自に考案しました!交換1I スペースが隣接表現の乗算として扱われるため(-1の平方根のためのMathematicaの内部シンボルである)が動作します。私は他のソリューションに保存された場所は、すなわちの必要性を回避することによってStringTrim、常に付加することである-0:中二進数終了した場合1には、この表現が終了すると、...I-0その値に影響を及ぼしません。一方、2進数が「0」で終わる場合、この表現は...+-0「負の0を追加」として解析され、末尾のプラス記号を取り除きます。


2

Matlab、99バイト

function c=z(b)
c=0;b=strsplit(dec2bin(b),'0');for j=1:numel(b)-isempty(b{end});c=c+i^nnz(b{j});end

テストケース:

z(656) = 3i
z(172) = -1 + 2i
z(707) = -2 + i
z(32)  = i
z(277) = 4i

2

ハスケル、102 91 89 87バイト

0%a=a
n%c@[a,b]|odd n=div n 2%[-b,a]|d<-div n 2=zipWith(+)c$d%[mod d 2,0]
(%[0,0]).(*2)

繰り返し2で除算し、ビットをチェックします。としてエンコードされるi^(number of odds)場所のアキュムレータを保持a+b*iします[a,b]*iある[a,b]↦[-b,a](90度回転)。最初(*2)は、最初のビットの検索を回避することです。

使用法(例については@OwenMorganに感謝):

(%[0,0]).(*2)<$>[656,172,707,32,277]
[[0,3],[-1,2],[-2,1],[0,1],[0,4]]

1

Java、172バイト

l->{int i=0,j=i;for(String x:l.toString(2).split("0")){int a=x.length();j+=a&1>0?(a&3>2?(a-3)/-4+1:(a-3)/4+1):0;i+=a&1<1?(a&3>1?(a-3)/4+1:(a-3)/-4+1):0;}return i+"|"j+"i";}

1

Clojure、183バイト

#(loop[x(clojure.string/split(Integer/toString % 2)#"0+")y[0 0]a 0](if(= a(count x))y(recur x(let[z([[1 0][0 1][-1 0][0 -1]](mod(count(x a))4))][(+(y 0)(z 0))(+(y 1)(z 1))])(inc a))))

これを行うことはできますか?

次のような関数を使用します。

(#(...) {num}) -> (Wrap the # function in brackets first!)

1

実際には、35バイト

├'0' aÆô' @s"j+"j'jo`"1j*1"'1τ(Æ`Y≡

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

説明:

├'0' aÆô' @s"j+"j'jo`"1j*1"'1τ(Æ`Y≡
├                                    binary representation of input
 '0' aÆ                              replace 0s with spaces
       ô                             trim leading and trailing spaces
        ' @s                         split on spaces
            "j+"j                    join with "j+"
                 'jo                 append "j"
                    `"1j*1"'1τ(Æ`Y   do until the string stops changing (fixed-point combinator):
                     "1j*1"'1τ(Æ       replace "11" with "1j*1"
                                  ≡  evaluate the resulting string to simplify it

ほぼ同等のPython 3コード:

a='j+'.join(bin(eval(input()))[2:].replace('0',' ').strip().split())+'j'
b=0
while a!=b:b,a=a,a.replace("11","1j*1")
print(eval(a))

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


'0'で分割し、後続の空の文字列をトリムするために'0@s使用``░すると、4バイト節約できます。
Sherlock9

1

ゼリー、10バイト

これは、デニスのゼリーの答えよりはましではありませんが、とにかくゼリーの答えで手を試してみたかったのです。ゴルフの提案を歓迎します!オンラインでお試しください!

BŒrm2Ṫ€ı*S

アンゴルフ

BŒrm2Ṫ€ı*S   Main link. Argument: n (integer)

B            Convert n to binary.
 Œr          Run-length encode the binary list.
   m2        Every 2nd element of the run_length encoding, getting only the runs of 1s.
     Ṫ€      Tail each, getting only the lengths of the runs.
       ı*    The imaginary unit raised to the power of each run (as * is vectorized).
         S   Sum it all into one complex number.

上記のリンクでは、入力1は1jを返し、入力2は1jを返します。
RosLuP

@RosLuPはい、そうですか?後続の0を削除するため、1 => 1 => 1jと同等2 => 10 => 1 => 1jです。
Sherlock9

1

実は、15バイト

ゴルフの提案を歓迎します!オンラインでお試しください!

├'0@s``░`lïⁿ`MΣ

アンゴルフ:

         Implicit input n.
├        Convert n to binary.
'0@s     Split by '0's.
``░      Filter out non-truthy values.
`...`M   Map over the filtered result, a list of runs of '1's.
  l        Yield the length of the run of '1's.
  ïⁿ       Yield the imaginary unit to the power of that length.
Σ        Sum all of this into one complex number.

0

公理、140、131、118の 108バイト

b(x)==(s:=0;repeat(x=0=>break;r:=x rem 2;repeat(x rem 2=1=>(r:=r*%i;x:=x quo 2);break);s:=s+r;x:=x quo 2);s)

%iは架空の共助者です。

sb(x:NNI):Complex INT==
  r:Complex INT;s:Complex INT:=0
  repeat
    x=0=>break
    r:=x rem 2
    repeat
       x rem 2=1=>(r:=r*%i;x:=x quo 2)
       break
    s:=s+r
    x:=x quo 2
  s

結果

(3) -> b 4538
   The type of the local variable r has changed in the computation.
   We will attempt to interpret the code.
   (3)  - 1 + %i
                                                    Type: Complex Integer
(4) -> b 29
   (4)  0
                                                    Type: Complex Integer
(5) -> sb 299898979798233333333333333339188888888888888888222
   Compiling function sb with type NonNegativeInteger -> Complex Integer
   (5)  - 7 + 12%i
                                                    Type: Complex Integer
(6) -> b 299898979798233333333333333339188888888888888888222
   (6)  - 7 + 12%i
                                                    Type: Complex Integer

0

Perl 6 40  46バイト

私はこれをかなり迅速に思いついた

*.base(2).comb(/1+/).map(i***.chars).sum

残念ながら、MoarVMのRakudo実装 では現在不正確です。
say i ** 3; # -1.83697019872103e-16-1i

そのため、次善策を講じなければなりませんでした。

*.base(2).comb(/1+/).map({[*] i xx.chars}).sum

拡張:

*\             # Whatever lambda
.base(2)       # convert to a Str representation in base 2
.comb(/ 1+ /)  # get a list of substrings of one or more 「1」s
.map({         # for each of those

  [*]            # reduce using 「&infix:<**>」
    i xx .chars    # 「i」 list repeated by the count of the characters matched

}).sum          # sum it all up

テスト:

.say for (4538, 29).map:

    *.base(2).comb(/1+/).map({[*] i xx.chars}).sum

# -1+1i
# 0+0i


0

PHP、87バイト

for($n=$argv[1];$n|$i;$n>>=1)$n&1?$i++:($i?$i=0*${$i&1}+=1-($i&2):0);echo"(${0},${1})";

ETHproductionsのソリューションとほぼ同じです。再帰的ではなく反復的のみ。
コマンドラインから入力を受け取り、変数${0}とを設定します${1}


0

TI-Basic(TI-84 Plus CE)、70バイト

Prompt X
0→S
0→N
While X
If remainder(X,2
Then
N+1→N
int(X/2→X
Else
S+i^Nnot(not(N→S
X/2→X
0→N
End
End
S+i^Nnot(not(N

バイナリ文字列に変換するビルトインはありません(文字列を解析するためのものもありません)。したがって、このプログラムは手動で2で除算します。ゼロが見つかった場合はN。



0

R、54バイト

function(n,x=rle(n%/%2^(0:log2(n))%%2))sum(1i^x$l*x$v)

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

n%/%2^(0:log2(n))%%22進数のベクトルを計算します。ランレングスエンコーディングを使用して、Rのcomplexタイプを使用して適切な合計を計算し、x$valuesゼロを削除するためにをます。

complex1つの要素のベクトルを返します。

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