How to resolve the algorithm Sailors, coconuts and a monkey problem step by step in the JavaScript programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Sailors, coconuts and a monkey problem step by step in the JavaScript programming language

Table of Contents

Problem Statement

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 he tosses it to a monkey and 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 in turn gets up 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 remaining coconuts are divided into five equal piles for each of the sailors, whereupon it is found that the pile of coconuts divides equally amongst the sailors with no remainder. (Nothing for the monkey in the morning.)

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Sailors, coconuts and a monkey problem step by step in the JavaScript programming language

About the code

The provided JavaScript code contains two main functions: wakeSplit and until (in the second code snippet only). These two functions perform tasks related to mathematical problem called 'wake Splitting'.

Wake Splitting

Wake Splitting is a puzzle where you have a certain number of nuts and an equal number of sailors, and each sailor has a depth to which they can dive. The goal is to find the minimum number of nuts needed such that each sailor can dive to their maximum depth and bring back exactly one nut.

The wakeSplit function:

The wakeSplit function takes three parameters:

  • intNuts: The total number of nuts.
  • intSailors: The number of sailors.
  • intDepth (optional): The depth of the sailors (defaults to the number of sailors).

The function calculates the portion of nuts that each sailor should get (portion) and the number of nuts that will remain (remain) after distributing the nuts evenly. It then checks the following conditions:

  • If the portion is less than or equal to 0, or if the remainder is not equal to 1 (when there are multiple depths) or 0 (when all depths are the same), the function returns null.
  • Otherwise, if there are multiple depths, it recursively calls itself with the following parameters:
    • intNuts: The number of nuts remaining after distributing the portion and the remainder.
    • intSailors: The number of sailors.
    • nDepth: The depth of the sailors reduced by 1.
  • If there are no multiple depths, it returns the number of nuts.

The until function (in the second code snippet only):

The until function is a generic utility function that takes two parameters:

  • p: A predicate function.
  • f: A mapping function.

The function applies the mapping function f repeatedly to the initial value x until the predicate function p returns true. It then returns the final value of x.

Putting it all together:

In the first code snippet, the wakeSplit function is used to calculate the minimum number of nuts needed for 5, 6, and 7 sailors. The main function in the second code snippet uses the until function to repeatedly apply the wakeSplit function with different values of intNuts until the wakeSplit function returns a non-null value.

Output:

Both code snippets produce the same output:

[3121, 233275, 823537]

These numbers represent the minimum number of nuts needed for 5, 6, and 7 sailors, respectively.

Source code in the javascript programming language

(function () {

    // wakeSplit :: Int -> Int -> Int -> Int
    function wakeSplit(intNuts, intSailors, intDepth) {
        var nDepth = intDepth !== undefined ? intDepth : intSailors,
            portion = Math.floor(intNuts / intSailors),
            remain = intNuts % intSailors;

        return 0 >= portion || remain !== (nDepth ? 1 : 0) ?
            null : nDepth ? wakeSplit(
                intNuts - portion - remain, intSailors, nDepth - 1
            ) : intNuts;
    }

    // TEST for 5, 6, and 7 intSailors
    return [5, 6, 7].map(function (intSailors) {
        var intNuts = intSailors;

        while (!wakeSplit(intNuts, intSailors)) intNuts += 1;

        return intNuts;
    });
})();


[3121, 233275, 823537]


(() => {
    "use strict";

    // wakeSplit :: Int -> Int -> Int -> Int
    const wakeSplit = intSailors =>
        (intNuts, intDepth) => {
            const
                nDepth = intDepth !== undefined ? (
                    intDepth
                ) : intSailors,
                portion = Math.floor(intNuts / intSailors),
                remain = intNuts % intSailors;

            return 0 >= portion || remain !== (
                nDepth ? (
                    1
                ) : 0
            ) ? (
                null
            ) : nDepth ? (
                wakeSplit(
                    intSailors
                )(
                    intNuts - portion - remain,
                    nDepth - 1
                )
            ) : intNuts;
        };

    // ---------------------- TEST -----------------------
    const main = () =>
        // TEST for 5, 6, and 7 Sailors
        [5, 6, 7].map(intSailors => {
            const intNuts = intSailors;

            return until(
                wakeSplit(intNuts)
            )(x => 1 + x)(intNuts);
        });


    // --------------------- GENERIC ---------------------

    // until :: (a -> Bool) -> (a -> a) -> a -> a
    const until = p =>
        // The value resulting from repeated applications
        // of f to the seed value x, terminating when
        // that result returns true for the predicate p.
        f => x => {
            let v = x;

            while (!p(v)) {
                v = f(v);
            }

            return v;
        };

    // MAIN ---
    return main();
})();


[3121, 233275, 823537]


  

You may also check:How to resolve the algorithm Luhn test of credit card numbers step by step in the Haskell programming language
You may also check:How to resolve the algorithm Generator/Exponential step by step in the OCaml programming language
You may also check:How to resolve the algorithm Increment a numerical string step by step in the Rust programming language
You may also check:How to resolve the algorithm Loops/Do-while step by step in the GAP programming language
You may also check:How to resolve the algorithm 21 game step by step in the Commodore BASIC programming language