Skip to content
Related Articles

Related Articles

Find winner of game where in each move division of N or subtraction is done

Improve Article
Save Article
  • Last Updated : 02 Dec, 2022
Improve Article
Save Article

Jon and Arya are playing a game. The rules of the game are as follows:

  • They have a single number N initially.
  • Both will play an alternate move. Jon starts first.
  • Both will play each move optimally.
  • In each move, they can perform only one of these operations:
    • Divide that number by 2, 3, 4, or 5 and take the floor of the result.
    • Subtract that number by 2, 3, 4, or 5.
  • If after making a move the number becomes 1, the player who made the move automatically loses the game.
  • When the number becomes zero, the game will stop and the player who can’t make a move loses the game.

Find the winner of the game.

Examples:

Input: N = 3
Output: Jon
Explanation: Jon will just subtract 3 from initial
number and win the game.

Input: N = 6
Output: Arya
Explanation: If  Jon subtracts any number or divides N, on the next move Arya can subtract any number and make N as 0.

Approach: The problem can be solved using dynamic programming based on the following idea:

As Jon is starting the game, he will try to maximize his chances of winning. So, for any value of i, check if there is any possible value less than i (say j) that ensures Jon’s win, i.e., if j was the initial then the one who starts the game would lose. Then on the first move Jon can move from N to j and ensure his win.

Follow the below steps to solve this problem:

  • If N = 1 return “Arya”.
  • If N ≤ 5 return “Jon”.
  • Make a dp[] array of size N + 1
  • Set arr[0] = 0 and i = 1.
  • Make arr[i] to min(arr[5], arr[N]) to 1.
  • Set i = 6.
  • While i ≤ N, whosever turn will it be, check if there is any move by performing which he can win, which means if any arr[condition] = 0 then he will win for sure else not.
    • If, arr[i / 2], arr[i / 4], arr[i / 3] or arr[i / 5] is 0,
      • Set, arr[i] = 1.
    • Else If, arr[i – 2], arr[i – 3], arr[i – 4] or arr[i – 5] is 0,
      • Set, arr[i] = 1.
    • Else,
      • Set, arr[i] = 0.
    • Increment i by 1 after every iteration.
  • If arr[N] = 1 then return “Jon”.
  • Else return “Arya”.

Below is the implementation of the above approach.

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to return who will win
string divAndSub(int N)
{
    // Edge Case
    if (N == 1)
        return "Arya";
 
    if (N < 6)
        return "Jon";
 
    // Make a dp array of size N+1
    int arr[N + 1];
    arr[0] = 0;
 
    // Initialize the variable
    int i = 1;
 
    // If it's whose turn it is to win on
    // that move, we'll do 1, otherwise 0
 
    // For 1-5 Jon always win
    while (i < 6 && i <= N) {
        arr[i] = 1;
 
        i++;
    }
 
    i = 6;
 
    while (i <= N) {
 
        // Whoosever turn will it be we will
        // check if there is any move by
        // performing, there is a chance for
        // him to win, means if any
        // arr[condition] = 0 then he will win
        // for sure else not
        if (arr[i / 2] == 0 || arr[i / 4] == 0
            || arr[i / 3] == 0 || arr[i / 5] == 0) {
 
            // Means the person doing the move
            // can win through division
            arr[i] = 1;
        }
 
        else if (arr[i - 2] == 0 || arr[i - 3] == 0
                 || arr[i - 4] == 0 || arr[i - 5] == 0) {
 
            // Means the person doing the move
            // can win through substraction
            arr[i] = 1;
        }
 
        else {
 
            // Else other person will win
            arr[i] = 0;
        }
 
        i++;
    }
 
    // If arr[N] is 1 then Jon win
    // else Arya win
    return arr[N] == 1 ? "Jon" : "Arya";
}
 
// Driver Code
int main()
{
    int N = 3;
 
    // Function Call
    cout << divAndSub(N) << endl;
 
    return 0;
}

Java




// Java code to implement the approach
import java.io.*;
 
class GFG {
 
