Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count number of tails since the last head

Consider a sequence of coin tosses: 1, 0, 0, 1, 0, 1 where tail = 0 and head = 1.

The desired output is the sequence: 0, 1, 2, 0, 1, 0

Each element of the output sequence counts the number of tails since the last head.

I have tried a naive method:

def timer(seq):
    if seq[0] == 1: time = [0]
    if seq[0] == 0: time = [1]
    for x in seq[1:]:
        if x == 0: time.append(time[-1] + 1)
        if x == 1: time.append(0)
    return time

Question: Is there a better method?

like image 336
visitor Avatar asked Jul 22 '17 17:07

visitor


People also ask

What is the total count of the head and tail count?

H means initially all the coins are facing in head direction, N means the total number of coins. Hence the total count of the head is 2 and tail is 3. After all the possible flips the head and tail count is 4 and 3. Recommended: Please try your approach on {IDE} first, before moving on to the solution.

Is there a way to change the number of lines tail produces?

No, the default number of lines produced by tail (and head) is mandated by the POSIX standard: If neither -c nor -n is specified, -n 10 shall be assumed. To get a different number of lines, use the -n command line option, or create a shell function: or, if you really want to keep the name of the utility and just change the default number of lines,

What does the tail() function do in R?

This is what tail () function will do in R. Similar to the head () function, the tail () function can return the last n rows of the specified count. #importing the data df<-datasets::airquality #returns the last 10 values tail(df,10)

What is the total number of heads after n rounds?

In the question above if we observe then there is a pattern that if initially, all the coins are facing towards head direction then the total number of heads after N rounds will be the floor value of (n / 2) and tails will be the cell value of (n / 2).


Video Answer


4 Answers

Using NumPy:

import numpy as np 
seq = np.array([1,0,0,1,0,1,0,0,0,0,1,0])
arr = np.arange(len(seq))
result = arr - np.maximum.accumulate(arr * seq)
print(result)

yields

[0 1 2 0 1 0 1 2 3 4 0 1]

Why arr - np.maximum.accumulate(arr * seq)? The desired output seemed related to a simple progression of integers:

arr = np.arange(len(seq))

So the natural question is, if seq = np.array([1, 0, 0, 1, 0, 1]) and the expected result is expected = np.array([0, 1, 2, 0, 1, 0]), then what value of x makes

arr + x = expected

Since

In [220]: expected - arr
Out[220]: array([ 0,  0,  0, -3, -3, -5])

it looks like x should be the cumulative max of arr * seq:

In [234]: arr * seq
Out[234]: array([0, 0, 0, 3, 0, 5])

In [235]: np.maximum.accumulate(arr * seq)
Out[235]: array([0, 0, 0, 3, 3, 5])
like image 83
unutbu Avatar answered Oct 16 '22 14:10

unutbu


Step 1: Invert l:

In [311]: l = [1, 0, 0, 1, 0, 1]

In [312]: out = [int(not i) for i in l]; out
Out[312]: [0, 1, 1, 0, 1, 0]

Step 2: List comp; add previous value to current value if current value is 1.

In [319]: [out[0]] + [x + y if y else y for x, y in zip(out[:-1], out[1:])]
Out[319]: [0, 1, 2, 0, 1, 0]

This gets rid of windy ifs by zipping adjacent elements.

like image 32
cs95 Avatar answered Oct 16 '22 16:10

cs95


Using itertools.accumulate:

>>> a = [1, 0, 0, 1, 0, 1]
>>> b = [1 - x for x in a]
>>> list(accumulate(b, lambda total,e: total+1 if e==1 else 0))
[0, 1, 2, 0, 1, 0]

accumulate is only defined in Python 3. There's the equivalent Python code in the above documentation, though, if you want to use it in Python 2.

It's required to invert a because the first element returned by accumulate is the first list element, independently from the accumulator function:

>>> list(accumulate(a, lambda total,e: 0))
[1, 0, 0, 0, 0, 0]
like image 3
Eric Duminil Avatar answered Oct 16 '22 16:10

Eric Duminil


The required output is an array with the same length as the input and none of the values are equal to the input. Therefore, the algorithm must be at least O(n) to form the new output array. Furthermore for this specific problem, you would also need to scan all the values for the input array. All these operations are O(n) and it will not get any more efficient. Constants may differ but your method is already in O(n) and will not go any lower.

like image 1
lhhong Avatar answered Oct 16 '22 15:10

lhhong