Open In App

Josephus Problem Using Bit Magic

The Problem

This problem is named after Flavius Josephus a Jewish historian who fought against the Romans. According to Josephus he and his group of Jewish soldiers were cornered & surrounded by the Romans inside a cave, and they choose to murder and suicide inside of surrender and capture. They decided that all the soldiers will sit in a circle and starting from the soldier sitting at the first position every soldier will kill the soldier to their sequentially. So if there are 5 soldiers sitting in a circle with positions numbered as 1, 2, 3, 4, 5. The soldier 1 kills 2, then 3 kills 4, then 5 kills 1, then 3 kills 5, and since 3 is the only one left then 3 commits suicide. 
Now Josephus doesn’t want to get murdered or commit suicide. He would rather be captured by the Romans and is presented with a problem. He has to figure out at which position should he sit in a circle (provided there are n men in total and the man sitting at position 1 gets the first chance to murder) so that he is the last man standing and instead of committing suicide he will surrender to the Romans.
 



The Pattern

If you work this out for different values of n you will find a pattern here. If n is a true power of 2 then the answer is always 1. For every n greater than that power of 2 the answer is incremented by 2.  



n soldiers 2a+ l Survivor W(n) = 2l + 1
1 1 + 0 2 * 0 + 1 = 1
2 2 + 0 2 * 0 + 1 = 1
3 2 + 1 2 * 1 + 1 = 3
4 4 + 0 2 * 0 + 1 = 1
5 4 + 1 2 * 1 + 1 = 3
6 4 + 2 2 * 2 + 1 = 5
7 4 + 3 2 * 3 + 1 = 7
8 8 + 0 2 * 0 + 1 = 1
9 8 + 1 2 * 1 + 1 = 3
10 8 + 2 2 * 2 + 1 = 5
11 8 + 3 2 * 3 + 1 = 7
12 8 + 4 2 * 4 + 1 = 9

Now for every n, the right position for Josephus can be found out by deducting the biggest possible power of 2 from the number and we get the answer (provided that value of n is not a pure power of 2 otherwise the answer is 1)  

N = 2a + something

where a = the biggest possible power

The Trick
Whenever someone talks about the powers of 2 the first word that comes to mind is “binary”. The solution to this problem is much is easier and shorter in binary than in decimal. There is a trick to this. Since we need to deduct the biggest possible power of in binary that number is the Most Significant Bit. In the original Josephus problem, there were 40 other soldiers along with Josephus which makes n = 41. 41 in binary is 101001. If we shift the MSB i.e. the leftmost 1 to the rightmost place we get 010011 which is 19 (in decimal) which is the answer. This is true for all cases. This can be done easily using bit manipulation.




// C++ program for josephus problem
#include <bits/stdc++.h>
using namespace std;
 
// function to find the position of the Most
// Significant Bit
int msbPos(int n)
{
    int pos = 0;
    while (n != 0) {
        pos++;
 
        // keeps shifting bits to the right
        // until we are left with 0
        n = n >> 1;
    }
    return pos;
}
 
// function to return at which place Josephus
// should sit to avoid being killed
int josephify(int n)
{
    /* Getting the position of the Most Significant
        Bit(MSB). The leftmost '1'. If the number is
    '41' then its binary is '101001'.
        So msbPos(41) = 6 */
    int position = msbPos(n);
 
    /* 'j' stores the number with which to XOR the
        number 'n'. Since we need '100000'
    We will do 1<<6-1 to get '100000' */
    int j = 1 << (position - 1);
 
    /* Toggling the Most Significant Bit. Changing
    the leftmost '1' to '0'.
    101001 ^ 100000 = 001001 (9) */
    n = n ^ j;
 
    /* Left-shifting once to add an extra '0' to
        the right end of the binary number
        001001 = 010010 (18) */
    n = n << 1;
 
    /* Toggling the '0' at the end to '1' which
    is essentially the same as putting the
    MSB at the rightmost place. 010010 | 1
    = 010011 (19) */
    n = n | 1;
 
    return n;
}
 
// hard coded driver main function to run the program
int main()
{
    int n = 41;
    cout <<josephify(n);
    return 0;
}// This code is contributed by Mukul singh.




// C program for josephus problem
 
#include <stdio.h>
 
// function to find the position of the Most
// Significant Bit
int msbPos(int n)
{
    int pos = 0;
    while (n != 0) {
        pos++;
 
        // keeps shifting bits to the right
        // until we are left with 0
        n = n >> 1;
    }
    return pos;
}
 
// function to return at which place Josephus
// should sit to avoid being killed
int josephify(int n)
{
    /*  Getting the position of the Most Significant
        Bit(MSB). The leftmost '1'. If the number is
       '41' then its binary is '101001'.
        So msbPos(41) = 6   */
    int position = msbPos(n);
 
    /* 'j' stores the number with which to XOR the
        number 'n'. Since we need '100000'
       We will do 1<<6-1 to get '100000' */
    int j = 1 << (position - 1);
 
    /* Toggling the Most Significant Bit. Changing
       the leftmost '1' to '0'.
       101001 ^ 100000 = 001001 (9) */
    n = n ^ j;
 
    /*  Left-shifting once to add an extra '0' to
        the right end of the binary number
        001001 = 010010 (18) */
    n = n << 1;
 
    /* Toggling the '0' at the end to '1' which
       is essentially the same as putting the
       MSB at the rightmost place. 010010 | 1
       = 010011 (19) */
    n = n | 1;
 
    return n;
}
 
