这个数字是邪恶的吗?


34

介绍

在数论中,如果二进制表示形式中的偶数个数为1,则该数字被认为是邪恶的。在今天的挑战中,您将确定给定的数字是否为邪恶。

挑战

您的工作是编写一个完整的程序或函数,以接受单个非负整数作为输入并输出(或返回)该数字是否为邪恶。

  • 如果数字是邪恶的,则可以输出任何值,而如果数字不是邪恶的,则可以输出任何虚假的值。
  • 您可以以任何可接受的格式输入和输出。
  • 不允许出现标准漏洞
  • OEIS序列A001969是包含所有邪恶数字的序列。
  • 是前10000个邪恶数字的列表,以供参考(还有更多测试用例!)
  • 这个问题是,所以越短越好。
  • 不要被打高尔夫球的简短答案所困扰。我鼓励您以喜欢的任何语言提交。
  • 以下是一些测试案例:

    3 => True
    11 => False
    777 => True
    43 => True
    55 => False
    666 => False
    

排行榜

页面底部是一个堆栈片段,其中包含此问题的页首横幅。(谢谢@MartinEnder)

为确保您的答案显示出来,请使用以下Markdown模板以标题开头。

# Language Name, N bytes

N您提交的文件大小在哪里。如果您提高了分数,则可以通过打败旧分数保持标题。例如:

# Ruby, <s>104</s> <s>101</s> 96 bytes

如果您想在标头中包含多个数字(例如,因为您的分数是两个文件的总和,或者您想单独列出解释器标志罚分),请确保实际分数是标头中的最后一个数字:

# Perl, 43 + 2 (-p flag) = 45 bytes

您还可以将语言名称设置为链接,然后该链接将显示在页首横幅代码段中:

# [><>](http://esolangs.org/wiki/Fish), 121 bytes

编辑:我认为这个问题是不是重复这个,因为这而问题是问计数的人的数量,这个问题是问的人的数量是偶数。尽管您可以通过简单地计算位数来解决此问题,但是还有其他方法


2
相关(对每个二进制数进行XOR运算与求和模2相同)。
凯文·克鲁伊森


2
@BetaDecay,但不能反向工作:即,您无法获取所有这些答案并删除mod2。因此,此挑战提出了一些新方法。
血液学

13
我认为这666 => False应该是一个测试案例。
user2390246

3
排行榜对我来说很残酷
Jo King

Answers:


35

Z80汇编(8位),2字节

以下代码仅适用于最大为255的值:

; Input is given in register A.
; P flag is set if A is evil.
B7     or A
C9     ret


16位版本(适用于所有测试用例),3字节

最多可使用65535。

; Input is given in BC.
; Output is the same as above.
78     ld A,B
A9     xor C
C9     ret

如果您喜欢冒险,可以通过将输入存储在其中来减少1个字节AC如下所示

      ld BC, 777
C5    push BC
F1    pop AF

然后运行

A9    xor C
C9    ret

但是,这给调用者带来了负担,因此可能也应同时计算两个字节(push BCpop AF)。


我喜欢这个,但是如何运作?我对汇编的记忆(6502 + arm)是ors按2个操作数按位排列
Northern-bradley

2
@ northern-bradley在Z80上,它意味着or助记符的第二个操作数是累加器A。在这种情况下,该命令不会更改A。它仅将状态寄存器(尤其是奇偶校验标志)刷新为反映A的内容
cschultz2048

1
是否P按照codegolf.meta.stackexchange.com/a/8509/29560允许?它是F(标志)寄存器中的单个位,只有三对指令受其影响。另外,这个答案没有提及它只是争夺8位值,因为A它是8位寄存器。这意味着它无法给出一个答案777,或者超过255的任何其他的无符号数
CJ丹尼斯

2
该死的内置插件:P
Jo King

