Alternating bit smearing

12

1

Introduction

This challenge requires you to set the trailing zeros of an integers binary representation to 010101…, this is best explained with an example:

Given the integer 400, the first step is to convert it to binary:

110010000

As we can see the fifth bit is the least significant 1 bit, so starting from there we replace the lower zeros by 0101:

110010101

Finally we convert that back to decimal: 405

Challenge

Given a positive integer return/output the corresponding resulting value of the above defined process.

Rules

  • This sequence is only defined for integers with at least one 1 bit, so the input will always be ≥ 1
  • You may take input as a string, list of digits (decimal) instead
  • You don't have to handle invalid inputs

Testcases

Here are some more testcases with the intermediary steps (you don't have to print/return these):

In -> … -> … -> Out
1 -> 1 -> 1 -> 1
2 -> 10 -> 10 -> 2
3 -> 11 -> 11 -> 3
4 -> 100 -> 101 -> 5
24 -> 11000 -> 11010 -> 26
29 -> 11101 -> 11101 -> 29
32 -> 100000 -> 101010 -> 42
192 -> 11000000 -> 11010101 -> 213
400 -> 110010000 -> 110010101 -> 405
298 -> 100101010 -> 100101010 -> 298

ბიმო

Posted 2017-12-22T17:10:22.227

Reputation: 15 345

Can we assume a 32-bit integer? – Arnauld – 2017-12-22T17:37:37.803

@Arnauld: Sure! – ბიმო – 2017-12-22T17:38:41.360

9Some golfing idea: If n is the maximal power of 2 that divides the input, then the answer is simply (input) + ceil((2^n - 2)/3) – JungHwan Min – 2017-12-22T17:45:37.363

Answers

12

Python 3, 20 bytes

lambda n:(n&-n)//3+n

Try it online!

Explanation

Take 192 as an example. Its binary form is 11000000, and we need to convert it to 11010101.

We note that we need to add 10101 to the number. This is a geometric series (4^0 + 4^1 + 4^2), which has a closed form as (4^3-1)/(4-1). This is the same as 4^3//3 where // denotes integer division.

If it were 101010, then it would still be a geometric series (2×4^0 + 2×4^1 + 2×4^2), which is 2×4^3//3 for the reasons above.

Anyway, 4^3 and 2×4^3 would just be the least significant bit, which we obtain by n&-n:

We notice that the complement of n is 00111111. If we add one, it becomes 01000000, and it only overlaps with n=11000000 at the least significant digit. Note that "complement and add one" is just negation.

Leaky Nun

Posted 2017-12-22T17:10:22.227

Reputation: 45 011

6@Mr.Xcoder nice sportsmanship – Leaky Nun – 2017-12-22T17:36:36.630

1

Possibly lambda n:(n&-n)//3+n works too? Passes all the sample test cases, but according to my intuition it shouldn't be valid, right?

– Mr. Xcoder – 2017-12-22T18:16:10.460

@Mr.Xcoder it is indeed valid. – Leaky Nun – 2017-12-22T18:17:30.857

1

Why not use Python 2 to save a byte? TIO

– FlipTack – 2017-12-22T22:38:07.920

4@FlipTack I hate python 2 – Leaky Nun – 2017-12-22T22:39:12.217

@LeakyNun haha, who doesn't – FlipTack – 2017-12-22T22:40:33.053

8

Jelly, 5 bytes

&N:3+

Try it online!

This time a port of Leaky Nun's approach (at least I helped him golf it down a bit :P)

Jelly, 7 bytes

^N+4:6ạ

Try it online!

Uses JungHwan Min's fantastic approach, with indirect help from Martin Ender.

Mr. Xcoder

Posted 2017-12-22T17:10:22.227

Reputation: 39 774

Dennis posted, then deleted, a very similar 5-byte solution just after you made that edit. Something like &N:3|. Congratulations; you beat Dennis in Jelly! (But not quite out-golfed.) – wizzwizz4 – 2017-12-22T18:22:49.060

@wizzwizz4 I really didn't do much, apart from suggesting a small golf to Leaky's approach and then porting it. But eh :-) – Mr. Xcoder – 2017-12-22T18:24:13.830

