2

I have been trying to solve the following problem using Python, and so far without success:

Assume you have a string with the characters '0', '1' and '?'. the '?' sign can be either '0' or '1'. Your goal is to print all the possible outputs for such given string.For example, the output for the string '0?1?' should be '0010', '0011', '0110' and '0111'

I have tried the following:

def comb(S):

    if not '?' in S:
        yield S
    else:
        yield comb(S.replace('?','0',1))
        yield comb(S.replace('?','1',1))             

S = '0?1??011'
S_generator = comb(S)
for s in  S_generator:
    print s

The result is strange, and is not what I am trying to get:

<generator object comb at 0x106b2ceb0>
<generator object comb at 0x106b2cf00>

Any idea why it is not working, and how I should change the code for this to work?

1
  • comb function seems to return generator object. So third and fourth yield statements in it are taking generator objects. They should take string. Commented Jul 30, 2015 at 4:02

4 Answers 4

7

comb() is a generator function , when you do -

yield comb(S.replace('?','0',1))

The yield statement does not automatically loop over all the values in the generator and yield them, you have to loop over the values and yield them one by one, Example -

def comb(S):
    if not '?' in S:
        yield S
    else:
        for i in comb(S.replace('?','0',1)):
            yield i
        for i in comb(S.replace('?','1',1)):  
            yield i

Example/Demo -

>>> def comb(S):
...     if not '?' in S:
...         yield S
...     else:
...         for i in comb(S.replace('?','0',1)):
...             yield i
...         for i in comb(S.replace('?','1',1)):
...             yield i
...
>>> for s in comb('abc?def?'):
...     print(s)
...
abc0def0
abc0def1
abc1def0
abc1def1
>>> for s in comb('0?1?'):
...     print(s)
...
0010
0011
0110
0111
>>> S = '0?1??011'
>>> for s in comb(S):
...     print(s)
...
00100011
00101011
00110011
00111011
01100011
01101011
01110011
01111011

[Edit]: Note that as of Python 3.3, you can use the new yield from syntax:

yield from comb(S.replace('?','0',1))
yield from comb(S.replace('?','1',1))
Sign up to request clarification or add additional context in comments.

7 Comments

Can the downvoter please comment why they think this answer is wrong? or bad?
How can you say that It does not automatically loop over all the values in the generator and yield them, if you see it's recursive call in comb function, what he has done is right and he is getting generator of generators.
Did you even try his code? It does not automatically loop over the generator returned by comb() . you have to loop over them. When creating recursive generator functions, you have to loop over the return values of the generator function where you call it in your generator function and then yield each result separately. Try creating a recursive generator function and you will understand.
@gsb-eng And if what he had done was correct, why wasn't he getting the result he wanted?
BTW he is getting the right values but he is not able to identify that, since he is getting generator of generators.
|
2

Anand's answer is correct and shows what is going on with your function.

You can also do this task non-recursively by using the itertools product function. For example:

import itertools

def allstrings(s):
    consts = s.split('?')
    allstrs = (2 * len(consts) - 1) * ['01']
    allstrs[::2] = ((x,) for x in consts)
    # Optimize out empty constants
    allstrs = (x for x in allstrs if x[0])
    return list(''.join(x) for x in itertools.product(*allstrs))

print(allstrings('0?1?'))

Comments

1

What you've done is also perfect, but the issue here is you are getting a generator of generators.. you've iterate over those to get the values..

def comb(S):

    if not '?' in S:
        yield S
    else:
        yield comb(S.replace('?','0',1))
        yield comb(S.replace('?','1',1))             

S = '0?1??011'
S_generator = comb(S)

def print_generator_values(parent_generator):
    import types
    for i in parent_generator:
        if isinstance(i, types.GeneratorType):
            print_generator_values(i)

print_generator_values(S_generator)

Comments

0

I know this post is 2 years old, but this solution might help other people checking this post in the future: Using python 3.6 (but works for previous releases too) and format:

from itertools import product

def replace_values(string):
    pattern_format = string.replace('?', '{}')
    return [pattern_format.format(*values) for values in product('10',   repeat=string.count('?'))]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.