1
@ cschultz2048 A与配对F,因此我不接受ABBA作为16位值。BC是16位的,但是A在对另一个进行异或之前,您需要额外的指令才能将其中一个加载到其中。我总是提到我的Z80答案在255或65535范围内完全有效,具体取决于问题。也许还要添加一个16位版本?因此2个字节用于8位值,3个字节用于16位值。
CJ丹尼斯

25

JavaScript(ES6),18个字节

f=n=>n?!f(n&~-n):1

在线尝试!

说明

按位逻辑如下所示:

  • 对于整数,~-n等于-(-n)-1,因此只是另一种处理方式n-1。在那种特殊情况下,我们实际上可以使用n-1
  • n & (n-1)删除n中设置为1的最低有效位,因为递减n会将所有尾随的0变为1,并清除紧随其后的1(通过进位传播),而其他所有内容保持不变。

    n = 24的示例(二进制为11000):

      11000 (24)                  11000 (24)
    -     1                   AND 10111 (23)
    -------                   ---------
    = 10111 (23)              =   10000 (16)
       ^                           ^
       |                           |
       +--- this bit is cleared ---+
    

因此,在n的二进制表示形式中,我们处理的递归调用数量与1一样多,每次都用反转结果。最后一次调用始终返回1!

例子:

f(24) = !f(16) = !!f(0) = !!1 = true
f(7) = !f(6) = !!f(4) = !!!f(0) = !!!1 = false

您好,我了解代码的作用,但是尽管阅读了几篇有关按位运算的文章,并检查了数字是否为2的幂等,但是我还是无法弄清楚其背后的逻辑/原因。我知道递归函数是什么。我只是不明白为什么以这种方式使用它,以及为什么它可以解决难题,即递归与!f(2的幂)<==>邪恶数之间的联系。如果您有时间,欢迎解释:)谢谢!
凌晨

1
@supafly我添加了一个解释。顺便说一句:欢迎来到PPCG!
Arnauld

现在的处理非常清楚。尽管如此,这个想法/理由还是很神奇的!谢谢你的解释!
凌晨

13

Python 2,25个字节

lambda n:int(bin(n),13)%2

在线尝试!

bin(n)给出类似的结果'0b10101'。将其读取为以13为底的整数,我们得到

这降低了模2至 1 1 5 + 1 1 4 + 0 1 3 + 1 1 2 + 0 1 1 + 1 1

11135+1134+0133+1132+0131+1130
1 + 1 + 0 + 1 + 0 + 1
115+114+013+112+011+110(mod2)
1+1+0+1+0+1(mod2).

因此int(bin(n),13)%2等于1 +(1中的个数bin(n))模2。

如果n是邪恶的,则结果为1;否则为1。否则为0。

我从Noodle9获得了这个技巧。


由于这是Python 2中,代码可以进一步被弃用再版反引号语法缩短:lambda n:int(`n`,13)%2在线尝试!
GarethPW

是的,那儿有点放屁,忘了int基本论证的目的。哎呀!
GarethPW


8

C#(Visual C#交互式编译器)43 38字节


高尔夫 在线尝试!

i=>Convert.ToString(i,2).Sum(c=>c)%2<1

不打高尔夫球

i => Convert.ToString( i, 2 ).Sum( c => c ) % 2 < 1

完整的测试代码

Func<Int32, Boolean> f = i => Convert.ToString( i, 2 ).Sum( c => c ) % 2 < 1;

Int32[] testCases = { 3, 11, 777, 43, 55 };

foreach( Int32 testCase in testCases ) {
    Console.Write( $" Input: {testCase}\nOutput: {f(testCase)}" );
    Console.WriteLine("\n");
}

Console.ReadLine();

发布

  • V1.1 - -5 bytes-替换CountSum
  • 1.0 - 43 bytes-初始溶液。

笔记

  • 没有

2
为您的“脱胶版”版本给我带来的笑声表示支持。
杰克·布劳恩斯坦

8

Bash(无外部实用程序),56 44字节

while(($1));do set $(($1/2)) $(($2+$1%2));done;!(($2%2))

(($1))&&exec $0 $[$1/2] $[$2+$1%2];!(($2%2))

假设已在中找到该数字,并将$1其作为第一个命令行参数传递。它还假定这是一个Shell脚本(以便它exec本身可以)。

它使用递归重复使用exec $0,直到(in $1)中的数字达到零,在每次迭代中将其除以2。它还将求和$2的次数相加(以表示)。最后,如果总和$2不是奇数,则原始数字为“邪恶” 。

调用示例:

$ ./script 3 && echo evil
evil

$ ./script 11 && echo evil

$ ./script 777 && echo evil
evil

$ ./script 43 && echo evil
evil

$ ./script 55 && echo evil

对于0

$ ./script 0 && echo evil
./script: line 1: ((: %2: syntax error: operand expected (error token is "%2")
evil

正确的结果,侧面还有一些额外的东西。


7

R37 26字节

!sum(scan()%/%2^(0:31))%%2

在线尝试!

罗伯特·S(Robert S.)的答案的一种替代方法,它避免了内置的位拆分,但是减少了高尔夫球运动,这要归功于杰伊(JayCe)和digEmAll最终使高尔夫球手变得更加高尔夫球。

2311


为什么不对31而不是log2进行硬编码?在线尝试!
digEmAll

@digEmAll反过来意味着无需定义x
JayCe '18年

231-1个%/%%%

同样,intToBits仅支持最大2 ^ 31-1的整数值;)
digEmAll

6

05AB1E,4 个字节

bSOÈ

在线尝试验证所有测试用例

说明:

b       # Convert to binary string
        #  i.e. 777 → 1100001001
 S      # Change it to a list of 0s and 1s
        #  i.e. 1100001001 → ['1','1','0','0','0','0','1','0','0','1']
  O     # Take the sum
        #  i.e. ['1','1','0','0','0','0','1','0','0','1'] → 4
   È    # Check if it's even (1 as truthy, 0 as falsey)
        #  i.e. 4 → 1


5

[R99 98 44 34 28字节

-1感谢Kevin Cruijssen!-54感谢ngm!-10感谢朱塞佩!-6感谢JayCe!

!sum(intToBits(scan())>0)%%2

在线尝试!


或者,使用 binaryLogic包(39个字节):

!sum(binaryLogic::as.binary(scan()))%%2

2
我不太了解R,但我很确定==0会是<1:)
Kevin Cruijssen



1
我认为这也
可行


5

C(gcc),36个字节

c;f(n){for(c=0;n;c++)n&=n-1;n=~c&1;}

在线尝试!

K&R的方法 https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan

必须以优化级别0进行编译


无法在gcc 5.4.0上编译:(error: expected constructor, destructor, or type conversion before '(' token箭头指向f函数名称中的)。我需要什么编译器标志?
villapx

1
不适用于-O
nwellnhof '18

2
“为真返回0,为假返回1”这合法吗?不要试图抹黑你的答案,只是好奇,因为这可以节省我一个字节。注意:问题中的真理一词链接到此答案。而此评论也提到感实性。
Borka223 '18

@nwellnhof @villapx在我的7.3.0上可以正常编译-只要确保您没有丢失-O0编译器标志即可。

@ Borka223 hmmm经过数月的浏览本网站后,我的印象是,只要您的解决方案中始终如一,则对与错可以是任何东西。但是,您链接的答案肯定似乎与此矛盾。我继续并添加了字节。谢谢
vazt


4

PHP,37 36字节

<?=1&~substr_count(decbin($argn),1);

要运行它:

echo '<input>' | php -nF <filename>

在线尝试!

打印1为true和0false。

-1个字节感谢Benoit Esnard


1
我想你可以通过删除模操作保存一个字节:<?=1&~substr_count(decbin($argn),1);。这个也为假打印0。
Benoit Esnard '18年

谢谢@BenoitEsnard!这非常聪明,我已经更新了答案:)您每天都在学习新知识!
Davіd