  // Function to return who will win
  public static String divAndSub(int N)
  {
    // Edge Case
    if (N == 1)
      return "Arya";
 
    if (N < 6)
      return "Jon";
 
    // Make a dp array of size N+1
    int[] arr= new int[N + 1];
    arr[0] = 0;
 
    // Initialize the variable
    int i = 1;
 
    // If it's whose turn it is to win on
    // that move, we'll do 1, otherwise 0
 
    // For 1-5 Jon always win
    while (i < 6 && i <= N) {
      arr[i] = 1;
 
      i++;
    }
 
    i = 6;
 
    while (i <= N) {
 
      // Whoosever turn will it be we will
      // check if there is any move by
      // performing, there is a chance for
      // him to win, means if any
      // arr[condition] = 0 then he will win
      // for sure else not
      if (arr[i / 2] == 0 || arr[i / 4] == 0
          || arr[i / 3] == 0 || arr[i / 5] == 0) {
 
        // Means the person doing the move
        // can win through division
        arr[i] = 1;
      }
 
      else if (arr[i - 2] == 0 || arr[i - 3] == 0
               || arr[i - 4] == 0 || arr[i - 5] == 0) {
 
        // Means the person doing the move
        // can win through substraction
        arr[i] = 1;
      }
 
      else {
 
        // Else other person will win
        arr[i] = 0;
      }
 
      i++;
    }
 
    // If arr[N] is 1 then Jon win
    // else Arya win
    return arr[N] == 1 ? "Jon" : "Arya";
  }
// Driver Code
public static void main (String[] args) {
 
    int N = 3;
 
    // Function Call
    System.out.println(divAndSub(N));
}
}
 
// This code is contributed by sanjoy_62.

C#




// C# implementation
using System;
 
public class GFG{
 
  // Function to return who will win
  public static string divAndSub(int N)
  {
    // Edge Case
    if (N == 1)
      return "Arya";
 
    if (N < 6)
      return "Jon";
 
    // Make a dp array of size N+1
    int[] arr= new int[N + 1];
    arr[0] = 0;
 
    // Initialize the variable
    int i = 1;
 
    // If it's whose turn it is to win on
    // that move, we'll do 1, otherwise 0
 
    // For 1-5 Jon always win
    while (i < 6 && i <= N) {
      arr[i] = 1;
 
      i++;
    }
 
    i = 6;
 
    while (i <= N) {
 
      // Whoosever turn will it be we will
      // check if there is any move by
      // performing, there is a chance for
      // him to win, means if any
      // arr[condition] = 0 then he will win
      // for sure else not
      if (arr[i / 2] == 0 || arr[i / 4] == 0
          || arr[i / 3] == 0 || arr[i / 5] == 0) {
 
        // Means the person doing the move
        // can win through division
        arr[i] = 1;
      }
 
      else if (arr[i - 2] == 0 || arr[i - 3] == 0
               || arr[i - 4] == 0 || arr[i - 5] == 0) {
 
        // Means the person doing the move
        // can win through substraction
        arr[i] = 1;
      }
 
      else {
 
        // Else other person will win
        arr[i] = 0;
      }
 
      i++;
    }
 
    // If arr[N] is 1 then Jon win
    // else Arya win
    return arr[N] == 1 ? "Jon" : "Arya";
  }
 
  static public void Main (){
 
    int N = 3;
 
    // Function Call
    Console.WriteLine(divAndSub(N));
 
  }
}
 
// This code is contributed by ksam24000

Javascript




// JavaScript code to implement the approach
 
// Function to return who will win
const divAndSub = (N) => {
    // Edge Case
    if (N == 1)
        return "Arya";
 
    if (N < 6)
        return "Jon";
 
    // Make a dp array of size N+1
    let arr = new Array(N + 1).fill(0);
    arr[0] = 0;
 
    // Initialize the variable
    let i = 1;
 
    // If it's whose turn it is to win on
    // that move, we'll do 1, otherwise 0
 
    // For 1-5 Jon always win
    while (i < 6 && i <= N) {
        arr[i] = 1;
 
        i++;
    }
 
    i = 6;
 
    while (i <= N) {
 
        // Whoosever turn will it be we will
        // check if there is any move by
        // performing, there is a chance for
        // him to win, means if any
        // arr[condition] = 0 then he will win
        // for sure else not
        if (arr[parseInt(i / 2)] == 0 || arr[parseInt(i / 4)] == 0
            || arr[parseInt(i / 3)] == 0 || arr[parseInt(i / 5)] == 0) {
 
            // Means the person doing the move
            // can win through division
            arr[i] = 1;
        }
 
        else if (arr[i - 2] == 0 || arr[i - 3] == 0
            || arr[i - 4] == 0 || arr[i - 5] == 0) {
 
            // Means the person doing the move
            // can win through substraction
            arr[i] = 1;
        }
 
        else {
 
            // Else other person will win
            arr[i] = 0;
        }
 
        i++;
    }
 
    // If arr[N] is 1 then Jon win
    // else Arya win
    return arr[N] == 1 ? "Jon" : "Arya";
}
 
// Driver Code
 
let N = 3;
 
// Function Call
console.log(divAndSub(N));
 
// This code is contributed by rakeshsahni

Output

Jon

Time Complexity: O(N)
Auxiliary Space: O(N)

Related Articles:


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!