Mr. Binary Counterman

Mr. Binary Counterman, son of Mr. Boolean Masker & Mrs. Even Oddify, follows in his parents’ footsteps and has a peculiar way of keeping track of the digits.

When given a list of booleans, he counts the 1s and 0s separately, numbering the 1s with the odds & the 0s with the evens.

For example, when he looks at 1 1 0 0 1 0 he counts: 1st odd, 2nd odd, 1st even, 2nd even, 3rd odd, 3rd even and copies it down as 1 3 2 4 5 6

Mr. Binary Counterman thinks it looks prettier to start counting odds at 1 and evens at 2. However the pattern is more symmetric if you start counting evens at 0. You may do either. So either 1 3 2 4 5 6 or 1 3 0 2 5 4 are good given the list above.

As input you may take any representation of a boolean list or binary number, the output should be the list of resulting numbers with any delimiter. (But the list elements should be separate & identifiable.)

This is , so least bytes wins.

Test Cases

1 0 1 0 1 0
1 2 3 4 5 6

1 1 1 1
1 3 5 7

0 0 0 0
2 4 6 8

0 1 1 0 0
2 1 3 4 6

0 1 1 0 0 1 0 1 1
2 1 3 4 6 5 8 7 9

0 0 1 0 0 1 1 1
2 4 1 6 8 3 5 7

0
2

1
1

1 1 1 0 0 0
1 3 5 2 4 6
• Can we take the bits flipped? Jun 15 '21 at 3:30
• Absolutely! Look forward to seeing what you've come up with. Jun 15 '21 at 3:54

JavaScript (ES6), 29 bytes

a=>a.map(v=>b[v]+=2,b=[0,-1])

Try it online!

• Have to laugh at everyone else trying to make this as convoluted as they can while you & I take the most simplistic approach possible and both our solutions are still competitive! Jun 18 '21 at 0:27

J, 12 bytes

+2*/:<.&/:\:

Try it online!

Explanation: Self plus twice the minimum of ascending and descending ranks.

Given a boolean array 1 1 0 0 1 1 1, ascending rank /:@/: and descending rank /:@\: are computed as follows:

array:       1 1 0 0 1 1 1
asc. rank:   2 3 0 1 4 5 6
desc. rank:  0 1 5 6 2 3 4
minimum:     0 1 0 1 2 3 4

APL(Dyalog Unicode), 9 bytes SBCS

⊢+2×⍋⌊⍥⍋⍒

Try it on APLgolf!

• Wow! Fantastic insight! Jun 15 '21 at 2:41
• Holy wow! You should def post the APL solution separately. It's one byte away from first! Jun 15 '21 at 4:04

Risky, 44 bytes

__0+0+_0+0+__0+0+_0+0+__0+0+_0+0+__0+0+_0+?1__0+0+_0+0+__0+0+_0!-_0!_{1+_0+0_[2_{0+__{1

Try it online!

How it works:

This is a really low level explanation:

... + __0+0+_0+?                                                  ;  the input array
1                                                ;  map with the following pairs:
... + __0+0+_0!-                               ;  [0, -1]
_                             ;  map to
0!_{1+_0+0                  ;  range with same length
_                ;  map to
[              ;  absolute value
+       ;    of the sum of
2_{0         ;      twice the index in the range and
__{1  ;      the offset (0 or -1)

That's useless, though. Here's a better description of how this works:

Risky has an operator called "map pairs" which takes an array, and maps the items according to a set of rules. The rules are arrays, starting with the item to be replaced, and with (typically) one item to map to. However, if multiple are specified, they'll be used in order.

This answer generates those mappings, which look like [[0, 2, 4, 6, ...], [1, 1, 3, 5, 7, ...]]. It does this by mapping [0, -1] to [2_{0+__{1 over a range [0, x), which is essentially (x, n) => abs(2 * x + n), where x is the number in the range and n is either 0 or -1.

• No way! You used Risky for a serious problem. And it's not a half bad score despite having half the symbols. Congrats!! Jun 15 '21 at 3:58
• Interesting language filled with 0s Jun 15 '21 at 7:26

Jelly, 8 bytes

,CÄḤ×ƊS_

Try it online!

-2 bytes thanks to Bubbler

How it works

,CÄḤ×ƊS_ - Main link. Takes a binary list B on the left
C       - Complement. Flip the bits of B
,        - Pair with B: [B, B']
Ä      -   Cumulative sum of each
Ḥ     -   Unhalve
×    -   Multiply modified B by B and modified B' by B'
S  - Columnwise sum
_ - Subtract B, elementwise
• Nice!! I was about to tackle it in Jelly the same way. I made an example-based explanation for my APL answer. I wonder if this is really the best way to do it. Jun 15 '21 at 1:41
• @AviFS Yep, I saw your explanation and went "Oh, that's basically my approach" :P Jun 15 '21 at 1:43
• 8 bytes Jun 15 '21 at 2:54

Japt-m, 8 bytes

?J±2:T±2

Try it

• J is initially -1,
• T is initially 0, and,
• ± is the shortcut for +=.

Jelly, 9 bytes

,CỤ€⁺«/Ḥ_

Try it online!

My convoluted port of my own APL/J answer.

Jelly, 9 bytes

CỤỤ«ỤỤ$Ḥ_ Try it online! Small modification of caird's 10-byter port. 05AB1E, 8 6 bytes η^_O·α Try it online! η # prefixes of the input ^ # XOR the first value of the input with the first prefix, second value of input with second prefix, ... _ # boolean negate O # sum each modified prefix · # double all integers α # absolute difference to the input η^_ can be replaced with δQÅl (equality table; lower-triangular matrix), which is a byte longer but might be shorter in some other language. δQÅlO·α Try it online! • Nice! Tied for first with cairdcoinheringaahing’s Jelly answer Jun 15 '21 at 6:40 PowerShell Core, 28 bytes$b=0,-1;$args|%{($b[$_]+=2)} Try it online! Port of Arnauld's solution, thanks ! Initial implementation, 35 bytes switch($args){0{++$e*2}1{$o++*2+1}}

Takes the input as a list of 0/1's
Returns a list of integers

Explanation

switch($args){ # For each argument passed as an integer 0{++$e*2}      # if it is 0, output an even number, starting from 2
1{$o++*2+1}} # if it is 1, output an odd number, starting from 1 Jelly, 7 6 bytes ċṪ$ƤḤ+

Try it online!

Basically a translation of an old version of ovs' 05AB1E answer.

Explanation

ċṪ$ƤḤ+ Main monadic link Ƥ Map over prefixes$    (
ċ        Count the occurences of
Ṫ         the last item after removing it

Try it Online!

Me when APL port

Explained

₌⇧⇩⇧$⇧∵d+ ₌⇧⇩ # grade up input, grade down input ⇧$⇧    # grade each of those up
∵d  # 2 * the minimum of those two lists
+ # added to the input

Python 2, 43 bytes

b=[2,1]
for e in input():print b[e];b[e]+=2

Try it online!

-5 bytes and fix thanks to @xnor

The program is now reusable

f(h:t)=h:f[x+mod(x-h-1)2*2|x<-t]
f e=e

Try it online!

The recursion happens on “the tail of the list, but with all elements x that have the same parity as the head incremented by 2.” Like so:

f [1,1,0,0,1,0]
= 1 : f [3,0,0,3,0]
= 1 : 3 : f [0,0,5,0]
= 1 : 3 : 0 : f [2,5,2]
= 1 : 3 : 0 : 2 : f [5,4]
= 1 : 3 : 0 : 2 : 5 : f 
= 1 : 3 : 0 : 2 : 5 : 4 : f []
= [1,3,0,2,5,4]

Jelly, 15 bytes

ṢŒg2ḷ$\€ÄFị@ỤỤ$

Try it online!

ṢŒg2ḷ$\€ÄFị@ỤỤ$  Main Link; take a list of 0s and 1s
Ṣ                Sort the list
Œg              Group runs of equal elements
€         For each group
$\ Cumulatively reduce by 2ḷ x => 2 (that is, all but the first element become 2) Ä Cumulative sum, vectorizing to depth 1 F Flatten ị@ Index into (reverse order) ỤỤ$  The input graded up twice

Grading up twice returns the permutation to index into another list to get the same ordering or something like that. I think that's how it works.

• Jun 15 '21 at 1:31
• @cairdcoinheringaahing :( Jun 15 '21 at 1:38

K (ngn/k), 15 bytes

{x+2*(<<x)&<>x}

Try it online!

A K port of @Bubbler's J and APL solutions - don't forget to upvote it!

Ruby-p, 29 bytes

Takes input as space separated digits (or any other non-digit separator).

gsub(/\d/){($`*2+?1).count$&}

Try it online!

Stax, 9 8 bytes

╜♪N·{☼►◄

Run and debug it

Inspired by Arnauld's idea.

0-indexed, takes the bits flipped.

Explanation

AEsF{Q2+}&
AEs        swap the input with  [1,0]
F       foreach i:
{   }&  modify the element at i in 2,1
Q      print without popping

Wolfram Language (Mathematica), 29 bytes

(a=0@-1;a[[#~Mod~2]]+=2&/@#)&

Try it online!

Boring answer. Mathematica's += etc. operators have different precedence than assignment = etc. operators. This gives them higher precedence than &, so unlike = expressions they don't need to be parenthesized on the left side of &. (//=, introduced in 12.2, is slightly different from both aforementioned groups).

• 0@-1 is clever! Jun 17 '21 at 9:23

C (clang), 52 bytes

-1 thanks to @AZTECCO, by using clang instead of gcc.

f(a,l)int*a;{for(int b[]={0,-1};l--;)*a++=b[*a]+=2;}

Try it online!

C (gcc), 53 bytes

f(a,l)int*a;{for(int b[]={0,-1};l--;a++)*a=b[*a]+=2;}

Try it online!

• Nice trick! You can save by switching to clang and incrementing a in assignment f(*a,l){for(int b[]={0,-1};l--;)*a++=b[*a]+=2;} Jun 15 '21 at 20:42

Raku, 21 bytes

*>>.&{(%.{$_}+=2)-$_}

Try it online!

Maps each element to the index into an anonymous hash, incrementing that value by two (initially zero), and finally subtracting the element itself to distinguish between odd and even.This could also be extended to values beyond 0 and 1 simply by changing the 2 to another number.

Julia, 33 30 bytes

f(x,y=[0,-1])=x.|>i->y[i+1]+=2

Try it online!

AWK, 42 bytes

d=1{for(;a++<NF;d[b]+=2)$a=+d[b=$a%2]}1

Try it online!

So this one is one test with a codeblock, and a naked 1 to print all the commandline arguments. It replaces each commandline argument with the appropriate even/odd counter in the codeblock.

The "test" for the codeblock is always truthy and it just used to initialize the "odd" counter to 1.

d=1{                                  }

The code block runs through each commandline argument,

for(;a++<NF;       )

Then sets that argument to the current value of the even/odd counter with:

$a=+d[b=$a%2]

And at the end of the loop, increments the current counter by 2 in preparation for the next match.

d[b]+=2

Once that's done, it just need to print out all the arguments.

1

Zsh, 23 bytes

for x
echo $[x+a$x++*2]

Attempt This Online!

Starts even numbers at 0.

Explanation:

• for x: for each $x in the input, •$[]: arithmetic expansion
• ++: increment and return original value
• a$x: the variable named a0 or a1 (which correspond to the number of 0s and 1s seen so far) • x+*2: double and add x to get the correct value • echo : print (can't use <<< because the mutation wouldn't work in the subshell it creates) Desmos, 64 bytes a(l)=\sum_{n=1}^{[1...length(l)]}l[n] b=1-l f(l)=2ba(b)+2la(l)-l Just implements the strategy shown in AviFS's Dyalog APL answer. Try It On Desmos! Try It On Desmos! - Prettified Explanation: a(l)=\sum_{n=1}^{[1...length(l)]}l[n]: Function that takes in a list $$\l\$$ and returns the running total of $$\l\$$. b=1-l: Variable that stores the inputted list, but with each bit flipped. f(l)=2ba(b)+2la(l)-l: Function that takes in a list of bits $$\l\$$ and outputs the correct answer, based on the strategy mentioned above. R, 42 bytes function(x,y=seq(x)*2){x[x]=y-1;x[!x]=y;x} Try it online! -8 bytes thanks to @Dominic Takes input as booleans: TRUE(1) and FALSE(0). Straightforward approach, but takes advantage of truncating the replacement to the length of items being replaced. Different approach: R, 47 bytes function(x,n=0:-1)for(i in x)show(n[i]<-n[i]+2) Try it online! Takes input incremented by 1: 2 (for 1) and 1 (for 0). • 42 bytes... Jun 15 '21 at 8:08 • @DominicvanEssen Thanks, nice one! Didn't think of leveraging the truncating of replacement vector! Jun 15 '21 at 8:21 Retina 0.8.2, 43 bytes (.)(?<=((\1)|.)*(1)?)$#3$*2$4¶
2
11
1+
$.& Try it online! Link includes test cases. Takes input as a string of bits. 1-indexed. Explanation: (.)(?<=((\1)|.)*(1)?) For each bit, count the number of preceding identical bits. If the current bit is 1 then count it separately otherwise include the current bit in the count.$#3$*2$4¶

Record a 2 for each duplicate plus one extra for a 1 bit.

2
11

Convert to unary.

1+

Try it online!