// hard coded driver main function to run the program
int main()
{
    int n = 41;
    printf("%d\n", josephify(n));
    return 0;
}




// Java program for josephus problem
 
public class GFG
{
    // method to find the position of the Most
    // Significant Bit
    static int msbPos(int n)
    {
        int pos = 0;
        while (n != 0) {
            pos++;
      
            // keeps shifting bits to the right
            // until we are left with 0
            n = n >> 1;
        }
        return pos;
    }
      
    // method to return at which place Josephus
    // should sit to avoid being killed
    static int josephify(int n)
    {
        /*  Getting the position of the Most Significant
            Bit(MSB). The leftmost '1'. If the number is
           '41' then its binary is '101001'.
            So msbPos(41) = 6   */
        int position = msbPos(n);
      
        /* 'j' stores the number with which to XOR the
            number 'n'. Since we need '100000'
           We will do 1<<6-1 to get '100000' */
        int j = 1 << (position - 1);
      
        /* Toggling the Most Significant Bit. Changing
           the leftmost '1' to '0'.
           101001 ^ 100000 = 001001 (9) */
        n = n ^ j;
      
        /*  Left-shifting once to add an extra '0' to
            the right end of the binary number
            001001 = 010010 (18) */
        n = n << 1;
      
        /* Toggling the '0' at the end to '1' which
           is essentially the same as putting the
           MSB at the rightmost place. 010010 | 1
           = 010011 (19) */
        n = n | 1;
      
        return n;
    }
     
    // Driver Method
    public static void main(String[] args)
    {
        int n = 41;
        System.out.println(josephify(n));
    }
}




# Python3 program for josephus problem
 
# Function to find the position
# of the Most Significant Bit
def msbPos(n):
    pos = 0
    while n != 0:
        pos += 1
        n = n >> 1
    return pos
 
# Function to return at which
# place Josephus should sit to
# avoid being killed
def josephify(n):
     
    # Getting the position of the Most
    # Significant Bit(MSB). The leftmost '1'.
    # If the number is '41' then its binary
    # is '101001'. So msbPos(41) = 6
    position = msbPos(n)
 
    # 'j' stores the number with which to XOR 
    # the number 'n'. Since we need '100000'
    # We will do 1<<6-1 to get '100000'
    j = 1 << (position - 1)
 
    # Toggling the Most Significant Bit.
    # Changing the leftmost '1' to '0'.
    # 101001 ^ 100000 = 001001 (9)
    n = n ^ j
 
    # Left-shifting once to add an extra '0' 
    # to the right end of the binary number
    # 001001 = 010010 (18)
    n = n << 1
 
    # Toggling the '0' at the end to '1' 
    # which is essentially the same as
    # putting the MSB at the rightmost
    # place. 010010 | 1 = 010011 (19)
    n = n | 1
 
    return n
 
# Driver Code
n = 41
print (josephify(n))
 
# This code is contributed by Shreyanshi Arun.




// C# program for Josephus Problem
using System;
 
public class GFG
{
     
    // Method to find the position
    // of the Most Significant Bit
    static int msbPos(int n)
    {
        int pos = 0;
        while (n != 0) {
            pos++;
     
            // keeps shifting bits to the right
            // until we are left with 0
            n = n >> 1;
        }
        return pos;
    }
     
    // method to return at which place Josephus
    // should sit to avoid being killed
    static int josephify(int n)
    {
         
        // Getting the position of the Most Significant
        // Bit(MSB). The leftmost '1'. If the number is
        // '41' then its binary is '101001'.
        // So msbPos(41) = 6
        int position = msbPos(n);
     
        // 'j' stores the number with which to XOR 
        // the number 'n'. Since we need '100000'
        // We will do 1<<6-1 to get '100000'
        int j = 1 << (position - 1);
     
        // Toggling the Most Significant Bit.
        // Changing the leftmost '1' to '0'.
        // 101001 ^ 100000 = 001001 (9)
        n = n ^ j;
     
        // Left-shifting once to add an extra '0'
        // to the right end of the binary number
        // 001001 = 010010 (18)
        n = n << 1;
     
        // Toggling the '0' at the end to '1' which
        // is essentially the same as putting the
        // MSB at the rightmost place. 010010 | 1
        // = 010011 (19)
        n = n | 1;
     
        return n;
    }
     
    // Driver code
    public static void Main()
    {
        int n = 41;
        Console.WriteLine(josephify(n));
    }
}
 
// This code is contributed by vt_m .




<?php
// PHP program for josephus problem
 
// function to find the position of
// the Most Significant Bit
function msbPos($n)
{
    $pos = 0;
    while ($n != 0)
    {
        $pos++;
 
        // keeps shifting bits to the right
        // until we are left with 0
        $n = $n >> 1;
    }
    return $pos;
}
 
