I am getting the error "Can't assign to Operator" - python

I am not sure why it is giving me this error... the part it says is giving me the error is the previousFirst + previousSecond = previousSecond. If you are wondering the goal is to print out as many fibonnaci numbers that the user wants to print out.
def fibbonaci():
fibbNumber = input("How many Fibonacci numbers should I print for you?")
fibbNumber = int(fibbNumber)
global counter
counter = 0
global previousFirst
previousFirst = 0
global previousSecond
previousSecond = 1
global previousSaved
previousSaved = 1
while (counter < fibbNumber):
previousSaved = previousSecond
previousFirst + previousSecond = previousSecond
print (previousFirst)
print (previousSecond)
counter += 1
fibbonaci()

1. You have the assignment turned around. The format is
<i>variable</i> = <i>new value</i>
so make that:
previous_second = previous second + previous_first
2. A more normal (non-Python) way to do this is:
next = current + previous
previous = current
current = next
where "next" is a temporary variable to compute the next in sequence.
3. Python has the ability to do multiple assignments, eliminating the need for temporary variables in this an many other cases. You can do all of the above with:
current, previous = current+previous, current
Both computations on the right are done before any assigning happens. The new value of current is the sum of the old values current+previous, and the new value of previous is the old value of current. Put that in a "for xyz in range(n):" loop, after initializing current=0, previous=1, and you get a loop that works for all non-negative n (including 0). The final value of current is your result.
4. Its "Fibonacci", not "Fibbonaci", and the guy's real name was Leonardo.

The left hand side of an assignment statement must be a valid name, not an expression. (The + is an operator, which means its included in expressions)
This is the line of the culprit,
previousFirst + previousSecond = previousSecond
Also, your code does have a little bit of formatting issues, namely the indentation is bad for the first function. Normally you can get away with this, but being Python, it's part of the language syntax. It also might just be how you copied and pasted it to Stack, take a look at the tips in How to Edit and How to Format bars, when editing your post.

The line should be
previousSecond = previousFirst + previousSecond
That's the problem
UPDATE:
There are some logic error to calculate fibbonaci number, the while part coule be:
while (counter < fibbNumber):
previousSaved = previousSecond
previousSecond = previousFirst + previousSecond
previousFirst = previousSaved
print (previousFirst)
print (previousSecond)
counter += 1

Related

Python if else statement in recursive function getting stuck:

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]

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.

Index Error in python

