Check if an array (or equivalent) has the same number of odd and even numbers - Code Golf Edition!

Inspired by this code review question, I am curious to see what happens if we turn that into a code-golf challenge!

The description is easy, the input is an array or any similar data structure with only unsigned integers, the output is a boolean if the number of odd numbers is equal to the number of even numbers inside (true or false doesn't matter, as long as the opposite is used in case the number doesn't match)

Here are some examples with true as output for matching (thanks to the original OP)

[5, 1, 0, 2]      ->  true
[5, 1, 0, 2, 11]  ->  false
[]                ->  true


Usual code-golf rules, shortest code wins.

• Challenges should be self contained. References to external resources are welcome, but you should not rely on them. Please post some test cases here. May 22 '20 at 10:39
• @ElPedro I could say no if I wanted to be strict but, why not, maybe something interesting comes out of it. I'll edit the question. May 22 '20 at 12:31
• @ElPedro sorry not empty lists exemptions, you should always consider edge cases to avoid bugs :P May 22 '20 at 12:36
• @DomenicoModica A similar assumption has been made for the C solution. Since the input is only unsigned numbers, using a sentinel of -1 for end I think is fair. Go ahead ;) May 22 '20 at 22:24
• Does it need to be a Boolean or falsy/truthy is fine as usual? May 22 '20 at 23:57

(==0).sum.map((-1)^)


Try it online!

Python 2, 33 bytes

lambda l:sum(n%-2|1for n in l)==0


Try it online!

n%-2|1 is a shorter way to do(-1)**n. It works like this:

   n  n%-2  n%-2|1
------------------
even     0       1
odd    -1      -1


36 bytes

lambda l:sum(map((-1).__pow__,l))==0


Try it online!

• Also works in Python 3 May 27 '20 at 16:04
• -3 bytes Jun 2 '20 at 18:15

Jelly, 4 bytes

ḂĠẈE


A monadic Link accepting a list of integers which yields 0 (falsey) or 1 (truthy).

Try it online!

How?

ḂĠẈE - Link: list of integers              e.g. [1,2,3,4,6]
Ḃ    - least-significant bit (vectorises)       [1,0,1,0,0]
Ġ   - group (1-based) indices by value         [[2,4,5],[1,3]]
Ẉ  - length of each                           [3,2]
E - all equal?                               0

• @MarcusMangelsdorf - the 5 is the 1-based index of the rightmost zero. May 23 '20 at 17:49

perl -alp, 20 19 bytes

$_=@F-2*grep$_%2,@F


Try it online!

Just checks whether the size of the input is twice the number of odd integers. Accepts a list of space separated integers on STDIN. Prints 0 if the number of even and odd numbers are equal, something else otherwise.

MathGolf, 4 bytes

Port of @xnor's Haskell answer. In MathGolf, summing an empty list yields 0.

b▬Σ┌


Try it online!

Explanation

b    Constant -1
▬   -1 ** input list (vectorizes)
Σ  Sum the resulting list
┌ Convert to inverted boolean


Here is my version (Thanks to @ElPedro and to everyone in the comments for the corrections):

Python 3, 37 bytes

lambda x:sum(i%2for i in x)==len(x)/2


Try it online!

• 37 if you use a lambda and lose the unneeded space between %2 and for May 22 '20 at 10:41
• The space in front of for keyword is not necessary. May 22 '20 at 10:44
• 34, if you port the most upvoted answer at Code Review.
– user92069
May 22 '20 at 11:24
• 34/31 if you use map instead of a comprehension: sum(map(lambda i:i%2,x))==len(x)/2 or sum(map(lambda i:i%2*2-1,x))==0 May 22 '20 at 18:50
• I don't think the first answer is even valid, because it relies on a hardcoded list, and takes no input. May 22 '20 at 22:19

dc, 25 24 23 bytes

?0[r_1r^+z1<F]sFz1<Fd/p


Try it online!

Or verify the test examples.

Input on stdin: a line of space-separated integers.

