Open In App

Shortest path to reach one prime to other by changing single digit at a time

Improve
Improve
Like Article
Like
Save
Share
Report

Given two four digit prime numbers, suppose 1033 and 8179, we need to find the shortest path from 1033 to 8179 by altering only single digit at a time such that every number that we get after changing a digit is prime. For example a solution is 1033, 1733, 3733, 3739, 3779, 8779, 8179 

Examples:

Input : 1033 8179
Output :6

Input : 1373 8017
Output : 7

Input  :  1033 1033
Output : 0
Recommended Problem

The question can be solved by BFS and it is a pretty interesting to solve as a starting problem for beginners. We first find out all 4 digit prime numbers till 9999 using technique of Sieve of Eratosthenes. And then using those numbers formed the graph using adjacency list. After forming the adjacency list, we used simple BFS to solve the problem. 

Implementation:

C++




// CPP program to reach a prime number from
// another by changing single digits and
// using only prime numbers.
#include <bits/stdc++.h>
 
using namespace std;
 
class graph {
    int V;
    list<int>* l;
public:
    graph(int V)
    {
        this->V = V;
        l = new list<int>[V];
    }
    void addedge(int V1, int V2)
    {
        l[V1].push_back(V2);
        l[V2].push_back(V1);
    }
    int bfs(int in1, int in2);
};
 
// Finding all 4 digit prime numbers
void SieveOfEratosthenes(vector<int>& v)
{
    // Create a boolean array "prime[0..n]" and initialize
    // all entries it as true. A value in prime[i] will
    // finally be false if i is Not a prime, else true.
    int n = 9999;
    bool prime[n + 1];
    memset(prime, true, sizeof(prime));
 
    for (int p = 2; p * p <= n; p++) {
 
        // If prime[p] is not changed, then it is a prime
        if (prime[p] == true) {
 
            // Update all multiples of p
            for (int i = p * p; i <= n; i += p)
                prime[i] = false;
        }
    }
 
    // Forming a vector of prime numbers
    for (int p = 1000; p <= n; p++)
        if (prime[p])
            v.push_back(p);
}
 
// in1 and in2 are two vertices of graph which are
// actually indexes in pset[]
int graph::bfs(int in1, int in2)
{
    int visited[V];
    memset(visited, 0, sizeof(visited));
    queue<int> que;
    visited[in1] = 1;
    que.push(in1);
    list<int>::iterator i;
    while (!que.empty()) {
        int p = que.front();
        que.pop();
        for (i = l[p].begin(); i != l[p].end(); i++) {
            if (!visited[*i]) {
                visited[*i] = visited[p] + 1;
                que.push(*i);
            }
            if (*i == in2) {
                return visited[*i] - 1;
            }
        }
    }
}
 
// Returns true if num1 and num2 differ
// by single digit.
bool compare(int num1, int num2)
{
    // To compare the digits
    string s1 = to_string(num1);
    string s2 = to_string(num2);
    int c = 0;
    if (s1[0] != s2[0])
        c++;
    if (s1[1] != s2[1])
        c++;
    if (s1[2] != s2[2])
        c++;
    if (s1[3] != s2[3])
        c++;
 
    // If the numbers differ only by a single
    // digit return true else false
    return (c == 1);
}
 
int shortestPath(int num1, int num2)
{
    // Generate all 4 digit
    vector<int> pset;
    SieveOfEratosthenes(pset);
 
 
    // Create a graph where node numbers are indexes
    // in pset[] and there is an edge between two
    // nodes only if they differ by single digit.
    graph g(pset.size());
    for (int i = 0; i < pset.size(); i++)
        for (int j = i + 1; j < pset.size(); j++)
            if (compare(pset[i], pset[j]))
                g.addedge(i, j);    
     
 
    // Since graph nodes represent indexes of numbers
    // in pset[], we find indexes of num1 and num2.
    int in1, in2;
    for (int j = 0; j < pset.size(); j++)
        if (pset[j] == num1)
            in1 = j;
    for (int j = 0; j < pset.size(); j++)
        if (pset[j] == num2)
            in2 = j;
 
    return g.bfs(in1, in2);
}
 
// Driver code
int main()
{
    int num1 = 1033, num2 = 8179;
    cout << shortestPath(num1, num2);
    return 0;
}


Java




// Java program to reach a prime number from
// another by changing single digits and
// using only prime numbers.
import java.io.*;
import java.util.*;
 
class Graph {
  private int V;
  private LinkedList<Integer>[] l;
 
  // Constructor
  @SuppressWarnings("unchecked") Graph(int v)
  {
    V = v;
    l = new LinkedList[v];
    for (int i = 0; i < v; i++)
      l[i] = new LinkedList<Integer>();
  }
 