This is the first ASCII-only Jelly answer I've ever seen. – MD XF – 2017-12-23T04:11:59.990

6

Wolfram Language (Mathematica), 36 28 26 24 bytes

-8 bytes thanks to @MartinEnder and -2 bytes thanks to @Mr.Xcoder

#+⌊(#~BitAnd~-#)/3⌋&

Try it online!

We only need to find the number of the trailing zeroes in the input, and find the number with alternating 0s and 1s with length one less than that, and add it to the input.

So, 400 -> 11001000 -> 110010000 + 0000 -> 110010101 + 101 -> 405

The explicit formula for nth number with alternating 1s and 0s was given in A000975 on OEIS. We can use the nth number since no two different numbers can the same length in binary and have alternating digits.

JungHwan Min

Posted 2017-12-22T17:10:22.227

Reputation: 13 290

12^#~IntegerExponent~2 is (BitXor[#,#-1]+1)/2 – Martin Ender – 2017-12-22T17:51:26.583

@MartinEnder wow! And then I can just combine the fractions to reduce more bytes – JungHwan Min – 2017-12-22T17:53:24.037

124 bytes. You can use #+⌊(#~BitAnd~-#)/3⌋& instead. – Mr. Xcoder – 2017-12-22T18:22:12.387

@Mr.Xcoder edited :) – JungHwan Min – 2017-12-22T18:25:00.053

5

J, 19 18 bytes

+(2|-.i.@#.-.)&.#:

Try it online!

Quick Explanation

This is an old answer, but it is very similar in nature to the current one, it just counts the trailing zeroes differently. See the comments for a link explaining how it works.

+(2|i.@i.&1@|.)&.#:
                 #:  Convert to binary list
       i.&1@|.       Index of last 1 from right
            |.         Reverse
       i.&1            Index of first 1
    i.               Range [0, index of last 1 from right)
  2|                 That range mod 2
               &.    Convert back to decimal number
+                    Add to the input

Other Answers:

Previous answer (19 bytes).

+(2|i.@i.&1@|.)&.#:

Longer than it should be because \ goes right-to-left.

+(2|#*-.#.-.)\&.(|.@#:)

cole

Posted 2017-12-22T17:10:22.227

Reputation: 3 526

118 bytes +(2|-.i.@#.-.)&.#: – miles – 2017-12-22T22:44:12.310

@miles mind explaining what's going on with the base conversion there? I'm guessing it's got something to do with the zeroes but I'm not sure. – cole – 2017-12-22T23:25:13.487

#.~ counts the number of trailing truths, so what we need is #.~ -. #: to count the number of trailing zeroes – miles – 2017-12-23T04:12:06.223

@miles Ah! That’s very, very clever. – cole – 2017-12-24T17:47:30.770

4

Julia 0.6, 12 bytes

!n=n|n&-n÷3

Try it online!

Dennis

Posted 2017-12-22T17:10:22.227

Reputation: 196 637

This looks like an efficient method, can you explain the operator precedence? For example, I can't tell whether it's evaluated as ((!n=(n|n))&-n)/3, or !n=(((n|n)&(-n))/3), etc. – MD XF – 2017-12-24T03:26:46.640

In Julia, bitwise operators have the same precedences as their arithmetic counterparts, so | is like + and & is like *. Therefore, n|n&-n÷3 is parsed as n | ((n&-n) ÷3). – Dennis – 2017-12-24T03:41:12.293

3

JavaScript (ES6), 40 39 bytes

Takes input as a 32-bit integer.

n=>n|((n&=-n)&(m=0xAAAAAAAA)?m:m/2)&--n

Test cases

let f =

n=>n|((n&=-n)&(m=0xAAAAAAAA)?m:m/2)&--n

console.log(f(1))   // 1 -> 1 -> 1
console.log(f(2))   // 10 -> 10 -> 2
console.log(f(3))   // 11 -> 11 -> 3
console.log(f(4))   // 100 -> 101 -> 5
console.log(f(24))  // 11000 -> 11010 -> 26
console.log(f(29))  // 11101 -> 11101 -> 29
console.log(f(32))  // 100000 -> 101010 -> 42
console.log(f(192)) // 11000000 -> 11010101 -> 213
console.log(f(400)) // 110010000 -> 110010101 -> 405
console.log(f(298)) // 100101010 -> 100101010 -> 298

Arnauld

Posted 2017-12-22T17:10:22.227

Reputation: 111 334

2

R, 71 58 bytes

thanks to NofP for -6 bytes

function(n){n=n%/%(x=2^(0:31))%%2
n[!cumsum(n)]=1:0
n%*%x}

Try it online!

Assumes input is a 32-bit integer. R only has signed 32-bit integers (casting to double when an integer overflows) anyway and no 64-bit or unsigned ints.

Giuseppe

Posted 2017-12-22T17:10:22.227

Reputation: 21 077

You can convert the which.max(n):1-1 to !cumsum(n) to get a 65 bytes solution

– NofP – 2017-12-22T19:39:51.067

@NofP thanks! That's a great idea. – Giuseppe – 2017-12-22T19:46:50.100

2

05AB1E, 13 8 5 bytes

Saved 5 bytes thanks to Mr. Xcoder and JungHwan Min's neat formula
Saved another 3 thanks to Mr. Xcoder

(&3÷+

Try it online!

Explanation

(      # negate input
 &     # AND with input
  3÷   # integer divide by 3
    +  # add to input

Emigna

Posted 2017-12-22T17:10:22.227

Reputation: 50 798

1

Maybe worth mentioning that porting the Mathematica answer gives you 8 bytes

– Mr. Xcoder – 2017-12-22T18:01:07.590

@Mr.Xcoder: Ooh, that's a neat formula. – Emigna – 2017-12-22T18:02:46.570

1Does 05ab1e have bitwise AND? If so, (<bitwise and here>3÷+ should work for ~5 bytes. – Mr. Xcoder – 2017-12-22T18:30:14.420

2

brainfuck, 120 bytes

>+<[[>-]++>[[>]>]<[>+>]<[<]>-]>[-<+>[-<[<]<]>]>[>]<[>+<[->+<]<[->+<]<]>>[<]+>[-[-<[->+<<+>]>[-<+>]]<[->++<]<[->+<]>>>]<<

Try It Online!

Starts with the value in the current cell and ends on the cell with the output value. Obviously won't work on numbers above 255 as that's the cell limit for typical brainfuck, but will work if you assume infinite cell size.

Jo King

Posted 2017-12-22T17:10:22.227

Reputation: 38 234

1

Python 3, 56 bytes

lambda n:eval((bin(n).rstrip("0")+"01"*n)[:len(bin(n))])

Try it online!

Not really happy with this yet, but I really didn't want to use the formula... -2 thanks to Rod. -1 thanks to Jonathan Frech.

Mr. Xcoder

Posted 2017-12-22T17:10:22.227

Reputation: 39 774

eval(...) instead of int(...,2) could save a byte. – Jonathan Frech – 2017-12-23T14:36:41.193

1

PowerShell, 168 bytes

param($n)$a=($c=[convert])::ToString($n,2);if(($x=[regex]::Match($a,'0+$').index)-gt0){$c::ToInt32(-join($a[0..($x-1)]+($a[$x..$a.length]|%{(0,1)[$i++%2]})),2)}else{$n}

Try it online!

Ouch. Conversion to/from binary and array slicing are not really PowerShell's strong suits.

Takes input $n as a number. We immediately convert that to binary base 2 and store that into $a. Next we have an if/else construct. The if clause tests whether a regex Match against 1 or more 0s at the end of the string ('0+$') has its index at a location greater than 0 (i.e., the start of the binary string). If it does, we have something to work with, else we just output the number.

Inside the if, we slice of the xth first digits, and array-concatenate + those with the remaining digits. However, for the remaining digits, we loop through them and select either a 0 or 1 to be output instead, using $i++%2 to choose. This gets us the 010101... pattern instead of 0s at the end. We then -join that back together into a string, and $convert it back into an Int32 from base 2.

In either situation, the number is left on the pipeline and output is implicit.

AdmBorkBork

Posted 2017-12-22T17:10:22.227

Reputation: 41 581

1

C, 56 bytes

i,k;f(n){for(k=i=1;n>>i<<i==n;k+=++i&1)k*=2;return n|k;}

Try it online!

C (gcc), 50 bytes

i,k;f(n){for(k=i=1;n>>i<<i==n;k+=++i&1)k*=2;k|=n;}

Try it online!

 51  48 bytes using Arnauld's solution:

Thanks to @l4m2 for saving three bytes!

m;f(n){return n|((n&-n)&(m=-1u/3*2)?m:m/2)&n-1;}

Try it online!

43 with gcc:

m;f(n){m=n|((n&-n)&(m=-1u/3*2)?m:m/2)&n-1;}

Try it online!

Steadybox

Posted 2017-12-22T17:10:22.227

Reputation: 15 798

0xAAAAAAAA => -1u/3*2 – l4m2 – 2017-12-25T12:57:45.557

1

PowerShell, 41 36 bytes

param($n)$n+(($x=$n-band-$n)-$x%3)/3

Try it online! or Verify all test cases

Port of Leaky Nun's Python answer.

Saved 5 bytes thanks to Leaky Nun

AdmBorkBork

Posted 2017-12-22T17:10:22.227

Reputation: 41 581

1

APL+WIN, 43 bytes

p←+/^\⌽~n←((⌊1+2⍟n)⍴2)⊤n←⎕⋄2⊥((-p)↓n),p⍴0 1

Prompts for screen input

Graham

Posted 2017-12-22T17:10:22.227

Reputation: 3 184

1

PHP, 47 bytes

<?php function b($a){echo(int)(($a&-$a)/3)+$a;}

Try it online!

Really just another port of @Leaky Nun's solution

NK1406

Posted 2017-12-22T17:10:22.227

Reputation: 739

1

Perl 5, 54 bytes

$_=sprintf'%b',<>;1while s/00(0*)$/01$1/;say oct"0b$_"

Try it online!

Xcali

Posted 2017-12-22T17:10:22.227

Reputation: 7 671

1

Rust, 18 bytes

A port of Leaky Nun's approach

|n:i32|(n&-n)/3+n;

Try it online!

Noskcaj

Posted 2017-12-22T17:10:22.227

Reputation: 421

1

Ruby, 15 bytes

Another port of Leaky Nun's approach.

->k{(k&-k)/3+k}

Try it online!

Tom Lazar

Posted 2017-12-22T17:10:22.227

Reputation: 41

1

AWK, 24 bytes

A port of JungHwan Min's Mathmatica answer

$0=int(and($0,-$0)/3+$0)

Try it online!

Noskcaj

Posted 2017-12-22T17:10:22.227

Reputation: 421

1

JavaScript ES6, 13 bytes

n=>(n&-n)/3|n

f = 
n=>(n&-n)/3|n
;
console.log (f(8));
console.log (f(243));
console.log (f(1048576));
console.log (f(33554432));

l4m2

Posted 2017-12-22T17:10:22.227

Reputation: 5 985

1

Pari/GP, 19 bytes

A port of Leaky Nun's approach.

n->n+bitand(n,-n)\3

Try it online!

alephalpha

Posted 2017-12-22T17:10:22.227

Reputation: 23 988

0

Jelly, 13 bytes

BŒgṪµ2Ḷṁ×CḄ+³

Try it online!

Explanation

Take 24 as an example input.

BŒgṪµ2Ḷṁ×CḄ+³
B                Binary representation of the input → 11000
 Œg              Group runs of equal length → [[1,1],[0,0,0]]
   Ṫ             Tail → [0,0,0]
    µ            New monadic link
     2Ḷ          [0,1] constant
       ṁ         Mold [0,1] to the shape of [0,0,0] → [0,1,0]
        ×        Multiply [0,1,0] by...
         C       1-[0,0,0]. If last bit(s) of the original input are 1 this will add nothing to the original input
          Ḅ      Convert to decimal from binary → 2
           +³    Add this with the original input → 26

dylnan

Posted 2017-12-22T17:10:22.227

Reputation: 4 993