Это число зло?


34

Введение

В теории чисел число считается злым, если в его двоичном представлении есть четное число единиц. В сегодняшнем испытании вы будете определять, является ли данное число злым.

Вызов

Ваша задача - написать полную программу или функцию, которая принимает одно неотрицательное целое число в качестве входных данных и выводит (или возвращает), является ли это число злым.

  • Вы можете вывести любое истинное значение, если число является злом, и любое ложное значение, если число не является злом.
  • Вы можете вводить и выводить данные в любом приемлемом формате .
  • Стандартные лазейки запрещены.
  • Последовательность OEIS A001969 - это последовательность, содержащая все злые числа.
  • Вот список первых 10000 злых чисел, для справки (и еще несколько тестов!)
  • Это вопрос , поэтому чем короче, тем лучше.
  • Не расстраивайтесь из-за очень коротких ответов на языках игры в гольф. Я призываю вас представить на любом языке, который вам нравится.
  • Вот несколько тестов:

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

Таблица лидеров

Внизу страницы находится фрагмент стека, содержащий таблицу лидеров для этого вопроса. (Спасибо, @MartinEnder)

Чтобы убедиться, что ваш ответ обнаружен, начните его с заголовка, используя следующий шаблон уценки:

# 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, но это не работает в обратном порядке: то есть вы не можете взять все эти ответы и удалить мод 2. Таким образом, этот вызов предлагает некоторые новые методы.
Амфибологическое

13
Я считаю, что это 666 => Falseдолжен быть контрольный пример.
user2390246

3
Таблица лидеров сломана для меня
Джо Кинг,

Ответы:


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 байт, сохраняя ввод Aи Cтак

      ld BC, 777
C5    push BC
F1    pop AF

а затем работает

A9    xor C
C9    ret

Однако это создает нагрузку на вызывающего, поэтому может быть так, что два байта ( push BCи pop AF) также должны быть учтены.


i like this but how does this work? my memory for assembly (6502 + arm) are that ors are bitwise with 2 operands
northern-bradley

2
@northern-bradley On the Z80, it's implied that the second operand of the or mnemonic is the accumulator A. In this case, the command doesn't change A. It only refreshes the status register (and in particular, the parity flag) to reflect the contents of A.
cschultz2048

1
Is P allowed as per codegolf.meta.stackexchange.com/a/8509/29560? It's a single bit within the F (flags) register which has only three pairs of instructions affected by it. Also, this answer fails to mention it's only competing for 8-bit values, since A is an 8-bit register. This means it is unable to give an answer for 777, or any other unsigned value over 255.
CJ Dennis

2
Damn built-ins :P
Jo King

1
@cschultz2048 A is paired with F, so I wouldn't accept AB or BA as a 16-bit value. BC is 16-bit, but then you need an extra instruction to load one of them into A before XORing the other. I've always just mentioned that my Z80 answers work fully up to 255 or 65535, depending on the question. Maybe add a 16-bit version as well? So 2 bytes for 8-bit values, 3 bytes for 16-bit values.
CJ Dennis

25

JavaScript (ES6), 18 bytes

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

Try it online!

Explanation

The bitwise logic goes like this:

  • For integers, ~-n is equivalent to -(-n)-1, so that just another way of doing n-1. In that particular case, we could actually have used n-1.
  • n & (n-1) removes the least significant bit set to 1 in n because decrementing n turns all trailing 0's into 1's and clears the 1 that immediately follows (by carry propagation), while leaving everything else unchanged.

    Example for n = 24 (11000 in binary):

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

Therefore, we process as many recursive calls as there are 1's in the binary representation of n, inverting the result each time with !. The last call always returns 1.

Examples:

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

Hello, I understand what the code does, but I just cannot figure out the logic/reasoning behind it, despite having read several articles about bitwise operations, checking if a number is a power of 2, etc. I know what a recursive function is. I just don't get why it has been used this way and why this works to answer to the puzzle, i.e. the link between the recursion and !f(power of two) <==> evil number. If you have time, explanation would be welcome :) thanks!
supafly

1
@supafly I've added an explanation. And BTW: welcome to PPCG!
Arnauld

The processing is very clear now. Still, the idea/reasoning is really magic! Thank you for the explanation!
supafly

13

Python 2, 25 bytes

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

Try it online!

bin(n) gives a result like '0b10101'. Reading this as a base-13 integer, we get

11135+1134+0133+1132+0131+1130
which reduces modulo 2 to
115+114+013+112+011+110(mod2)
1+1+0+1+0+1(mod2).

So int(bin(n),13)%2 equals 1 + (number of ones in bin(n)) modulo 2.

If n is evil, then the result is 1; otherwise it is 0.

I picked up this trick from Noodle9.


Since this is Python 2, the code can be further shortened with the deprecated repr backtick syntax: lambda n:int(`n`,13)%2. Try it online!
GarethPW

Yeah, had a bit of a brain fart there and forgot the purpose of int’s base argument. Whoops!
GarethPW

11

Japt -h!, 5 4 3 bytes

¤å^

Try it


Explanation

¤       :Convert to base-2 string
 å^     :Cumulatively reduce by XORing
        :Implicitly output the last element negated

@LuisfelipeDejesusMunoz, porting Kevin's 05AB1E solution also works out at 5 bytes, if you want to try for that.
Shaggy

¤¬x v this is kevin's answer
Luis felipe De jesus Munoz

@LuisfelipeDejesusMunoz, yup, that's it.
Shaggy

8

C# (Visual C# Interactive Compiler), 43 38 bytes


Golfed Try it online!

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

Ungolfed

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

Full code with tests

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();

Releases

  • v1.1 - -5 bytes - Replaced Count to Sum
  • v1.0 - 43 bytes - Initial solution.

Notes

  • None

2
Upvoted for the chuckle your "ungolfed" version gave me.
Jack Brounstein

8

Bash (no external utilities), 56 44 bytes

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

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

This assumes that the number is found in $1, having been passed as the first command line argument. It also assumes that this is a shell script (so that it can exec itself).

It recurses, after a fashion, using exec $0, until the number (in $1) reaches zero, dividing it by two in each iteration. It also sums (in $2) the number of times we get a number that is odd. At the end, the original number was "evil" if the sum in $2 in not odd.

Example invocations:

$ ./script 3 && echo evil
evil

$ ./script 11 && echo evil

$ ./script 777 && echo evil
evil

$ ./script 43 && echo evil
evil

$ ./script 55 && echo evil

For 0:

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

Correct result, with a bit of extra on the side.


7

R, 37 26 bytes

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

Try it online!

An alternative to Robert S.'s answer, this eschews the built-in bit splitting but ends up less golfy and thanks to JayCe and digEmAll ends up coming in slightly golfier.

Only works for positive integers less than 2311.


Why don't hardcode 31 instead of log2 ? Try it online!
digEmAll

@digEmAll Which in turn means no need to define x
JayCe

@digEmAll thanks! I wasn't sure about precision issues, although I suppose that past 2311 we (probably) lose precision in the %/% and %% operators so it would be a moot point.
Giuseppe

Also intToBits supports only integer values up to 2^31-1 ;)
digEmAll

6

05AB1E, 4 bytes

bSOÈ

Try it online or verify all test cases.

Explanation:

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

R, 99 98 44 34 28 bytes

-1 thanks to Kevin Cruijssen! -54 thanks to ngm! -10 thanks to Giuseppe! -6 thanks to JayCe!

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

Try it online!


Alternatively, using the binaryLogic package (39 bytes):

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

2
I don't know R too well, but I'm pretty sure ==0 can be <1 :)
Kevin Cruijssen



1
This works as well I think : 32 bytes But requires a bit of an explanations :)
digEmAll


5

C (gcc), 36 bytes

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

Try it online!

Method from K&R https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan

Must be compiled with optimization level 0


Doesn't compile on gcc 5.4.0: error: expected constructor, destructor, or type conversion before '(' token (arrow is pointing at the f in the function name). What compiler flag(s) do I need?
villapx

1
Doesn't work with -O.
nwellnhof

2
"Returns 0 for truthy, 1 for falsey" Is this legal? Not trying to discredit your answer, just curious, and because it would save me a byte. Note: The word truthy in the question links to this answer. And this comment also mentions truthiness.
Borka223

@nwellnhof @villapx Compiles fine on my 7.3.0 - just make sure you're not missing the -O0 compiler flag.

@Borka223 hmmm after months of perusing this site, I was under the impression that truthy and falsey could be anything, so long as they are consistent within your solution. However, the answer you linked certainly seems to contradict that. I went ahead and added the byte. Thanks
vazt


4

PHP, 37 36 bytes

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

To run it:

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

Or Try it online!

Prints 1 for true, and 0 for false.

-1 byte thanks to Benoit Esnard!


1
I think you can save one byte by removing the modulo operation: <?=1&~substr_count(decbin($argn),1);. This one also prints 0 for false.
Benoit Esnard

Thanks @BenoitEsnard! That's very clever, I've updated my answer :) You learn something new every day!
Davіd