  // Function to add an edge into the graph
  void addedge(int V1, int V2)
  {
    l[V1].add(V2);
    l[V2].add(V1);
  }
 
  // Finding all 4 digit prime numbers
  static void SieveOfEratosthenes(LinkedList<Integer> v)
  {
    // Create a boolean array "prime[0..n]" and
    // initialize all entries it as true. A value in
    // prime[i] will finally be false if i is Not a
    // prime, else true.
    int n = 9999;
    Boolean prime[] = new Boolean[n + 1];
    Arrays.fill(prime, true);
 
    for (int p = 2; p * p <= n; p++) {
 
      // If prime[p] is not changed, then it is a
      // prime
      if (prime[p] == true) {
 
        // Update all multiples of p
        for (int i = p * p; i <= n; i += p)
          prime[i] = false;
      }
    }
 
    // Forming a vector of prime numbers
    for (int p = 1000; p <= n; p++) {
      if (prime[p])
        v.add(p);
    }
  }
 
  // in1 and in2 are two vertices of graph which are
  // actually indexes in pset[]
  int bfs(int in1, int in2)
  {
    int visited[] = new int[V];
    Arrays.fill(visited, 0);
    Queue<Integer> que = new LinkedList<Integer>();
    visited[in1] = 1;
    que.add(in1);
 
    while (!que.isEmpty()) {
      int p = que.poll();
      for (int i : l[p]) {
        if (visited[i] == 0) {
          visited[i] = visited[p] + 1;
          que.add(i);
        }
        if (i == in2) {
          return visited[i] - 1;
        }
      }
    }
 
    return 0;
  }
 
  // Returns true if num1 and num2 differ
  // by single digit.
  static Boolean compare(int num1, int num2)
  {
    // To compare the digits
    char[] s1 = (Integer.toString(num1)).toCharArray();
    char[] s2 = (Integer.toString(num2)).toCharArray();
    int c = 0;
    if (s1[0] != s2[0])
      c++;
    if (s1[1] != s2[1])
      c++;
    if (s1[2] != s2[2])
      c++;
    if (s1[3] != s2[3])
      c++;
 
    // If the numbers differ only by a single
    // digit return true else false
    return (c == 1);
  }
 
  static int shortestPath(int num1, int num2)
  {
    // Generate all 4 digit
    LinkedList<Integer> pset
      = new LinkedList<Integer>();
    SieveOfEratosthenes(pset);
 
    // Create a graph where node numbers are indexes
    // in pset[] and there is an edge between two
    // nodes only if they differ by single digit.
    Graph g = new Graph(pset.size());
    for (int i = 0; i < pset.size(); i++) {
      for (int j = i + 1; j < pset.size(); j++) {
        if (compare(pset.get(i), pset.get(j)))
          g.addedge(i, j);
      }
    }
 
    // Since graph nodes represent indexes of numbers
    // in pset[], we find indexes of num1 and num2.
    int in1 = 0, in2 = 0;
    for (int j = 0; j < pset.size(); j++) {
      if (pset.get(j) == num1)
        in1 = j;
    }
 
    for (int j = 0; j < pset.size(); j++) {
      if (pset.get(j) == num2)
        in2 = j;
    }
 
    return g.bfs(in1, in2);
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int num1 = 1033, num2 = 8179;
    int ans = shortestPath(num1, num2);
    System.out.println(ans);
  }
}
 
// This code is contributed by cavi4762.


Python3




# Python3 program to reach a prime number
# from another by changing single digits 
# and using only prime numbers.
import queue
 
class Graph:
     
    def __init__(self, V):
        self.V = V;
        self.l = [[] for i in range(V)]
         
    def addedge(self, V1, V2):
        self.l[V1].append(V2);
        self.l[V2].append(V1);
 
    # in1 and in2 are two vertices of graph 
    # which are actually indexes in pset[]
    def bfs(self, in1, in2):
        visited = [0] * self.V
        que = queue.Queue()
        visited[in1] = 1
        que.put(in1)
        while (not que.empty()):
            p = que.queue[0]
            que.get()
            i = 0
            while i < len(self.l[p]):
                if (not visited[self.l[p][i]]):
                    visited[self.l[p][i]] = visited[p] + 1
                    que.put(self.l[p][i])
                if (self.l[p][i] == in2):
                    return visited[self.l[p][i]] - 1
                i += 1
     
    # Returns true if num1 and num2
    # differ by single digit.
     
