Python Forum
Stuck with using lists to solve task
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Stuck with using lists to solve task
#1
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. Undecided
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")
Reply
#2
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]
gery576 likes this post
Reply
#3
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.
gery576 likes this post
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
Reply
#4
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.
Reply
#5
At last an entertaining question, it's been a while.
I'm interested in the result, so here is my solution (True = open),
Anybody. ? Wink
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'.
Reply
#6
(Jan-16-2024, 06:57 AM)DPaul Wrote: I'm interested in the result, so here is my solution (True = open),
Anybody. ? Wink
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 »
Reply
#7
(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'.
Reply
#8
(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
Reply
#9
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.
Reply
#10
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'.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How to solve this task? DERO 2 1,809 Dec-06-2021, 07:15 PM
Last Post: BashBedlam
  simple task with lists... Maxwell123 3 2,393 Jun-27-2020, 01:00 PM
Last Post: GOTO10
  I need help to solve this task using while statement rico4pepe 6 9,282 Apr-02-2020, 11:34 AM
Last Post: pyzyx3qwerty

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020