4

Brachylog, 4 bytes

ḃo-0

Try it online!

With multiple test cases (😈 is evil and 👼 is not.)

Uses something I discovered recently about the - predicate: its documentation just says "the difference of elements of [input]", but what it actually does is "sum of even-indexed elements (starting from 0th) of input, minus the sum of odd-indexed elements of input".

Here,

converts the number into an array of binary digits,

o sorts them to bring all the 1s together.

Now, if there were an even number of 1s, there would be an equal number of 1s in even indices and odd indices. So the - after that would give a 0. But if there were an odd number of 1s, there would be an extra 1 sticking out, resulting in the difference being either -1 or 1.

So, finally, we assert that the difference is 0, and get a true or false result according to that. With more flexible output requirements, this could be removed for a 3 byte answer, with 0 as truthy output and -1 and 1 as both falsey outputs.


4

INTERCAL, 90 65 63 bytes

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

Try it online!

Ungolfed and expanded (for what it's worth) with C style comments.

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

I had to make a few concessions to make this feasible in INTERCAL. The first is, as with all INTERCAL programs, numerical input must be written out. So if you want to input 707 you would provide SEVEN OH SEVEN.

The second is that INTERCAL doesn't really have proper truthy or falsy value. Instead, it will output the Roman Numeral I (1) if the number is not evil, or a 0 (typically represented as - since Roman Numerals can't normally represent 0).

If you want to flip those so that evil numbers return 1 and non-evil numbers return 0, you can change lines 4 and 5 from the ungolfed version as follows, although it does add 3 bytes.

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


3

dc, 18 16 bytes

[2~rd1<M+]dsMx2%

Returns (to the stack) 0 for evil and 1 for not evil

Try it online!

Fairly straightforward - recursively applies the combined quotient/remainder operator ~ to the new quotient and adds all the remainders together, then mods by 2 (after spending two bytes to flip to a standard truthy/falsy).

Edited to reflect consensus that 0 for truthy and 1 for falsy is okay, especially in a language that has no sort of if(boolean) construct.


3

Python 2, 29 bytes

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

Try it online!

Returns 1 if True, else 0.

Converts the number to a binary string like '0b11', counts the number of 1s, gets the complement of result, and returns the last bit of the complement (thanks, https://codegolf.stackexchange.com/users/53560/cdlane!) (1 if the original number was even, 0 if it was odd).


1
No fewer bytes but lambda n:~bin(n).count('1')&1 replaces the modular division with something potentially less expensive.
cdlane

3

x86-16, 3 bytes

NASM listing:

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

16-bit integer function arg in AX (which is destroyed), return value in PF.

The hardware calculates the parity of the result for us, in x86's Parity Flag. The caller can use jp / jnp to branch, or whatever they like.

Works exactly like @cschultz's Z80 / 8080 answer; in fact 8086 was designed to make mechanical source-porting from 8080 easy.

Note that PF is only set from the low byte of wider results, so test edi,edi wouldn't work for an x86-64 version. You'd have to horizontal-xor down to 16 bits, or popcnt eax, edi / and al,1 (where 0 is truthy).


3

C++ (gcc) (-O0),  36  31 bytes

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

Try it online!


C++ (clang), 35 bytes

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

Try it online!


Here is my first attempt at code golfing, hope I didn't break any rule I might have missed.

Edit:
- Saved 5 bytes thanks to @Jonathan Frech : replaced != by - and return by i= (the last replacement does not seem to work with clang though)
- Since there seems to be a debate whether I should use gcc -O0 abuse, I thought I could just give both versions


Welcome to PPCG! You may be able to save a byte by golfing != to - and another four by golfing return to i=.
Jonathan Frech

@JonathanFrech It's been a long time since I did C++, does it implicitly return the last assigned expression in a function if there's no return statement? I'm guessing it's a gcc thing?
sundar - Reinstate Monica

1
It is a gcc specific undefined behaviour abuse on optimization level O0.
Jonathan Frech

By switching to K&R C, you can get it down to 23 bytes (very impressive!) Try it online!
ErikF

@JonathanFrech: why do people insist on using that stupid gcc -O0 hack? It's not like the length of a language's total boilerplate matters much when comparing implementations. Also, it makes it more interesting to choose between return vs. call-by-reference (updating *i in place). I'd rather write C or C++ answers, not un-optimized-gcc-only answers, because un-optimized-gcc isn't a very useful language.
Peter Cordes

3

SML, 32 Bytes

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

Explaination:

  • % is function name
  • 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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.