recursive function that finds depth of empty list of lists - python

i need to write a recursive function that finds the depth of an empty list of lists, and it can only have one parameter, which is the list used. there is a test driver code for the problem which ill include below. i cant use advanced python stuff like isinstance or max and map because my professor wont allow it. i also am not sure what the make_list_structure function does exactly so if someone can explain what that was well that would be great.
import random
def make_list_structure(max_depth, p=.8):
if max_depth and random.random() < p:
new_list = []
for i in range(5):
sub_list = make_list_structure(max_depth - 1, p * .9)
if sub_list is not None:
new_list.append(sub_list)
return new_list
return None
if __name__ == '__main__':
print(how_deep([[[], [], [], [[[]]]], []]))
print(how_deep([]))
print(how_deep([[], []]))
print(how_deep([[[]], [], [[]], [[[]]]]))
print(how_deep([[[[], [[]], [[[]]], [[[[]]]]]]]))
print(how_deep([[[], []], [], [[], []]]))

Here's a short solution using max and map, and it's adaptation without it
def how_deep(values):
if not values:
return 1
sub_depth = 0
for value in values:
val_depth = how_deep(value)
if val_depth > sub_depth:
sub_depth = val_depth
return sub_depth + 1
def how_deep_nice(l):
if isinstance(l, list):
return 1 + max((how_deep_nice(item) for item in l), default=0)
return 0
print(how_deep([[[], [], [], [[[]]]], []])) # 5
print(how_deep([])) # 1
print(how_deep([[], []])) # 2

Related

Find the Word Pair - Codewars 5 kyu

Hello everyone, I have a problem with 5-kyu kata:
Given an array of words and a target compound word, your objective is to find the two words which combine into the target word, returning both words in the order they appear in the array, and their respective indices in the order they combine to form the target word. Words in the array you are given may repeat, but there will only be one unique pair that makes the target compound word. If there is no match found, return null/nil/None.
Examples:
fn(['super','bow','bowl','tar','get','book','let'], "superbowl") => ['super','bowl', [0,2]]
fn(['bow','crystal','organic','ally','rain','line'], "crystalline") => ['crystal','line', [1,5]]
fn(['bow','crystal','organic','ally','rain','line'], "rainbow") => ['bow','rain', [4,0]]
fn(['bow','crystal','organic','ally','rain','line'], "organically") => ['organic','ally', [2,3]]
fn(['top','main','tree','ally','fin','line'], "mainline") => ['main','line', [1,5]]
fn(['top','main','tree','ally','fin','line'], "treetop") => ['top','tree', [2,0]]
This kata on Codewars
I got a solution:
def compound_match(words, target):
#check input
if words == None or target == None:
return None
#find solution
indx = []
result = []
for i in range(len(words)-1):
for k in range(i+1, len(words)):
if words[i]+words[k] == target:
indx[0:1] = i, k
result[0:2] = words[i], words[k], indx
return result
elif words[k]+words[i] == target:
indx[0:1] = k, i
result[0:2] = words[i], words[k], indx
return result
return None
I pass TEST, pass "Some very short random tests" and "Some short random tests", but cant pass "Some very long random tests" and got error:
STDERR
Execution Timed Out (12000 ms)
I understand that my code is not optimal or perfect, but what can I do to improve?
Here's a complete solution.
def compound_match(words, target):
if words is None or target is None:
return None
word_dict = {w:i for i, w in enumerate(words)}
for i, w in enumerate(words):
w = words[i]
if target.startswith(w):
tail = target[len(w):]
if tail in word_dict:
k = word_dict[tail]
idx = [i, k]
result = [words[min(i,k)], words[max(i,k)], idx]
return result
return None
When run on the sampe input, it produces the following:
['super', 'bowl', [0, 2]]
['crystal', 'line', [1, 5]]
['bow', 'rain', [4, 0]]
['organic', 'ally', [2, 3]]
['main', 'line', [1, 5]]
['top', 'tree', [2, 0]]
Note: I left out any check for duplicate words, or for i and k being the same. It can be adapted to handle that, although the constraints about duplicate words, or a target that consists of the same word repeated, weren't entirely clear to me.
However, I did paste it into the code wars link from your post, and it said it passed all the tests.
Prob. you can speed up by using the set idea, like this:
I think it will work, did not do much testing though. Let me know if you find out it helps.
def compound_match(words, target):
S = set(words)
for i in range(1, len(target)):
x, y = target[:i], target[i:]
if x in S and y in S:
ix, iy = words.index(x), words.index(y)
ordered = [x, y] if ix < iy else [y, x]
return [*ordered, [ix, iy]]

Finding all the elements of the deepest list within a list in python without NUMPY

I am trying to code to retrieve all the list which is the "deepest" within a list. I managed to retrieve only one of the list which is the deepest and I am unable to print out all if they have the same "depth". I tried hardcoding it by it will not work if there is 2 or more values of the same depth. Can anyone share how can I modify my code to make it work?
Input: [1,2,[[3]],[[4]],[[5]], [6]]
Output: [3],[4],[5]
def get_deepest(L):
def get_dpst(L, maxdepth):
deepest_list = [L, maxdepth]
for e in L:
is_list = isinstance(e,list)
if is_list:
rList = get_dpst(e, maxdepth+1)
if rList[1] > deepest_list[1]:
deepest_list = rList
elif rList [1] == deepest_list[1]:
deepest_list[1] = rList[0]
return deepest_list
rList = get_dpst(L, 0)
return rList[0]
print (get_deepest(my_list))
How about a pair of functions like this?
unnest is a recursive function that walks a tree of lists, yielding tuples of any non-list value and its depth
get_deepest_values uses unnest and keeps track of the deepest depth it has returned, gathering only those values.
def unnest(lst, depth=0):
for atom in lst:
if isinstance(atom, list):
yield from unnest(atom, depth + 1)
else:
yield (atom, depth)
def get_deepest_values(inp):
deepest_depth = 0
deepest_depth_values = []
for value, depth in unnest(inp):
if depth > deepest_depth:
deepest_depth = depth
deepest_depth_values.clear()
if depth == deepest_depth:
deepest_depth_values.append(value)
return (deepest_depth, deepest_depth_values)
inp = [1, 2, [[3]], [[4]], [[5, "foo"]], [6]]
deepest_depth, deepest_values = get_deepest_values(inp)
print(f"{deepest_depth=} {deepest_values=}")
The output is
deepest_depth=2 deepest_values=[3, 4, 5, 'foo']

Split a list and create partitions(list) depending upon the unique set of values

deck = [1,2,3,4,4,3,2,1]
Output: True
Explanation: Possible partition [1,1],[2,2],[3,3],[4,4].
Input: deck = [1,1,1,2,2,2,3,3]
Output: False
Explanation: No possible partition.
The solution i tried was very , very basic but i couldn't solve further than this. P.S:I am starting my coding experience.
v=[1,2,3,4,4,3,2,1]
t=list()
flag=0
for i in v:
t.append(v.count(i))
for i in range(len(t)):
for j in range(len(t)):
if(t[i]==t[j]):
flag=0
else:
flag=1
if(flag==1):
print("NO")
else:
q=len(list(set(v)))
n = q
lists = [[] for _ in range(n)]
Try this:
How it works - It goes through all the list and stores the occurrence of each value. Then It makes of a set of it. Returns true if length of set is 1 i.e every number appears exactly the same number of times.
EDIT - set has a property that its element dont repeat. So say if the value of dikt is {1: 3, 2:3, 3:3} then the value of dikt.values is [3,3,3]. Making a set out of it will be (3).
IF the value of dikt was {1:3, 2:3, 3:2} then the set would be (3, 2)
def foo(x):
dikt = {}
for i in x:
if i in dikt.keys():
dikt[i]+=1
else:
dikt[i] = 1
return len(set(dikt.values())) == 1
You can use Counter here.
from collections import Counter
def partition(lst):
count=Counter(lst)
if len(set(count.values()))>1:
return 'No partition'
else:
return [[i]*n for i,n in count.items()]
deck = [1,2,3,4,4,3,2,1]
partition(deck)
#[[1, 1], [2, 2], [3, 3], [4, 4]]
deck=[1,1,1,2,2,2,3,3]
partition(deck)
#'No partition found'
If you just want the output to be True or False try this.
def partition(lst):
return len(set(Counter(lst).values()))==1

defining multiple variables to an empty list in a loop

I am trying to create and assign 10 variables, only differenciated by their index, all as empty lists within a for loop.
The ideal output would be to have agent_1 = [], agent_2 = [], agent_n = []
I know I could write this all out but thought I should be able to create a simple loop. The main issue is assigning the empty list over each iteration
for i in range(1,10):
agent_ + i = []
Why don't you use dict object with keys equal to agent_i.
dic = {}
for i in range(1,10):
dic["agent_" + str(i)] = []
// access the dic directly and iterating purpose also just iterate through the dictionary.
print dic["agent_1"]
# iteration over the dictionary
for key,value in dic.items():
print key,value
Here is the link to code snippet
This is a horrible idea. I will let the code speak for itself:
n = 10
for i in range(n):
globals()['agent_%d' % (i + 1)] = []
a = {}
for i in xrange(10):
ab = "{}_{}".format("agent", i)
a[ab] = []
print a
#OP
{'agent_0': [], 'agent_1': [], 'agent_2': [], 'agent_3': [], 'agent_4': [], 'agent_5': [], 'agent_6': [], 'agent_7': [], 'agent_8': [], 'agent_9': []}

How to find the number of lists in an input? (python)

def lists(A: list) -> int:
'''Return the total number of lists in A (including A itself).
Each element of A and any nested lists are either ints or other lists.
Example:
>>> lists([1, 2, 3])
1
>>> lists([[1], [2], [3]])
4
>>> lists([[[1, 2], [], 3]])
4
'''
Does anyone know how to do this?
All I have is
for i in range(0, len(A)):
if (isinstance(A[i], list)):
count=count+1
return(lists(A[i]))
else:
B=A[i:]
return(count)
Here is a 'dirty' but easy way to do it
def lists(l):
'''
Return the total number of lists in A (including A itself).
Each element of A and any nested lists are either ints or other lists.
'''
# convert the list to string and count the ['s
# each [ is the start of a list, so the number of ['s equals
# the number of lists
nr_of_lists = str(l).count('[')
# return the number of sublists
return nr_of_lists
No recursion required
Here's one way to write it:
def numlists(lst, num = 1):
for item in lst:
if isinstance(item, list):
num += numlists(item)
return num
Sample outputs:
print(numlists([1, 2, 3])) # 1
print(numlists([[1], [2], [3]])) # 4
print(numlists([[[1, 2], [], 3]])) # 4
print(numlists([[1,[2,3,[4,5,[6]]]],7,8,[9]])) # 6
You should do this with recursion:
def count_list(a):
result = 0
if isinstance(a, list):
result += 1
try:
for b in a:
result += count_list(b)
except:
pass
return result
def lists(a):
if not isinstance(a, list):
return 0
s = 1
for x in a:
s += lists(x)
return s
print lists([])
print lists([1,2,3])
print lists([[1], [2], [3]])
print lists([[[1, 2], [], 3]])
def lists(A):
return 1 + sum(lists(e) if isinstance(e, list) else 0 for e in A)

Categories