Numbers with multiple runs of ones

Python, 48

lambda n:[i for i in range(2**n)if'01'in bin(i)]

I had been vastly overthinking this. We just need to check if the binary expansion contains '01'.

For there to be two runs of ones, the one on the right must be preceded by a 0. If there's only one run, there won't be any leading 0's, so that won't happen.


Old answer:

lambda n:[i for i in range(2**n)if len(set(bin(i).split('0')))>2]

The Python binary representation works very nicely here. A binary number is written like bin(9)=='0b10110'. Splitting at '0' results in a list of

  • Empty strings to the left of the initial 0, between any two consecutive 0's, and to the right of any final 0
  • The letter b followed by one or more leading ones
  • Runs of 1's that are not leading

The first two categories always exist, but the last one only exists if there is a run one 1's that doesn't contain the leading '1', and so only if there's more than one run of 1's. So, it suffices to check if the list contains more than 2 distinct elements.

Python 3.5 saves 2 chars by unpacking {*_} in place of set(_).


Ruby, 44 40 38 chars

crossed out 44 is still regular 44 ;(

->n{(0..2**n).select{|x|/01/=~'%b'%x}}

An anonymous function (proc, actually) that takes an integer and returns an array.

Uses the regex /10+1/: a 1, at least one 0, and then another 1. @histocrat points out that if 01 is anywhere in the string, there must be a 1 somewhere before it.


Julia, 43 41 bytes

n->filter(i->ismatch(r"01",bin(i)),1:2^n)

This creates an unnamed function that accepts an integer and returns an array. It uses histocrats's regex trick (used in Doorknob's answer), where 01 will only match if there's a preceding 1.

Ungolfed:

function f(n::Int)
    # Take the integers from 1 to 2^n and filter them down to
    # only those such that the binary representation of the integer
    # matches the regex /01/.
    filter(i -> ismatch(r"01", bin(i)), 1:2^n)
end