Open In App

Number of triangles that can be formed with given N points

Improve
Improve
Like Article
Like
Save
Share
Report

Given X and Y coordinates of N points on a Cartesian plane. The task is to find the number of possible triangles with the non-zero area that can be formed by joining each point to every other point.
 Examples:

Input: P[] = {{0, 0}, {2, 0}, {1, 1}, {2, 2}}
Output: 3
Possible triangles can be [(0, 0}, (2, 0), (1, 1)], 
[(0, 0), (2, 0), (2, 2)] and [(1, 1), (2, 2), (2, 0)]

Input : P[] = {{0, 0}, {2, 0}, {1, 1}}
Output : 1

A Naive approach has been already discussed in Number of possible Triangles in a Cartesian coordinate system 
7Efficient Approach: Consider a point Z and find its slope with every other point. Now, if two points are having the same slope with point Z that means the 3 points are collinear and they cannot form a triangle. Hence, the number of triangles having Z as one of its points is the number of ways of choosing 2 points from the remaining points and then subtracting the number of ways of choosing 2 points from points having the same slope with Z. Since Z can be any point among N points, we have to iterate one more loop.

Steps to solve the problem:

  • Initialize an empty map mp and a variable ans to 0.
  •  Iterate from 0 to N-1.
    • Clear the map mp.
    • For each point i, calculate the slope of all other points with respect to the current point.
    • calculate the greatest common divisor (GCD) of the difference in X and Y coordinate
    • between point i and j. Divide the difference in X and Y coordinates by their GCD.
    • Store the slope as a key-value pair in the map mp, where the key is a pair of integers representing the slope and the value is the frequency of that slope.
    • Calculate the number of ways by the formula (N – (i + 1)) * (N – (i + 1) – 1) / 2. Add this value to the and.
    • Iterate over the map mp, and for each key-value pair, calculate the number of ways by the formula j.second * (j.second – 1) /2.
    • Subtract this value from the and.
  • Return the final value of ans.

 Below is the implementation of the above approach: 

C++




// C++ implementation of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// This function returns the required number
// of triangles
int countTriangles(pair<int, int> P[], int N)
{
    // Hash Map to store the frequency of
    // slope corresponding to a point (X, Y)
    map<pair<int, int>, int> mp;
    int ans = 0;
 
    // Iterate over all possible points
    for (int i = 0; i < N; i++) {
        mp.clear();
 
        // Calculate slope of all elements
        // with current element
        for (int j = i + 1; j < N; j++) {
            int X = P[i].first - P[j].first;
            int Y = P[i].second - P[j].second;
 
            // find the slope with reduced
            // fraction
            int g = __gcd(X, Y);
            X /= g;
            Y /= g;
            mp[{ X, Y }]++;
        }
        int num = N - (i + 1);
 
        // Total number of ways to form a triangle
        // having one point as current element
        ans += (num * (num - 1)) / 2;
 
        // Subtracting the total number of ways to
        // form a triangle having the same slope or are
        // collinear
        for (auto j : mp)
            ans -= (j.second * (j.second - 1)) / 2;
    }
    return ans;
}
 
// Driver Code to test above function
int main()
{
    pair<int, int> P[] = { { 0, 0 }, { 2, 0 }, { 1, 1 }, { 2, 2 } };
    int N = sizeof(P) / sizeof(P[0]);
    cout << countTriangles(P, N) << endl;
    return 0;
}


Java




// Java implementation of the above approach
 
import java.util.*;
 
class GFG {
    // A recursive function to find gcd of two numbers.
    static int __gcd(int x, int y)
    {
        x = Math.abs(x);
        y = Math.abs(y);
        while (y > 0) {
            int t = y;
            y = x % y;
            x = t;
        }
        return x;
    }
 
    // This function returns the required number
    // of triangles
    static int countTriangles(int[][] P, int N)
    {
        // Hash Map to store the frequency of
        // slope corresponding to a point (X, Y)
        // map<pair<int, int>, int> mp;
        HashMap<String, Integer> mp
            = new HashMap<String, Integer>();
 
        int ans = 0;
 
        // Iterate over all possible points
        for (int i = 0; i < N; i++) {
            mp.clear();
 
            // Calculate slope of all elements
            // with current element
            for (int j = i + 1; j < N; j++) {
                int X = P[i][0] - P[j][0];
                int Y = P[i][1] - P[j][1];
 
                // find the slope with reduced
                // fraction
                int g = __gcd(X, Y);
                X = (int)(X / g);
                Y = (int)(Y / g);
 
                String key = String.valueOf(X) + ","
                             + String.valueOf(Y);
 
                if (!mp.containsKey(key))
                    mp.put(key, 0);
                mp.put(key, mp.get(key) + 1);
            }
 
            int num = N - (i + 1);
 
            // Total number of ways to form a triangle
            // having one point as current element
            ans += (int)((num * (num - 1)) / 2);
 
            // Subtracting the total number of ways to
            // form a triangle having the same slope or are
            // collinear
            for (Map.Entry<String, Integer> entry :
                 mp.entrySet())
                ans -= (entry.getValue()
                        * (entry.getValue() - 1))
                       / 2;
        }
        return ans;
    }
 
    // Driver Code to test above function
    public static void main(String[] args)
    {
        int[][] P
            = { { 0, 0 }, { 2, 0 }, { 1, 1 }, { 2, 2 } };
        int N = P.length;
        System.out.println(countTriangles(P, N));
    }
}
 
// The code is contributed by phasing17


Python3




# Python3 implementation of the above approach
from collections import defaultdict
from math import gcd
 
# This function returns the
# required number of triangles
def countTriangles(P, N):
 
    # Hash Map to store the frequency of
    # slope corresponding to a point (X, Y)
    mp = defaultdict(lambda:0)
    ans = 0
 
    # Iterate over all possible points
    for i in range(0, N):
        mp.clear()
 
        # Calculate slope of all elements
        # with current element
        for j in range(i + 1, N):
            X = P[i][0] - P[j][0]
            Y = P[i][1] - P[j][1]
 
            # find the slope with reduced
            # fraction
            g = gcd(X, Y)
            X //= g
            Y //= g
            mp[(X, Y)] += 1
         
        num = N - (i + 1)
 
        # Total number of ways to form a triangle
        # having one point as current element
        ans += (num * (num - 1)) // 2
 
        # Subtracting the total number of
        # ways to form a triangle having
        # the same slope or are collinear
        for j in mp:
            ans -= (mp[j] * (mp[j] - 1)) // 2
     
    return ans
 
# Driver Code
if __name__ == "__main__":
 
    P = [[0, 0], [2, 0], [1, 1], [2, 2]]
    N = len(P)
    print(countTriangles(P, N))
     
# This code is contributed by Rituraj Jain


C#




// C# implementation of the above approach
 
using System;
using System.Collections.Generic;
 
class GFG {
    // A recursive function to find gcd of two numbers.
    static int __gcd(int x, int y)
    {
        x = Math.Abs(x);
        y = Math.Abs(y);
        while (y > 0) {
            int t = y;
            y = x % y;
            x = t;
        }
        return x;
    }
 
    // This function returns the required number
    // of triangles
    static int countTriangles(int[, ] P, int N)
    {
        // Hash Map to store the frequency of
        // slope corresponding to a point (X, Y)
        // map<pair<int, int>, int> mp;
        Dictionary<string, int> mp
            = new Dictionary<string, int>();
 
        int ans = 0;
 
        // Iterate over all possible points
        for (int i = 0; i < N; i++) {
            mp.Clear();
 
            // Calculate slope of all elements
            // with current element
            for (int j = i + 1; j < N; j++) {
                int X = P[i, 0] - P[j, 0];
                int Y = P[i, 1] - P[j, 1];
 
                // find the slope with reduced
                // fraction
                int g = __gcd(X, Y);
                X = (int)(X / g);
                Y = (int)(Y / g);
 
                int[] l1 = { X, Y };
                string key = string.Join(", ", l1);
 
                if (!mp.ContainsKey(key))
                    mp[key] = 0;
                mp[key]++;
            }
 
            int num = N - (i + 1);
 
            // Total number of ways to form a triangle
            // having one point as current element
            ans += (int)((num * (num - 1)) / 2);
 
            // Subtracting the total number of ways to
            // form a triangle having the same slope or are
            // collinear
            foreach(var entry in mp) ans
                -= (entry.Value * (entry.Value - 1)) / 2;
        }
        return ans;
    }
 
    // Driver Code to test above function
    public static void Main(string[] args)
    {
        int[, ] P
            = { { 0, 0 }, { 2, 0 }, { 1, 1 }, { 2, 2 } };
        int N = P.GetLength(0);
        Console.WriteLine(countTriangles(P, N));
    }
}
 
// The code is contributed by Nidhi goel


Javascript




// JavaScript implementation of the above approach
 
// A recursive function to find gcd of two numbers.
function __gcd(x, y) {
  if ((typeof x !== 'number') || (typeof y !== 'number'))
    return false;
  x = Math.abs(x);
  y = Math.abs(y);
  while(y) {
    var t = y;
    y = x % y;
    x = t;
  }
  return x;
}
 
// This function returns the required number
// of triangles
function countTriangles(P, N)
{
    // Hash Map to store the frequency of
    // slope corresponding to a point (X, Y)
    // map<pair<int, int>, int> mp;
    let mp = new Map();
     
    let ans = 0;
 
    // Iterate over all possible points
    for (let i = 0; i < N; i++) {
        mp.clear();
 
        // Calculate slope of all elements
        // with current element
        for (let j = i + 1; j < N; j++) {
            let X = P[i][0] - P[j][0];
            let Y = P[i][1] - P[j][1];
 
            // find the slope with reduced
            // fraction
            let g = __gcd(X, Y);
            X = Math.floor(X/g);
            Y = Math.floor(Y/g);
             
            if(mp.has([X, Y].join())){
                mp.set([X, Y].join(), mp.get([X, Y].join()) + 1);
            }
            else{
                mp.set([X, Y].join(), 1);
            }
             
        }
        let num = N - (i + 1);
 
        // Total number of ways to form a triangle
        // having one point as current element
        ans += Math.floor((num * (num - 1)) / 2);
 
        // Subtracting the total number of ways to
        // form a triangle having the same slope or are
        // collinear
        for (const [key, value] of mp.entries())
            ans -= (value * (value - 1)) / 2;
    }
    return ans;
}
 
// Driver Code to test above function
let P = [[0, 0], [2, 0], [1, 1 ], [2, 2 ]];
let N = P.length;
console.log(countTriangles(P, N));
 
// The code is contributed by Nidhi goel


Output:

3

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



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