| Bytes | Lang | Time | Link |
|---|---|---|---|
| 053 | Zsh | 230728T065153Z | roblogic |
| 014 | x86/x8664 machine code | 170917T025357Z | Peter Co |
| 046 | Python 3 | 170917T131936Z | lifebala |
| 044 | Mathematica | 210930T122108Z | ntrupin |
| 083 | Python 3 | 210930T121611Z | Amir rez |
| 021 | APL Dyalog Unicode | 170918T205413Z | Adá |
| 032 | JavaScript ES6 | 170916T203600Z | Arnauld |
| 071 | Javascript | 170921T224139Z | Washingt |
| 021 | APL Dyalog Classic | 170917T113808Z | ngn |
| 044 | Excel VBA | 170917T193536Z | Taylor A |
| 060 | C# .NET Core | 170917T060746Z | Ayb4btu |
| 398 | MS SQL Server | 170918T220200Z | phroureo |
| 117 | R | 170919T171013Z | Zahiro M |
| 080 | C gcc | 170918T190845Z | cleblanc |
| 081 | Java 8 | 170919T070859Z | Kevin Cr |
| 096 | ObjectiveC | 170918T115546Z | Fennelou |
| 094 | Google Sheets | 170918T193530Z | Engineer |
| 043 | Retina | 170916T234101Z | mbomb007 |
| 451 | Perl 5 | 170918T133135Z | user7392 |
| 045 | Python 2 | 170917T062133Z | Mr. Xcod |
| 054 | Javascript | 170918T100509Z | nl-x |
| 041 | Python 2 | 170918T102652Z | xnor |
| 017 | J | 170916T225147Z | miles |
| 066 | R | 170918T012817Z | Julian Z |
| 011 | Jelly | 170916T205803Z | fireflam |
| 075 | Haskell | 170916T221508Z | Laikoni |
| 4535 | Perl 6 | 170916T205430Z | Ramillie |
| 077 | Kotlin | 170917T152244Z | jrtapsel |
| 019 | Jelly | 170916T210739Z | Mr. Xcod |
| 008 | Jelly | 170917T065545Z | Dennis |
| 017 | Pyth | 170917T065355Z | Mr. Xcod |
| 011 | Jelly | 170916T221811Z | Jonathan |
| 015 | MATL | 170917T001816Z | B. Mehta |
| 011 | 05AB1E | 170916T224422Z | Justin M |
| 012 | Husk | 170916T234805Z | H.PWiz |
| 078 | Python 2 | 170916T203749Z | Chas Bro |
Zsh, 53 bytes
b=$[[##2]$1];set ${(Ons:0:)b};<<<$[$#b-${(SE)b#$1}+1]
b is argument $1 in binary. Then we set $1 again, to the longest sequence of 1s in b. ${(SE)b#$1 finds the first occurrence (from the left) of $1 in b, and returns the index+1 of the last matching char. However since the question is counting by powers of 2 we do a subtraction from the length of b.
Other approaches reverse b, but that took more bytes.
x86/x86-64 machine code, 14 bytes
(TODO: 13 bytes with input in EAX, return value in EDX).
Using @Arnauld's algorithm of x &= x>>1 and taking the highest set bit position in the step before x becomes 0.
Callable from C/C++ with signature unsigned longest_set(unsigned edi); in the x86-64 System V ABI. The same machine-code bytes will decode the same way in 32-bit mode, but the standard 32-bit calling conventions don't put the first arg in edi. (Changing the input register to ecx or edx for Windows _fastcall / _vectorcall or gcc -mregparm could be done without breaking anything.)
address machine-code
bytes
global longest_set
1 longest_set:
2 00000000 31C0 xor eax, eax ; 0 for input = 0
3
4 .loop: ; do{
5 00000002 0FBDC7 bsr eax, edi ; eax = position of highest set bit
6 ;; bsr leaves output unmodified when input = 0 (and sets ZF)
7 ;; AMD documents this; Intel manuals say unspecified but Intel CPUs implement it
8 00000005 89F9 mov ecx, edi
9 00000007 D1E9 shr ecx, 1
10 00000009 21CF and edi, ecx
11 0000000B 75F5 jnz .loop ; } while (x &= x>>1);
12
13 0000000D C3 ret
x86's BSR instruction (Bit Scan Reverse) is perfect for this, giving us the bit-index directly, rather than counting leading zeros. (bsr doesn't directly produce 0 for input=0 like 32-lzcnt(x) would, but we need bsr=31-lzcnt for non-zero inputs, so lzcnt wouldn't even save instructions, let alone byte count. Zeroing eax before the loop works because of bsr's semi-official behaviour of leaving the destination unmodified when the input is zero.)
This would be even shorter if we could return the MSB position of the longest run. In that case, lea ecx, [rdi+rdi] (3 bytes) would copy + left-shift instead of mov + shr (4 bytes).
See this TIO link for an asm caller that does exit(longest_set(argc-1));
Testing with a shell loop:
l=(); for ((i=0;i<1025;i++));do
./longest-set-bitrun "${l[@]}"; # number of args = $i
printf "$i %#x: $?\n" $i;
l+=($i);
done | m
0 0: 0
1 0x1: 0
2 0x2: 1
3 0x3: 0
4 0x4: 2
5 0x5: 2
6 0x6: 1
7 0x7: 0
8 0x8: 3
9 0x9: 3
10 0xa: 3
11 0xb: 0
12 0xc: 2
13 0xd: 2
14 0xe: 1
15 0xf: 0
16 0x10: 4
17 0x11: 4
18 0x12: 4
19 0x13: 0
20 0x14: 4
21 0x15: 4
...
747 0x2eb: 5
748 0x2ec: 5
749 0x2ed: 5
750 0x2ee: 5
751 0x2ef: 0
752 0x2f0: 4
753 0x2f1: 4
754 0x2f2: 4
13 bytes with a custom calling convention
We could save a byte by taking the arg in EAX and returning in EDX: then we could use cdq (1 byte) to zero the return value in the case where input = 0 (so bsr leaves it unmodified). The value in other cases doesn't matter, overwritten by bsr.
So cdq replaces xor eax, eax, saving a byte.
We do need a 0 in a different register to (not) overwrite; in the non-zero case we can't let bsr replace the input value with its log2. So we can't avoid the instruction entirely, and taking input + returning in EAX (like GCC regparm) would mean we'd need to start with mov edx, eax or something to copy it somewhere else, while leaving the return value 0 for the input=0 case.
Mathematica, 44 bytes
I feel like I can trim off a few more bytes, though I'm not sure how yet.
We save space by using an assignment within If, using #0 for pure function recursion, and using infix notation when possible.
If[(k=BitAnd[#,#/2])>0,#0@k,Log2@#~BitOr~0]&
Python 3, 83 bytes
len(bin(num)[2:].split('1'*(max(list(map(len,bin(num)[2:].split('0'))))))[1])
It does not support the condition that two or more arrays of 1s are longest.
APL (Dyalog Unicode), 21 bytes (SBCS)
Requires ⎕IO←0 which is default on many systems.
⊃⌽⍸b⍷⍨∨⌿↑⊆⍨b←⌽2⊥⍣¯1⊢⎕
⎕ prompt for input
⊢ yield that (separates ¯1 from ⎕)
2⊥⍣¯1 convert to base-2, using as many positions as needed
⌽ reverse
b← store as b (for binary)
⊆⍨b self-partition b (i.e. the 1-streaks of b)
↑ mix (make list of lists into matrix, padding with zeros)
∨⌿ vertical OR reduction (yields longest streak)
b⍷⍨ mark the start positions of that in b
⍸ ɩndices of those starting positions
⌽ reverse
⊃ pick the first one (yields zero if none available)
JavaScript (ES6), 33 32 bytes
f=x=>x&(k=x>>1)?f(x&k):k&&1+f(k)
JavaScript (ES6), 41 40 36 34 bytes
Saved 4 bytes thanks to @ThePirateBay
f=x=>(k=x&x/2)?f(k):Math.log2(x)|0
How?
General case x > 0
We recursively AND the input x with x / 2 which progressively reduces the patterns of consecutive set bits until only the rightmost bit of the sequence remains. We keep a copy of the last non-zero value and determine the position of its most significant bit by floor-rounding its base-2 logarithm.
Below are the steps we go through for x = 750 (1011101110 in binary).
1011101110 --.
,----------------'
'-> 1011101110
AND 0101110111
----------
= 0001100110 --.
,----------------'
'-> 0001100110
AND 0000110011
----------
= 0000100010 --. --> output = position of MSB = 5 (0000100010)
,----------------' ^
'-> 0000100010
AND 0000010001
----------
= 0000000000
Edge case x = 0
The special case x = 0 immediately leads to Math.log2(0) | 0. The logarithm of 0 evaluates to -Infinity and the binary bitwise OR forces a coercion to a 32-bit integer. In compliance with the specification of the abstract operation ToInt32, this gives the expected 0:
If number is NaN, +0, −0, +∞, or −∞, return +0
Javascript, 71 bytes
I was thinking about regular expressions and...
x=>+x.toString(2).replace(/.*?0?(1*)(?!.*\1[1])(.*)/,(x,m,a)=>a.length)
Excel VBA, 54 44 Bytes
-10 Bytes thanks to @EngineerToast
Anonymous VBE immediate window function that takes input from range [A1] and outputs to the VBE immediate window
?Instr(1,StrReverse([Dec2Bin(A1)]),1)+[A1>0]
C# (.NET Core), 64 60 bytes
T=a=>(a&a/2)>0?T(a&a/2):Math.Log(a,2)<0?0:(int)Math.Log(a,2)
A C# version of @Arnauld's answer
Acknowledgements
4 bytes saved thanks to Kevin Cruijssen.
C# (.NET Core), 131 123+18=141 bytes
a=>{string s=Convert.ToString(a,2),t=s.Split('0').OrderBy(x=>x.Length).Last();return a<1?0:s.Length-s.IndexOf(t)-t.Length;}
+18 bytes for using System.Linq;
Acknowledgements
8 bytes saved thanks to Grzegorz Puławski.
Degolfed
a=>{
string s=Convert.ToString(a,2), // Convert to binary
t=s.Split('0') // get largest group of 1's
.OrderBy(x=>x.Length)
.Last();
return
a<1?0: // handle 0 case
s.Length-s.IndexOf(t)-t.Length; // get position in reversed string
}
C# (.NET Core), 164 161 bytes
a=>{var s=Convert.ToString(a,2);int c=0,l=0,p=0,k=0,j=s.Length-1,i=j;for(;i>=0;i--){if(s[i]>'0'){if(i==j||s[i+1]<'1'){p=i;c=0;}if(++c>=l){l=c;k=p;}}}return j-k;}
A non-Linq solution, which I'm sure could be improved, though nothing is immediately apparent.
Degolfed
a=>{
var s=Convert.ToString(a,2); // Convert to binary
int c=0,l=0,p=0,k=0,j=s.Length-1,i=j;
for(;i>=0;i--) // Loop from end of string
{
if(s[i]>'0') // if '1'
{
if(i==j||s[i+1]<'1') // if first digit or previous digit was '0'
{
p=i; // set the position of the current group
c=0; // reset the count
}
if(++c>=l) // if count is equal or greater than current largest count
{
l=c; // update largest count
k=p; // store position for this group
}
}
}
return j-k; // as the string is reversed, return string length minus position of largest group
}
MS SQL Server, 437 426 407 398 bytes
I'm sure that I could remove line breaks, etc, but this is as compact as I was willing to make it:
create function j(@ int)
returns int
as BEGIN
declare @a varchar(max)='',@b int,@c int=0,@d int=0,@e int=0,@f int=0,@g int=0,@h int=0
while @>0 BEGIN SELECT @a=cast(@%2 as char(1))+@a,@=@/2
END
SET @b=len(@a)
while @<@b
BEGIN
select @c=@d,@d=cast(substring(@a,@b-@,1)as int)
IF @d=1
BEGIN IF @c=0
SELECT @e=@,@g=1
else SET @g+=1 END
IF @g>=@h BEGIN select @h=@g,@f=@e END
SET @+=1
END
return @f
END
Here's a more readable version:
create function BinaryString(@id int)
returns int
as BEGIN
declare @bin varchar(max)
declare @binLen int
declare @pVal int = 0
declare @Val int = 0
declare @stC int = 0 --start of current string of 1s
declare @stB int = 0 --start of biggest string of 1s
declare @lenC int = 0 --length of current string of 1s
declare @lenB int = 0 --length of biggest string of 1s
set @bin = ''
while @id>0
BEGIN
SET @bin = cast(@id%2 as varchar(1)) + @bin
SET @id = @id/2
END
SET @binLen = len(@bin)
while @id<@binLen
BEGIN
set @pVal = @Val
set @Val = cast(substring(@bin,@binLen-@id,1) as int)
IF @Val = 1 and @pVal = 0
BEGIN
SET @stC = @id
SET @lenC = 1
END
IF @Val = 1 and @pVal = 1
BEGIN
SET @lenC = @lenC + 1
END
IF @lenC >= @lenB
BEGIN
set @lenB = @lenC
set @StB = @StC
END
SET @id = @id + 1
END
return @StB
END
The real trick is that as far as I could find, there is no native SQL functionality to convert a number from decimal to binary. As a result, I had to code the conversion to binary manually, then I could compare that as a string, one character at a time until I found the right number.
I'm sure there's a better way to do this, but I didn't see a(n) SQL answer, so I figured I'd throw it out there.
R, 117 Bytes
z=rev(Reduce(function(x,y)ifelse(y==1,x+y,y),strtoi(intToBits(scan())),,,T));ifelse(!sum(z),0,33-which.max(z)-max(z))
C (gcc), 81 80 bytes
i,l,c,r;f(n){for(i=l=c=r=0;n;n/=2,i++)c=n&1?c+1:c>=l?r=i-(l=c),0:0;n=c<l?r:i-c;}
C (gcc), 43 bytes
A C version of @Arnauld's answer
k;f(n){n=(k=n&n/2)?f(k):(k=log2(n))<0?0:k;}
Java 8, 81 bytes
int c(int n){int x=(int)(Math.log(n)/Math.log(2));return(n&=n/2)>0?c(n):x<0?0:x;}
Port of @Arnauld's JavaScript answer.
Objective-C, 96 chars
for(int h=0,c=0,l=0,p=0;;x/=2,p++){if(x%2==0){if(c<=h){h=c;l=p;}c=0;if(x==0){return p;}}else{c++;}}
- If
xis even the highest count is checked and count resets - If
xis also 0 then return the highest count - If
xisn't even, then the last digit is 1 and count increments xis divided by two
Google Sheets, 94 bytes
=Len(Dec2Bin(A1))-Find(MAX(Split(Dec2Bin(A1),0)),Dec2Bin(A1))-Len(MAX(Split(Dec2Bin(A1),0)))+1
No, it's not very pretty. It'd be real nice to be able to store Dec2Bin(A1) as a variable for reference.
Key point: Like Excel, the Dec2Bin function has a max input value of 511. Anything larger than that returns an error, as seen below.
Retina, 52 43 bytes
Convert to binary, then replace with the length of what follows the largest string of ones.
.*
$*
+`(1+)\1
$+0
01
1
$'¶
O`
A-3`
^1+
.
Try it online - all test cases
Saved 9 bytes thanks to Martin.
Perl 5, 45 + 1 (-p)
(sprintf"%b",$_)=~/(1+)(?!.*1\1)/;$_=length$'
If you write this out on the command line of most shells, you may have to type this as:
perl -pE'(sprintf"%b",$_)=~/(1+)(?!.*1\1)/;$_=length$'"'"
The dance of the quotes at the end is just to get perl see a ', which would otherwise be consumed by the shell.
Python 2, 45 bytes
f=lambda x:f(x&x/2)if x&x/2else len(bin(x))-3
Saved plenty of bytes thanks to Dennis! (The heads up for len(bin(...))-3 instead of math.frexp)
Thanks to @xnor for finding a bug, which fortunately was easily fixable!
Javascript, 54 chars
f=i=>i.toString(2).split(0).sort().reverse()[0].length
i.toString(2)gets the binary string for the integer.- The
.split(0)gets each sequential ones part in an array element. .sort().reverse()gets us the highest value as first.- The
[0].lengthgives us the length of that first value.
J, 18 17 bytes
(#-0{#\\:#.~\)@#:
Explanation
(#-0{#\\:#.~\)@#: Input: integer n
#: Binary
#\ Length of each prefix
\: Sorted down using
#.~\ Mixed base conversion on each prefix
0{ Get the value at index 0
- Subtract from
# Length
R, 66 Bytes
function(i){a=rle(intToBits(i));max(0,a[[1]][which(a[[2]]==1)])}
Explanation:
function(i){
a = rle( # Run-length encode
intToBits(i) # The bits in i
); # And assign it to a.
max(0, # Return the maximum of zero and
a[[1]][ # The lengths of a,
which(a[[2]]==1) # But only those where the repeated bit is 1
])
}
Jelly, 19 17 11 bytes
HÐĿ&\ḟ0ṪBL’
-6 (!) bytes thanks to @Dennis's keen observations
How it Works
HÐĿ&\ḟ0ṪBL’
HÐĿ - halve repeatedly until reaching 0 due to rounding
&\ - cumulative AND
ḟ0Ṫ - final non-zero, or 0 if all elements are 0
BL - length of binary representation (log base 2). 0->[0]->1
’ - decrement
Haskell, 101 98 96 75 bytes
snd.maximum.(`zip`[0..]).c
c 0=[0]
c n|r<-c$div n 2=sum[r!!0+1|mod n 2>0]:r
Try it online! Usage: snd.maximum.(`zip`[0..]).c $ 142 yields 1.
Explanation:
cconverts the input into binary while at the same time counting the length of streaks of one, collecting the results in a list.r<-c$div n 2recursively computes the restrof this list, whilesum[r!!0+1|mod n 2>0]:radds the current length of the streak tor. The list comprehension checks ifmod n 2>0, that is whether the current binary digit is a one, and if so, takes the length of the previous streak (the first element ofr) and adds one. Otherwise the list comprehension is empty, andsum[]yields0. For the example input,c 142yields the list[0,3,2,1,0,0,0,1,0].(`zip`[0..])adds the position to each element of the previous list as the second component of a tuple. For the example this gives[(0,0),(3,1),(2,2),(1,3),(0,4),(0,5),(0,6),(1,7),(0,8)].maximumfinds the lexicographically maximal tuple in this list, that is the streak lengths are considered first as they are the first component, and in the event of a tie the second component, namely the larger index, decides. This yields(3,1)in the example, andsndreturns the second component of the tuple.
Perl 6, 45 35 bytes
This highly improved version is courtesy of @nwellnhof.
{.msb+1-(.base(2)~~m:g/1+/).max.to}
Kotlin, 77 bytes
{val b=it.toString(2)
b.reversed().lastIndexOf(b.split(Regex("0+")).max()!!)}
Beautified
{
val b = it.toString(2)
// Find the left position of the first instance of
b.reversed().lastIndexOf(
// The largest group of 1s
b.split(Regex("0+")).max()!!)
}
Test
var s:(Int)->Int =
{val b=it.toString(2)
b.reversed().lastIndexOf(b.split(Regex("0+")).max()!!)}
fun main(args: Array<String>) {
r(0, 0)
r(142, 1)
r(48, 4)
r(750, 5)
}
fun r(i: Int, i1: Int) {
var v = s(i)
println("$i -> $v [$i1] ${i1 == v}")
}
Jelly, 19 bytes
BŒgḄṀB
BwÇɓÇL+ɓBL_‘
Thanks to Jonathan Allan for saving 4 6 bytes!
I've worked too much to just abandon this, although it is kind of long. I really wanted to add a solution that literally searches for the longest substring of 1s in the binary representation...
Explanation
BŒgḄṀB - Monadic helper link. Will be used with Ç in the next link.
B - Binary representation.
Œg - Group runs of consecutive equal elements.
Ḅ - Convert from binary to integer.
Ṁ - Maximum value.
B - Convert from integer to binary.
BwÇɓÇL+ɓBL_‘ - Main link.
B - Binary representation (of the input).
Ç - Last link as a monad. Takes the input integer.
w - First sublist index.
ɓ - Start a separate dyadic chain. Reverses the arguments.
Ç - Last link as a monad.
L - Length.
+ - Addition
ɓ - Start a separate dyadic chain. Reverses the arguments.
B - Binary.
L - Length.
_‘ - Subtract and increment the result (because Jelly uses 1-indexing).
- Implicitly output.
Jelly, 10 8 bytes
Ba\ÐƤṀċ¬
How it works
Ba\ÐƤṀċ¬ Main link. Argument: n
B Binary; convert n to base 2.
ÐƤ Apply the link to the left to all postfixes of the binary array.
a\ Cumulatively reduce by logical AND.
For example, the array
[1, 0, 1, 1, 1, 0, 1, 1, 1, 0]
becomes the following array of arrays.
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 0, 0, 0, 0, 0]
[1, 1, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[1, 1, 1, 0]
[1, 1, 0]
[1, 0]
[0]
Ṁ Take the lexicographical maximum, i.e., the array with the most 1's at
the beginning, breaking ties by length.
¬ Yield the logical NOT of n, i.e., 0 if n > 0 and 1 if n = 0.
ċ Count the occurrences of the result to the right in the one to the left.
Pyth, 17 bytes
This is a recursive function. The link includes y in order to call the function on the given input.
L|&K.&b/b2yKsl|b1
Pyth, 20 bytes
-lK.B|Q1+xKJeScK\0lJ
Jelly, 14 13 12 11 bytes
Bµṣ0Ṫ$ƤMḢạL
A monadic link taking and returning non-negative integers.
Try it online! or see the test-suite.
How?
Bµṣ0Ṫ$ƤMḢạL - Main link: number, n e.g. 750
B - convert to a binary list [1,0,1,1,1,0,1,1,1,0]
µ - monadic chain separation, call that b
Ƥ - map over prefixes: (i.e. for [1], [1,0], [1,0,1], [1,0,1,1],...)
$ - last two links as a monad: e.g.: [1,0,1,1,1,0,1,1]
0 - literal zero 0
ṣ - split (prefix) at occurrences of (0) [[1],[1,1,1],[1,1]]
Ṫ - tail [1,1]
M - maximal indices [5,9]
Ḣ - head 5
L - length (of b) 10
ạ - absolute difference 5
MATL, 15 bytes
`tt2/kZ&t]xBnq&
Uses the half and AND idea. The k is necessary only to make it terminate for 1 - for some reason, 1 AND 0.5 returns 1, causing an infinite loop.
(alternate solution: BtnwY'tYswb*&X>)- by converting to binary and run-length encoding)
05AB1E, 14 12 11 bytes
bDγàŠrkrJgα
Try it online! or run test cases.
Explanation
bDγàŠrkrJgα Implicit input (ex: 750)
bD Convert input to binary string and duplicate
'1011101110', '1011101110'
γ Split into groups of 1s or 0s
'1011101110', ['1', '0', '111', '0', '111', '0']
à Pull out max, parsing each as an integer
'1011101110', ['1', '0', '0', '111', '0'], '111'
Šrk Rearrange stack and get first index of max run of ones
['1', '0', '0', '111', '0'], 2
rJg Reverse stack, join the array to a string, and get its length
2, 7
α Get absolute difference
5
Husk, 12 bytes
→S§-€¤≠Lo▲gḋ
Explanation
Implicit input, e.g 750
ḋ Convert to binary [1,0,1,1,1,0,1,1,1,0]
g Group equal elements [[1],[0],[1,1,1],[0],[1,1,1],[0]]
o▲ Maximum [1,1,1]
€ Index of that substring in the binary number 3
¤≠L Absolute difference of lengths abs (3 - 10) = 7
S§- Subtract the two 7 - 3 = 4
→ Increment 5
Python 2, 89 78 bytes
m=t=i=j=0
for c in bin(input()):
t=-~t*(c>'0');i+=1
if t>m:j=i;m=t
print i-j
EDIT: Saved 11 bytes thanks to Mr. Xcoder.
