复数二进制数


36

让我们创建一个从正整数到高斯整数的简单的射影映射,高斯整数复数,其中实部和虚部都是整数。

例如4538,给定一个正整数,以二进制形式表示,且不带前导号0

4538 base 10 = 1000110111010 base 2

删除任何尾随0的:

100011011101

用一个替换任意一个或多个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

输出可以用传统的数学方式表示,也可以用两个单独的整数表示实部和复杂部分。对于4538例如,任何这些就可以了:

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

对于像输入29,mathy格式化输出,诸如00i0+0i都是细。

如果您的语言更自然,则使用j(或其他方式)代替i可以。

以字节为单位的最短代码获胜。


从标题中,我认为挑战将是关于二进制的复数,例如4+2j-> 100+10j...
Erik the Outgolfer'Apr 1'17

Answers:


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个字节,而我能得到的最好的是MATLAB中的58个字节。=)
Stewie Griffin

1
@StewieGriffin很容易在图表或绘图中表现最好,也许也是从我​​见过他的出色答案中获得的矩阵算术。
魔术章鱼缸

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'December

@ETHproductions我的想法正好,但不幸的是,0**k它不适用于复杂的k...
Sp3000 '16

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最终变得更短了。
JungHwan Min

是的-更好:)
马丁


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,并以二进制表示形式收集每次运行。n的每次运行对应于i n。这对应于在两个项目数组的索引n和1处将1-(n&2)添加到项目。就是这样。

我可能应该添加更多的解释,但是我无法想到其他需要解释的内容。如有任何问题,请随时发表评论。


5

Python中,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个字节的正则表达式较短。摆脱了仅被调用一次的两个不必要的变量,从而获得了
-8个字节。通过使用复数而不是我的怪异东西来获得
-22个字节。感谢@Dennis的回答,让我知道复数!通过意识到
-4字节map只是列表理解的一种奇特方式,除了更长。切换到一种稍微神秘的方法来避免
-19个字节,从而避免使用j ** 0和避免使用正则表达式出错。受到@Griffin的评论的启发。谢谢!:)
-8字节(通过将if部分移到末尾)。
-2个字节 感谢@Griffin通过删除方括号使它成为生成器表达式来节省2个字节!


我有一个非常相似的内容,因此不会单独发布答案,尽管简短一些sum(1j**x.count('1')for x in bin(input()).split('0')if x)
Griffin

@格里芬尼斯。我认为您可以发布一个单独的答案就足够了,因为它使用了不同的计数1块方法,并且不像我的那样使用正则表达式。而且,我不想从您那里窃取代码,因为它比我的版本好得多。:)
HyperNeutrino

@Griffin我发现了另一个解决方案,该解决方案的长度与您的解决方案相同,只不过它不是先计算1s而是计算长度,而是先删除了0x一部分。感谢您if将结尾移到最后的想法;我永远都不会知道那行得通!
HyperNeutrino

您不需要列表理解。删除方括号以使其成为生成器表达式
Griffin

@格里芬哦。好的谢谢!我会记住这为今后的高尔夫
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

幸运的是,1+++1其行为与1+1MATLAB中的行为相同,因此以上结果为:1+111+1

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

现在,这个strrep-call是真正的宝石!通过插入i*11我们得到了非常好的东西。如果只有一个1,我们只是得到i*1i。如果有多个,则i*1重复并串联成一个序列:i*1i*1i*1i*1。由于i==1i在MATLAB和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)。另外,+++不仅仅+以八度为单位进行评估,因为那样会破坏增量/减量快捷键x++x--


1
使用时总是+1 eval:-P您不能使用1i代替1*i吗?
Luis Mendo

1
哦,您使用的方式有所不同。非常聪明!
Luis Mendo

谢谢:-)我必须承认,我对这i*1一部分感到非常满意……
Stewie Griffin


2

Mathematica,84个字节

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

匿名函数。以数字作为输入,并返回复数作为输出。


6
哇,我很惊讶Mathematica没有内置的功能!
HyperNeutrino

2

Mathematica,75个字节

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

独立地提出了与LegionMammal978在23分钟前发布的解决方案几乎相同的解决方案!替换1I (这是Mathematica的-1平方根的内部符号)有效,因为将空格视为相邻表达式的乘法。我在其他解决方案上保存的位置(即避免了对的需要StringTrim)是始终附加-0:如果二进制数字以结尾1,则该表达式在...I-0不影响其值的情况下结束;而如果二进制数以“ 0”结尾,则此表达式...+-0以“ add negative 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

Haskell,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)

反复除以二并检查该位。保持的蓄能器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@s和分割为0 ``░来修剪任何结尾的空字符串应为您节省四个字节。
Sherlock16年

1

果冻,10字节

这并不比Dennis的Jelly答案要好,但是无论如何我都想尝试一下Jelly的答案。欢迎打高尔夫球!在线尝试!

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
Sherlock16年

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

不幸的是,它目前在MoarVMRakudo实现中 不准确。
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基本(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,每次看到1时就递增N,并将i ^ N加到S(N> 0)并重置如果看到零,则为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))%%2计算二进制数字的向量。使用游程长度编码,我们使用R的complex类型来计算适当的总和,然后乘以x$values以去除零。

返回complex一个元素的向量。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.