// function to return at which place Josephus
// should sit to avoid being killed
function josephify($n)
{
    /* Getting the position of the Most
       Significant Bit(MSB). The leftmost '1'.
       If the number is '41' then its binary
       is '101001'. So msbPos(41) = 6 */
    $position = msbPos($n);
 
    /* 'j' stores the number with which to
        XOR the number 'n'. Since we need
    '100000'. We will do 1<<6-1 to get '100000' */
    $j = 1 << ($position - 1);
 
    /* Toggling the Most Significant Bit.
    Changing the leftmost '1' to '0'.
    101001 ^ 100000 = 001001 (9) */
    $n = $n ^ $j;
 
    /* Left-shifting once to add an extra '0'
       to the right end of the binary number
       001001 = 010010 (18) */
    $n = $n << 1;
 
    /* Toggling the '0' at the end to '1' which
    is essentially the same as putting the
    MSB at the rightmost place. 010010 | 1
    = 010011 (19) */
    $n = $n | 1;
 
    return $n;
}
 
// Driver Code
$n = 41;
print(josephify($n));
 
// This code is contributed by mits
?>




<script>
 
// javascript program for josephus problem
 
// method to find the position of the Most
// Significant Bit
function msbPos(n)
{
    var pos = 0;
    while (n != 0) {
        pos++;
  
        // keeps shifting bits to the right
        // until we are left with 0
        n = n >> 1;
    }
    return pos;
}
  
// method to return at which place Josephus
// should sit to avoid being killed
function josephify(n)
{
    /*  Getting the position of the Most Significant
        Bit(MSB). The leftmost '1'. If the number is
       '41' then its binary is '101001'.
        So msbPos(41) = 6   */
    var position = msbPos(n);
  
    /* 'j' stores the number with which to XOR the
        number 'n'. Since we need '100000'
       We will do 1<<6-1 to get '100000' */
    var j = 1 << (position - 1);
  
    /* Toggling the Most Significant Bit. Changing
       the leftmost '1' to '0'.
       101001 ^ 100000 = 001001 (9) */
    n = n ^ j;
  
    /*  Left-shifting once to add an extra '0' to
        the right end of the binary number
        001001 = 010010 (18) */
    n = n << 1;
  
    /* Toggling the '0' at the end to '1' which
       is essentially the same as putting the
       MSB at the rightmost place. 010010 | 1
       = 010011 (19) */
    n = n | 1;
  
    return n;
}
 
// Driver Method
var n = 41;
document.write(josephify(n));
 
// This code is contributed by Amit Katiyar
</script>

Output
19

Time Complexity: O(log n)
Auxiliary Space: O(1)

Another Approach: If we see carefully we can see a pattern, if we represent any number in the form of (2a + L) then the answer will be (2*L + 1).

Below is the code implementation of the above approach:




// C++ program for josephus problem
#include <bits/stdc++.h>
using namespace std;
 
// function to return at which place Josephus
// should sit to avoid being killed
int josephify(int n)
{
 
    int ans = log2(n);
    int l = n - pow(2, ans);
    return 2 * l + 1;
}
 
// hard coded driver main function to run the program
int main()
{
    int n = 41;
    cout << josephify(n);
    return 0;
}
// This code is contributed by Arpit Jain




public class GFG {
 
    static int josephify(int n)
    {
 
        int ans = (int)(Math.log(n) / Math.log(2));
        int l = n - (int)Math.pow(2, ans);
        return 2 * l + 1;
    }
    public static void main(String[] args)
    {
        int n = 41;
        System.out.print(josephify(n));
    }
}




# Python3 program for josephus problem
import math
 
# function to return at which place Josephus
# should sit to avoid being killed
def josephify(n):
     
    ans = math.log(n, 2);
    ans = round(ans);
    l = n - 2 ** ans;
    return 2 * l + 1;
 
# hard coded driver main function to run the program
n = 41;
print(josephify(n));
 
# This code is contributed by phasing17.




using System;
class GFG {
 
    static int josephify(int n)
    {
 
        int ans = (int)Math.Log(n, 2);
        int l = n - (int)Math.Pow(2, ans);
        return 2 * l + 1;
    }
 
    // Driver's code
    public static void Main(string[] args)
    {
        int n = 41;
 
        // Function call
        Console.Write(josephify(n));
    }
}




// Javascript program for josephus problem
 
// function to return at which place Josephus
// should sit to avoid being killed
 function josephify(n)
{
    let ans = Math.log2(n);
    ans = Math.round(ans);
    let l = n - Math.pow(2, ans);
    return 2 * l + 1;
}
 
// hard coded driver main function to run the program
    let n = 41;
    console.log(josephify(n));
 
// This code is contributed by garg28harsh.

Output
19

Time Complexity: O(log(log(n))), for using pow() function.
Auxiliary Space: O(1) 

Previous articles on the same topic:  

  1. Josephus problem | Set 1 (A O(n) Solution)
  2. Josephus problem | Set 2 (A Simple Solution when k = 2)

Article Tags :