Python while sampling - python

I'm searching to make a loop to go throw samples till I reach the result. Example:
i=(list(np.random.randint(2, size=5)),list(np.random.randint(2, size=2)),list(np.random.randint(2, size=7)),list(np.random.randint(2, size=7)),list(np.random.randint(2, size=9)),list(np.random.randint(2, size=8)),list(np.random.randint(2, size=7)))
tot=0
for j in range(0,len(anytable)):
if resp(i,(anytable.iloc[j,0:7].tolist())): #this function "resp" gives me True and False and add 1 to variable "tot"
tot=tot+1
Now I want to stop till I have to tot>=100 .
So I have to generate many "i" samples lists till I get to tot>=100.
How can I do this?
Thank you very much

From guessing I would say, this could be your solution.
j, tot = 1, 1
while j<len(anytable) and tot<100 :
tot += int( resp(i,(anytable.iloc[j,0:7].tolist())) )
j += 1
The condition is false if one of the inequations is false. The incementing operator += on tot is adding the integer representation of a boolean True = 1 or False = 0 to the value of tot.

Related

scope of a variable in python for this question

I don't know why, but I am getting value of scope as final as 0 even len(s) as zero in the last line of countfrequency(s) function.
import collections
def countfrequency(s):
final = 0
flag = 1
d = dict(collections.Counter(s))
for item in d:
if d[item] <= k:
flag = 0
if flag == 1: #Here
final = max(final, len(s))
print(final)
s = "ababbc"
k = 2
for x in range(len(s)):
for y in range(1, len(s)):
countfrequency(s[x:y + 1])
It is because of 2 reasons :
Value of flag is 0 at last so it wont change the value of final
Length function takes object as a parameter and when unchanged it gives 0
So you can can either make flag 1 so that control goes inside if condition or print the value of len(s) out side the if condition
In addition to the answer posted by shaktiraj jadeja, the modified code is as follows:
import collections
def countfrequency(s, k):
final = 0
flag = 0
d = dict(collections.Counter(s))
# print(d)
for item in d:
if d[item] > k:
flag = 1
break
if flag == 1: #Here
# print("Inside:", final, len(s))
final = max(final, len(s))
print(final)
s = "ababbc"
k = 2
for x in range(len(s)):
for y in range(1, len(s)):
# print(s[x:y])
countfrequency(s[x:y + 1], k)
To start with there is no problem of scope.
Now lets get back to the problem
Lets define a rule.
Rule: If a sub string has each character repeated more than k(=2) times in it. Then it is a good substring. Else it is a bad substring
Then your code simply prints the length of good sub string or 0 in case of bad substring
In short in your example string s= "ababbc" contains no good substring
if you try S = "aaaaaa" you will see many numbers printed other than 0 (exactly 11 0's and 10 other numbers)
Now either this was your confusion or you wrote the wrong code for some logic
I hope this helps

If, else return else value even when the condition is true, inside a for loop

Here is the function i defined:
def count_longest(field, data):
l = len(field)
count = 0
final = 0
n = len(data)
for i in range(n):
count = 0
if data[i:i + l] is field:
while data[i - l: i] == data[i:i + l]:
count = count + 1
i = i + 1
else:
print("OK")
if final == 0 or count >= final:
final = count
return final
a = input("Enter the field - ")
b = input("Enter the data - ")
print(count_longest(a, b))
It works in some cases and gives incorrect output in most cases. I checked by printing the strings being compared, and even after matching the requirement, the loop results in "OK" which is to be printed when the condition is not true! I don't get it! Taking the simplest example, if i enter 'as', when prompted for field, and 'asdf', when prompted for data, i should get count = 1, as the longest iteration of the substring 'as' is once in the string 'asdf'. But i still get final as 0 at the end of the program. I added the else statement just to check the if the condition was being satisfied, but the program printed 'OK', therefore informing that the if condition has not been satisfied. While in the beginning itself, data[0 : 0 + 2] is equal to 'as', 2 being length of the "field".
There are a few things I notice when looking at your code.
First, use == rather than is to test for equality. The is operator checks if the left and right are referring to the very same object, whereas you want to properly compare them.
The following code shows that even numerical results that are equal might not be one and the same Python object:
print(2 ** 31 is 2 ** 30 + 2 ** 30) # <- False
print(2 ** 31 == 2 ** 30 + 2 ** 30) # <- True
(note: the first expression could either be False or True—depending on your Python interpreter).
Second, the while-loop looks rather suspicious. If you know you have found your sequence "as" at position i, you are repeating the while-loop as long as it is the same as in position i-1—which is probably something else, though. So, a better way to do the while-loop might be like so:
while data[i: i + l] == field:
count = count + 1
i = i + l # <- increase by l (length of field) !
Finally, something that might be surprising: changing the variable i inside the while-loop has no effect on the for-loop. That is, in the following example, the output will still be 0, 1, 2, 3, ..., 9, although it looks like it should skip every other element.
for i in range(10):
print(i)
i += 1
It does not effect the outcome of the function, but when debugging you might observe that the function seems to go backward after having found a run and go through parts of it again, resulting in additional "OK"s printed out.
UPDATE: Here is the complete function according to my remarks above:
def count_longest(field, data):
l = len(field)
count = 0
final = 0
n = len(data)
for i in range(n):
count = 0
while data[i: i + l] == field:
count = count + 1
i = i + l
if count >= final:
final = count
return final
Note that I made two additional simplifications. With my changes, you end up with an if and while that share the same condition, i.e:
if data[i:i+1] == field:
while data[i:i+1] == field:
...
In that case, the if is superfluous since it is already included in the condition of while.
Secondly, the condition if final == 0 or count >= final: can be simplified to just if count >= final:.

Is there a way to increment the iterator if an 'if' condition is met

I'm solving this HackerRank challenge:
Alice has a binary string. She thinks a binary string is beautiful if and only if it doesn't contain the substring '010'.
In one step, Alice can change a 0 to a 1 or vice versa. Count and print the minimum number of steps needed to make Alice see the string as beautiful.
So basically count the number of '010' occurrences in the string 'b' passed to the function.
I want to increment i by 2 once the if statement is true so that I don't include overlapping '010' strings in my count.
And I do realize that I can just use the count method but I wanna know why my code isn't working the way I want to it to.
def beautifulBinaryString(b):
count = 0
for i in range(len(b)-2):
if b[i:i+3]=='010':
count+=1
i+=2
return count
Input: 0101010
Expected Output: 2
Output I get w/ this code: 3
You are counting overlapping sequences. For your input 0101010 you find 010 three times, but the middle 010 overlaps with the outer two 010 sequences:
0101010
--- ---
---
You can't increment i in a for loop, because the for loop construct sets i at the top. Giving i a different value inside the loop body doesn't change this.
Don't use a for loop; you could use a while loop:
def beautifulBinaryString(b):
count = 0
i = 0
while i < len(b) - 2:
if b[i:i+3]=='010':
count += 1
i += 2
i += 1
return count
A simpler solution is to just use b.count("010"), as you stated.
If you want to do it using a for loop, you can add a delta variable to keep track of the number of positions that you have to jump over the current i value.
def beautifulBinaryString(b):
count = 0
delta = 0
for i in range(len(b)-2):
try:
if b[i+delta:i+delta+3]=='010':
count+=1
delta=delta+2
except IndexError:
break
return count
You don't need to count the occurrences; as soon as you find one occurrence, the string is "ugly". If you never find one, it's beautiful.
def is_beautiful(b):
for i in range(len(b) - 2):
if b[i:i+3] == '010':
return False
return True
You can also avoid the slicing by simply keeping track of whether you've started to see 010:
seen_0 = False
seen_01 = False
for c in b:
if seen_01 and c == '0':
return False
elif seen_1 and c == '1':
seen_01 = True
elif c == '0':
seen_0 = True
else:
# c == 1, but it doesn't follow a 0
seen_0 = False
seen_01 = False
return True

changing a for loop to a while loop

I was wondering how I could change the following lines of codes to use a while loop instead of a for loop.
for num in range(10):
print(num+1)
It currently prints out the following:
1
2
3
4
5
6
7
8
9
10
Thanks!
start = 0
while start != 10:
start = start + 1
print(start)
hope this hepls
number = 1
while (number <=10):
print 'The number is:', number
number = number + 1
The for loop runs over an iterable, while a while loop runs while a condition is true, so you just need to think of the right condition.
Here, something counting up to 10 will work:
>>> number = 0
>>> while number < 10:
... print(number + 1)
... number += 1
...
1
2
3
4
5
6
7
8
9
10
Writing code that has the same output is not the same as rewriting code to do the same thing. Other answers simply do the former, so this solves the latter:
numbers = range(10)
while numbers:
numbers.pop(0) + 1
The original code iterates over a list that does not exist outside of the loop - it could work with a list of something other than range(10), but it's not necessarily just a '+ 1' operation.
The conditional statement for a while loop, however, needs to be true for the loop to begin so the list should already exist. To keep true to the spirit of the original code, we use range() to create the list, and use pop() to iteratively remove the first element from it.
The differences here are that a variable (numbers) gets used, but is empty after the loop, and we don't rely on list comprehension to iterate, but explicitly remove the first element until 'numbers', being empty, results in a false condition.
well..... a while statement operates UNTIL a certain condition is met, as the for operates for a set of given iterations.
in your case you want to print stuff until num reaches 10, so
while num <= 10 :
print num
num = num + 1
would do

Trying to Solve Monty Hall in Python

I'm trying to understand this solution of the Monty Hall problem, I understand most of the code, but am stuck on two pieces.
Below is the code, but specifically I'm stuck on these two parts
result[bad] = np.random.randint(0,3, bad.sum())
and the entire switch_guess function.
If anyone could explain in plain English for me that would be awesome.
#Simulates picking a prize door
def simulate_prizedoor(nsim):
return np.random.randint(0,3,(nsim))
#Simulates the doors guessed
def simulate_guesses(nsim):
return np.zeros(nsim, dtype=np.int)
#Simulates the "game host" showing whats behind a door
def goat_door(prize_doors, guesses):
result = np.random.randint(0,3, prize_doors.size)
while True:
bad = (result == prize_doors) | (result == guesses)
if not bad.any():
return result
result[bad] = np.random.randint(0,3, bad.sum())
#Used to change your guess
def switch_guess(guesses, goat_doors):
result = np.zeros(guesses.size)
switch = {(0, 1): 2, (0, 2): 1, (1, 0): 2, (1, 2): 1, (2, 0): 1, (2, 1): 0}
for i in [0,1,2]:
#print "i = ", i
for j in [0,1,2]:
#print "j = ", j
mask = (guesses == i) & (goat_doors == j)
#print "mask = ", mask
if not mask.any():
continue
result = np.where(mask, np.ones_like(result) * switch[(i, j)], result)
return result
#Calculates the win percentage
def win_percentage(guesses, prizedoors):
return 100 * (guesses == prizedoors).mean()
#The code to pull everything together
nsim = 10000
#keep guesses
print "Win percentage when keeping original door"
print win_percentage(simulate_prizedoor(nsim), simulate_guesses(nsim))
#switch
pd = simulate_prizedoor(nsim)
guess = simulate_guesses(nsim)
goats = goat_door(pd, guess)
guess = switch_guess(guess, goats)
print "Win percentage when switching doors"
print win_percentage(pd, guess)
… specifically I'm stuck on these two parts
result[bad] = np.random.randint(0,3, bad.sum())
Let's break this down into pieces. It may help to reduce that 10000 to something small, like 5, so you can print out the values (either with print calls, or in the debugger) and see what's going on.
When we start this function, prize_doors is going to have 5 random values from 0 to 2, like 2 2 0 1 2, and guesses will have 5 values, all 0, like 0 0 0 0 0. result will therefore start off with 5 random values from 0 to 2, like 0 2 2 0 1.
Each first time through the loop, bad will be a list of 5 bool values, which are each True if the corresponding value in result matches the corresponding value in either prize_doors or guesses. So, in this example, True True False True False, because guess #1 matches prize_doors, and guesses #0 and #3 match goats.
Unfortunately, we're just going to go around that loop forever, because there's nothing inside the loop that modifies result, and therefore bad is going to be the same forever, and doing the same check forever is always going to return the same values.
But if you indent that result[bad] = … line so it's inside the loop, that changes everything. So, let's assume that's what you were supposed to do, and you just copied it wrong.
When treated as numbers, True and False have values 1 and 0, respectively. So, bad.sum() is a count of how many matches there were in bad—in this case, 3.
So, np.random.randint(0, 3, bad.sum()) picks 3 random values from 0 to 2, let's say 1 0 1.
Now, result[bad] selects all of the elements of result for which the corresponding value in bad is True, so in this example it's result[0], result[1], and result[3].
So we end up assigning that 1 0 1 to those three selected locations, so result is now 1 0 2 1 1.
So, next time through the loop, bad is now True False False False False. We've still got at least one True value, so we run that result[bad] = line again. This time, bad.sum() is 1, so we pick 1 random value, let's say 0, and we then assign that 1 value to result[0], so result is now 0 0 2 1 1.
The next time through, bad is now False False False False False, so bad.any() is False, so we're done.
In other words, each time through, we take all the values that don't match either the prize door or the goat door, and pick a new door for them, until finally there are no such values.
It also confused me, until 5 mins ago when I finally figured it out.
Since the first question has been solved, I will only talk about the second one.
The intuition goes like this : given a sequence of (guesses, goatdoors),in the (i,j) loop, there are always some simulation (e.g., simulation[0] and simulation[5]) that 'hit' by the (i,j), that is the say, the 0th and 5th simulation have guess i and goatdoor j.
Variable mask record 0 and 5 in this example. Then result in 0th and 5th can be decided, because in these simulation, the only possible door to switch to is determined by i and j. So np.where refreshes result in these simulation, leave other simulations unchanged.
Intuition is above. You need to know how np.where work if you want to know what I'm talking about. Good luck.

Categories

Resources