AND and OR are switched? - python

I want to create two random sets and compare them to two other sets.
The programm should stop when both sets are the same as the other two sets.
This is a boiled down version of the code i'm having trouble with:
import random
random.seed()
a = set()
b = set()
c = set()
d = set()
for i in range(3):
a.add(random.randint(1,10))
b.add(random.randint(1,10))
while a!=c and b!=d:
c.clear()
d.clear()
for i in range(3):
c.add(random.randint(1,10))
d.add(random.randint(1,10))
print(a,b)
print(c,d)
The exact line with my problem:
while a!=c and b!=d:
With "and" the loop already stops when just one pair of sets are the same.
When i switch the "and" for "or" it does exacly what i want, i just don't understand why?
Can somebody please explane.

The condition holds when both a is not c and b is not d. As soon as one pair is equal then the and fails and the loop is broken.
As you have identified you could use an or which will work, but it may be more clear to use:
while not (a == c and b == d):
...
which works exactly how you would say it!

Think about it. You have the condition:
a != c and b != d
What exactly is this condition telling Python? Well, we can see it uses the and operator. The and operator will only return True, if both of its conditions are true. From this, we can see that the above condition will only return true if both the a set is not equal to the c set and the b set is not equal to the d set.
So what would happen when one pair of sets becomes equal? The above condition will fail. Since one of the comparisons between two sets would return False, rather than True, and will also return false, since both of its conditions are not true.
What you actually want is this:
not (a == c and b == d)
I'll leave it as an exercise up to you to figure why the above condition works, whereas a != c and b != d does not.

While loops repeat when the statement is True, in this case when either a != c orb != devaluates to False, so will the while loop argument.
You want to alter the logic, change:
a != c and b !=d
to:
not (a == c and b == d)
or:
a != c or b != d
This will achieve what you are after.

You might try:
while not (a == c and b == d):
#code

Related

Which one will run faster

lst is a very large list of integers
a,b and c are numbers
code 1
if a in lst or b in lst or c in lst:
print("found in lst")
code 2
if a in lst:
print("found in lst")
elif b in lst:
print("found in lst")
elif c in lst:
print("found in lst")
is there any speed difference in code 1 and code 2
Strictly speaking, both of your code samples will run equally since the or operator supports short-cuiting. That means that Python will not evaluate subsequent conditions unless the one before it evaluated to False. For example, if we have A or B or C, unless both A and B are False, Python will not evaluate C.
The same thing occurs with your if statements: C will only be evaluated if both A and B are False.
However, on large lists, you shouldn't be doing any sort of query like this. If don't need to index the elements of the list, a hash table (Dictionary) is almost always better since you'll get O(1) lookup time.

Difference between defining multiple variable at a time and individually