4

Brachylog,4个字节

ḃo-0

在线尝试!

有多个测试用例(😈是邪恶的,👼不是。)

使用我最近发现的有关-谓词的内容:其文档仅显示“ [input]的元素之差”,但实际上所做的是“ input的偶数索引元素的总和(从0开始),减去奇数的总和索引的输入元素”。

这里,

将数字转换为二进制数字数组,

o 对它们进行排序以将所有1组合在一起。

现在,如果偶数为1,则偶数索引和奇数索引的个数等于1。所以-其后的值将为0。但是,如果奇数个数为1,则将有一个额外的1伸出,导致差值为-1或1。

因此,最后,我们断言差异是0,并据此得出对或错的结果。对于更灵活的输出要求,可以将其删除以得到3个字节的答案,其中0为真实输出,-1和1为两个虚假输出。


4

INTERCAL90 65 63字节

DOWRITEIN:1
DO:2<-'#0$#65535'~?':1~:1'
DOREADOUT:2
PLEASEGIVEUP

在线尝试!

用C样式注释取消扩展(按其价值)。

DO WRITE IN :1 //Store user input in 1
DO :2<-:1~:1 //Select just the ones. So will convert binary 10101 to 111
DO :3<-:?2 //Run the unary xor over the result. Essentially, xor with the right bitshifted
           //(with wraparound) value).
DO :9<-#0$#65535 //Intermingle the 16 bit values of all 0's and all 1's, to create a
                 //32 bit number with 1's in the odd positions.
DO :4<-:9~:3 //It turns out that at this point, evil numbers will have no bits in odd
             //positions, and non-evil numbers will have precisely one bit in an odd
             //position. Therefore, the ~ will return 0 or 1 as appropriate.
PLEASE READ OUT :4 //Politely output
PLEASE GIVE UP //Polite and self explanatory

为了使这在INTERCAL中可行,我不得不做出一些让步。首先,与所有INTERCAL程序一样,必须将数字输入写出。因此,如果您想输入707,则可以提供SEVEN OH SEVEN

第二个问题是INTERCAL并没有真正的真实性或虚假性。相反,I如果数字不是邪恶的,它将输出罗马数字(1),或者输出0(通常表示为-罗马数字通常不能表示0)。

如果要翻转这些值,以使邪恶数字返回1而非邪恶数字返回0,则可以从非高尔夫版本更改行4和5,如下所示,尽管它确实增加了3个字节。

DO:9<-#65535$#0
DO:4<-#1~:9~3


3

dc18 16字节

[2~rd1<M+]dsMx2%

返回(返回堆栈)0为邪恶,1为非邪恶

在线尝试!

相当简单-将组合的商/余数运算符递归地应用~到新商,并将所有余数相加,然后加2的mod (在花了两个字节以翻转为标准的true / falsy之后)

编辑以反映共识,即0为真,1为虚假是可以的,尤其是在没有任何if(boolean)构造的语言中。


3

Python 2,29个字节

lambda n:~bin(n).count('1')&1

在线尝试!

如果为True,则返回1,否则返回0。