I am new to programming, and I am trying to write a Vigenère Encryption Cipher using python. The idea is very simple and so is my function, however in this line:
( if((BinKey[i] == 'b')or(BinKey[i+1] == 'b')): )
It seems that I have an index problem, and I can't figure out how to fix it.
The error message is:
IndexError: string index out of range
I tried to replace the i+1 index by another variable equal to i+1, since I thought that maybe python is re-incrementing the i, but it still won't work.
So my questions are:
How to fix the problem, and what have I done wrong?
Looking at my code, what can I learn to improve my programming skills?
I want to build a simple interface to my program (which will contain all the encryption ciphers), and all I came up with from Google is pyqt, but it just seems too much work for a very simple interface, so is there a simpler way to build an interface? (I am working with Eclipse Indigo and pydev with Python3.x)
The Vigenère Encryption function (which contains the line that causes the problem) is:
def Viegner_Encyption_Cipher(Key,String):
EncryptedMessage = ""
i = 0
j = 0
BinKey = Bin_It(Key)
BinString = Bin_It(String)
BinKeyLengh = len(BinKey)
BinStringLengh = len(BinString)
while ((BinKeyLengh > i) and (BinStringLengh > j)):
if((BinKey[i] == 'b')or(BinKey[i+1] == 'b')):
EncryptedMessage = EncryptedMessage + BinKey[i]
else:
EncryptedMessage = EncryptedMessage + Xor(BinKey[i],BinString[j])
i = i + 1
j = j + 1
if (i == BinKeyLengh):
i = i+j
return EncryptedMessage
This is the Bin_It function:
def Bin_It(String):
TheBin = ""
for Charactere in String:
TheBin = TheBin + bin(ord(Charactere))
return TheBin
And finally this is the Xor function:
def Xor(a,b):
xor = (int(a) and not int(b)) or (not int(a) and int(b))
if xor:
return chr(1)
else:
return chr(0)
In your while condition, you are ensuring that i < len(BinKey). This means that BinKey[i] will be valid, but BinKey[i+1] will not be valid at the last iteration of your loop, as you will then be accessing BinKey[len(BinKey)], which is one past the end of your string. Strings in python start at 0 and end at len-1 inclusive.
To avoid this, you can update your loop criterion to be
while BinKeyLength > i+1 and ...:
You can either change
while ((BinKeyLengh > i) and (BinStringLengh > j)):
to
while ((BinKeyLengh > i-1) and (BinStringLengh > j)):
or change
if((BinKey[i] == 'b')or(BinKey[i+1] == 'b')):
to
if((BinKey[i] == 'b') or (BinKeyLengh > i-1 and BinKey[i+1] == 'b')):
This will avoid trying to go into BinKey[BinKeyLength], which is out of scope.
Looking at my code, what can I learn to improve my programming skills?
Looping over an index is not idiomatic Python. It's better to loop over the elements of an iterator where possible. After all, that's usually what you're interested in: for i in... is often followed by my_list[i].
In this example, you should use the built-in function zip (or itertools.izip if your code is lazy, though this isn't necessary in Python 3), which gives you pairs of values from two or more iterators, and stops when the shortest one is exhausted.
for key_char, string_char in zip(BinKey, BinString): # takes values sequentially from
# BinKey and BinString
# and binds them to the names
# key_char and string_char
# do processing on key_char and string_char
If you really must do a while loop on an index, then put the test the other way around so it's clearer what you're doing. Compare
while len(BinKey) > i and len(BinString) > j: # this looks like len(BinKey) and
# len(BinString) are varying and you're
# comparing them to static variables i and j
with
while i < len(BinKey) and j < len(BinString): # this looks like you're varying i and j
# and comparing them to len(BinKey) and len(BinString)
Which better communicates the purpose of the loop?
Finally, the clause
if (i == BinKeyLengh):
i = i+j
doesn't seem to do anything. If i == BinKeyLength then the while loop will stop in a moment anyway.
I think your error, as Python interpreter says, is that you accessing invalid array positions.
In order to solve this, unlike it's being said, you should change your code to
while (BinKeyLength > i+2 and ...):
This is because in the last step, BinKeyLength = i+2, then i+1 is BinKeyLength-1, which is the last position of your array.
Concerning your programming skills I recommend you two things:
Be the code. Sounds mystic but the most important thing that is missing here is figuring out which indices numbers are used.
As it has been said by rubik, follow some style guides like PEP8 style guide.

Local variables in Python

I wrote this small program to print multiplication tables. I was understanding the local variables then I added two variables with same name in each function. but it is running and I am not getting any 2 variables with same name error. Please help me understand the idea here -
def printMultiples(n):
i = 1
i = 5
while i <= 10:
print n*i, '\t',
i = i + 1
print
def printMultTable():
i = 1
i = 10
while i <= 10:
printMultiples(i)
i = i + 1
The variable i gets defined as soon as the function is run, it does not wait until the lines
i = 1
i = 10
are run. When the code is compiled, Python looks at every variable that is assigned in the function, and creates definitions for any that aren't declared to be global or nonlocal.
Each i = line will just change the value, it doesn't cause it to be defined again.
Here's what's happening in your script:
i = 1
creates the variable i and assigns the value 1 to it
i = 5
replaces the value held in i with 5
while i <= 10:
starts your loop
print n*i, '\t',
The first iteration of the loop will print n * 5 and a tab character
i = i + 1
increments i by one
There aren't two variables with the same name, there's one variable that is being assigned to twice.
i = 1 # i is declared and assigned to 1
i = 5 # the same i is reassigned to 5
In python, symbols are just names for variables. They are do not allocate memory as they do for say, C/C++. So what you are doing is simply reassigning the values to 'i' in each case.
You're not actually creating two variables with the same name; your second i = is reassigning i to a new value, same as i = i + 1 is setting i to the value of i + 1.
There are more Pythonic ways to deal with looping a fixed number of times, by the way:
for i in range(1, 11):
printMultiples(i)
This will execute printMultiples for values starting in 1 and less than 11.

python look-and-say sequence improved

I would like to introduce look-and-say sequence at first. It goes like a = {1, 11, 21, 1211, 111221 ...
The system is it checks the previous digit and counts the numbers.
1 = one 1 (so = 11)
11 = two 1 (so = 21)
21 = one 2 one 1 (so = 1211)
As a rule of the sequence, no number can go beyond 3, so creating a translation table can fit in. But it is not semantic, I don't like it.
What I want is, a script which evaluates the given value and return a look-and-say-alike string.
However, to go beyond out limits, I want it to even evaluate chars, so it can return 1A2b41.
I have been trying to make it work for hours, the logic went bad and I am having a brainfreeze at the moment.
Here is the script that actually doesn't work(returns false results), but it can give you the idea, at least.
def seq(a):
k,last,result,a = 1,'','',str(a)
for i in range(len(a)):
if last==a[i]:k+=1
else:
result = result+str(k)+a[i]
k=1
last = a[i]
return result
You can use groupby, it's just what you want:
from itertools import groupby
def lookandsay(n):
return ''.join( str(len(list(g))) + k for k, g in groupby(n))
>>> lookandsay('1')
'11'
>>> lookandsay('1A2b41')
'111A121b1411'
>>> lookandsay(lookandsay('1A2b41'))
'311A1112111b111421'
groupby returns consecutive keys and groups from an iterable object. The key is a function computed for each element, or an identity function if not specified (as above). The group is an iterator - a new group is generated when the value of the key function changes. So, for instance, according to the documentation:
# [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
I can see two issues with your code:
The result is expanded by k and a[i] although the counter k does not count chars a[i] but chars last. Replace a[i] by last here (you may not want to add anything in the first round).
After the loop you have to add the last value of the counter together with the last character again (this was not yet done), i.e. add another result = result+str(k)+last after the loop.
In total it looks like
def seq(a):
a = str(a)
k,last,result = 1,a[0],''
for i in range(1,len(a)):
if last==a[i]:k+=1
else:
result = result+str(k)+last
k=1
last = a[i]
result = result+str(k)+last
return result
I think part of why you got stumped is your use of meaningless variable names. You described the problem quite well and called it by name, but didn't even use that name for your function.
If you think of the string you start with as "look", and the one you end up with as "say", that is a start. result is probably fine but a and k have confused you. last is, I think, misleading, because it can mean either previous or final.
Also, Python's for is really foreach for a reason -- you're taking each character in the "look" one at a time, so do it explicitly in the loop.
def looksay(look):
look = str(look)
prev, count, say = look[0], 1, ''
for char in look[1:]:
if char == prev:
count += 1
continue
say += str(count) + prev
prev = char
count = 1
return say + str(count) + prev
The spacing is less important, but Python does have a standard coding style, and it does help readability to use it. The less mental time you have to spend parsing your code, the more focus you have for the problem.

Categories

Resources