the prisoner box problem, simulating the solution - python-3.x

I am trying to write code to simulate the prisoners going to the box labeled with their number, then to the box that the ticket inside send them too and so on.
I'm getting a list index out of range error but not sure if the code is even right anyway
total = 0
for s in range(100):
prisoners = []
boxes = []
counter = 0
winners = 0
number = 0
for i in range(1, 101):
prisoners.append(i)
#print(prisoners)
for x in range(1, 101):
boxes.append(x)
shuffle(boxes)
#print(boxes)
while counter!=99:
for h in range(1, 51):
if prisoners[counter] == boxes[number]:
print("winner")
winners +=1
counter +=1
break
else:
number = boxes[number]
print("loser")

The issue is you store boxes numbers as range [1,100], but use them as indices of 100-long array (0-99), so when it runs number = boxes[number] it sometimes assigns number to be 100 and causes error.
One way to solve it is make it number = boxes[number] - 1.
Another is use 0-99 ranges in logic, but add 1 if you want to print them.

Related

What is the problem with this for loop in python?

I want to create a function to calculate the sum of number which are multiples of 3.
What is the problem here, because I get numbers repeated 3 times until I get to 18, which is out of range. I don't understand.
summ = 0
for n in range(10):
if n % 3 == 0:
summ = summ+n
print(summ)
Try:
summ = 0
for n in range(10):
if n % 3 == 0:
summ = summ+n
print(summ)
Your code print(summ) is inside the loop, meaning it will print multiple times (as many times as the loop runs). Moving it outside of the loop will only make it print once after the loop is done running.

python return / print highest number of value in a row in a list

I am a beginner.
Trying to make a function that can return the highest number in a row a value in a list was picked.
Basicly I want to simulate a head or tails game, and find out how many times in a row it was for example tails.
import random
def simulations(runs):
sequence = []
in_a_row = []
tæller = 0
for run in range(0, int(runs)):
my_random = random.randint(0,1)
sequence.append(my_random)
if my_random == 0:
in_a_row.append(my_random)
tæller = tæller + 1
print()
elif my_random == 1:
tæller = 0
in_a_row = []
print()
print(f'{tæller}')
print(sequence)
# runs = input('How many simulations do you want to run ? ')
runs = 10
simulations(runs)
I think I am almost there. But I cant figure it out, when I run this code I first print the actual value that was picked, and then see the list that was created so far.
if for example my_random == 0 3 times in a row it will print each time it was 0 until it picks 1.
Want i want is for the code to print only the longest sequence where 0 was picked in the entire list
I know my code is spagetti, and the function is not finished, but i belive I can do that by myself. I just need some help with isolating the number of times a given value was picked in a row from the list.
Hmm I think I was finally able to create a solution by myself.
So happy i think i spend like 5 hours trying to figure it out.
Here is my solution. I would still appriciate it a lot if someone can comment on my solution, and maybe show another more simple way of doing it :-)
import random
def simulations(runs):
sequence = []
in_a_row = []
found_zero = 0
all_time_high = [0]
for run in range(int(runs)):
my_random = random.randint(0,1)
sequence.append(my_random)
if my_random == 0:
in_a_row.append(my_random)
found_zero = found_zero + 1
print(f'fundet 0 ja: {found_zero} Gange')
all_time_high.append(found_zero)
elif my_random == 1:
found_zero = 0
in_a_row = []
print()
print(sequence)
print(f'Higest number of times in a row zero was found: {max(all_time_high)}')
# runs = input('How many simulations do you want to run ? ')
runs = 10
simulations(runs)

How can I avoid an “out of index” error with 2D arrays in Python?

The task is to iterate over all elements within a two-dimensional list and do some specific calculations on each element and its nearest neighbors:
count = 0
for i in range(0,len(arr)):
for j in range(0,len(arr)):
if arr[i][j] == 7 and is_perfect_cube(arr[i-1][j] + arr[i+1][j] + arr[i][j-1] + arr[i][j+1]):
count += 1
Unfortunately, I keep getting an index out of range error. Basing on what I’ve managed to debug so far is that the error occurs for the first and last elements of the collection. I know I could use float[int], but I’m not sure how to apply it to my particular implementation. I couldn’t find any similar questions.
Your code explicitly tries to use elements that are out of array bounds. In this call,
is_perfect_cube(arr[i-1][j]+arr[i+1][j]+arr[i][j-1]+arr[i][j+1])
you are asking for arr[i-1][j] which equals to -1 for i=0 - and fetches the last row - this may be desirable in some cases. Then you also ask for arr[i+1][j] which for i equal to the last element, i.e. len(arr)-1 is clearly out of bounds and causes an error. The same holds for arr[i][j+1] - just in terms of columns and not rows.
To handle this, you need to either ignore the end points (loop from 1 to size-2 in both dimensions) or modify your algorithm for the end points. The choice depends on the problem you are trying to solve. All established algorithms consider end points, you can check what are the solutions for yours.
count = 0
for i in range(0,len(arr)):
for j in range(0,len(arr)):
if arr[i][j] == 7:
try:
up = arr[i-1][j]
except:
up = 0
try:
down = arr[i+1][j]
except:
down = 0
try:
left = arr[i][j-1]
except:
left = 0
try:
right = arr[i][j+1]
except:
right = 0
if is_perfect_cube(up+down+left+right):
count += 1
This is my solutions for my question. I don't know if this is the correct way to solve out of boundary problems. I am still open for advice

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.

Number of Combinations to make change with coins

We have unlimited coins of different values - Calculate the unique combinations of how these coins can make up a specific amount. For example:
n = 4 (say, 4 cents)
coins_list = [1,2] - we have 1-cent coins, and 2-cent coins
The different combinations would be 112, 1111, and 22. (121 and 211 should be excluded since it's not unique - using one 2-cent coin and two 1-cent coin)
I have watched this video: https://www.youtube.com/watch?v=k4y5Pr0YVhg
countless number of times, and edited my codes countless number of times, but I cannot manage to get rid of the same combination of different orders.
def make_change(n, coinlist_index=None):
coin_list = [1, 2]
if coinlist_index == None:
coinlist_index = 0
#coin index position in coin_list; starts at index 0 and cycles through all the coins
if n == 0:
return 1
if n < 0:
return 0
ways = 0
# if I use for i in range(len(coin_list)), it returns an error message saying that index is out of range
for coinlist_index in range(len(coin_list)):
ways += make_change((n - coin_list[coinlist_index]), coinlist_index)
coinlist_index += 1
return ways
make_change(4)
Output: 5
My output was 5 (different ways to make change for 4 cents with 1 and 2-cent coins), instead of 3 (which is what I want).
I'm sure it has to do with the for loop toward the end, but when i change "for coinlist_index in range..." to a different iterator, i, I get an error that says index is out of range.
What is going on, and more importantly, how can I fix it?
EDIT: P.S. This is just a simple example that I'm working through to solve the actual assignment - Which is with 6 types of coins, in cents, (1, 5, 10, 25, 50, 100), and calculate how many ways to make change for 200 dollars. I have seen and tried the dynamic programming method out there, which worked, but we have to use recursion for assignment purposes.
Looks like I got it working. In each recursive pass you want to make sure that you aren't double counting possible ways to make the change. My thought to do this was to make sure that you never go backwards in the coin_list. So for the coin_list [1,2] if we ever use the 2 cent coin we never want the option to use the 1 cent coin afterwards. I made sure it follows this order by changing your for loop a bit:
for i in range(len(coin_list)-coinlist_index):
ways += make_change((n - coin_list[i+coinlist_index-1]), coinlist_index)
In the for loop I subtracted coinlist_index from the upper bound so we don't cycle over all coins once the index reaches 1, then added the index to where you pull from the coin_list, making sure once coinlist_index is 1 or more, we NEVER usecoin_list[0]. This got me to 3 in your sample case, hopefully it works for all cases. Full code:
def make_change(n, coinlist_index=None):
coin_list = [1, 2]
if coinlist_index == None:
coinlist_index = 0
#coin index position in coin_list; starts at index 0 and cycles through all the coins
if n == 0:
return 1
if n < 0:
return 0
ways = 0
# if I use for i in range(len(coin_list)), it returns an error message saying that index is out of range
for i in range(len(coin_list)-coinlist_index):
ways += make_change((n - coin_list[i+coinlist_index-1]), coinlist_index)
coinlist_index += 1
return ways
print(make_change(4))
I feel 5 is actually the correct answer.
1 1 1 1
1 1 2
1 2 1
2 1 1
2 2
Or if you want distinct result, you may store results in the list and remove the duplicate result.
def make_change(n, coinlist_index=0):
coin_list = [1, 2]
if n == 0:
return [[]]
if n < 0:
return []
ways = []
for coinlist_index in range(len(coin_list)):
res = make_change((n - coin_list[coinlist_index]), coinlist_index)
ways += list(map(lambda x : x + [coin_list[coinlist_index]], res))
return ways
def remove_dup(lolist):
res = []
for lst in lolist:
lst.sort()
if lst not in res:
res.append(lst)
return res
print remove_dup(make_change(4))

Resources