100 Prisoners and a light bulb

4

100 Prisoners and a light bulb

You may have seen this puzzle over on the puzzles exchange or perhaps heard it somewhere else. If you are unfamiliar with this puzzle check out:

100 Prisoners and a Light bulb

The gist of this puzzle is that there are 100 prisoners, each one is separated from one another and must go into a room one at a time. The prisoner selected to go into the room is selected uniformly at random each time. In this room there is a light bulb and a switch, the prisoner must either turn the light on, turn the light off, or do nothing. At any given time one of the prisoners may say that all 100 prisoners have been in the room at least once. If he is correct they are all freed, if they are incorrect they are all killed. Prior to being separated the group of prisoners may discuss a strategy and they may never communicate again.

One working strategy:

The prisoners select one prisoner as the leader. When anyone else enters the room they do nothing unless it's the first time they enter the room and the light is off; in that case, they turn the light on. When the leader enters the room and the light is on then he turns the light off and maintains a counter, adding one to it. Once he counts 99 (the light has been turned on once for every other prisoner) he knows that all 100 (including himself) have been in the room, and he claims their freedom.

The code challenge:

Take no input into your program.

Simulate the strategy and output the number of times a prisoner entered the room before the leader claimed their freedom.

n represents the number of times a prisoner enters the room for the first time.
k represents the leader of the prisoners.
d represents a data structure holding boolean values for each prisoner.
l represents a boolean value to hold the state of the light bulb.
i represents the number of iterations of the puzzle before it ends.

Examples:

Randomly pick an element from d. if l is false and k[rand] is false then l is now true and d[rand] is true. i = i + 1

Randomly pick an element from d. if l is true and d[rand] is false then do nothing. i = i + 1

Randomly pick an element from d. if l is false and d[rand] is true then do nothing. i = i + 1

Randomly pick an element from d. if d[rand] = k and if l is false then do nothing. i = i + 1

Randomly pick an element from d. if d[rand] = k and if l is true, set l to false, add 1 to n. i = i + 1

Randomly pick an element from d. if d[rand] = k and if l is true and n = 99 then end puzzle. i = i + 1 and output i.

this is so the shortest code wins. Have Fun!

jacksonecac

Posted 2016-10-24T12:09:43.193

Reputation: 2 584

4Shouldn't the close vote people add some useful comment? – None – 2016-10-24T12:23:28.407

@Lembik I would hope so, I am watching the close votes pile up and as I read my question over and over I am struggling to find a reason. – jacksonecac – 2016-10-24T12:24:35.110

It's probably not clear what is asked. I'll try to add an answer, but I'm not too sure too – edc65 – 2016-10-24T13:13:42.137

7Better a close vote with no explanation than nothing at all. If it results in the question being put on hold then a reason will be displayed, and others can comment with suggestions for improvement. The idea of putting on hold is to prevent answers coming in until the challenge is ready, so answers aren't invalidated by any changes that need to be made to the wording. It's a positive thing. – trichoplax – 2016-10-24T13:15:11.953

@trichoplax point taken, however a close vote and a comment is much more helpful to the OP to make corrects faster and easier. – jacksonecac – 2016-10-24T13:20:12.887

3What needs to be quick is putting on hold. That prevents any answers so then improvements can be made slowly until it's ready. I've just read through and decided it isn't yet clear to me, so I've voted to put on hold as unclear. That was the urgent bit. Now I can take the time to try and explain what I found unclear so the challenge can be edited and then reopened. – trichoplax – 2016-10-24T13:24:36.063

Randomly select one element from an array of 100 where one is the leader For this I wasn't sure if "one is the leader" meant that one should also be randomly selected, or whether the leader is always at index 1. – trichoplax – 2016-10-24T13:29:59.827

4

For future challenges, I recommend leaving them in the sandbox for a few days to gather feedback before posting here on main. I've done this for all of my challenges except one, and that one didn't go well... I find the sandbox works well for fine tuning and potentially making changes that are harder to make after posting.

– trichoplax – 2016-10-24T13:34:48.380

I have some problems reading the challenge (and the edit). Probably due to difficulties with the english language. But overall the challenge seems clear. @trichoplax do you really not understand Randomly select one element from an array of 100 where one is the leader as Randomly select one element from an array of 100 so that this one is the leader? – edc65 – 2016-10-24T13:43:11.267

