1

I'm trying to create a function "generate_tree(L)", that takes a list of letters and returns a binary tree. Where each letter is a leaf. for example, with the list:

L = ['A', 'B', 'C']

the function should randomly return one of these trees:

['A',['B', 'C']] or [['A','B'], 'C'] 

Where the first example represent this tree:

binary tree

Well it's not going too well - I had a solution but it also returned a lot of empty lists and it was a mess. This is my attempt so far:

from random import randint
def generate_tree(L):
    n = len(L)
    if not L: #base case yield empty
        yield L
        return
    randomSplit = randint(1,n-1)
    leftList = L[0:randomSplit]
    rightList = L[randomSplit:]

List = ['A','B','C']
list(generate_tree(L))

My attempt with randomSplit is to divide the list into two lists in a random non-empty position:

['A','B','C'] --> leftList: ['A'], rightList: ['B','C']

I know I need to send leftList and rightList recursively, but I can't get it right. I would love your take on this issue

2 Answers 2

1

This solution chooses a random split point and divides the list down from there:

from random import randint

def tree(lst):
    if len(lst) == 1:
        return lst[0]
    elif len(lst) <= 2:
        return lst
    else:
        ix = randint(1, len(lst) - 1)
        retval = [tree(lst[:ix]) , tree(lst[ix:])]
        return retval

tree(['A','B','C']) only produces one of the two required outputs.

Sample outputs from:

for _ in range(10):
    print(tree(['A','B','C','D']))

[['A', 'B'], ['C', 'D']]
[[['A', 'B'], 'C'], 'D']
['A', [['B', 'C'], 'D']]
[['A', 'B'], ['C', 'D']]
[['A', 'B'], ['C', 'D']]
['A', [['B', 'C'], 'D']]
[['A', ['B', 'C']], 'D']
[['A', ['B', 'C']], 'D']
[[['A', 'B'], 'C'], 'D']
['A', ['B', ['C', 'D']]]
Sign up to request clarification or add additional context in comments.

Comments

1

I think your base case is when length of list is 2 (or smaller in special cases), so here's an idea based on using random.randint:

from random import randint

def tree(lst):
    if len(lst) <= 2:
        return lst
    else:
        ix = randint(0, len(lst) - 1)
        retval = [lst[ix]]
        retval.append(tree(lst[:ix] + lst[ix+1:]))
        return retval

It should work also for list of length greater than 3 or of length 0 or 1.


EDIT:

If the first element of the list must be the first element (as suggested by your example), this should do:

from random import randint

def tree(lst):
    if len(lst) == 1:
        return lst[0]
    if len(lst) <= 2: # this matters is lst == []
        return lst
    else:
        ix = randint(1, len(lst) - 1)
        retval = [lst[:ix]] if ix > 1 else lst[:ix]
        retval.append(tree(lst[ix:]))
        return retval

1 Comment

For the case of ['A', 'B', 'C'] your function possibly produces additional results beyond the two alternatives that the OP requires.

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.