Is it possible to stop this recursive function? - python

I wanted to implement the code by using recursive function without for loop or while loop.
And I wanted to implement function called go_through() and take two parameters as a list(list1) and an integer(letters) so that if the element of each length of string has bigger or equal to integer, I replace it using the other function called replace_it()
def go_through(list1, letters):
get_list = list1[:]
num =len(list1)
index = 0
if index != num:
if len(get_list[0]) >= letters:
get_list += replace_it(get_list[0])
index += 1
print(get_list, 'True')
return go_through(get_list[1:], letters)
else:
get_list += [get_list[0]]
index += 1
print(get_list, 'False')
return go_through(get_list[1:], letters)
else:
print(get_list)
def replace_it(string):
if string == 'pineapple':
return ['peach', 'and', 'pear']
if string== 'delicious':
return ['really', 'gross']
go_through(['pineapple','is','delicious','I', 'want', 'it'],7)
should be looking like
peach and pear is really gross I want it
So I have a problem for this codes
It doesn't allow me to stop print as what I want to print is one line
The result would be looking like the picture I attached
But I want to stop where I highlighted and return it as it is the same output what I wrote above.
How can I fix this problem?

The list is not reducing at any point. get_list += [get_list[0]] in the else block keeps the list the same size when followed by return go_through(get_list[1:], letters), while get_list += replace_it(get_list[0]) in the if will always extend the list.
Maybe you meant something like
else:
# this isn't needed
# get_list += [get_list[0]]
return go_through(get_list[1:], letters)
Also, it seems that you're getting the list order mixed up in the first bit maybe.
if len(get_list[0]) >= letters:
# this is adding the new list at the end, not replacing the word
# get_list += replace_it(get_list[0])
# you can send the shortened list to the function again,
# and stick the replacement words at the start
return replace_it(get_list[0]) + go_through(get_list[1:], letters)

Related

What is wrong with this function, and how can I make it work?

def func(sentence):
sumn = sentence.split()
if len(sumn) >= 5:
return sumn
plswork = func("me name goooose")
print(plswork)
When I use this if statement with a list outside of a function, it returns the element in the list that is 5 characters or greater. When applied to this function, it fails.
Essentially I am trying to create a function that identifies elements of a certain length, reverses these specific elements, and prints the new list. Though, I have not yet gotten to the reverse portion of my function yet.
This is what you want:
def func(sentence):
sumn = sentence.split()
for i in sumn:
if len(i) >= 5:
print(i)
func("me name goooose")

How to index list when there is 2 of the same char

I have been trying to make the even letters in a string become upper-cased and the odd letters to become lower-cased with a function, like so:
def myfunc('apple'):
#OUTPUTS: 'ApPlE'
This is what I made:
def myfunc(mystring):
stringList = [letter for letter in mystring]
for letter in stringList[1::2]:
stringList[stringList.index(letter)] = letter.lower()
for letter in stringList[::2]:
stringList[stringList.index(letter)] = letter.upper()
return ''.join(stringList)
I believe that, when I use words like 'apple' where there is two identical letters, the index() function can only manage to give me the index of the first 'p', if my word is apple.
It returns:
'APplE'
How could I fix this?
By iterating over the indices of the string, using the built-in function enumerate, together with the characters of the string (strings are also iterable):
def myfunc(mystring):
out = []
for i, c in enumerate(mystring):
if i % 2 == 0:
out.append(c.upper())
else:
out.append(c.lower())
return "".join(out)
Example output:
>>> myfunc('apple')
'ApPlE'
This is also a lot more efficient, since it only iterates over the string once. Your code iterates many times (each stringList.index call does a linear search for the letter).
If you want to make it a bit harder to read but re-use a bit more of what you already have, you can also use this, but I would not recommend it (as it iterates three times over the string, once to build the list and then twice to replace the characters):
def myfunc(mystring):
stringList = list(mystring)
stringList[::2] = map(str.upper, stringList[::2])
stringList[1::2] = map(str.lower, stringList[1::2])
return "".join(stringList)
The method list.index returns the index of the first occurence, making it unfit for recovering the index of the current element. Instead, you should use enumerate, this will allow you to get the expected result with a single list-comprehension.
def myFunc(s):
return ''.join([c.lower() if i % 2 else c.upper() for i, c in enumerate(s)])
print(myFunc('apple')) # ApPlE

Passing modified list to each node of binary tree

I am writing a function to grow a tree:
def collect_append(collect,split):
collect.append(split)
return collect
def tree(string,passwords,collect): #collect is a list and passwords is also a list
matching_list = []
match = 0
if len(string)==0:
print(collect)
return 0
for j in passwords:
for i in range(min(len(j),len(string))):
if string[i]!=j[i]:
break
else :
matching_list.append(j)
match = match + 1
if match == 0:
return 1
else:
for split in matching_list:
x =tree(string.strip(split),passwords,collect_append(collect,split))
return x
My question is, for each split in matching_list(say two), I want to add different strings to the existing list at that point (i.e. I want two versions of list).
In this case the collect_append function I use is modifying the list in first iteration of the for loop and using the same for further iterations. What I want is to just modify the collect list just for the parameter and without permanently changing it. Is there a way to do this?
I see two serious errors in your code. First, this else clause is never executed:
for j in passwords:
for i in range(...):
if ...:
break
else:
...
Since the break is in the inner for loop, the outer for loop is never exited via a break so the else is never taken. Second, this doesn't do what you want:
string.strip(split)
You're trying to remove split from the beginning of string but you're removing all the letters in split from both ends of string, bruising it badly. Here's one way to do it correctly:
string[len(split):]
I'm going to go out on a limb, and rewrite your code to do what I think you want it to do:
def tree(string, passwords, collect):
length = len(string)
if length == 0:
return False
matching_list = []
for j in passwords:
i = min(len(j), length)
if string[:i] == j[:i]:
matching_list.append(j)
if not matching_list:
return False
result = False
for split in matching_list:
local_collection = list([split])
if split == string or tree(string[len(split):], passwords, local_collection):
collect.append(local_collection)
result = True
return result
collection = []
print(tree('dogcatcher', ['cat', 'catch', 'cher', 'dog', 'dogcat', 'dogcatcher', 'er'], collection))
print(collection)
OUTPUT
% python3 test.py
True
[['dog', ['cat', ['cher']], ['catch', ['er']]], ['dogcat', ['cher']], ['dogcatcher']]
%
Giving you a tree of all the ways to assemble string from the words in passwords.

Intro to Python - Lists questions

we've started doing Lists in our class and I'm a bit confused thus coming here since previous questions/answers have helped me in the past.
The first question was to sum up all negative numbers in a list, I think I got it right but just want to double check.
import random
def sumNegative(lst):
sum = 0
for e in lst:
if e < 0:
sum = sum + e
return sum
lst = []
for i in range(100):
lst.append(random.randrange(-1000, 1000))
print(sumNegative(lst))
For the 2nd question, I'm a bit stuck on how to write it. The question was:
Count how many words occur in a list up to and including the first occurrence of the word “sap”. I'm assuming it's a random list but wasn't given much info so just going off that.
I know the ending would be similar but no idea how the initial part would be since it's string opposed to numbers.
I wrote a code for a in-class problem which was to count how many odd numbers are on a list(It was random list here, so assuming it's random for that question as well) and got:
import random
def countOdd(lst):
odd = 0
for e in lst:
if e % 2 = 0:
odd = odd + 1
return odd
lst = []
for i in range(100):
lst.append(random.randint(0, 1000))
print(countOdd(lst))
How exactly would I change this to fit the criteria for the 2nd question? I'm just confused on that part. Thanks.
The code to sum -ve numbers looks fine! I might suggest testing it on a list that you can manually check, such as:
print(sumNegative([1, -1, -2]))
The same logic would apply to your random list.
A note about your countOdd function, it appears that you are missing an = (== checks for equality, = is for assignment) and the code seems to count even numbers, not odd. The code should be:
def countOdd(lst):
odd = 0
for e in lst:
if e%2 == 1: # Odd%2 == 1
odd = odd + 1
return odd
As for your second question, you can use a very similar function:
def countWordsBeforeSap(inputList):
numWords = 0
for word in inputList:
if word.lower() != "sap":
numWords = numWords + 1
else:
return numWords
inputList = ["trees", "produce", "sap"]
print(countWordsBeforeSap(inputList))
To explain the above, the countWordsBeforeSap function:
Starts iterating through the words.
If the word is anything other than "sap" it increments the counter and continues
If the word IS "sap" then it returns early from the function
The function could be more general by passing in the word that you wanted to check for:
def countWordsBefore(inputList, wordToCheckFor):
numWords = 0
for word in inputList:
if word.lower() != wordToCheckFor:
numWords = numWords + 1
else:
return numWords
inputList = ["trees", "produce", "sap"]
print(countWordsBeforeSap(inputList, "sap"))
If the words that you are checking come from a single string then you would initially need to split the string into individual words like so:
inputString = "Trees produce sap"
inputList = inputString.split(" ")
Which splits the initial string into words that are separated by spaces.
Hope this helps!
Tom
def count_words(lst, end="sap"):
"""Note that I added an extra input parameter.
This input parameter has a default value of "sap" which is the actual question.
However you can change this input parameter to any other word if you want to by
just doing "count_words(lst, "another_word".
"""
words = []
# First we need to loop through each item in the list.
for item in lst:
# We append the item to our "words" list first thing in this loop,
# as this will make sure we will count up to and INCLUDING.
words.append(item)
# Now check if we have reached the 'end' word.
if item == end:
# Break out of the loop prematurely, as we have reached the end.
break
# Our 'words' list now has all the words up to and including the 'end' variable.
# 'len' will return how many items there are in the list.
return len(words)
lst = ["something", "another", "woo", "sap", "this_wont_be_counted"]
print(count_words(lst))
Hope this helps you understand lists better!
You can make effective use of list/generator comprehensions. Below are fast and memory efficient.
1. Sum of negatives:
print(sum( i<0 for i in lst))
2. Count of words before sap: Like you sample list, it assumes no numbers are there in list.
print(lst.index('sap'))
If it's a random list. Filter strings. Find Index for sap
l = ['a','b',1,2,'sap',3,'d']
l = filter(lambda x: type(x)==str, l)
print(l.index('sap'))
3. Count of odd numbers:
print(sum(i%2 != 0 for i in lst))

Reverse String Function in Python (Primitive Steps)

I tried coming up with a way to do a reverse string function without using the [ : : -1] method. I'm new to coding and am trying to only use the "primitive" steps. Below is my function and specifications. I was wondering if this is an efficient way to write the function. I appreciate any help. Thanks!
def reverse(word):
x = -2 #word in reversed order counter
y = 1 #starts counter to end "while" statement below
reversed = word[-1] #starts the reversed-word at last letter of word
while len(word) > y: #ending parameter for when all letters run through loop
reversed += word[x] #adds letters to reversed word starting at word[-2]
x -= 1 #moves position in word 1 to the left
y += 1 #increases the counter by 1
return reversed
Adding to a string is slow. It's probably best to make a list of the characters in the string in reversed order, then use the string method join on it.
Example code (fairly close to your original function):
def reverse(word):
index = len(word)-1
result = []
while index >= 0:
result.append(word[index])
index -= 1
return "".join(result)
Better example code:
def reverse(word):
word_list = []
for i in range(len(word)-1, -1, -1):
word_list.append(word[i])
return "".join(word_list)
def reverse(word):
return "".join(word[i] for i in range(len(word)-1, -1, -1))
Even better code:
def reverse(word):
return "".join(reversed("abc"))
or
def reverse(word):
return word[::-1]
But of course, the most efficient code is that with the fewest characters. [/sarcasm]
reverse =lambda s:s and s[-1]+reverse(s[:-1])or s
Yet another solution (I think it is likely to be slow):
def reverse(word):
word_list = []
for i in word:
word_list.insert(0, word[i])
return "".join(word_list)
I like the functional-ish recursive way, but this may not be the best for Python:
def rev(w):
return rev(w[1:]) + w[0] if w else w
You'd want to include type checking or something, or possibly extend this a bit to handle any iterable and not just a string.

Categories