Sailors, coconuts and a monkey problem

From Rosetta Code
Revision as of 20:00, 1 May 2015 by rosettacode>Paddy3118 (New draft task and Python solution.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Sailors, coconuts and a monkey problem is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Five sailors are shipwrecked on an island and collect a large pile of coconuts during the day. That night the first sailor wakes up and decides to take his first share early so tries to divide the pile of coconuts equally into five piles but finds that there is one coconut left over so tosses it to a monkey, he then hides "his" one of the five equally sized piles of coconuts and pushes the other four piles together to form a single visible pile of coconuts again and goes to bed.

To cut a long story short, each of the sailors gets up singly, once during the night and performs the same actions of dividing the coconut pile into five, finding that one coconut is left over and giving that single remainder coconut to the monkey.

In the morning (after the surreptitious and separate action of each of the five sailors during the night), The pile of coconuts are divided into five equal piles for each of the sailors and whereupon it is found that the pile of coconuts divides equally amongst the sailors with no remainder. (Nothing for the monkey in the morning).

The task
  1. Calculate the minimum size of the initial pile of coconuts collected during the first day.
  2. Use a method that assumes an answer then applies the constraints of the tale to see if it is correct. (I.e. no applying some formula that generates the correct answer without integer divisions and remainders and tests on remainders; but constraint solvers are allowed).
  3. Calculate the size of the initial pile of coconuts if Six sailors were marooned and went through a similar process (but split into six piles instead of five of course).
  4. Show your answers here.
Extra credit (optional)
  • Give some indication of the number of coconuts each sailor hides during the night.
Note
  • Of course the tale is told in a world where the collection of any amount of coconuts in a day and multiple divisions of the pile, etc can occur in time fitting the story line, so as not to affect the mathematics.
  • The tale is also told in a version where the monkey also gets a coconut in the morning. This is not that tale!

C.f:

Python

Python: Procedural

<lang python>def monkey_coconuts(sailors=5):

   "Parameterised the number of sailors using an inner loop including the last mornings case"    
   nuts = sailors
   while True:
       n0, wakes = nuts, []
       for sailor in range(sailors + 1):
           portion, remainder = divmod(n0, sailors)
           wakes.append((n0, portion, remainder))
           if portion <= 0 or remainder != (1 if sailor != sailors else 0):
               nuts += 1
               break
           n0 = n0 - portion - remainder
       else:
           break
   return nuts, wakes

if __name__ == "__main__":

   for sailors in [5, 6]:
       nuts, wake_stats = monkey_coconuts(sailors)
       print("\nFor %i sailors the initial nut count is %i" % (sailors, nuts))
       print("On each waking, the nut count, portion taken, and monkeys share are:\n ", 
             ',\n  '.join(repr(ws) for ws in wake_stats))</lang>
Output:
For 5 sailors the initial nut count is 3121
On each waking, the nut count, portion taken, and monkeys share are:
  (3121, 624, 1),
  (2496, 499, 1),
  (1996, 399, 1),
  (1596, 319, 1),
  (1276, 255, 1),
  (1020, 204, 0)

For 6 sailors the initial nut count is 233275
On each waking, the nut count, portion taken, and monkeys share are:
  (233275, 38879, 1),
  (194395, 32399, 1),
  (161995, 26999, 1),
  (134995, 22499, 1),
  (112495, 18749, 1),
  (93745, 15624, 1),
  (78120, 13020, 0)

Python: Recursive

<lang python>def wake_and_split(n0, sailors, depth=None):

   if depth is None:
       depth = sailors
   portion, remainder = divmod(n0, sailors)
   if portion <= 0 or remainder != (1 if depth else 0):
       return None
   else:
       return n0 if not depth else wake_and_split(n0 - portion - remainder, sailors, depth - 1)
       
   

def monkey_coconuts(sailors=5):

   "Parameterised the number of sailors using recursion including the last mornings case"    
   nuts = sailors
   while True:
       if wake_and_split(n0=nuts, sailors=sailors) is None:
           nuts += 1
       else:
           break
   return nuts

if __name__ == "__main__":

   for sailors in [5, 6]:
       nuts = monkey_coconuts(sailors)
       print("For %i sailors the initial nut count is %i" % (sailors, nuts))

</lang>

Output:
For 5 sailors the initial nut count is 3121
For 6 sailors the initial nut count is 233275