Search code examples
javascriptalgorithmdata-structureslogicpseudocode

Assistance with pseudocoding


From the viking code school engineering principles prep course:

10 friends are sitting in a circle around a table and decide to play a new game. In it, they count up through the numbers from 1 to 100. The first person says "1", the second says "2" and so on... but with a few catches:

Whenever the number is divisible by 7, they switch directions. So person 6 will say "6", person 7 will say "7", then person 6 again will say "8". Whenever the number is divisible by 11, they skip the next person.

Pseudocode a program that will determine which player is the one to say "100". How does one begin figuring out the logic to this one?


Solution

  • Oftentimes in programming, choosing a suitable data structure can drastically simplify the algorithm for solving a particular problem. Your problem can be elegantly solved using a circular doubly-linked list. Since there are ten friends sitting in a circle, we'll put them into the linked list as follows:

                       next   +-------+   next
                   +--------->|       |----------+
                   |          |   1   |          |
                   |       +--|       |<--+      v
               +-------+   |  +-------+   |  +-------+
               |       |   |              |  |       |
           +-->|  10   |<--+ prev    prev +--|   2   |---+
           |   |       |                     |       |   |
      next |   +-------+                     +-------+   | next
           |       |                             ^       v
       +-------+   | prev                   prev |   +-------+
       |       |   |                             |   |       |
       |   9   |<--+                             +---|   3   |
       |       |                                     |       |
       +-------+                                     +-------+
         ^   |                                         ^   |
    next |   | prev                               prev |   | next
         |   v                                         |   v
       +-------+                                     +-------+
       |       |                                     |       |
       |   8   |---+                             +-->|   4   |
       |       |   |                             |   |       |
       +-------+   | prev                   prev |   +-------+
           ^       v                             |       |
      next |   +-------+                     +-------+   | next
           |   |       |                     |       |   |
           +---|   7   |--+ prev    prev +-->|   5   |<--+
               |       |  |              |   |       |
               +-------+  |   +-------+  |   +-------+
                   ^      +-->|       |--+       |
                   |          |   6   |          |
                   +----------|       |<---------+
                       next   +-------+   next
    

    For example, in JavaScript you could write it as:

    var firstFriend = toList([1,2,3,4,5,6,7,8,9,10]);
    
    function Node(prev, data, next) {
        this.prev = prev;
        this.data = data;
        this.next = next;
    }
    
    function toList(array) {
        var length = array.length;
        if (length === 0) throw new Error("empty array");
        var root = new Node(null, array[0], null), node = root, i = 1;
        while (i < length) node = node.next = new Node(node, array[i++], null);
        return (root.prev = node).next = root;
    }
    

    Now, we can solve the problem using two mutually recursive functions: one for the friends counting in the forward direction and one for the friends counting in the reverse direction:

    var answer = forward(1, firstFriend);
    
    function forward(count, friend) {
        if (count      === 100) return friend.data;
        if (count % 7  === 0 &&
            count % 11 === 0)   return reverse(count + 1, friend.prev.prev);
        if (count % 7  === 0)   return reverse(count + 1, friend.prev);
        if (count % 11 === 0)   return forward(count + 1, friend.next.next);
                                return forward(count + 1, friend.next);
    }
    
    function reverse(count, friend) {
        if (count      === 100) return friend.data;
        if (count % 7  === 0 &&
            count % 11 === 0)   return forward(count + 1, friend.next.next);
        if (count % 7  === 0)   return forward(count + 1, friend.next);
        if (count % 11 === 0)   return reverse(count + 1, friend.prev.prev);
                                return reverse(count + 1, friend.prev);
    }
    

    Putting it all together, the answer is 1:

    var firstFriend = toList([1,2,3,4,5,6,7,8,9,10]);
    
    var answer = forward(1, firstFriend);
    
    alert(answer);
    
    function Node(prev, data, next) {
        this.prev = prev;
        this.data = data;
        this.next = next;
    }
    
    function toList(array) {
        var length = array.length;
        if (length === 0) throw new Error("empty array");
        var root = new Node(null, array[0], null), node = root, i = 1;
        while (i < length) node = node.next = new Node(node, array[i++], null);
        return (root.prev = node).next = root;
    }
    
    function forward(count, friend) {
        if (count      === 100) return friend.data;
        if (count % 7  === 0 &&
            count % 11 === 0)   return reverse(count + 1, friend.prev.prev);
        if (count % 7  === 0)   return reverse(count + 1, friend.prev);
        if (count % 11 === 0)   return forward(count + 1, friend.next.next);
                                return forward(count + 1, friend.next);
    }
    
    function reverse(count, friend) {
        if (count      === 100) return friend.data;
        if (count % 7  === 0 &&
            count % 11 === 0)   return forward(count + 1, friend.next.next);
        if (count % 7  === 0)   return forward(count + 1, friend.next);
        if (count % 11 === 0)   return reverse(count + 1, friend.prev.prev);
                                return reverse(count + 1, friend.prev);
    }

    Solving it manually to check for correctness:

    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  | 10  |
    +=====+=====+=====+=====+=====+=====+=====+=====+=====+=====+
    |  1  |  2  |  3  |  4  |  5  |  6  |  7  |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 12  |     | 11  | 10  |  9  |  8  |     |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     |     |     | 14  | 13  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     |     |     |     | 15  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 16  | 17  | 18  | 19  | 20  | 21  |     |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 25  | 24  | 23  |     | 22  |     |     |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     |     | 28  | 27  | 26  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     |     |     | 29  | 30  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 31  | 32  | 33  |     | 34  | 35  |     |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 40  | 39  | 38  | 37  | 36  |     |     |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     |     |     | 42  | 41  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     |     |     |     | 43  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 44  |     | 45  | 46  | 47  | 48  | 49  |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 55  | 54  | 53  | 52  | 51  | 50  |     |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     |     |     | 56  |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     |     |     |     | 57  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 58  | 59  | 60  | 61  | 62  | 63  |     |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 67  |     | 66  | 65  | 64  |     |     |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     |     | 70  | 69  | 68  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     |     |     | 71  | 72  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 73  | 74  | 75  | 76  | 77  |     |     |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 80  | 79  | 78  |     |     |     |     |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     | 84  | 83  | 82  | 81  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     |     | 85  | 86  | 87  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 88  |     | 89  | 90  | 91  |     |     |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 95  | 94  | 93  | 92  |     |     |     |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     |     | 98  | 97  | 96  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |     |     |     |     |     |     |     |     | 99  |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 100 |     |     |     |     |     |     |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    

    Although this solution is recursive, every recursive program can be converted into a non-recursive program using a stack. The pseudocode for this program is very simple. Hence, I'll leave it as an exercise for you to figure out.