# Finding all 4 digit prime numbers
def SieveOfEratosthenes(v):
     
    # Create a boolean array "prime[0..n]" and 
    # initialize all entries it as true. A value
    # in prime[i] will finally be false if i is
    # Not a prime, else true.
    n = 9999
    prime = [True] * (n + 1)
 
    p = 2
    while p * p <= n:
 
        # If prime[p] is not changed,
        # then it is a prime
        if (prime[p] == True):
 
            # Update all multiples of p
            for i in range(p * p, n + 1, p):
                prime[i] = False
        p += 1
 
    # Forming a vector of prime numbers
    for p in range(1000, n + 1):
        if (prime[p]):
            v.append(p)
     
def compare(num1, num2):
     
    # To compare the digits
    s1 = str(num1)
    s2 = str(num2)
    c = 0
    if (s1[0] != s2[0]):
        c += 1
    if (s1[1] != s2[1]):
        c += 1
    if (s1[2] != s2[2]):
        c += 1
    if (s1[3] != s2[3]):
        c += 1
 
    # If the numbers differ only by a single
    # digit return true else false
    return (c == 1)
     
def shortestPath(num1, num2):
     
    # Generate all 4 digit
    pset = []
    SieveOfEratosthenes(pset)
 
    # Create a graph where node numbers
    # are indexes in pset[] and there is
    # an edge between two nodes only if
    # they differ by single digit.
    g = Graph(len(pset))
    for i in range(len(pset)):
        for j in range(i + 1, len(pset)):
            if (compare(pset[i], pset[j])):
                g.addedge(i, j)    
 
    # Since graph nodes represent indexes
    # of numbers in pset[], we find indexes
    # of num1 and num2.
    in1, in2 = None, None
    for j in range(len(pset)):
        if (pset[j] == num1):
            in1 = j
    for j in range(len(pset)):
        if (pset[j] == num2):
            in2 = j
 
    return g.bfs(in1, in2)
 
# Driver code
if __name__ == '__main__':
 
    num1 = 1033
    num2 = 8179
    print(shortestPath(num1, num2))
 
# This code is contributed by PranchalK


C#




// C# program to reach a prime number from
// another by changing single digits and
// using only prime numbers.
using System;
using System.Collections.Generic;
 
class Graph {
    private int V;
    private List<int>[] l;
 
    // Constructor
    Graph(int v)
    {
        V = v;
        l = new List<int>[ v ];
        for (int i = 0; i < v; i++)
            l[i] = new List<int>();
    }
 
    // Function to Add an edge into the graph
    void Addedge(int V1, int V2)
    {
        l[V1].Add(V2);
        l[V2].Add(V1);
    }
 
    // Finding all 4 digit prime numbers
    static void SieveOfEratosthenes(List<int> v)
    {
        // Create a bool array "prime[0..n]" and
        // initialize all entries it as true. A value in
        // prime[i] will finally be false if i is Not a
        // prime, else true.
        int n = 9999;
        bool[] prime = new bool[n + 1];
        Array.Fill(prime, true);
 
        for (int p = 2; p * p <= n; p++) {
 
            // If prime[p] is not changed, then it is a
            // prime
            if (prime[p] == true) {
 
                // Update all multiples of p
                for (int i = p * p; i <= n; i += p)
                    prime[i] = false;
            }
        }
 
        // Forming a vector of prime numbers
        for (int p = 1000; p <= n; p++) {
            if (prime[p])
                v.Add(p);
        }
    }
 
    // in1 and in2 are two vertices of graph which are
    // actually indexes in pset[]
    int Bfs(int in1, int in2)
    {
        int[] visited = new int[V];
        Array.Fill(visited, 0);
        Queue<int> que = new Queue<int>();
        visited[in1] = 1;
        que.Enqueue(in1);
 
        while (que.Count > 0) {
            int p = que.Dequeue();
            foreach(int i in l[p])
            {
                if (visited[i] == 0) {
                    visited[i] = visited[p] + 1;
                    que.Enqueue(i);
                }
                if (i == in2) {
                    return visited[i] - 1;
                }
            }
        }
 
        return 0;
    }
 
    // Returns true if num1 and num2 differ
    // by single digit.
    static bool Compare(int num1, int num2)
    {
        // To compare the digits
        string s1 = num1.ToString();
        string s2 = num2.ToString();
        int c = 0;
        if (s1[0] != s2[0])
            c++;
        if (s1[1] != s2[1])
            c++;
        if (s1[2] != s2[2])
            c++;
        if (s1[3] != s2[3])
            c++;
 
        // If the numbers differ only by a single
        // digit return true else false
        return (c == 1);
    }
 
