Open In App
Related Articles

Check if chords of a Circle are symmetric after some rotation

Improve Article
Improve
Save Article
Save
Like Article
Like

Given two Integers N and M, N indicating equidistant points on circumference of a circle and M indicating number of chords formed with those points. Also given is a vector of pairs C containing position of chords. The task is to rotate the circle by any degree, say X, where 0 < X < 360, and check if the chords of are still symmetric to the original circle.

Example: 

Input: N = 12, M = 6, C = {{1, 3}, {3, 7}, {5, 7}, {7, 11}, {9, 11}, {11, 3}};
Output: YES

Original

After Rotation

Input: N = 10, M = 3,  C = {{1, 2}, {3, 2}, {7, 2}}
Output: NO

No rotational symmetry possible

Naive Approach: Rotate for every distance K in the range[1, N] and check for each point [a, b] if the rotated point [a + K, b + K] exits. 
If there exists any k then print YES else print NO
Time Complexity: O(N*M)

Efficient Approach: It is enough to check for the divisors of N
Let us suppose if we rotate the image by K units then the whole image will be divided into N/K blocks. Then if K is not a divisor of N, there will be an asymmetric block of length less than K and the image will never be symmetric to the original figure.
So calculate all the divisors of N and check for each chord the rotated chord exists or not.

Below is the implementation of the above approach:

C++




// C++ Program to for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Utility function to calculate
// divisors of a number in O(sqrt(N))
vector<int> calculateDivisors(int N)
{
    vector<int> div;
    for (int i = 1; i * i <= N; i++) {
        if (N % i == 0) {
            div.push_back(i);
            if (N / i != i && i != 1) {
                div.push_back(N / i);
            }
        }
    }
    return div;
}
int checkRotationallySymmetric(
    vector<pair<int, int> > A,
    int N, int M)
{
    // Maintain a set to check quickly
    // the presence of a chord
    set<pair<int, int> > st;
    for (int i = 0; i < M; i++) {
        --A[i].first, --A[i].second;
        if (A[i].first > A[i].second) {
            swap(A[i].first, A[i].second);
        }
        st.insert(A[i]);
    }
 
    // Calculate the divisors of N.
    vector<int> div = calculateDivisors(N);
 
    // Iterate through the divisors
    for (auto x : div) {
        bool exist = 1;
        for (int i = 0; i < M; i++) {
            int dx = (A[i].first + x) % N;
            int dy = (A[i].second + x) % N;
            if (dx > dy) {
                swap(dx, dy);
            }
            if (st.find({ dx, dy }) != st.end()) {
 
                // There exists a valid
                // chord after rotation
            }
            else {
 
                // There is no valid chord after rotation
                exist = false;
                break;
            }
        }
 
        // if there exist another chord after
        // rotation for every other chord print
        // YES and exit the function
        if (exist) {
            cout << "YES";
            return 0;
        }
    }
    cout << "NO";
    return 0;
}
 
// Driver Code
int main()
{
    int N = 12, M = 6;
    vector<pair<int, int> > C
        = { { 1, 3 }, { 3, 7 }, { 5, 7 },
             { 7, 11 }, { 9, 11 }, { 11, 3 } };
    checkRotationallySymmetric(C, N, M);
    return 0;
}


Java




import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
 
class GFG {
 
  // function to calculate divisors
  static List<Integer> calculateDivisors(int N)
  {
    List<Integer> div = new ArrayList<>();
 
    // checking all possible divisors
    for (int i = 1; i * i <= N; i++) {
      if (N % i == 0) {
        div.add(i);
        if (N / i != i && i != 1) {
          div.add(N / i);
        }
      }
    }
    return div;
  }
 
  static int checkRotationallySymmetric(List<int[]> A,
                                        int N, int M)
  {
    // Maintain a set to check quickly
    // the presence of a chord
    Set<String> st = new HashSet<>();
    for (int i = 0; i < M; i++) {
      A.get(i)[0] = A.get(i)[0] - 1;
      A.get(i)[1] = A.get(i)[1] - 1;
      if (A.get(i)[0] > A.get(i)[1]) {
        int temp = A.get(i)[0];
        A.get(i)[0] = A.get(i)[1];
        A.get(i)[1] = temp;
      }
      st.add(A.get(i)[0] + " " + A.get(i)[1]);
    }
 
    // Calculate the divisors of N.
    List<Integer> div = calculateDivisors(N);
 
    // Iterate through the divisors
    for (int x : div) {
      boolean exist = true;
      for (int i = 0; i < M; i++) {
        int dx = (A.get(i)[0] + x) % N;
        int dy = (A.get(i)[1] + x) % N;
        if (dx > dy) {
          int temp = dx;
          dx = dy;
          dy = temp;
        }
        if (st.contains(dx + " " + dy)) {
 
          // There exists a valid chord after
          // rotation
        }
        else {
 
          // There is no valid chord after
          // rotation
          exist = false;
          break;
        }
      }
 
      // if there exist another chord after rotation
      // for every other chord print YES and exit the
      // function
      if (exist) {
        System.out.println("YES");
        return 0;
      }
    }
    System.out.println("NO");
    return 0;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int N = 12, M = 6;
    List<int[]> C = new ArrayList<>();
    C.add(new int[] { 1, 3 });
    C.add(new int[] { 3, 7 });
    C.add(new int[] { 5, 7 });
    C.add(new int[] { 7, 11 });
    C.add(new int[] { 9, 11 });
    C.add(new int[] { 11, 3 });
 
    // function call
    checkRotationallySymmetric(C, N, M);
  }
}
 
// This code is contributed by phasing17


Python3




# Python3 program to implement the approach
from typing import List, Tuple
 
def calculateDivisors(N: int) -> List[int]:
    """
    Utility function to calculate
    divisors of a number in O(sqrt(N))
    """
    div = []
    for i in range(1, int((N ** 0.5) + 1)):
        if N % i == 0:
            div.append(i)
            if N // i != i and i != 1:
                div.append(N // i)
    return div
 
def checkRotationallySymmetric(A: List[Tuple[int, int]], N: int, M: int) -> None:
    """
    Main function to check rotationally symmetric
    """
    # Maintain a set to check quickly
    # the presence of a chord
    st = set()
    for i in range(M):
        A[i] = (A[i][0] - 1, A[i][1] - 1)
        if A[i][0] > A[i][1]:
            A[i] = (A[i][1], A[i][0])
        st.add(tuple(A[i]))
 
    # Calculate the divisors of N.
    div = calculateDivisors(N)
 
    # Iterate through the divisors
    for j in range(len(div)):
        exist = True
        for i in range(M):
            dx = (A[i][0] + div[j]) % N
            dy = (A[i][1] + div[j]) % N
            if dx > dy:
                # swapping dx and dy.
                temp = dx
                dx = dy
                dy = temp
            if tuple((dx, dy)) in st:
                # There exists a valid chord after rotation
                pass
            else:
                # There is no valid chord after rotation
                exist = False
                break
        # if there exist another chord after rotation for every other chord print YES and exit the function
        if exist:
            print("YES")
            return
    print("NO")
    return
 
# Driver code
N = 12
M = 6
C = [(1, 3), (3, 7), (5, 7), (7, 11), (9, 11), (11, 3)]
checkRotationallySymmetric(C, N, M)
 
 
# This code is contributed by phasing17


C#




// C# code to implement the above approach
using System;
using System.Collections.Generic;
 
class GFG {
 
  // function to calculate divisors
  static List<int> calculateDivisors(int N)
  {
    List<int> div = new List<int>();
 
    // checking all possible divisors
    for (int i = 1; i * i <= N; i++) {
      if (N % i == 0) {
        div.Add(i);
        if (N / i != i && i != 1) {
          div.Add(N / i);
        }
      }
    }
    return div;
  }
 
  static int
    checkRotationallySymmetric(List<Tuple<int, int> > A,
                               int N, int M)
  {
    // Maintain a set to check quickly
    // the presence of a chord
    HashSet<Tuple<int, int> > st
      = new HashSet<Tuple<int, int> >();
    for (int i = 0; i < M; i++) {
      A[i] = new Tuple<int, int>(A[i].Item1 - 1,
                                 A[i].Item2 - 1);
      if (A[i].Item1 > A[i].Item2) {
        A[i] = new Tuple<int, int>(A[i].Item2,
                                   A[i].Item1);
      }
      st.Add(A[i]);
    }
 
    // Calculate the divisors of N.
    List<int> div = calculateDivisors(N);
 
    // Iterate through the divisors
    foreach(var x in div)
    {
      bool exist = true;
      for (int i = 0; i < M; i++) {
        int dx = (A[i].Item1 + x) % N;
        int dy = (A[i].Item2 + x) % N;
        if (dx > dy) {
          Tuple<int, int> temp
            = new Tuple<int, int>(dy, dx);
          dx = temp.Item1;
          dy = temp.Item2;
        }
        if (st.Contains(
          new Tuple<int, int>(dx, dy))) {
 
          // There exists a valid
          // chord after rotation
        }
        else {
 
          // There is no valid chord after
          // rotation
          exist = false;
          break;
        }
      }
 
      // if there exist another chord after
      // rotation for every other chord print
      // YES and exit the function
      if (exist) {
        Console.WriteLine("YES");
        return 0;
      }
    }
    Console.WriteLine("NO");
    return 0;
  }
 
  // Driver Code
  static void Main(string[] args)
  {
    int N = 12, M = 6;
    List<Tuple<int, int> > C
      = new List<Tuple<int, int> >{
      new Tuple<int, int>(1, 3),
      new Tuple<int, int>(3, 7),
      new Tuple<int, int>(5, 7),
      new Tuple<int, int>(7, 11),
      new Tuple<int, int>(9, 11),
      new Tuple<int, int>(11, 3)
      };
 
    // function call
    checkRotationallySymmetric(C, N, M);
  }
}
 
// This code is contributed by phasing17


Javascript




// JavaScript Program to for the above approach
 
// Utility function to calculate
// divisors of a number in O(sqrt(N))
function calculateDivisors(N)
{
    let div = new Array();
    for (let i = 1; i * i <= N; i++) {
        if (N % i == 0) {
            div.push(i);
            if (Math.floor(N / i) != i && i != 1) {
                div.push(Math.floor(N / i));
            }
        }
    }
 
    return div;
}
function checkRotationallySymmetric( A, N, M)
{
    // Maintain a set to check quickly
    // the presence of a chord
    let st = new Set();
    for (let i = 0; i < M; i++) {
        A[i][0] = A[i][0] - 1;
        A[i][1] = A[i][1] - 1;
        if (A[i][0] > A[i][1]) {
            let temp = A[i][0];
            A[i][0] = A[i][1];
            A[i][1] = temp;
        }
        st.add(A[i].join(''));
    }
 
    // Calculate the di   ors of N.
    let div = calculateDivisors(N);
     
    // Iterate through the divisors
    for (let j = 0; j < div.length; j++){
         
        let exist = true;
        for (let i = 0; i < M; i++) {
            let dx = (A[i][0] + div[j]) % N;
            let dy = (A[i][1] + div[j]) % N;
            if (dx > dy) {
                 
                // swapping dx and dy.
                let temp = dx;
                dx = dy;
                dy = temp;
            }
             
            if (st.has([dx, dy].join(''))) {
                // There exists a valid
                // chord after rotation
            }
            else {
                // console.log([dx, dy]);
                // There is no valid chord after rotation
                exist = false;
                break;
            }
        }
 
        // if there exist another chord after
        // rotation for every other chord print
        // YES and exit the function
        if (exist) {
            console.log("YES");
            return 0;
        }
    }
    console.log("NO");
    return 0;
}
 
// Driver Code
let N = 12, M = 6;
let C
    = [[1, 3 ], [3, 7 ], [5, 7 ],
         [7, 11 ], [9, 11], [11, 3 ]];
checkRotationallySymmetric(C, N, M);
 
// The code is contributed by Gautam goel (gautamgoel962)


Output

YES

Time Complexity: O(M*sqrt(N)*log M)
Space Complexity: O(M)


Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!

Last Updated : 15 Feb, 2023
Like Article
Save Article
Previous
Next
Similar Reads
Complete Tutorials