将数字转换为二进制字符串,例如“ 0b11”,计算1的数目,获取结果的补码,然后返回补码的最后一位(谢谢, https://codegolf.stackexchange.com/users/53560/cdlane!)(如果原始数字为偶数则为1,如果为奇数则为0)。


1
字节lambda n:~bin(n).count('1')&1数不多,但是用可能更便宜的东西代替了模块划分。
cdlane

3

x86-16,3个字节

NASM列表:

 1                                  parity16:
 2 00000000 30E0                        xor al,ah
 3 00000002 C3                          ret

AX中的16位整数函数arg(已销毁),PF中的返回值。

硬件在x86的奇偶校验标志中为我们计算结果的奇偶校验。呼叫者可以使用jp/ jnp进行分支,也可以随意分支。

就像@cschultz的Z80 / 8080答案一样工作 ; 实际上8086 旨在简化8080的机械源移植

请注意,PF仅从较宽结果的低字节设置,因此test edi,edi不适用于x86-64版本。您必须对16位进行水平异或,或popcnt eax, edi/ and al,1(其中0为真)。


3

C ++(gcc)(-O0), 36  31字节

int f(int i){i=!i||i%2-f(i/2);}

在线尝试!


C ++(clang),35个字节

int f(int i){return!i||i%2-f(i/2);}

在线尝试!


这是我第一次尝试打高尔夫球,希望我没有违反任何我可能错过的规则。

编辑:
-保存5个字节感谢@Jonathan弗雷希:取代!=通过-return通过i=(上次更换似乎没有工作,虽然铿锵不)
-由于有似乎是一个辩论中,我是否应该使用gcc -O0虐待,我以为我可以只给两个版本


欢迎来到PPCG!您可以通过打高尔夫球来保存字节!=-,另有4通过高尔夫returni=
乔纳森·弗雷希

@JonathanFrech自从我执行C ++已有很长时间了,如果没有return语句,它是否隐式返回函数中最后分配的表达式?我猜这是gcc吗?
sundar-恢复莫妮卡

1
这是优化级别为O0的gcc特定的未定义行为滥用。
乔纳森·弗雷希

通过切换到K&R C,您可以将其压缩到23个字节(非常令人印象深刻!)在线尝试!
ErikF

@JonathanFrech:为什么人们坚持使用这种愚蠢的骇客gcc -O0?比较实现时,语言的总样板的长度并不重要。同样,它使在return按引用调用与按引用调用之间进行选择(*i就地更新)变得更加有趣。我宁愿写C或C ++的答案,而不是只写未优化的gcc的答案,因为未优化的gcc并不是一种非常有用的语言。
彼得·科德斯

3

SML,32字节

fun%0=1| %n=(n+ %(n div 2))mod 2

说明:

  • % 是函数名称
  • takes in input in repl and returns 1 if evil, 0 otherwise
  • n is input, returns (n + %(n//2)) % 2

Made by 2 bored Carnegie Mellon Students


Welcome to PPCG, and good first answer!
mbomb007

2

Forth (gforth), 53 bytes

: f 1 swap begin 2 /mod -rot xor swap ?dup 0= until ;

Try it online!

Explanation

Takes the xor-sum of the digits of the binary form of the number. (repeatedly divides by 2 and xors the remainder with the "sum" value)

Code Explanation

: f              \ begin a new word definition
  1 swap         \ place 1 on the stack below the input (n)
  begin          \ start an indefinite loop
    2 /mod       \ get the quotient and remainder of dividing n by 2
    -rot         \ move the sum and remainder to the top of the stack
    xor          \ xor the sum and remainder
    swap         \ move the quotient back to the top of the stack
    ?dup         \ duplicate if > 0
    0=           \ get "boolean" indicating if quotient is 0
  until          \ end the loop if it is, otherwise go back to the beginning
;                \ end the word definition

2

Java 8, 40 36 bytes

n->n.toString(n,2).chars().sum()%2<1

-4 bytes thanks to @Okx for something I shouldn't have forgotten myself..

Try it online.

Explanation:

n->                // Method with Integer parameter and boolean return-type
  n.toString(n,2)  //  Convert the integer to a binary String
   .chars()        //  Convert that to an IntStream of character-encodings
   .sum()          //  Sum everything together
    %2<1           //  And check if it's even

Note that the character encoding for 0 and 1 are 48 and 49, but summing them and taking modulo-2 still holds the correct results because 48%2 = 0 and 49%2 = 1.


1
n.toString(n,2) saves 4 bytes.
Okx

@Okx Not sure how I forgot about that one, lol.. Thanks! ;)
Kevin Cruijssen

If you're allowed to use 1 and 0 instead of true and false (not sure for Java), you can change to: ~n.toString(n,2).chars().sum()%2 to save one byte.
Mario Ishac

1
@MarDev Unfortunately 0 and 1 aren't truthy/falsey in Java, only booleans/Booleans are. If a challenge would state two distinct outputs are allowed the <1 could have been removed to save 2 bytes indeed. :)
Kevin Cruijssen


2

Retina 0.8.2, 28 bytes

.+
$*
+`(1+)\1
$+0
0

11

^$

Try it online! Link includes test cases. Explanation:

.+
$*

Convert to unary.

+`(1+)\1
$+0

Partial binary conversion (leaves extra zeroes).

0

Delete all the zeros.

11

Modulo the ones by two.

^$

Test whether the result is zero.


2

x86 Assembly, 12 11 bytes

F3 0F B8 44 24 04  popcnt      eax,dword ptr [esp+4] ; Load EAX with the number of ones in arg
F7 D0              not         eax ; One's complement negation of EAX
24 01              and         al,1 ; Isolate bottom bit of EAX
C3                 ret             

-1 byte thanks to @ceilingcat's suggestion


@ceilingcat Good catch!
Govind Parmar

1
Suggest inc eax instead of not eax. Also may want to mention that this requires a processor with support for the popcnt instruction.
ceilingcat

1
also you do not have to take arg from stack. see allowed calling conventions codegolf.stackexchange.com/a/161497/17360 (Peter Cordes's more in-depth answer codegolf.stackexchange.com/a/165020/17360)
qwr

1
Note that you may return a boolean in FLAGS stackoverflow.com/a/48382679/3163618
qwr

Shouldn't 666 be a test case?
Arcanist Lupus

2

Bash + GNU utilities, 33

dc -e2o?p|tr -d 0|wc -c|dc -e?2%p

Try it online!

Reads input from STDIN. Outputs 1 for True and 0 for False.

  • dc converts input to a binary string
  • tr removes zeros
  • wc counts remaining ones (and trailing newline, which corrects sense of logic
  • dc calculates count mod 2 and outputs the answer

2

Python 2, 28 27 bytes

f=lambda n:n<1or n&1^f(n/2)

Try it online!

Returns a truthy value if exactly one of the ones-bit is a 1 and the result of calling this function on n/2 is truthy is true (or n==0). It works because n/2 is equivalent to a right bitshift with floor division (so Python 2 only).

Alternate version, also 28 27 bytes

g=lambda n:n<1or g(n&n-1)^1

Try it online!

Based on the K&R method of counting set bits referenced by vazt.

Both of these could be two bytes shorter if the output allowed falsey to mean evil.

Edit: Thanks to Amphibological for saving a byte!


You can remove the spaces between the 1 and the or to save +1 byte. Nice solution!
Amphibological

Man, I thought I tried that. Good catch!
Jack Brounstein

2

APL (Dyalog Unicode), 10 bytesSBCS

Anonymous tacit function. Can take any array of integers as argument.

≠⌿12∘⊥⍣¯1

Try it online!

2∘⊥⍣¯1 convert to binary, using as many digits as needed by the largest number, separate digits along primary axis

1⍪ prepend ones along the primary axis

≠⌿ XOR reduction along the primary axis


2

J, 9 bytes

Anonymous tacit function. Can take any integer array as argument.

1-2|1#.#:

Try it online!

1- one minus (i.e. logical negation of)

2| the mod-2 of

1#. the sum (lit. the base-1 evaluation) of

#: the binary representation


Nice one! the boring approach is 9 bytes: 2|1+1#.#:
Conor O'Brien

This only seems to work because 777 in the input makes every number be represented in 10 bits. Replace it with e.g. 480 and the output flips.
FrownyFrog

@ConorO'Brien Boring trumps incorrect.
Adám

@FrownyFrog Fixed.
Adám
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.