Let's say I want to get the the number of jumps of each consecutive 1's in a binary string of say, 169, which is 10101001.
The answer then it'd be 3, 2, 2 because when the algorithm starts at the most right digit of the binary number needs to move thrice to the left to reach the next 1, twice to get the next 1 and so on.
So the algorithm should have a counter that starts at 0, increments in one while finds 0's and reset each time it reaches a 1.
I need the output to be in form of a list using list comprehesion.
This is what I got so far:
number = 169
list = []
c = 1
for i in bin(number>>1)[:1:-1]:
if i == '1':
list.append(c)
c = 0
c = 1
The algorithm indeed works but the idea is to transform it into one line code using list compreshesion. I think that there should be one way to do it using enumerate().
Just like:
n = 169
list = [i for i, c in enumerate(bin(number>>1)[:1:-1], 1) if c == '1']
The problem is that the output will be [3, 5, 7] instead of [3, 2, 2] because the i (index variable) didn't reset.
I'm looking for an asnwer that isn't just straight list[a 1] - list[a] but more elegant and efficient solution.
CodePudding user response:
Here's a one-liner for this problem that's most probably not readable.
s = "10101001"
result = [p - q for p, q in zip([index for index, a in enumerate(s[::-1]) if a == "1"][1:], [index for index, b in enumerate(s[::-1]) if b == "1"][:s.count("1")-1])]
CodePudding user response:
You can use groupby here:
bs = "10101001"
result = [
sum(1 for _ in g) 1 # this can also be something like len(list(g)) 1
for k, g in groupby(reversed(bs))
if k == "0"
]
You cannot really do this easily with just the list comprehension, because what you want cannot be expressed with just mapping/filtering (in any straightforward way I can think of), but once you have a grouping iterator, it simply becomes suming the length of "0" runs.
CodePudding user response:
you can easily do this with a regex pattern
import re
out = [len(i) for i in re.findall("0*1", num)]
output
print(out)
>>> [3, 2, 2]