Code Solution to sword puzzle


We will discuss two approaches to solve the sword puzzle. In the first approach, we will use circular linked list, while the second approach is based on general intuition. In this article, we will discuss what is a sword puzzle problem and how we can solve a sword puzzle problem.

Problem Statement

We have an arrangement of n people in a circle in which, first person is carrying a sword. The first person kills the second person and hands over the sword to the next alive person in the circle. Now the next person carrying the sword kills the next person and handovers the sword to the next alive person. This process continues till only a single person is left. We call the only alive person as the luckiest person alive. Let us now consider this situation with an example.

Example

  • N=10

  • We have 10 people in a circular arrangement Person 1, Person 2 …, Person 10, Person 1.

  • At first, Person 1 kills Person 2 and hands over the sword to Person 3.

  • So after 1 iteration from Person 1 to Person 10, we have a list of alive people as {Person 1, person 3, person 5, person 7, person 9}

  • And Person 1 is having the sword, now again in next iteration, we have a list of people alive as: {Person 1, Person 5, Person 9} and Person 9 is having the sword.

  • In next iteration, we have people alive as Person 5

  • Hence, we can say that the luckiest person was Person 5 who was alive till last.

Approach 1: Using Circular Linked List

We are first solving the puzzle using a circular linked list. For this, we will first create a circular linked list having n different nodes representing n different soldiers and then will start iterating the linked list. According to the rule, we have to kill an adjacent soldier and handover the sword to the next alive person and repeat this until we have only a single person left for this, we will represent the killed soldier by deleting the adjacent linked list and the linked list left in the last represents the alive soldier.

Example

Following is the implementation of the above approach in different programming languages: C, C++, Java, and Python −

#include <stdio.h>
#include <stdlib.h>

// Defining the linked list as Soldier
struct Soldier {
   int data;
   struct Soldier* next;
};

struct Soldier* newSoldier(int data) {
   struct Soldier* soldier = (struct Soldier*)malloc(sizeof(struct Soldier));
   if (soldier == NULL) {
      // Handle memory allocation failure
      exit(EXIT_FAILURE);
   }
   soldier->data = data;
   soldier->next = NULL;
   return soldier;
}

// This function calculates the luckiest person alive
int Luckiest(int N) {
   if (N == 1)
      return 1;

   struct Soldier* last = newSoldier(1);
   last->next = last;

   for (int iterator = 2; iterator <= N; iterator++) {
      struct Soldier* dummy = newSoldier(iterator);
      dummy->next = last->next;
      last->next = dummy;
      last = dummy;
   }

   struct Soldier* current = last->next;
   struct Soldier* dummy;

   while (current->next != current) {
      dummy = current;
      current = current->next;
      dummy->next = current->next;
      free(current);
      dummy = dummy->next;
      current = dummy;
   }
   int result = dummy->data;
   free(dummy);
   return result;
}
int main() {
   int N = 100;
   printf("The luckiest person alive at last is the person numbered as %d\n", Luckiest(N));
   return 0;
}

Output

The luckiest person alive at last is the person numbered as 73
#include <bits/stdc++.h>
using namespace std;
// Defining the linked list as soldier
struct Soldier {
   int data;
   struct Soldier* next;
};
Soldier *newSoldier(int data){
   Soldier *soldier = new Soldier;
   soldier->data = data;
   soldier->next = NULL;
   return soldier;
}

// This function calculates the luckiest person alive
int Luckiest (int N){
   if (N == 1)
   return 1;
   Soldier *last = newSoldier(1);
   last->next = last;
   for (int iterator = 2; iterator <= N; iterator++) {
      Soldier *dummy = newSoldier(iterator);
      dummy->next = last->next;
      last->next = dummy;
      last = dummy;
   }
   Soldier *current = last->next;
   Soldier *dummy;
   while (current->next != current) {
      dummy = current;
      current = current->next;
      dummy->next = current->next;
      delete current;
      dummy = dummy->next;
      current = dummy;
   }
   int result = dummy->data;
   delete dummy;
   return result;
}
int main(){
   int N = 100;
   cout << "The luckiest person alive at last is the person numbered as " << Luckiest(N)<< endl;
   return 0;
}

Output

The luckiest person alive at last is the person numbered as 73
class Soldier {
   int data;
   Soldier next;
   Soldier(int data) {
      this.data = data;
      this.next = null;
   }
}
public class LuckiestPerson {
   static Soldier newSoldier(int data) {
      return new Soldier(data);
   }
   // This function calculates the luckiest person alive
   static int luckiest(int N) {
      if (N == 1)
         return 1;

      Soldier last = newSoldier(1);
      last.next = last;

      for (int iterator = 2; iterator <= N; iterator++) {
         Soldier dummy = newSoldier(iterator);
         dummy.next = last.next;
         last.next = dummy;
         last = dummy;
      }

      Soldier current = last.next;
      Soldier dummy = null;  // Initialize dummy to null

      while (current.next != current) {
         dummy = current;
         current = current.next;
         dummy.next = current.next;
         dummy = dummy.next;
         current = dummy;
      }

      if (dummy != null) {
         return dummy.data;
      } else {
         // Handle the case where dummy is not initialized
         System.err.println("Error: dummy not initialized");
         return -1;  // or some other appropriate error value
      }
   }
   public static void main(String[] args) {
      int N = 100;
      System.out.println("The luckiest person alive at last is the person numbered as " + luckiest(N));
   }
}

Output

The luckiest person alive at last is the person numbered as 73
class Soldier:
   def __init__(self, data):
      self.data = data
      self.next = None

def new_soldier(data):
   soldier = Soldier(data)
   soldier.next = None
   return soldier

# This function calculates the luckiest person alive
def luckiest(N):
   if N == 1:
      return 1

   last = new_soldier(1)
   last.next = last

   for iterator in range(2, N + 1):
      dummy = new_soldier(iterator)
      dummy.next = last.next
      last.next = dummy
      last = dummy

   current = last.next
   dummy = None

   while current.next != current:
      dummy = current
      current = current.next
      dummy.next = current.next
      dummy = dummy.next
      current = dummy

   return dummy.data

def main():
   N = 100
   print("The luckiest person alive at last is the person numbered as", luckiest(N))

if __name__ == "__main__":
   main()	  

Output

The luckiest person alive at last is the person numbered as 73

As we are traversing a loop of n elements, time complexity is O(n).

Space complexity − As we are using extra space for linked list, space complexity is O(n)

Approach 2

In this approach, we will deduct a method to calculate the luckiest element by intuition. If the number of soldiers can be expressed as a power of 2, then we can say that the first soldier who started the killing process will be left alive at last. As we know that after every iteration, the number of soldiers decreases by 2 without any remainder. Hence for starting every iteration, we will have the first soldier carrying the sword automatically and this continues but the first person is never killed.

If we have a number of soldiers which is not a power of 2, then in the first iteration when the number of soldiers becomes a power of two, at that time the soldier having the sword will win. Intuition behind this is: When the number of soldiers becomes a power of 2, we can assume it to be a new puzzle with soldiers as a power of two and the soldier having the sword as the first soldier. We will first deduct a method to implement this approach.

  • Step 1 − Find the largest number (which can be represented as a power of 2) smaller than the given number. Let it be m.

  • Step 2 − Subtract m from the given number “n”.

  • Step 3 − Now, multiply m with 2 to know the number of people killed.

  • Step 4 − At last, we will be having sword in (2*m+1)th soldier's hand hence 2m+1 soldier will be alive at last.

Example

Following is the implementation of the above approach in different programming languages: C, C++, Java, and Python −

#include <stdio.h>
#include <stdlib.h>

// Function to calculate largest number (which can be represented as a power of 2) smaller than the given number
int Power_of_two(int number){
   int result = 0;
   for (int iterator = number; iterator >= 1; iterator--) {
      if ((iterator & (iterator - 1)) == 0){
         result = iterator;
         break;
      }
   }
   return result;
}
// main code goes here
int main() {
   int number=100;
   int m= Power_of_two(number);
   int p;
   p=number-m;
   printf(" The luckiest person alive is person numbered as %d ", (2*(p)) +1);
   return 0;
}

Output

The luckiest person alive is person numbered as 73 
#include <bits/stdc++.h>
using namespace std;
// Function to calculate largest number (which can be represented as a power of 2) smaller than the given number
int Power_of_two(int number){
   int result = 0;
   for (int iterator = number; iterator >= 1; iterator--) {
      if ((iterator & (iterator - 1)) == 0){
         result = iterator;
         break;
      }
   }
   return result;
}
// main code goes here
int main(){
   int number=100;
   int m= Power_of_two(number);
   int p;
   p=number-m;
   cout<< " The luckiest person alive is person numbered as " <<(2*(p)) +1;
   return 0;
}

Output

The luckiest person alive is person numbered as 73
public class Main {
// Function to calculate largest number (which can be represented as a power of 2) smaller than the given number
   public static int Power_of_two(int number) {
      int result = 0;
      for (int iterator = number; iterator >= 1; iterator--) {
         if ((iterator & (iterator - 1)) == 0) {
            result = iterator;
            break;
         }
      }
      return result;
   }
   public static void main(String[] args) {
      int number=100;
      int m= Power_of_two(number);
      int p;
      p=number-m;
      int res = (2*(p)) + 1;
      System.out.println(" The luckiest person alive is person numbered as " + res);
   }
}

Output

The luckiest person alive is person numbered as 73
# Function to calculate the largest number (which can be represented as a power of 2) smaller than the given number
def power_of_two(number):
   result = 0
   for iterator in range(number, 0, -1):
      if (iterator & (iterator - 1)) == 0:
         result = iterator
         break
   return result

# main code goes here
number = 100
m = power_of_two(number)
p = number - m
print("The luckiest person alive is person numbered as", (2 * p) + 1)

Output

The luckiest person alive is person numbered as 73

Time Complexity − Time complexity of this approach is O(n)

Space Complexity − As we are only using constant space to store od variables, apace complexity will be O(1).

Conclusion

In this article, we have discussed two approaches to solve the sword puzzle problem. In first approach, we used a circular linked list and kept deleting each node that dies in the process and the last element left is the luckiest soldier alive. In our second approach, we created an intuitive formula to find our solution.

Updated on: 09-Feb-2024

181 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements