Python random.randint stops randomizing after a few loops - python

I'm running a python script that will display messages on a board. One of the subroutines that I've created is supposed to grab a random line from a small text file, and display that line. It mostly works, except after looping a few times, it gets stuck on the same number, and just displays the same thing over and over.
I am running this in Python 2.7, on a Raspberry Pi in Raspbian. I am using this github as the base for the project, and added lines of my own to it:
https://github.com/CalebKussmaul/Stranger-Things-Integrated
This is part of a halloween display that will be Stranger Things-themed, so the preloaded messages have a reference to the show. I noticed this issue the other day, and have been pouring over the internet to try and figure out what the problem could be. I've tried doing different methods of selecting a randomized number, including some in some similar (but different) threads on this site. All of them produce exactly the same issue.
Below is the subroutine I created:
def preloaded_messages():
print "Preloaded Messages thread is loaded."
global displaying
while True:
if not displaying:
with open('preloaded_messages.txt') as f:
lines = len(f.readlines())
rgn = random.randint(1,lines)
msg = linecache.getline('preloaded_messages.txt', rgn)
print "rng: ", rgn
print "total lines: ", lines
print "line: ", msg
print "displaying from preloaded_messages.txt: ", msg
display(msg)
time.sleep(10)
And here's my preloaded_messages.txt file:
help me
im trapped in the upside down
leggo my eggo
friends dont lie
run /!
hopper is alive
rip barb
demogorgon is coming /!
mouthbreather
When I run it, my output is like this:
rng: 6
total lines: 9
line: hopper is alive
rng: 2
total lines: 9
line: im trapped in the upside down
rng: 9
total lines: 9
line: mouthbreather
...
rng: 9
total lines: 9
line: mouthbreather
the first few times are always random (and the number of times it successfully randomizes varies), but when it gets on 9, it just stays there for as long as I let it run. I am at a loss as to why it works the first few times, but not once it gets to 9.
EDIT: Interestingly, as I've been writing this, I also tried adding a blank line at the end, and while it looked like it'd be stuck again, as it did that one three times in a row, then it finally moved to others. I'm not sure how that changes things. And ideally, I'd rather not have the blank line in there, as it eats up time displaying nothing. So it'd be nice to fix the issue. Anyone have any ideas?

It is reseeding the random generator. See line 49 of stranger.py in the https://github.com/CalebKussmaul/Stranger-Things-Integrated: random.seed(i).
The color_of function should be written as:
def color_of(i):
"""
This function generates a color based on the index of an LED. This will always return the same color for a given
index. This allows the lights to function more like normal christmas lights where the color of one bulb wont change.
:param i: index of LED to get color of
:return: a pseudorandom color based on the index of the light
"""
_random = random.Random(i)
rgb = colorsys.hsv_to_rgb(_random.random(), 1, 1)
return int(rgb[0] * 255), int(rgb[1] * 255), int(rgb[2] * 255)
To create its own Random instance with the given seed rather than reseeding the Random instance that is a singleton in the random module.

This appears to work for me. Note that I'm seeding the RNG.
import time
import random
from datetime import datetime
def preloaded_messages():
print("Preloaded Messages thread is loaded.")
displaying = False
while True:
if not displaying:
with open('preloaded_messages.txt') as f:
random.seed(datetime.utcnow())
text = f.read().splitlines()
msg = random.choice(text)
print("line: ", msg)
# print("displaying from preloaded_messages.txt: ", msg)
time.sleep(10)
if __name__ == "__main__":
preloaded_messages()

Related

How do I fix infinite loop bugs in Python?

I have a problem regarding a competition question I'm attempting to do. Here is the question (its a bit long)
""""
Welcome aboard, Captain! Today you are in charge of the first ever doughnut-shaped spaceship, The
Circular. There are N cabins arranged in a circle on the spaceship. They are numbered from 1 to N in
a clockwise direction around the ship. The ith and the (i + 1)th cabins are connected. So too are cabin
1 and cabin N.
Currently the ith cabin has Ai crewmates, however the spaceship cannot depart unless there are exactly
Bi crewmates in this cabin.
To achieve this, you have the power to pay crewmates to change cabins. You can pay a crewmate $1 to
move to an adjacent cabin. A crewmate can be asked to move multiple times, provided that you pay
them $1 each time.
What is the fewest dollars you must pay before you can depart? It is always be possible to depart.
""""
https://orac2.info/problem/aio22spaceship/ (the link to the intereactive Qs)
I searched the web and i found no solutions to the Q. My code seems to be infinite looping i guess but im not sure as i cant see what cases the sit uses to determine if my code is right.
Heres my code
#!/usr/bin/env python
import sys
sys.setrecursionlimit(1000000000)
#
# Solution Template for Spaceship Shuffle
#
# Australian Informatics Olympiad 2022
#
# This file is provided to assist with reading and writing of the input
# files for the problem. You may modify this file however you wish, or
# you may choose not to use this file at all.
#
# N is the number of cabins.
N = None
# A contains the initial number of crewmates in each cabin. Note that here the
# cabins are numbered starting from 0.
A = []
# B contains the desired number of crewmates in each cabin. Note that here the
# cabins are numbered starting from 0.
B = []
answer = 0
# Open the input and output files.
input_file = open("spacein.txt", "r")
output_file = open("spaceout.txt", "w")
# Read the value of N.
N = int(input_file.readline().strip())
# Read the values of A and B.
input_line = input_file.readline().strip()
A = list(map(int, input_line.split()))
input_line = input_file.readline().strip()
B = list(map(int, input_line.split()))
AM = A
#AM is my modifying set
# TODO: This is where you should compute your solution. Store the fewest
# dollars you must pay before you can depart into the variable
while AM != B:
#Check if the set is correct
#notfound is a testing variable to see if my code was looping due to input error
notfound = True
for i in range(N):
#Check which places needs people to be moved
while AM[i]>B[i]:
notfound = False
#RV and LV check the "neediness" for each half's people requirements. I check how many people
#are needed on one side compared to the other and subtract the "overflow of people"
RV = 0
LV = 0
for j in range(int(N/2-0.5)):
#The range thing makes sure that if N is odd, im splitting the middle but if N is even, i leave out the end pod
RV += B[(i+j+1)%N]-AM[(i+j+1)%N]
LV += B[(i-j-1)%N]-AM[(i-j-1)%N]
answer +=1
if RV>LV:
AM[i]+=-1
AM[(i+1)%N]+=1
else:
AM[i]+=-1
AM[(i-1)%N]+=1
print(AM,B)
if notfound:
break
print(answer)
# Write the answer to the output file.
output_file.write("%d\n" % (answer))
# Finally, close the input/output files.
input_file.close()
output_file.close()
please help i really neeed to know the answer, driving me mad ngl
Welp, there aren't any resources online and I've tried everything. I think the problem might be that because of my solving method, passengers may be flicked between two pods indefinitely. Not sure since i could make a case that demoed this.
also my post probably is messy since this is my first time posting

100 Prisoners Dilemma - Python code isn't working

I stumbled across an interesting probability problem about half an hour ago. https://en.wikipedia.org/wiki/100_prisoners_problem
Essentially, there are 100 boxes, drawers, etc, each with a unique number between 1-100 inside of them. There are also 100 prisoners. Each prisoner has 50 chances to find the box with their number. If even one does not, they all fail. The chances would be abysmally low if they all randomly picked 50 boxes, but there's a better strategy.
Each prisoner first opens the box labeled with their own number.
If this box contains their number, they are done and were successful.
Otherwise, the box contains the number of another prisoner, and they next open the drawer labeled with this number.
The prisoner repeats steps 2 and 3 until they find their own number, or fail because the number is not found in the first fifty opened drawers.
This should increase their chances to above 30 percent with the way everything can fall into a loop
I glanced through this and decided it was interesting enough to quickly code out in python, but I'm getting a really interesting (and probably wrong) result. Could someone take a look at the code?
import random
def begin(p=False): #print
prisoners = [i for i in range(100)]
boxes = prisoners.copy()
random.shuffle(boxes) #we now have a list of shuffled boxes. index represents box num
if p: #prints
for i,num in enumerate(boxes): #i=index, num=content of box. Just to print it out
print(i,num)
def run(p=True): #print
results ={"Success":False, "NumSucceed":0, "NumFail":0 }
for prisoner in prisoners: #Try every prisoner
fail = True #check if they fail
choice = boxes[prisoner] #initialize choice as box with prisoner num
for i in range(49): #49 becaues first choice counts as well
if choice==prisoner:
fail = False
break
choice = boxes[choice]
if fail:
results["NumFail"] +=1
else:
results["NumSucceed"]+=1
if results["NumSucceed"]==100:
results["Success"] = True
if p: #just if I choose not to print results
print(results)
return results
for i in range(100):
begin()
run()
How many ever times I run it I always get a failing result where 17 prisoners succeeded and the rest failed (I randomize the rotation of the boxes each time too). Does anyone know why? I hope I didn't just make some stupid error somewhere and waste your time lol, if you do look through this I'd appreciate it
Couple of notes first.
Make sure you keep locality/scope in mind with variables. You have a begin() function thats used to declare your variables for the entire script, but they aren't declared globally so when the other method runs, it won't be able to find the variables to declare in begin()
not sure how you got it to run as is tbh
so let's scrap the method and just initialize our prisoners and boxes
import random
prisoners = [i for i in range(100)]
boxes = [i for i in range(100)]
now you can put the shuffle in your run method, since only boxes need to be randomized and conceptually, randomizing boxes would be the first thing done each time the prisoner dilemma happens.
def run(p=True): #print
random.shuffle(boxes)
results ={"Success":False, "NumSucceed":0, "NumFail":0 }
# ...
I ran a couple times and got 20-40 out of 100 total runs where all prisoners found their tag
nice little riddle there.
I tried to execute your code, but ran into an NameError exception due to a name space problem. Basically both prisoners and boxes within your code are only defined while begin() is running.
I've used your solution and modified it a bit:
import random
from operator import countOf
PRISONERS = 100
class PrisonerProblemSolver:
def __init__(self) -> None:
# Generate prisoners and boxes
self.prisoners = list(range(PRISONERS))
self.boxes = self.prisoners.copy()
random.shuffle(self.boxes)
# collector for results
self.results = {"Success": False, "NumSucceed": 0, "NumFail": 0}
def solve(self):
for prisoner in self.prisoners:
fail = True
choice = self.boxes[prisoner] # tries own box first
for _ in range(49): # remaining attempts
if choice == prisoner:
fail = False # will not die
break
choice = self.boxes[choice] # follows and hopes
if fail:
self.results["NumFail"] += 1
else:
self.results["NumSucceed"] += 1
return self.results["NumSucceed"] == PRISONERS
if __name__ == '__main__':
solver = PrisonerProblemSolver()
results = []
# Let's look at 100 prisons
for _ in range(100):
solver = PrisonerProblemSolver()
results.append(solver.solve())
# how successful were they in dying?
print(countOf(results, True))
Hope this helps.
Best regards

How To Print Grid In Python Without "Flashing" Screen

In the program I've been working on in Python, I need to be able to print a list of elements one by one, going to a new line after n elements to form a grid. However, every time the program reprints the grid, you can see it progressing element by element, which looks rather ugly and distracting to the user. I was wondering if there was a way to "pause" the console output for a brief amount of time to allow the grid to be printed, then show the grid afterwards, erasing the previous printout, as to not show it printing element by element. The reason I need to do this is because the program uses Colorama for colored outputs, but different elements in the list will need to have different colors, meaning each element has to be printed one by one.
EDIT (Current code):
import time as t
from os import system as c
h = 50
w = 50
loop1 = 0
ostype = "Windows"
def cl():
if(ostype == "Linux"):
c('clear')
if(ostype == "Windows"):
c('cls')
def do():
grid = []
for x in range(0,h):
temp = []
for z in range(0,w):
temp.append("#")
grid.append(temp)
for a in range(0,h):
for b in range(0,w):
print(grid[a][b], flush=False, end="")
print()
while(loop1 == 0):
do()
t.sleep(1)
cl()
You can probably tell print to not to flush the standard out buffer, and have the last print to flush everything. Depends on what version of python you're using, for python 3 print function takes a flush argument, set that to true/false accordingly.

Changing the output inside a while True loop

I am very new in Python and I decided to make a game.
I want a value to be output like this:
Heat: x #x would always be changing
For that I have the following block of code:
while True:
print("Heat: {}".format(Heat))
but all it does is spam "Heat: xHeat: xHeat: x"
When it should be only one Heat bar
What should I do?
In that code 'Heat' in the loop and it will be printed all the time:
Heat = 0
while True:
Heat +=1
print ('Heat: {heat}'.format(heat=Heat))
In that code 'Heat' out of the loop and it will be printed once:
Heat = 0
print ('Heat:')
while True:
Heat +=1
print ('{heat}'.format(heat=Heat))
if you want more newlines use '\n' char (strictly depends on OS).
You can use carriage return to send the cursor to the start of the line.
import sys
while True:
sys.stdout.write("\rHeat: {}".format(Heat))
sys.stdout.flush()
But this approach doesn't sound like you will be able to extend it into any sort of game.
You should look up the python curses library for complete control over the console output.
Also if the number of digits in your output changes then you might want to right-align the output so that you don't get any left-overs. This code demonstrates what happens if you go from a 2 digit number to a 1 digit number:
import sys
import time
for heat in reversed(range(5, 12)):
time.sleep(0.5)
sys.stdout.write("\rHeat: {:>5}".format(heat))
sys.stdout.flush()

Python for loop executing once for size 2 array

There seems to be something strange going on in this loop. I tried to debug it, and I have no explanation for what is going on.
This code is from another Stack Overflow post, and I made some edits to it.
modelImages = ['/home/lie/Desktop/dylan.jpg','/home/lie/Desktop/melissa.jpg']
for modelImage in modelImages:
**print modelImage**
template=cv2.imread(modelImage)
templateg = cv2.cvtColor(template,cv2.COLOR_BGR2GRAY)
keys = surf.detect(templateg)
keys,desc = surfDescriptorExtractor.compute(templateg, keys)
count = 0
for h,des in enumerate(desc):
des = np.array(des,np.float32).reshape((1,64))
retval, results, neigh_resp, dists = knn.find_nearest(des,1)
res,dist = int(results[0][0]),dists[0][0]
if dist<0.1: # draw matched keypoints in red color
count=count + 1
print "space"**
The important parts have asterisks. This is a portion of the code that was suppose to identify similarities among images of faces. What the code does is not important. The strange part is that this loop is executing 1 time for an array of size two.
The output is:
/home/lie/Desktop/dylan.jpg
/home/lie/Desktop/melissa.jpg
space
Notice that both strings in modelImages are printed before space. By the way this is part of a function that is called from a loop. This seems to be more of a python issue than an opencv issue. It almost seems like there is a hidden continue statment
Thanks

Categories

Resources