I am a newbie in Python and I'm trying to learn Python through self-learning. I was trying to build Fibonacci series using a while loop. Here is my code, which doesn't return the desired result. Could anyone explain the problem?
a = 0
b = 1
while b<100:
print(b)
a = b
b = a + b
If we define a, b simultaneously like a, b = b, a+b, this works perfectly. Why is this happening? I don't understand because in both cases I am defining a and b the same way.
This is because programming languages like Python, and many others, execute the statements you write in the order you write them.
This means that by the time you execute b = a + b, the value of a has already changed in the previous line.
An easy way to solve this would be using a third variable to store the results temporarily.
a = 0
b = 1
c = 1
while c < 100:
print(c)
c = a + b
a = b
b = c
You are making one small mistake.
When you do a = b, you are changing the value of a. After this, when you do b=a+b, it is actually equivalent to b = b+b => b=2b.
To avoid this, use a temporary variable temp and storethe value of a in it. Then change the value of a using a = b. Then do, a = a+b.
Following is the code:
a=0
b=1
while b<100:
print(b)
temp = a
a = b
b = temp+b
When you do a, b = b, a+b, the previous value of a is used for calculating the new b, we have don a similar thing above by storing the previous value of a in temp
Operator "comma" (,) in Python is used to create a tuple, and it is allowed to omit the parentheses that surround a tuple. The expression a, b = b, a+b is actually an assignment of one tuple to another:
(a, b) = (b, a + b)
This statement is executed by evaluating the tuple constructor on the right-hand side (b, a + b). At this point, a new anonymous tuple (let's call it c) is created and the original values of a and b are not needed anymore. The tuple is then assigned elementwise to the tuple on the left-hand side. The new value of a becomes c[0] (that is, former b) and the new value of b becomes c[1] (that is, former a+b).
Your code is not working because you are changing the value of a before evaluating b. In the Fibonacci series, you want the previous value of a and b. You can use list as above or can introduce another variable to store values.
while True:
temp = a + b
if temp >100:
break
print(temp)
a = b
b = temp
For reference, here is a simple implementation using list:
lst = [0, 1]
while True:
temp = lst[-1]+lst[-2]
if temp>100:
break
lst.append(temp)
print(lst)

Understanding recursion with the help of Iteration

def unZip(master3):
c = len(master3)
sub1=''
sub2=''
for i in range(0,c,2):
sub1+=master3[i]
sub2+=master3[i+1]
print(sub1,",",sub2)
basically I have written this code that separates alternative char from string and shows them separately,
I have been trying to convert or comprehend this with recursion but I have been failing lately.
Here is my try, can someone tell me how should I approach it?
def unzip(a):
storage1=''
storage2=''
storage3=''
storage4=''
if len(a)==0:
return 0
else:
if len(a)>=1:
storage1=a[0::2]
storage2=a[1::2]
storage3+=storage1
storage4+=storage2
print(storage3,storage4)
return unzip(a[0]+a[1:])
instead of using slicing to determine your strings you should be taking one character at a time off your string and then recalling your recursive function like so
def unzip(s, a, b='', c=''):
if len(a) == 0:
return b + ', ' + c
if s%2 == 0:
b += a[0]
else:
c += a[0]
return unzip(s+1, a[1:], b, c)
print unzip(0, 'HelloWorld')
Hlool, elWrd
What that does is it starts with the string a and alternates between adding to b or c with the variable s depending on whether it is even or odd. Add the first letter of a to either b or c and then remove that letter from a. Then call the function again but with s+1. If the length of a is zero then return b and c and then print your result
To get the same results with what you have you could simplify yours down to
a = 'HelloWorld'
storage1=a[0::2]
storage2=a[1::2]
print(storage1,storage2)
('Hlool', 'elWrd')
The slicing takes care of getting every other letter in a and then you can just print that. The way you have it set up now it will just keep passing a and become an infinite loop since the size of a will never change.

Sudoku Solver in Python

So, I'm trying to create a function that will take in a list of lists, each consisting of 9 integers numbered 1 through 9, and return a Boolean if it is a valid solution to for a Sudoku. Right now, I've managed to solve part of the problem with checking for rows and columns, but I am stuck on the implementation of checking the three by three boxes. Here's my code so far.
alist = [1,2,3,4,5,6,7,8,9]
def checkSudoku(grid):
a = grid
b = grid
c = grid
d = False
e = False
f = False
newlist = []
for i in a:
i.sort()
if i == alist:
d = True
else:
d = False
break
for j in range(9):
for k in b:
newlist.append(k)
newlist.sort()
if i == alist:
e = True
newlist = []
else:
e = False
break
if d == True and e == True:
return True
else:
return False
Basically, My was to test all three factors necessary for it to be true, then return True if all three are True, else return false. Any help?
Not sure if this is your problem, but there is a pretty obvious problem with this code:
a = grid
b = grid
c = grid
It looks like you think this creates 3 copies of the grid, but it doesn't. It creates three different references to the same object. This means that your i.sort() on a will affect the logic on b later on.
What you should do is actually copy the object. That it's a nested list makes this a little bit tricky, but an easy way to do this is with the library function deepcopy:
a = copy.deepcopy(grid)
b = copy.deepcopy(grid)
c = copy.deepcopy(grid)
One major problem with how your code works is that you're using list.sort, meaning that grid itself changes. Consider using sorted, which works with all iterables and returns a copy instead:
for row in grid:
if sorted(row) == alist:
# now you know that the row contains all ints 1-9.
This also means you don't need to try to manually duplicate grid. If you need help duplicating a list (especially a multidimensional list) check out this question.
As for checking each 3x3 box: iterate through each of the 9 "top left" corners first like so:
for x in (0,3,6):
for y in (0,3,6):
subgrid = grid[y][x:x+3] + grid[y+1][x:x+3] + grid[y+2][x:x+3]
if sorted(subgrid) == alist:
# do your thing
For help with list slicing check this out.

Python: yield vs print in a loop

I am a beginner in Python currently working through Project Euler's problems (here for those who have not heard about it). I have solved this particular problem, however it leaves me with some questions:
def fibsum():
result = []
a, b = 0, 1
while True:
a, b = b, a + b
print b
if b < 4000000 and b % 2 == 0:
result.append(b)
if b > 4000000:
break
print sum(result)
fibsum()
When I run this using PowerShell, first it prints out all the numbers I need (although, it goes one over), and then finally prints the sum:
1
2
3
5
8
...
3524578
5702887 <-- This is over 4,000,000. Why is this here?
4613732 <-- This is the answer.
Is there any way that I can have the loop stop iterating before it reaches the first value over 4,000,000?
For the sake of saving space, is there any way that I can have all of the values print out in a list format ([ , , , ]), if I decide to use print?
When I replace print in the original code with yield or return(for the variable b), the program won't print anything out, despite there still being
print sum(result)
at the end of the function.
Is there any way that I can make this easier, without having to define result and appending values to it? When the values are returned in a format similar to the actual outcome, sum() doesn't seem to work.
1.Just move the 2nd condition before you print b:
while True:
a, b = b, a + b
if b > 4000000:
break
print b
if b < 4000000 and b % 2 == 0:
result.append(b)
2.Don't print b in loop, rather print the result once you break out.
3.Well, as for return, it's pretty clear that you return out of function, so the following code in function is not executed and hence your list is not populated.
yield is used to create a generator function, where every execution of your function returns the next value. So, you would have to call your function multiple times, thus adding the yielded value to a list defined outside. And when there is nothing to return, your function will break.
To understand yield keyword usage more clearly, take a look at this post: What does the "yield" keyword do in Python?
You can edit your code to use yield like this (haven't tested it):
def fibsum():
a, b = 0, 1
while True:
a, b = b, a + b
if b > 4000000:
break
yield b
result = []
for val in fibsum():
if val < 4000000 and val % 2 == 0:
result.append(val)
print sum(result)
So, in for loop, each call to fibsum() function generates the next value, which you add in the list, based on the condition.

Categories