logic

26 prisoners and a light bulb logic problem in python

I was sent a interesting logic problem by samsamsam which is as follows (or very similar):

Q: How can the prisoners tell, with certainty, that all 26 of them have visited the central living room with the light bulb.

Riddle:
26 prisoners are in solitary cells, unable to see, speak or communicate in any way from those solitary cells with each other. There’s a central living room with one light bulb; the bulb is initially off. No prisoner can see the light bulb from his own cell. Everyday, the warden picks a prisoner at random, and that prisoner goes to the central living room. While there, the prisoner can toggle the bulb if he or she wishes. Also, the prisoner has the option of asserting the claim that all 26 prisoners have been to the living room. If this assertion is false (that is, some prisoners still haven’t been to the living room), all 26 prisoners will be shot for their stupidity. However, if it is indeed true, all prisoners are set free. Thus, the assertion should only be made if the prisoner is 100% certain of its validity.

Solution

I won’t explain the solution in words as that might ruin it if you were planning on figuring it out, instead I have posted some python code that calculates the probability of number of days it will take.

# -*- coding: utf-8 -*-
from random import randint

bin=[]
binstep=50

# Loop 
for i in xrange(0,50000):

	nopris=26
	light=0
	count=0
	days=0

	# Create a set of prisoners with value 0 or 1
	# for having visited the room when light is off
	p=[]
	for i in range(0,nopris):
		p.append(0)

	# Until all prisoners have switched light on and have
	# been counted
	while count<nopris-1:
		x=randint(0,nopris-1)
		# First person to be picked is the counter
		if days==0:
			counter=x
			p[x]=1
		# Counter adds one if light is on and resets it
		elif x==counter and light==1:
			light=0
			count+=1
		# If light is off and prisoner hasn't turned light 
		# on before he does so
		elif p[x]==0 and light==0:
			p[x]=1
			light=1
		else:
			pass
		days+=1
		

	# Expand our bin if it isn't big enough
	while days>len(bin)*binstep:
		bin.append(0)
	bin[days/binstep]+=1	
	

# Just chucking data into a histogram type layout
# to speed up processing afterwards (I'm crap at
# openoffice stuff)
for i in range(0,len(bin)):
	print i*binstep+binstep/2,",",bin[i]

For 50k iterations I got the following output:

$ python prisoners.py
25 , 0
75 , 0
125 , 0
175 , 0
225 , 0
275 , 0
325 , 2
375 , 31
425 , 162
475 , 636
525 , 1659
575 , 3492
625 , 5448
675 , 7134
725 , 7755
775 , 7103
825 , 5758
875 , 4341
925 , 2884
975 , 1701
1025 , 909
1075 , 511
1125 , 255
1175 , 124
1225 , 63
1275 , 25
1325 , 4
1375 , 2
1425 , 1

Which shown as a histogram looks like:

Histogram for the 26 prisoners problem (50k iterations)

Histogram for the 26 prisoners problem (50k iterations)

Let me know how you’d improve this method or any other cool logic problems I can have a go at 🙂

Read More