Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looping over numbers

So this is the question that is given.

You are in a room with a circle of 100 chairs. The chairs are numbered sequentially from 1 to 100.

At some point in time, the person in chair #1 will be asked to leave. The person in chair #2 will be skipped, and the person in chair #3 will be asked to leave. This pattern of skipping one person and asking the next to leave will keep going around the circle until there is one person left, the survivor.

And this is the answer I came up with. I believe this is the right answer, I've done it on paper about 10 times as well and came up with 74 every time. Is this a trick question or something? Because I'm not sure what to do from here.

Here is the jsfiddle http://jsfiddle.net/cQUaH/

var console = {
    log : function(s) {
        document.body.innerHTML += s + "<br>";
    }
};

var chairArr = [];
for (var i = 1; i <= 100; i++){
    chairArr.push(i);
}

var j = 2;
while(chairArr.length > 1) {
    console.log('removing ' + chairArr[j]);
    chairArr.splice(j, 1);
    j++;
    if(j >= chairArr.length) {
       console.log('--- Finished pass');
       console.log('--- Array state:');
       console.log(chairArr);
       j = (j == chairArr.length) ? 0 : 1;   
    } 
}
console.log('--- Final result: ' + chairArr); 
//result 74
like image 423
user2677350 Avatar asked Sep 07 '13 01:09

user2677350


People also ask

What is the correct way to iterate over a range of numbers?

To loop through a set of code a specified number of times, we can use the range() function, The range() function returns a sequence of numbers, starting from 0 by default, and increments by 1 (by default), and ends at a specified number.

Can a for loop iterate over a range of numbers?

For loops can iterate over a sequence of numbers using the "range" and "xrange" functions. The difference between range and xrange is that the range function returns a new list with numbers of that specified range, whereas xrange returns an iterator, which is more efficient.

How do you iterate over a number in Python?

Use a for-loop and range() to iterate over a number Use the for-loop syntax for num in sequence with sequence as range(number) to iterate through all the numbers between 0 and number .


2 Answers

With a minor change in indices, you have the Josephus problem. In the traditional formulation, person 1 kills person 2, 3 kills 4, etc. To convert to that form, kill off person 1, as your problem states, and then renumber people 2-100 by subtracting 1, giving people 1-99.

A good treatment of the Josephus problem, including an account of its origin in the Jewish Revolt of 70-73 CE, is in Concrete Mathematics, 2nd edition, by Graham, Knuth, and Patashnik, Section 1.3. Both Wikipedia and Wolfram MathWorld have articles on the problem, Wikipedia even includes the original description by Josephus in The Jewish War.

The book gives a mildly complicated recursion for the solution, and a simpler algorithm. If the number of people is n, and n = 2^l + m where l is as large as possible, then the answer is 2m+1. So, since 99 = 2^6 + 35, the solution is 2*35 + 1 = 71. But you need to reverse the renumbering, so the real answer is 72.

As far as your programming problem, however, why don't you take as your basic operation Remove the first person in the circle and move the second person to the end. So, with 5 people, [1,2,3,4,5], you remove the first getting [2,3,4,5]and moving the new first element to the end getting [3,4,5,2].

var killAndRotate = function(array) { // say [1,2,3,4,5]
    var dead    = array.shift(),      // dead    = 1, array = [2,3,4,5]
        skipped = array.shift();      // skipped = 2, array = [3,4,5]
    array.push(skipped);              //              array = [3,4,5,2]
}

And then the main loop becomes:

while (chairArray.length > 1) {
    killAndRotate(chairArray);
}
alert(chairArray[0]); // or console.log, or return.
// In turn, array is:
// [1,2,3,4,5]
// [3,4,5,2]
// [5,2,4]
// [4,2]
// [2] and we alert, log, or return 2.

Added

The easy way to find that result for the original Josephus problem is to see that:

If there are 2^l people, then in the first pass all the even-numbered people are killed, so the first person remains alive.

1 2 3 4 5 6 7 8

  X   X   X   X

Now there are 2^(l - 1) people. Again, the first person survives:

1 2 3 4 5 6 7 8

  X   X   X   X

    X       X

Repeat the process; the first person survives each pass, and so is the last survivor.

Now, suppose there are m extra people with m < 2^l. Here, l = 3 and m = 5. Kill the first m people to die.

1 2 3 4 5 6 7 8 9 10 11 12 13

  X   X   X   X    X  Y

Now, there are 2^l people left, and person 2 m + 1 = 11 is the first in line. So he survives.

One should also point out that adding a new index variable and splicing can lead to programmer error. Since you only need to remove from the front and add to the back, use the basic methods of arrays.

like image 117
Eric Jablow Avatar answered Sep 29 '22 15:09

Eric Jablow


It seems to me the answer is 72. When you realize that rather than removing numbers you can skip them, the code becomes very short and straight-forward.

var chairArr = [];
for (var i = 1; i <= 100; i++)
    chairArr.push(i);

for (i = 1; i < chairArr.length-2; i = i + 2)
    chairArr.push(chairArr[i]);

console.log('--- Final result: ' + chairArr[i]);
like image 37
dcaswell Avatar answered Sep 29 '22 14:09

dcaswell