Output on stdout: 0 for truthy, and 1 for falsey (dc doesn't have standard truthy/falsey values).

K (Kona), 7 6 bytes

-1 byte thanks to coltim

~+/-1^


Try it online!

J, 9 bytes

0=1#._1^]


Try it online!

• You can trim a byte from Kona version by replacing 0= with ~ Mar 25 at 19:47
• @coltim Yes, indeed. Thank you! Mar 25 at 21:43

-2 bytes, BIG Thanks to Arnauld

JavaScript (V8), 31 bytes

s=>s.map(e=>d+=e&1||-1,d=0)&&!d


Try it online!

Wolfram Language (Mathematica), 14 bytes

Tr[(-1)^#]==0&


Try it online!

• Perfect! ... :) May 23 '20 at 17:26

Python 3, 30 bytes

lambda x:sum(i%2-.5for i in x)


Try it online!

x86 32-bit machine code, 13 bytes

Input: uint32_t *esi, size_t ecx
returns: EDX = len - 2*even = 0 for balanced, non-zero for unbalanced.
This conveniently works even for len=0 = balanced. As part of this asm custom calling convention / ABI, my boolean data type is 0 / non-zero, rather than the 0 / 1 that C ABIs use.

This avoids needing to actually compare, just decrement twice inside the loop, starting with the list length.

     1                         boe:
2 00000000 89CA               mov    edx, ecx           ; balance = len
3 00000002 E309               jecxz  .end
4                         .loop:                        ; do {
5 00000004 AD                 lodsd                       ; eax = *p++
6 00000005 A801               test   al, 1
7 00000007 7502               jnz   .odd
8 00000009 4A                 dec    edx
9 0000000A 4A                 dec    edx                 ; more compact than sub edx,2 in 32-bit code
10                         .odd:
11 0000000B E2F7               loop   .loop              ; }while(--ecx);
12                         .end:
13                         ;    xchg   eax, edx          ; custom calling convention: return in EDX instead of spending a byte on xchg
14 0000000D C3                 ret


Try it online! (with a _start test case that exits with the return value as exit status)

An alternate version that calculates in EAX to return in the standard calling convention's register is 14 bytes. It uses test byte [edi], 1 (1 byte longer than test al,1) and increments the pointer with scasd (without caring about the FLAGS result of the eax - [edi] it also does). See the TIO link.

Uncommenting the xchg eax, edx at the bottom of the 13-byte version would do the same thing, and that version's loop is more efficient.

For 8-bit integer input, use lodsb instead. Unfortunately, we can't use and al, 1 / add dl, al or similar (without branching). That would only work for array sizes up to 255. and eax,1 is 3 bytes.

Also, masking and adding only does one increment. lea edx, [edx + eax*2] could work but that's also 3 bytes. Branching on the low bit with test/jnz seems to be best for size, although it sucks for performance with branch mispredicts.

Of course if we wanted to go fast, we'd load 16 bytes at once with movdqa, isolate the low bits with pand, and sum with paddd. Then hsum at the end. Or hsum with psadbw against a zeroed register, then paddq. SIMD is of course especially good for 8-bit elements, 16 per vector instead of 4, with an outer loop to avoid overflowing 8-bit counters. e.g. this AVX2 SO answer.

Something like this could maybe be smallish code-size if we limited it to a fixed-size 16-byte input array, or maybe 8-byte in MMX registers. Unfortunately we rarely get to play with SIMD in code golf because the instructions are larger and inputs can be odd lengths requiring cleanup loops.

APL (Dyalog Extended), 7 bytes

Port of xnor's Haskell solution. Prompts for the input; -2 thanks to @Graham.

-1 byte thanks to @Adám by switching the language.

=+/¯1*⎕


Try it online!

• Can you save 2 bytes by dropping ()∘ and replacing it by simple ⎕ input May 22 '20 at 12:05
• You can save another byte by switching to Extended Dyalog APL (=+/¯1*⎕) or dzaima/APL (0=1⊥¯1*).
May 23 '20 at 22:57

[Excel], 28 bytes

Paste this into a cell outside of column A, the array goes in column A.

=0=SUM(IF((A:A<>""),-1^A:A))


An example:

• Got some extra parens around the comparison, I think? Aug 1 '20 at 15:11

Ruby, 23 bytes

->x{x.sum{|n|~0**n}==0}


Try it online!

Special thanks to Manatwork, Dingus and to histocrat for finding the shortest solution, all credit to them.

• You know the other method is shorter in Ruby too, right? Try it online! May 23 '20 at 22:33
• @manatwork Even shorter. May 24 '20 at 13:20
• Yet shorter May 24 '20 at 14:43
• Thank you all, I tried to understand all your solutions, very clever. Didn't know that n%-2 is equivalent to -(n%2) @histocrat would you mind explaining how the binary one's complement operator in ruby works? I don't understand how 05 = 0 is different from 04 = 0. Thanks! May 27 '20 at 9:32
• @ArmandFardeau, sure. ~ in Ruby is a two's complement negation, so ~0 is equal to -1. -1 to the power of an even number is one, but to the power of an odd number is negative one. The reason we can't just do the more readable -1**n is that ** has a higher precedence than -, so it ends up being parsed like -(1**n)which is always negative one. May 27 '20 at 15:14

Burlesque, 17 14 bytes

ps{2.%}pt)L[sm


Try it online!

Saved 3 bytes using shorthand map

Explanation:

ps                # Parse input as a block
{2.%}pt         # Partition block based on modulo 2
)L[      # Map blocks to their length
sm    # Check lengths are the same


Befunge-98 (PyFunge), 13 12 bytes

-1 byte thanks to @Jo King!

#.&2%2*1-+#@


Try it online!

This uses the same logic (&2%2*1-+) as @Abigail's answer, but has a different control flow structure. Befunge-98 adds extra "error handling" functionality to the & and ~ input instructions: when EOF is reached, they reflect the instruction pointer. When this happens, the program can execute a different section of code without the need for an explicit conditional.

#.&2%2*1-+#@

(Implicit: the counter, the top of the (empty) stack, starts at 0)
(Implicit in program structure: begin loop)

#              Skip the next instruction
.             (skipped)
&            Get integer from STDIN
2%          Take the integer modulo 2
2*        Multiply that by 2 (results in 2 if the number was odd and 0 if even)
1-      Subtract 1 (results in 1 if the number was odd and -1 if even)
+     Add that to the counter
#    Skip the next instruction
@   (skipped)
Repeat

When the input runs out:
&            Catch the EOF and reverse direction
.             Output the counter (0 if odds and evens are matched, nonzero otherwise) as an integer
#              Skip the next instruction (a space)
@   End the program


MATL, 6 5 bytes

-1 bytes thanks to @LuisMendo

oEqs~


Try it online!

Explanation

oEqs~
o      % Replace each elements with its parity (i.e. mod 2)
E     % Multiply all element by 2
q    % Decrement all elements by 1
s   % Sum the array
~  % Boolean not the sum


05AB1E, 6 4 bytes

ÉD¢Ë


Try it online!

Explanation

É    Is the number odd?
D   Duplicate
¢  Count the occurances of the bits in the original copy
Ë Are all items in the list equal?


Factor, 52 bytes

: f ( s -- ? ) [ odd? ] partition [ length ] bi@ = ;


Try it online!

Pyth, 6 bytes

!sm^_1


Try it online!

Explanation

!sm^_1
m    : map
^_1 : -1 power value
: over implicit input
s     : sum it
!      : logical negate the sum (i.e. 0 -> True, -1 -> False, 10 -> False)


R, 18 17 bytes

!sum((-1)^scan())


Try it online!

Edit: -1 byte thanks to Bart-Jan van Rossum

• You can save 1 byte using !sum((-1)^scan()) May 25 '20 at 11:58
• Thankyou! That is clever, and I'm jealous that I didn't think of it myself. May 25 '20 at 12:18

Java (JDK), 28 bytes

a->a.map(n->-n%2|1).sum()==0


Try it online!

• Nice job golfing it in Java!
– rues
Jul 31 '20 at 23:02

C (gcc), 45 44 43 bytes

Saved a byte thanks to ceilingcat!!!

Saved a byte thanks to Olivier Grégoire!!!

b;f(int*a){for(b=0;~*a;b+=-*a++%2|1);b=!b;}


Try it online!

Input:

$$\-1\$$ terminated int array.

Output

C boolean values: $$\1\$$ if number of odd are equal to the number of even numbers, $$\0\$$ otherwise.

How

Initialise a counter b to $$\0\$$. Then go through the elements in the array adding $$\1\$$ to b for every odd number and $$\-1\$$ to b for every even number. Return the boolean result of testing b equal to $$\0\$$.

• b+=-*a++%2|1 to save a byte May 25 '20 at 13:06
• @OlivierGrégoire Nice one - thanks! :-) May 25 '20 at 21:48

