"If" statement seems to behave erratically in my code - python-3.x

I'm just learning Python and decided to try a bit of code resembling the old Milton Bradley 'Simon' game. Which is a memory sequence game with four colored buttons. I'm using numbers 1-4. I'm stuck at the moment where the 'if' statement decides if the my answer is correct or not. I've run this through quite a few time and I can't figure out why it jumps to the you LOSE when the answer is correct. For example:
Start game?: Y
[4, 1, 4, 2, 4]
Pick: 4
Pick: 1
Pick: 4
Pick: 2
you LOSE
Pick: 4
Process finished with exit code 0
import random
START=input('Start game?: ')
length_of_game=5
Simon_List=[]
if START == 'Y':
i=0
while i<length_of_game:
i += 1
number=random.randint(1,4)
Simon_List.append (number)
print (Simon_List)
for x in Simon_List:
#print (x)
Your_guess=int(input('Pick: '))
if Your_guess == Simon_List[x]:
break
print('you LOSE')

Simon_List[x] isn't doing what you think its doing, its using the value at each element in the list and then you're using that to look up a value in the list at that given index (so the first iteration would be looking up the value at index 4 in the example), you just need to compare vs x
if Your_guess == x:

Related

How to extract numbers with repeating digits within a range

I need to identify the count of numbers with non-repeating digits in the range of two numbers.
Suppose n1=11 and n2=15.
There is the number 11, which has repeated digits, but 12, 13, 14 and 15 have no repeated digits. So, the output is 4.
Wrote this code:
n1=int(input())
n2=int(input())
count=0
for i in range(n1,n2+1):
lst=[]
x=i
while (n1>0):
a=x%10
lst.append(a)
x=x//10
for j in range(0,len(lst)-1):
for k in range(j+1,len(lst)):
if (lst[j]==lst[k]):
break
else:
count=count+1
print (count)
While running the code and after inputting the two numbers, it does not run the code but still accepts input. What did I miss?
The reason your code doesn't run is because it gets stuck in your while loop, it can never exit that condition, since n1 > 0 will never have a chance to be evaluated as False, unless the input itself is <= 0.
Anyway, your approach is over complicated, not quite readable and not exactly pythonic. Here's a simpler, and more readable approach:
from collections import Counter
n1 = int(input())
n2 = int(input())
count = 0
for num in range(n1, n2+1):
num = str(num)
digit_count = Counter(num)
has_repeating_digits = any((True for count in digit_count.values() if count > 1))
if not has_repeating_digits:
count += 1
print(count)
When writing code, in general you should try to avoid nesting too much stuff (in your original example you have 4 nested loops, that's readability and debugging nightmare), and try using self-describing variable names (so a, x, j, k, b... are kind of a no-go).
If in a IPython session you run import this you can also read the "Zen of Python", which kind of sums up the concept of writing proper pythonic code.

Why does using modulus and floor division in Python return a reversed binary number?

I'm new to programming, and I don't understand why this code returns the binary number of the input.
x = int(input())
while x > 0:
print(x % 2, end='')
x = x // 2
For example, when I enter 6, I expect it to return 0 (6 % 2 = 0, 0 // 2 = 0), but it returns 011.
I stated contemplating this because, in an assignment, we're supposed to use this coding to help us reverse the output (while using a string) but I don't know how to reverse it when I don't know why it works.
The answer of 011 is correct for your code, just trace it thru. You start with 6%2 so you get a 0. Then 6 floor 2 is 3, which is then the x for the next iteration so it becomes 3%2 which is 1 and the final iteration creates the last 1. Remember that you're not changing the value of x in the print statement, it only changes in the last line.

Array sorting timing out for huge size of arrays

I am doing an online code challenge. I have an array which I need to sort and record to minimum number of iterations required to be sorted. I have the following code.
def minSwap(ar):
c = 0
for i in range(0, len(ar)):
if ar[i] == i+1:
continue
else:
for k in range(i+1, len(ar)):
if ar[k] == i+1:
ar[k] = ar[i]
ar[i] = i+1
c = c+1
break
return c
This code passes majority of test cases, however for really huge number of case such as where array size is beyond (let's say 50000) it gets timeout.
How can I identify the faulty block of code? I can't see a way to tweak it further.
Looking at the problem statement, it looks like you want to sort a list that has numbers starting from 1 thru n.
If you are trying to sort the list, and the final list is expected to be [1, 2, 3, 4, 5, 6, 7 , 8, .....], then all you need to do is to insert the i+1 to the current position and pop the value of i+1 from its current position. That will reduce the number of iterations you need to sort or swap.
Here's the code that does this with least number of moves. At least that's what I found based on my tests.
def minSwap(ar):
c=0
for i in range(0, len(ar)):
if ar[i] != i+1:
#find the value of i+1 from i+1th position
temp = ar.index(i+1,i+1)
ar.insert(i,i+1) #insert i+1 in the ith position
ar.pop(temp+1) #remove the value of i+1 from the right
c+=1 #every time you do a swap, increment the counter
print (ar) #if you want to check if ar is correct, use this print stmt
return c
a = [1,3,4,5,6,7,2,8]
print (minSwap(a))
The total number of swaps for the above example is 1. It just inserts 2 in the second place and pops out 2 from position 6.
I ran the code for a = [1,6,5,4,3,8,2,7] and it swapped in 5 moves.
I ran the code for a = [1,3,5,4,6,8,2,7] and it swapped in 3 moves.
If you are trying to figure out how this works, use a print statement right after the if statement. It will tell you the element being swapped.
From your code I take it that sorting isn't the issue here, since you know you'll end up with ar[i] == i+1. Given that, why not change your else block to swap the current element into its slot, and repeat until you ar[i] is correct.
else:
while ar[i] != i+1:
temp = ar[i]
ar[i] = ar[temp - 1]
ar[temp - 1] = temp
You don't actually need to do a sort on this array. You just need to figure out the minimum number of swaps needed. If we just look at the following pattern, we can form a hypothesis to be tested:
1234 = 0
1324 = 1, swap 2 and 3
1423 = 2, swap 2 and 4, swap 3 and 4
4213 = 2, swap 1 and 4, swap 3 and 4
4123 = 3, swap 4 and 1, swap 4 and 2, swap 4 and 3
Based on these observations, I think we can work on the hypothesis that the answer will be max(0, n - 1) where n is the count of the number of "out of place" elements.
Then the code becomes simplified to:
def minSwap(ar):
c = 0
for i in range(0, len(ar)):
if ar[i] != i+1:
c = c + 1
return c < 0 ? 0 : c
Note that I don't actually know python so don't know if that last ternary is valid in python.

Misaligned Sting summation

I was trying to find the sum of all the positive numbers in a python string,
b=[1,2,3,4,5,-1,-2,-3,-4,6].
I used While loop and break to stop the loop. The loop is stop as soon the index is getting '-1'.
b=[1,2,3,4,5,-1,-2,-3,-4,6]
total=0
i=0
f=0
while i<len(b) and b[i]>0:
total=total+b[i]
i=i+1
while i<len(b) and b[i]<0:
i+=1
break
print(total)
Can someone provide alternative ideas of how to solve this issue ? I am getting 15 as output but I am expecting 21. Thank you for the help.
how about just that:
sum(n for n in b if n > 0)
the generator expression in the sum selects the positive values only.
Your whole problem is simply the break statement. You don't really need it as the loop will exit alone when the condition is not met.
What happens right now, is that your inner loop skips the first negative number - -1 - but then breaks immediately. So at this point in time i = 6 and we're back in the outer loop. So now b[i] = -2 and the outer loop exits.
So, bottom line, remove the break statement and the inner loop will exit alone, just when you want it to, and you will magically get 21 as athe output.
A side note: This is a messy solution for a simple problem with built-in options to handle, as hiro's answer shows.
Still, going with your line of thought, there is no need to get your hands dirty with maintaining indices with while loops. A for-loop is just what you need - iterate through each element, and just add a check if it is positive:
b=[1, 2, 3, 4, 5, -1, -2, -3, -4, 6]
total = 0
for num in b:
if num > 0:
total += num

How does this code work? What tells it to stop printing after the third row? Can someone break it down for me, in the most dumbed down way possible?

import random
def main():
printMatrix(3)
i don't understand how this code stops after the third row
def printMatrix(n):
for i in range(1, n + 1):
for j in range(1, n + 1):
print(random.randint(0, 1), end = " ")
print()
main()
range(1,n+1) is a builtin that returns [1, 2, 3], so iterating over range(1, n+1) is the same as iterating over [1, 2, 3] - each for loop body executes three times before terminating. The inner one prints your entries horizontally and the outer one causes the inner one to execute three times.
Frankly this is a little basic, if you have trouble here I think anybody would suggest that you fetch a drink, get comfortable, open a book and start learning properly.
That said, I'll play:
The first for construct is responsible for (1) iterating the columns and (2) breaking the line. It does all these things once for each value of i in the range 1..4 (where 4 comes from n+1 with n=3). Hence, you already have your answer: it iterates three times and thus (2) happens three times.
To do (1), it uses another for construct, which is completely independent.
To do (2), it uses print().

Resources