In fact, after the edit it's so less clear. The first few paragraph of the added section are a total mess. From the initial text, is seems that the leader is chosen at random from the 100 prisoners, but now ... I cannot tell – edc65 – 2016-10-24T13:48:11.977

@edc65 The sentence didn't make immediately clear to me what the meaning was, so I'd like to see it replaced with an unambiguous one. Removing such ambiguities will make the challenge read more smoothly, which will increase the number of people who answer, which is better for everyone. – trichoplax – 2016-10-24T13:48:51.383

I don't mind how long it takes to get it clear, or how many edits. There's no rush. – trichoplax – 2016-10-24T13:50:13.117

2The hidden quoted block seems to be essential rather than optional. I think it should be a non-hidden quoted block. Also, in this challenge I find it hard to decide when an answer is correct – Luis Mendo – 2016-10-24T13:52:57.343

4

It's worth considering this meta post on non observable requirements. Is it a requirement that code follows the steps described and uses the same method? Or is any code that gives output with the equivalent probability distribution valid?

– trichoplax – 2016-10-24T13:54:31.380

@trichoplax Good point. I was about to point out the same, but the linked post explains it much better – Luis Mendo – 2016-10-24T13:55:58.240

Hopefully the new edit makes things a little more clear. – jacksonecac – 2016-10-24T14:09:01.200

1If the edit is to correct a previous unclear wording, then it would be better to remove the previous wording and just settle on one new wording that is unambiguous. The old versions are all stored in the edit history, so it isn't necessary to have "Edit" as a heading - you can simply rewrite and delete anything no longer required. – trichoplax – 2016-10-24T14:42:41.197

"Output the number of times a prisoner enters the room after it is guaranteed they have all been in the room at least once." Huh? Guaranteed by what process? Don't they claim their freedom once it's guaranteed that they've all been in the room at least once, so that the output would be 0 unconditionally? – Peter Taylor – 2016-10-24T14:49:34.577

@PeterTaylor Output the number of times a prisoner enters the room after the prisoners have gained their freedom. n iterations. – jacksonecac – 2016-10-24T14:51:06.197

Do they not stop entering the room when they're free? – Peter Taylor – 2016-10-24T14:53:34.727

They do not keep entering no.. while(not free){iterate, n++} return n; – jacksonecac – 2016-10-24T14:54:58.983

I believe "the number of times a prisoner enters the room after the prisoners have gained their freedom" is intended to mean "the total number of times a prisoner has entered the room when the prisoners gain their freedom". The current phrasing gives a meaning that is almost opposite, so I feel this challenge would benefit from being on hold longer while this is discussed. – trichoplax – 2016-10-24T14:59:15.890

@Emigna no it isn't as the leader will be the last random chosen index. – jacksonecac – 2016-10-24T15:06:26.590

2@jacksonecac That's not true. The light will be turned on by the 99th prisoner, and the leader has already entered the room, but needs to enter again after the light was turned on the 99th time in order to count the last prisoner, even though they've all been in the room. Also, it's probably helpful to note in the question that if you're doing it right, you should be getting a number ~10000. The algorithm is probably O(n^2) – mbomb007 – 2016-10-24T15:07:39.170

@mbomb007 so the i.e. is correct the definition isn't. – jacksonecac – 2016-10-24T15:08:29.273

@jacksonecac So it's not while (not free) {...}, it's really while (count < 99) {...}, and you have to increment that count whenever the leader turns off the light. – mbomb007 – 2016-10-24T15:11:04.833

@mbomb007 not free and count < 99 are synonymous. You can't be free if count < 99 and you can't be in prison if count > 98 – jacksonecac – 2016-10-24T15:12:53.040

1@jacksonecac The leader doesn't know "magically" when the 99th prisoner has turned on the light. The leader is chosen randomly, so you have to wait for the leader to be chosen and see that the light is on for the 99th time. We're just trying to be clear for users who might try to implement the algorithm wrong. The prisoners are not freed until the leader has entered the room and counted 99, which is different than checking whether every prisoner has been in the room and flipped the light with your code. – mbomb007 – 2016-10-24T15:24:43.650