brainfuck, 34 bytes

+>+>>,[[-[->]<]<<+[>]>,]<<[-<->]<.


Try it online! (Check the ! box to enter input automatically.)

Takes input as code points. Prints a null byte if there are equal number of odds and evens. Otherwise, prints a non-null byte.

Memory layout:

a b 0 n 0


where a is the current number of odds, b is the current number of evens, and n is the current element in the array.

Explanation:

+>+>>        set a and b to 1, and pointer to n
,[           for each element n in the array
[-[->]<]     if n is even, pointer stops at n, else, pointer stops at left of n
in both case, n is set to 0
this requires the cells left and right of n to be 0
<<+          increment a or b appropriately
[>]>,        pointer back to n, read new n
]            stop if n = 0 (end of array)
<<[-<->]<.   find b - a, and print that value


Brainetry, 342 bytes

Golfed version:

a b c d
a b
a b c d
a bb
a b
a b c d e f
a b c d e f g h
a b c d e f g h
a b c d e
a b c d e f g h
a b c d e
a b
a b c d e f g h i
a b c
a b c d e f g h i
a b c
a b c
a b c d
a b c d e f g h
a b
a b c d e f g h i
a b
a b c d e f
a b c d e f g h i
a b c
a b c
a b c d e f g h
a b c d e
a b c
a b c d e
a b
a b c d e f g h i
a b c
a b c d e f g


To make our lives easier we use the --numeric-io flag, so that we can take input and give output as integers, but we don't really need to and the answer works without it. Read the program below for due credit.

The golfed version was adapted from the program found below. To try this online you can

• head over to this replit link, copy&paste the code into the btry/replit.btry file and hit the green "Run" button (takes input as ASCII characters (converts them to codepoints) and outputs ASCII characters, use CTRL-D in a newline to terminate input, doesn't really work well for this challenge.);
• clone the github repo and from your terminal run ./brainetry btry/ppcg/evens_and_odds.btry --numeric-io (give one integer per line, use CTRL-Z or CTRL-D in an empty line to stop giving input).
"Check if an array
(or equivalent)
has the same number
of odd
and even
numbers - Code Golf Edition !"
That is the title of the codegolf.stackexchange.com challenge
that this brainetry program solves. Once more, with
no shame at all ,
I am piggy backing on someone else's answer.
Oh boy!
You can check the original answer over here: https://codegolf.stackexchange.com/a/205621/75323
Go upvote that!
This is a very literal port of that answer.
I am pretty
sure I could
have used brainetry's builtins
to make this easier, like » or ≥,
except that
would mean I would have to think... ugh... nope!
For now
I will stick to the low
hanging fruit just to show that brainetry is out.
If this is
the first time
you find a brainetry program, welcome! By now
you probably understood you are
allowed to write
pretty much anything as source.
(source code)
You only have to write lines of correct size
and with the
correct line modifiers. (That's a recent addition.)

• This is amazing, +1 for the poem Jul 3 '20 at 19:31

Keg, 13 10 bytes

÷⑷0;$Ë⑸⅀0=  Try it online! Transpiled Code item_split(stack) keg_map(stack, '0;$Ë')
summate(stack)
integer(stack, 0)
comparative(stack, '=')


0;$Ë turns into: integer(stack, 0) decrement(stack) swap(stack) exponate(stack)  sed -E, 78 80 bytes +7 to account for 0's and empty lists, -5 from golfing Tried to have some fun:) Input is spaced separated unary numbers. Ex: echo "!!! !! !!!!" | sed -Ef main.sed (if the code is saved to main.sed) s/_/@/g s/(!!)+/@/g s/@*!/!/g s/ //g :l s/(!@|@!)//g tl s/!+/true/g s/^$/false/g


Try it online!

jq, 24 characters

map(.%2)|add+0==length/2


Just a write of the question owner's Python solution.

(Grr! 2 characters wasted because []|add results null.)

Sample run:

bash-5.0$jq 'map(.%2)|add+0==length/2' <<< '[5, 1, 0, 2]' true  jq, 21 characters map(.%2*2-1)|add+0==0  The other most efficient solution from Code Review. Sample run: bash-5.0$ jq 'map(.%2*2-1)|add+0==0' <<< '[5, 1, 0, 2]'
true

• Does jq not have a logical negation operator that can return true for both null and 0, so that you don't have to use +0==0?
– Neil
May 22 '20 at 12:34
• @Neil If jq has one, I'd be able to golf my Erlang solution.
– user92069
May 22 '20 at 12:35
• @Neil, in jq the only negation is the not filter, but as jq is quite strictly typed, all numbers are truthy: jq -c 'map(not)' <<< '[null,0]' results [true,false]. Even that + is working as an exception as the other arithmetic operators throw error on null operand. May 22 '20 at 13:05

Husk, 6 bytes

Why does need so many bytes... help!

EmLk%2


Try it online!