    static int ShortestPath(int num1, int num2)
    {
        // Generate all 4 digit
        List<int> pset = new List<int>();
        SieveOfEratosthenes(pset);
 
        // Create a graph where node numbers are indexes
        // in pset[] and there is an edge between two
        // nodes only if they differ by single digit.
        Graph g = new Graph(pset.Count);
        for (int i = 0; i < pset.Count; i++) {
            for (int j = i + 1; j < pset.Count; j++) {
                if (Compare(pset[i], pset[j]))
                    g.Addedge(i, j);
            }
        }
 
        // Since graph nodes represent indexes of numbers
        // in pset[], we find indexes of num1 and num2.
        int in1 = 0, in2 = 0;
        for (int j = 0; j < pset.Count; j++) {
            if (pset[j] == num1)
                in1 = j;
        }
 
        for (int j = 0; j < pset.Count; j++) {
            if (pset[j] == num2)
                in2 = j;
        }
 
        return g.Bfs(in1, in2);
    }
 
    // Driver code
    static void Main(string[] args)
    {
        int num1 = 1033, num2 = 8179;
        int ans = ShortestPath(num1, num2);
        Console.WriteLine(ans);
    }
}
 
// This code is contributed by cavi4762.


Javascript




// JS Code
 
class Graph {
  constructor(V) {
    this.V = V;
    this.l = new Array(V);
    for(let i=0;i<V;i++)
    {
     this.l[i] = new Array();
    }
  }
 
  addedge(V1, V2) {
    this.l[V1].push(V2);
    this.l[V2].push(V1);
  }
 
  bfs(in1, in2) {
    let visited = new Array(this.V).fill(0);
    let que = [];
    visited[in1] = 1;
    que.push(in1);
    while (que.length > 0) {
      let p = que[0];
      que.splice(0, 1);
      for (let i = 0; i < this.l[p].length; i++) {
        if (!visited[this.l[p][i]]) {
          visited[this.l[p][i]] = visited[p] + 1;
          que.push(this.l[p][i]);
        }
        if (this.l[p][i] == in2) {
          return visited[this.l[p][i]] - 1;
        }
      }
    }
  }
}
 
// Finding all 4 digit prime numbers
function SieveOfEratosthenes(v)
{
 
  // Create a boolean array "prime[0..n]" and
  // initialize all entries it as true. A value
  // in prime[i] will finally be false if i is
  // Not a prime, else true.
  let n = 9999;
  let prime = new Array(n + 1).fill(true);
 
  let p = 2;
  while (p * p <= n)
  {
   
    // If prime[p] is not changed,
    // then it is a prime
    if (prime[p] == true)
    {
     
      // Update all multiples of p
      for (let i = p * p; i <= n; i += p) {
        prime[i] = false;
      }
    }
    p++;
  }
 
  // Forming a vector of prime numbers
  for (let p = 1000; p <= n; p++) {
    if (prime[p]) {
      v.push(p);
    }
  }
}
 
function compare(num1, num2) {
  // To compare the digits
  let s1 = String(num1);
  let s2 = String(num2);
  let c = 0;
  if (s1[0] != s2[0]) {
    c += 1;
  }
  if (s1[1] != s2[1]) {
    c += 1;
  }
  if (s1[2] != s2[2]) {
    c += 1;
  }
  if (s1[3] != s2[3]) {
    c += 1;
  }
 
  // If the numbers differ only by a single
  // digit return true else false
  return c == 1;
}
 
function shortestPath(num1, num2) {
  // Generate all 4 digit
  let pset = [];
  SieveOfEratosthenes(pset);
 
  // Create a graph where node numbers
  // are indexes in pset[] and there is
  // an edge between two nodes only if
  // they differ by single digit.
  let g = new Graph(pset.length);
  for (let i = 0; i < pset.length; i++) {
    for (let j = i + 1; j < pset.length; j++) {
      if (compare(pset[i], pset[j])) {
        g.addedge(i, j);
      }
    }
  }
 
  // Since graph nodes represent indexes
  // of numbers in pset[], we find indexes
  // of num1 and num2.
  let in1, in2;
  for (let j = 0; j < pset.length; j++) {
    if (pset[j] == num1) {
      in1 = j;
    }
  }
  for (let j = 0; j < pset.length; j++) {
    if (pset[j] == num2) {
      in2 = j;
    }
  }
 
  return g.bfs(in1, in2);
}
 
// Driver code
if (true) {
  let num1 = 1033;
  let num2 = 8179;
  console.log(shortestPath(num1, num2));
}
 
// This code is contributed by ishankhandelwals.


Output : 

6

Time Complexity : O(n*log(log(n)) + n^2 + n^2) = O(n^2).

Space complexity: O(n + V^2), which is equivalent to O(n).



Last Updated : 12 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads