Python if else statement in recursive function getting stuck: - python

so I'm making a function that takes a string and the number of gaps that i need to insert in it, and i want it to output a list of strings of all possible combinations where those gaps are inserted.
I have written a recursive function for that, but the stopping if condition is not being activated no matter what i do. Even printing the expression in itself gives the proper answer but the if condition doesn't follow that expression.
I hope you guys can help with this, even though it's probably a very simple error on my part, i just cant seem to find it.
Thanks in advance.
f = open("bonusoutput.txt",'w')
sequence1 = raw_input("Sequence 1:")
sequence2 = raw_input("Sequence 2:")
l1 = int(len(sequence1))
l2 = int(len(sequence2))
#---------------Function that has problem-----------------------------
def insertBlanks(numGap,string):
if (numGap <= 0):
return [string]
else:
outSeq = []
for cp in range(0,len(string)+1):
outSeq.append(string[:cp] + "_" + string[cp:])
for seq in outSeq:
outSeq += (insertBlanks(numGap-1,seq))
return outSeq
#-------------------------------------------------------------
nGap1 = l2
nGap2 = l1
outSeq2 = insertBlanks(nGap1,sequence2)
f.write(str(outSeq2))
print outSeq2

While looping for seq in outSeq, you are appending items to outSeq. You're returning a list of at least one item each time (base case returns [string] therefore you will add at least 1 item for each item you visit, so you have an infinite loop. Consider adding your output to a new list (or using a list comprehension, like [insertBlanks(numGap - 1, seq) for seq in outSeq]

Related

Changing(replacing) a value in a list without using range(len())

My purpose is to change the value of the elements 3 and 4 to 4 and 3 and I have written a function that takes a list, first number and second number as arguments:
def pre9(the_list, value_to_replace, the_replacing_value):
for i in the_list:
if i == value_to_replace:
value_to_replace = the_replacing_value
elif i == the_replacing_value:
the_replacing_value = value_to_replace
return the_list
I then assign a test-case to a variabel and then print it:
test_pre9 = pre9([1,2,3,4,5,7,3,4], 3, 4)
print(test_pre9)
The result is: [1,2,3,4,5,7,3,4]
I expect it to be: [1,2,4,3,5,7,4,3]
I have for a long time ago written a code that accoplishes this task:
def uppgift_9():
the_list = [3,5,8,9,4,5]
for i in range(len(the_list)-1):
temp = the_list[3]
the_list[3] = the_list[4]
the_list[4] = temp
return the_list
But I've read in many places that using range(len()) is not "pythonic" and it is possible to do anything without using it.
Does anyone know why my code fails?
You don't actually change the item in the list, try this:
def pre9(the_list, value_to_replace, the_replacing_value):
for i, value in enumerate(the_list):
if value == value_to_replace:
the_list[i] = the_replacing_value
elif value == the_replacing_value:
the_list[i] = value_to_replace
return the_list
Now the list will have the actually items changed to what you wanted it to be. Enumerate() returns the index and value of an item in a list, it's very handy! And indeed, the range(len()) is not very pythonic and is usually used when people jump from other languages like Java, C# etc. Using enumerate() is the correct 'pythonic' way of achieving this.

sub-sum from a list without loops

So i'm studying recursion and have to write some codes using no loops
For a part of my code I want to check if I can sum up a subset of a list to a specific number, and if so return the indexes of those numbers on the list.
For example, if the list is [5,40,20,20,20] and i send it with the number 60, i want my output to be [1,2] since 40+20=60.
In case I can't get to the number, the output should be an empty list.
I started with
def find_sum(num,lst,i,sub_lst_sum,index_lst):
if num == sub_lst_sum:
return index_lst
if i == len(sum): ## finished going over the list without getting to the sum
return []
if sub_lst_sum+lst[i] > num:
return find_sum(num,lst,i+1,sub_lst_sum,index_lst)
return ?..
index_lst = find_sum(60,[5,40,20,20,20],0,0,[])
num is the number i want to sum up to,
lst is the list of numbers
the last return should go over both the option that I count the current number in the list and not counting it.. (otherwise in the example it will take the five and there will be no solution).
I'm not sure how to do this..
Here's a hint. Perhaps the simplest way to go about it is to consider the following inductive reasoning to guide your recursion.
If
index_list = find_sum(num,lst,i+1)
Then
index_list = find_sum(num,lst,i)
That is, if a list of indices can be use to construct a sum num using elements from position i+1 onwards, then it is also a solution when using elements from position i onwards. That much should be clear. The second piece of inductive reasoning is,
If
index_list = find_sum(num-lst[i],lst,i+1)
Then
[i]+index_list = find_sum(num,lst,i)
That is, if a list of indices can be used to return a sum num-lst[i] using elements from position i+1 onwards, then you can use it to build a list of indices whose respective elements sum is num by appending i.
These two bits of inductive reasoning can be translated into two recursive calls to solve the problem. Also the first one I wrote should be used for the second recursive call and not the first (question: why?).
Also you might want to rethink using empty list for the base case where there is no solution. That can work, but your returning as a solution a list that is not a solution. In python I think None would be a the standard idiomatic choice (but you might want to double check that with someone more well-versed in python than me).
Fill in the blanks
def find_sum(num,lst,i):
if num == 0 :
return []
elif i == len(lst) :
return None
else :
ixs = find_sum(???,lst,i+1)
if ixs != None :
return ???
else :
return find_sum(???,lst,i+1)

Function to reverse text characters

I am trying to make a reverse function which takes an input (text) and outputs the reversed version. So "Polar" would print raloP.
def reverse(text):
list = []
text = str(text)
x = len(text) - 1
list.append("T" * x)
for i in text:
list.insert(x, i)
x -= 1
print "".join(list)
reverse("Something")
As others have mentioned, Python already provides a couple of ways to reverse a string. The simple way is to use extended slicing: s[::-1] creates a reversed version of string s. Another way is to use the reversed function: ''.join(reversed(s)). But I guess it can be instructive to try implementing it for yourself.
There are several problems with your code.
Firstly,
list = []
You shouldn't use list as a variable name because that shadows the built-in list type. It won't hurt here, but it makes the code confusing, and if you did try to use list() later on in the function it would raise an exception with a cryptic error message.
text = str(text)
is redundant. text is already a string. str(text) returns the original string object, so it doesn't hurt anything, but it's still pointless.
x = len(text) - 1
list.append("T" * x)
You have an off-by-one error here. You really want to fill the list with as many items as are in the original string, this is short by one. Also, this code appends the string as a single item to the list, not as x separate items of one char each.
list.insert(x, i)
The .insert method inserts new items into a list, the subsequent items after the insertion point get moved up to make room. We don't want that, we just want to overwrite the current item at the x position, and we can do that by indexing.
When your code doesn't behave the way you expect it to, it's a Good Idea to add print statements at strategic places to make sure that variables have the value that they're supposed to have. That makes it much easier to find where things are going wrong.
Anyway, here's a repaired version of your code.
def reverse(text):
lst = []
x = len(text)
lst.extend("T" * x)
for i in text:
x -= 1
lst[x] = i
print "".join(lst)
reverse("Something")
output
gnihtemoS
Here's an alternative approach, showing how to do it with .insert:
def reverse(text):
lst = []
for i in text:
lst.insert(0, i)
print "".join(lst)
Finally, instead of using a list we could use string concatenation. However, this approach is less efficient, especially with huge strings, but in modern versions of Python it's not as inefficient as it once was, as the str type has been optimised to handle this fairly common operation.
def reverse(text):
s = ''
for i in text:
s = i + s
print s
BTW, you really should be learning Python 3, Python 2 reaches its official End Of Life in 2020.
You can try :
def reverse(text):
return text[::-1]
print(reverse("Something")) # python 3
print reverse("Something") # python 2
Easier way to do so:
def reverse(text):
rev = ""
i = len(text) - 1
while i > -1:
rev += text[i]
i = i - 1
return rev
print(reverse("Something"))
result: gnihtemoS
You could simply do
print "something"[::-1]

my python code is not working.....i want to find if the entered list contains duplicate items

I want to use this function to find duplicate items in my list, but this code is not working:
p = "enter a list\n"
t = raw_input(p)
def has_duplicate(t):
o = sorted(t)
i = 0
while i < len(o):
if o[i] == o[i + 1]:
print "the list has duplicates"
elif o[i] != o[i+1]:
i += 1
if i >= len(o):
print "the list has no duplicate"
It gives me an error saying has_duplicates not defined.
As #mgilson commented, your issue is you are calling the function incorrectly (has_duplicates vs has_duplicate) however...
The most straight forward way to do this is using a set and comparing len.
def has_duplicates(t):
return len(set(t)) != len(t)
If you take an iterable and wrap it in a set you will end up with only unique items. If the length of the set is the same as your original iterable then you have no duplicates. If the length is different (will always be equal to or smaller) then you have duplicates which were removed when converting to a set type.
First thing is you do list_name.sort().
Other easy way to find duplicates is
len(your_list)!=len(set(your_list))
you might be calling function has_duplicates but you have defined has_duplicate function.
try to call has_duplicate

Recursive fibonnaci-like cumulative [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
calling func. change the input
I have to write a recursive function that takes a list of numbers in input and returns a list of numbers in output, for example called like this:
rec_cumsum([2,2,2,3])
the output should be like:
[2,4,6,9]
Thing is, I cant seem to get my head around for this to work.. this got me questioning my whole recursive thinking..
what i have so far is :
newlist = []
k = 1
def rec_cumsum(numbers):
if len(numbers) == 0:
return 0
if len(numbers) > 1 and len(numbers) != (k+1):
newlist[k+1] == newlist[k+1] + newlist[k]
k = k+1
return rec_cumsum(numbers)
but I'm getting errors which doesn't really make any sense to me.
the recursion should always take the number, and add it to the one before it, than save it in the next location of the list.. (new one or original one)
I would write it like this:
def cumulative_sum(lst,prev=0):
if not lst:
return []
else:
elem = prev+lst[0]
return [elem] + cumulative_sum(lst[1:],prev=elem)
print cumulative_sum([2,2,2,3])
Now to look at your code (note I didn't actually work through the logic to decide whether it would give the correct result, the following only addresses possible exceptions that your code is probably throwing):
You're probably getting an IndexError because of this line:
newlist[k+1] == newlist[k+1] + newlist[k]
You're assigning to a list position which doesn't exist yet. You could pre-allocate your list:
newlist = [0]*len(lst)
but even if you fix that, you'll get a recursion error with your code because of the line:
k = k + 1
The problem here is that on the left hand side, k is local whereas on the right hand side, k is global. So essentially each time you run this, you're getting the local k == 2 and not touching the global one. If you really want to modify the global k, you need to declare k as global via global k. Of course, then you need to reset k every time you're going to use this function which would be a somewhat strange API.

Categories

Resources