@mbomb007 that depends entirely on when you increment n. Which should only be when the leader is in the room. n is set to 99 when the leader has entered the room for the last time and when he counts to 99. Once he counts to 99, the program should exit and return the number iterations, n. – jacksonecac – 2016-10-24T15:27:45.140

Correct. But it wasn't clear from your description of the challenge. "Repeat this process until all elements are true and output how many iterations there were." - this description is wrong – mbomb007 – 2016-10-24T15:30:12.620

It seems that we now know what the requirement is, but the challenge wording doesn't make that clear for new people arriving, so it needs to be edited to be short, clear and unambiguous. – trichoplax – 2016-10-24T16:38:14.253

The comment "n is set to 99 when the leader has entered the room for the last time ... the program should exit and return the number of iterations, n." means "always output 99", which isn't what is intended. This is just a typo, but it's these little things that need to be tidied up to avoid confusing people. We're getting there but this isn't ready yet. – trichoplax – 2016-10-24T16:40:42.247

This needs re-opened or deleted. I cannot do either. – jacksonecac – 2016-10-25T14:58:27.440

Answers

2

Python 2, 133 bytes

I used binary operations to keep track. I had if(i<1)*b:... but I think that's an off-by-one error. Not sure.

from random import*
L=2**99-1
b=l=c=0
while l<99:
    i=randint(0,99)
    if(i>98)*b:b=0;l+=1
    elif(L&1<<i)*(b<1):b=1;L|=1<<i
    c+=1
print c

Try it online

Less golfed:

from random import*
L=[1for _ in range(100)]
b=l=c=0
while l<99:                         # check leader's count of prisoners
    i=randint(0,99)
    if b and i==99:b=0;l+=1         # if light on and leader, turn off and count
    elif L[i] and b<1:b=1;L[i]=0    # else if new prisoner and light off, turn on
    c+=1                            # iterations
print c

mbomb007

Posted 2016-10-24T12:09:43.193

Reputation: 21 944

2

CJam (26 bytes)

100,1a*0-{{__100mr>!}g;}%,

Dissection

100,1a*0-  e# Generate a list [1 1 1 2 1 3 1 ... 98 1 99] representing (in reverse order)
           e# the number of prisoners at each step who can advance to the next step
{          e# For each element in the list...
  {        e#   While we fail to select a suitable prisoner...
    __     e#     dup twice: once to leave on stack as a counter, and once for comparison
    100mr  e#     Select a random prisoner
    >!     e#     Test whether that prisoner is suitable
  }g
  ;        e#  Pop to avoid overcounting by one
}%
,          e# Count up the values we left on the stack

Peter Taylor

Posted 2016-10-24T12:09:43.193

Reputation: 41 901

0

Python 3, 164 bytes, aka garbage :)

from random import*
d={}
a=l=n=p=0
for i in range(100):
 d[i]=0
while n<100:
 a+=1
 p=randint(0,99)
 if p==50:
  l=0
 else:
  l=1
 if d[p]==0:
  d[p]=1
  n+=1
print(a)

user78881

Posted 2016-10-24T12:09:43.193

Reputation:

I think you've misunderstood the problem. This always prints 100, while the number of times the prisoners have entered the room is variable. – Dennis – 2018-05-10T15:34:47.363

it only prints at the end like @mbomb's answer – None – 2018-05-10T16:48:38.113

As it should. But your answer counts the number of different prisoners that have entered the room, so the result is always 100. – Dennis – 2018-05-10T16:56:43.340

Oh You want the iterations, I see. – None – 2018-05-10T16:57:18.463

That's better, but the output is still incorrect. Compare your answer with mbomb's.

– Dennis – 2018-05-10T17:08:10.717

You're ignoring a large part of the problem and only check if all 100 have already entered the room. The problem is a bit more complex than that. – Dennis – 2018-05-10T17:09:22.357

I think i get it now will edit later – None – 2018-05-10T18:22:40.967

0

Perl 5, 77 bytes

++$i,($s=0|rand 100)?!$a[$s]&&!$l++&&$a[$s]++:$l&&++$n&($l=0)while$n<99;say$i

Try it online!

Xcali

Posted 2016-10-24T12:09:43.193

Reputation: 7 671