0

Hi I'm learning to code in python and thought it would be cool to automate a task I usually do for my room mates. I write out a list of names and the date for each month so that everyone knows whos turn it is for dishes. Here's my code:

def dish_day_cycle(month, days):
    print('Dish Cycle For %s:' % month)
    dish_list = ['Jen', 'Zack', 'Hector', 'Arron']
    days = days + 1

    for day in range(1, days):
        for i in dish_list:
            print('%s %s : %s' % (month, day, i))

The problem is that it repeats everyone's name for each and every day, obviously not what I want. I need it to print only one name per day. Not this:

>>> dish_day_cycle(month, days)
Dish Cycle For December:

December 1 : Jen
December 1 : Zack
December 1 : Hector
December 1 : Arron
December 2 : Jen
December 2 : Zack
December 2 : Hector
December 2 : Arron
December 3 : Jen
December 3 : Zack
December 3 : Hector
December 3 : Arron
December 4 : Jen
December 4 : Zack
December 4 : Hector
December 4 : Arron
December 5 : Jen
December 5 : Zack
December 5 : Hector
December 5 : Arron

Please let me know how I could correct this function to work properly.

Adam
  • 709
  • 4
  • 16
TheEngineer
  • 31
  • 1
  • 6

3 Answers3

5

You used a nested for loop, therefore for every day - each of the names is printed along with that day. Use only the outer loop, and calculate who's turn it is. should be something like:

for day in range(1, days):
    print('%s %s : %s' % (month, day, dish_list[day % len(dish_list)]))

assuming your roomates & you split the dishing equally.

motyzk
  • 366
  • 3
  • 14
  • Nice, but if it were to start at the beginning of the list, the index should start at `0`. I.e. `dish_list[(day - 1) % len(dish_list)]` – Adam Dec 29 '18 at 01:00
  • 1
    It doesn't matter...I mean, maybe it matters, but I aim to solve the technical problem, not to determine whether Jen or Zack wash the dishes in the first day of December. – motyzk Dec 29 '18 at 01:04
  • Merely for completeness given the example starts with Jen. – Adam Dec 29 '18 at 01:06
  • 2
    For added fairness: a month-based list will skip a few persons at the turn of a month. You could use a nth-day-of-the-year based list, but then people might complain at the turn of the year `:)` Perhaps using `%` on a Unix time, which has a fixed starting point, is the most fair in the short run. (It might get complicated around January 19, 2038.) – Jongware Dec 29 '18 at 01:12
  • 1
    Thanks this solved the problem and works perfectly. I did need to change the part that Adam suggested in order to start the list with Jen. I would appreciate if you could explain how this code works to calculate who's turn it is, as I am learning python and would like to understand it. – TheEngineer Dec 29 '18 at 01:29
  • The `%` is the modulus operator, and returns the remainder. Refer to https://stackoverflow.com/questions/4432208/how-does-work-in-python for more details. – Adam Dec 29 '18 at 01:46
1

You can loop through both lists together and repeating the shorter with itertools.cycle:

import itertools
for day, person in zip(range(1, days), itertools.cycle(dish_list)):
     print('{} {} : {}'.format(month, day, person))

Update:

zip will pair elements in the two iterables--range object of days and dish_list--to create a new list of tuple pairs from the two iterables. However, zip only creates a list up to the shortest iterable. itertools.cycle circumvents this problem so zip cycles back to through dish_list. The for loop will now cycle through these two together, rather than in a nested fashion in your original code.

Documentation will probably explain better than I just did: zip, itertools.cycle

busybear
  • 10,194
  • 1
  • 25
  • 42
  • This solution also works perfectly by busybear. Thank you and could you please explain what the pieces are doing. – TheEngineer Dec 29 '18 at 01:45
1

The problem is that you're iterating over the days and then for over the list of names. Imagine running line by line because a for loop only repeats after it has gotten to the end of an item. So you've said in your function, for each day each person has to do the dishes which is why you have all this repetition.

Much easier would be to only have one for loop, and add 1 to day and to dish_list inside that loop as such

person = 0 # this will serve as the index of the list

for day in range(days):
    print("%s %s : %s" % (month, day + 1, dish_list[person]))

    if person == 3:
        person = 0
    else:
        person += 1

Also just to point out, there should be an indent after defining your function otherwise it will throw off an error. Hope this helps

Tom_G_99
  • 461
  • 1
  • 5
  • 13