Posts: 1
Threads: 1
Joined: Jan 2024
Jan-15-2024, 11:03 AM
(This post was last modified: Jan-15-2024, 11:03 AM by gery576.)
Hi everyone,
I am struggling with solving below task which I received as a home assignment in my Python course to practice lists (I've been learning Python loosely for a few months).
Task description (translated from Hungarian):
"On the occasion of the Turkish Sultan's birthday, he sent his first servant to the prison to open the doors of all 100 cells. The Sultan had his second servant close every second door after him. With the third servant, the Sultan made him open every third door in case it was closed, and closed it if it was found open. The fourth slave changed the state of every fourth door, and so on, up to the 100th slave. Which cell doors were left open at the end?"
This is where I got so far:
Basically I was trying to use for loops to close/open every 2nd/3rd/4th doors in a sequence. But this only gets me until the fourth slave while the task requires 100 slaves and also it doesn't quite seem correct up to that point either. So I'm out of my depth at this point.
Could anyone help me with finding the solution? I guess it needs some other approach...
("t" is list)
t=[1]*100
for i in range(0,len(t),2):
t[i]=0
for i in range(0,len(t),3):
if t[i]==1:
t[i]=0
else:
t[i]=1
for i in range(0,len(t),4):
if t[i]==1:
t[i]=0
else:
t[i]=1
print(t)
for i in range(len(t)):
if t[i]==1:
print(f"{i+1}. cell: open")
else:
print(f"{i+1}. cell: closed")
Posts: 12,031
Threads: 485
Joined: Sep 2016
Jan-15-2024, 11:46 AM
(This post was last modified: Jan-15-2024, 11:47 AM by Larz60+.)
this is much easier if you define a function:
example:
# zero = open, 1 = close
doors = [1] * 100 # assumption all doors closed at start ... change to 0 if all open
def change_door(door_list, action_every=1, open_close='open'):
doornum = action_every - 1
while doornum < len(doors):
if open_close == 'open':
doors[doornum] = 0
else:
doors[doornum] = 1
doornum += action_every
# example open every third door:
change_door(doors, action_every=3, open_close='open')
print(doors) After running example doors:
Output: [1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1]
Posts: 453
Threads: 16
Joined: Jun 2022
Jan-15-2024, 01:48 PM
(This post was last modified: Jan-15-2024, 01:49 PM by rob101.)
Hi and welcome.
No doubt there are a few different ways this could be done, such as using 0 and 1 for the status of the cell doors. Then, you could use if door: which would return True or False for 1 and 0 . That way, you don't need to code if door == 0: , but I would go with a more literal approach and you may not have been introduced to constructing custom functions yet.
I would use the step parameter of the range function. Have you learned about that?
As an example, this will close every other door, as the second servant has been asked to do.
door_open = "open" # door is open
door_closed = "closed" # door is closed
cell_doors = [door_open]*100 # open all the doors
for door in range(1, 100, 2): # close every second door
if cell_doors[door] == door_open:
cell_doors[door] = door_closed The above is where I would start from: it sets all the doors to 'open' and then closes every second door. Technically, you don't need the if: branch at this stage, because we know the status from the get-go, but I've put it in, for completeness.
Caveat: this potential solution is simply my first thoughts and I'll have a think some more about if it's going to be practical or not.
To add: I think this could work, if you set up servants = range(1, 101) then nest for servant in servants: with what I have above, using servant as the 'step' parameter, and simply alternate each door (if it's closed, open; if it's open, close it). For that to work, start with all of the doors closed, not open, and 0 as the first door, not 1 .
I can't be more specific, without breaking the Forum rules; I'm close to doing that, as it is.
Sig:
>>> import this
The UNIX philosophy: "Do one thing, and do it well."
"The danger of computers becoming like humans is not as great as the danger of humans becoming like computers." :~ Konrad Zuse
"Everything should be made as simple as possible, but not simpler." :~ Albert Einstein
Posts: 1,950
Threads: 8
Joined: Jun 2018
If using 0 and 1 to represent closed / open doors it's simple to toggle value using XOR (bitwise exclusive OR). Something along those lines (just an idea, haven't tested it):
# 1 means door open, 0 mean doors closed
# create list of 100 doors open
doors = [1] * 100
# toggle every second value
for i in range(1, 100, 2):
doors[i] ^= True
# toggle nth value with nth step
for n in range(2, 101):
for i in range(n, 100, n):
doors[i] ^= True
print(doors)
print(sum(doors))
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy
Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Posts: 741
Threads: 122
Joined: Dec 2017
At last an entertaining question, it's been a while.
I'm interested in the result, so here is my solution (True = open),
Anybody. ?
1 True
4 True
9 True
16 True
25 True
36 True
49 True
64 True
81 True
100 True
Paul.
It is more important to do the right thing, than to do the thing right.(P.Drucker)
Better is the enemy of good. (Montesquieu) = French version for 'kiss'.
Posts: 4,790
Threads: 76
Joined: Jan 2018
Jan-16-2024, 08:33 AM
(This post was last modified: Jan-16-2024, 08:35 AM by Gribouillis.)
(Jan-16-2024, 06:57 AM)DPaul Wrote: I'm interested in the result, so here is my solution (True = open),
Anybody. ?  I think the result is True if the number of divisors of n is odd. The number of divisors of a number is given by the sequence https://oeis.org/A000005. This page says
oeis.org Wrote:a(n) is odd iff n is a square. All of this needs to be clarified.
This page also contains a python code that uses sympy to get the number of divisors of a number.
« We can solve any problem by introducing an extra level of indirection »
Posts: 741
Threads: 122
Joined: Dec 2017
Jan-16-2024, 08:44 AM
(This post was last modified: Jan-16-2024, 08:45 AM by DPaul.)
(Jan-16-2024, 08:33 AM)Gribouillis Wrote: All of this needs to be clarified. I interpreted the problem as:
"...The fourth slave changed the state of every fourth door, and so on, up to the 100th ..."
The 5th every 5th door
The 6th every 6th door
....
The 100th every 100th door.
Or ?
Paul
It is more important to do the right thing, than to do the thing right.(P.Drucker)
Better is the enemy of good. (Montesquieu) = French version for 'kiss'.
Posts: 453
Threads: 16
Joined: Jun 2022
Jan-16-2024, 12:54 PM
(This post was last modified: Jan-16-2024, 12:54 PM by rob101.)
(Jan-16-2024, 08:44 AM)DPaul Wrote: (Jan-16-2024, 08:33 AM)Gribouillis Wrote: All of this needs to be clarified. I interpreted the problem as:
"...The fourth slave changed the state of every fourth door, and so on, up to the 100th ..."
The 5th every 5th door
The 6th every 6th door
....
The 100th every 100th door.
Or ?
Paul
Yeah, I came to the same conclusion.
My output is a little more "verbose":
Assuming that we don't use 'zero indexing', rather the first door is #1
Output: Door: 1 - open
Door: 4 - open
Door: 9 - open
Door: 16 - open
Door: 25 - open
Door: 36 - open
Door: 49 - open
Door: 64 - open
Door: 81 - open
Door: 100 - open
Sig:
>>> import this
The UNIX philosophy: "Do one thing, and do it well."
"The danger of computers becoming like humans is not as great as the danger of humans becoming like computers." :~ Konrad Zuse
"Everything should be made as simple as possible, but not simpler." :~ Albert Einstein
Posts: 1,094
Threads: 143
Joined: Jul 2017
Maybe like this:
# first servant opens all doors
tstart = ['open' for i in range(0, 100)]
# all doors are open, second servant closes every second door and so on
def change(num):
for i in range(num, len(tstart), num + 1):
if tstart[i] == 'open':
tstart[i] = 'closed'
else:
tstart[i] = 'open'
# all servants except the first servant
for j in range(1, 100):
change(j)
count = 0
for i in range(0, 100):
if tstart[i] == 'open':
count +=1
print(f'Finally, {count} doors are still open. Mean old Sultan! Unhappy Birthday!') Not sure if j needs to go up to 99, check that.
Posts: 741
Threads: 122
Joined: Dec 2017
I find it less complicated that it seems.
Why it is called an exercise on lists, dunno...?
I think that starting like this
open = True
closed = not open
cells = [closed] * 100 saves you at least 10 lines of code.
(you save some if .. else statements)
I do use "enumerate", not knowing if that is allowed.
What is our friend the TS doing in the mean time?
Paul
It is more important to do the right thing, than to do the thing right.(P.Drucker)
Better is the enemy of good. (Montesquieu) = French version for 'kiss'.
|