Number of Triangles that can be formed given a set of lines in Euclidean Plane
Last Updated :
23 Jun, 2022
Given a set L = {l1, l2, ………, ln} of ‘n’ distinct lines on the Euclidean Plane. The ith line is given by an equation in the form aix + biy = ci. Find the number of triangles that can be formed using the lines in the set L. Note that no two pairs of lines intersect at the same point.
Note: This problem doesn’t mention that the lines can’t be parallel which makes the problem difficult to solve.
Examples:
Input: a[] = {1, 2, 3, 4}
b[] = {2, 4, 5, 5}
c[] = {5, 7, 8, 6}
Output: 2
The number of triangles that can be formed are: 2
Input: a[] = {1, 2, 3, 2, 4, 1, 2, 3, 4, 5}
b[] = {2, 4, 6, 3, 6, 5, 10, 15, 20, 25}
c[] = {3, 5, 11, 10, 9, 17, 13, 11, 7, 3}
Output: 30
The number of triangles that can be formed are: 30
Naive Algorithm
The naive algorithm can be described as:
- Pick up 3 arbitrary lines from the set L.
- Now check if a triangle can be formed using the selected 3 lines. This can be done easily by checking that none of them is pairwise parallel.
- Increment the counter if the triangle can be formed.
Time Complexity: There are nC3 triplets of lines. For each triplet, we have to do 3 comparisons to check that any 2 lines are not parallel which means the check can be done in O(1) time. This makes the naive algorithm O(n3).
Efficient Algorithm
This can also be achieved in O(n log n). The logic behind the efficient algorithm is described below.
We divide the set L in various subsets. The formation of subsets is based on slopes i.e. all the lines in a particular subset have the same slope i.e. they are parallel to each other.
Let us consider three sets (say A, B and C). For a particular set (say A) the lines belonging to this are all parallel to each other. If we have A, B, and C, we can pick one line from each set to get a triangle because none of these lines will be parallel. By making the subsets we have ensured that no two lines which are parallel are being picked together.
Now if we have only these 3 subsets,
Number of triangles = (Number of ways to pick a line from A) *
(Number of ways to pick a line from B) *
(Number of ways to pick a line from C)
= m1*m2*m3
Here m1 is count of elements with first slope (in Set A)
Here m2 is count of elements with first slope (in Set B)
Here m3 is count of elements with first slope (in Set C)
Similarly, if we have 4 subsets, we can extend this logic to get,
Number of triangles = m1*m2*m3 + m1*m2*m4 + m1*m3*m4 + m2*m3*m4
For number of subsets greater than 3, If we have ‘k’ subsets, our task is to find the sum of number of elements of the subset taken 3 at a time. This can be done by maintaining a count array. We make a count array where counti denotes the count of the ith subset of parallel lines.
We one by one compute following values.
sum1 = m1 + m2 + m3 .....
sum2 = m1*m2 + m1*m3 + ... + m2*m3 + m2*m4 + ...
sum3 = m1*m2*m3 + m1*m2*m4 + ...... m2*m3*m4 + ....
sum3 gives our final answer
C++
#include <bits/stdc++.h>
using namespace std;
#define EPSILON numeric_limits<double>::epsilon()
bool compareDoubles( double A, double B)
{
double diff = A-B;
return (diff<EPSILON) && (-diff<EPSILON);
}
int numberOfTringles( int a[], int b[], int c[], int n)
{
double slope[n];
for ( int i=0; i<n; i++)
slope[i] = (a[i]*1.0)/b[i];
sort(slope, slope+n);
int count[n], k = 0;
int this_count = 1;
for ( int i=1; i<n; i++)
{
if (compareDoubles(slope[i], slope[i-1]))
this_count++;
else
{
count[k++] = this_count;
this_count = 1;
}
}
count[k++] = this_count;
int sum1 = 0;
for ( int i=0; i<k; i++)
sum1 += count[i];
int sum2 = 0;
int temp[n];
for ( int i=0; i<k; i++)
{
temp[i] = count[i]*(sum1-count[i]);
sum2 += temp[i];
}
sum2 /= 2;
int sum3 = 0;
for ( int i=0; i<k; i++)
sum3 += count[i]*(sum2-temp[i]);
sum3 /= 3;
return sum3;
}
int main()
{
int a[] = {1, 2, 3, 4};
int b[] = {2, 4, 5, 5};
int c[] = {5, 7, 8, 6};
int n = sizeof (a)/ sizeof (a[0]);
cout << "The number of triangles that"
" can be formed are: "
<< numberOfTringles(a, b, c, n);
return 0;
}
|
Java
import java.util.*;
class GFG{
static double EPSILON = 1 .0842e- 19 ;
static boolean compareDoubles( double A, double B)
{
double diff = A - B;
return (diff < EPSILON) &&
(-diff < EPSILON);
}
static int numberOfTringles( int []a, int []b,
int []c, int n)
{
Vector<Double> slope = new Vector<>();
for ( int i = 0 ; i < n; i++)
slope.add(( double )(a[i] * 1.0 ) / b[i]);
Collections.sort(slope);
int []count = new int [n];
int k = 0 ;
int this_count = 1 ;
for ( int i = 1 ; i < n; i++)
{
if (compareDoubles(( double )slope.get(i),
( double )slope.get(i - 1 )))
this_count++;
else
{
count[k++] = this_count;
this_count = 1 ;
}
}
count[k++] = this_count;
int sum1 = 0 ;
for ( int i = 0 ; i < k; i++)
sum1 += count[i];
int sum2 = 0 ;
int temp[] = new int [n];
for ( int i = 0 ; i < k; i++)
{
temp[i] = count[i] * (sum1 - count[i]);
sum2 += temp[i];
}
sum2 /= 2 ;
int sum3 = 0 ;
for ( int i = 0 ; i < k; i++)
sum3 += count[i] * (sum2 - temp[i]);
sum3 /= 3 ;
return sum3;
}
public static void main(String[] args)
{
int a[] = { 1 , 2 , 3 , 4 };
int b[] = { 2 , 4 , 5 , 5 };
int c[] = { 5 , 7 , 8 , 6 };
int n = a.length;
System.out.println( "The number of triangles " +
"that can be formed are: " +
numberOfTringles(a, b, c, n));
}
}
|
Python3
import math
EPSILON = 1.0842e - 19
def compareDoubles(A, B):
diff = A - B
return (diff < EPSILON) and ( - diff < EPSILON)
def numberOfTringles(a, b, c, n):
slope = []
for i in range ( 0 , n):
slope.append((a[i] * 1.0 ) / b[i])
slope.sort()
k = 0
count = []
this_count = 1
for i in range ( 1 , n):
if compareDoubles(slope[i], slope[i - 1 ]):
this_count = this_count + 1
else :
count.append(this_count)
k = k + 1
this_count = 1
count.append(this_count)
k = k + 1
sum1 = 0
for i in range ( 0 , k):
sum1 + = count[i]
sum2 = 0
temp = []
for i in range ( 0 , k):
temp.append(count[i] * (sum1 - count[i]))
sum2 + = temp[i]
sum2 = math.floor(sum2 / 2 )
sum3 = 0
for i in range ( 0 , k):
sum3 + = count[i] * (sum2 - temp[i])
sum3 = math.floor(sum3 / 3 )
return sum3
a = [ 1 , 2 , 3 , 4 ]
b = [ 2 , 4 , 5 , 5 ]
c = [ 5 , 7 , 8 , 6 ]
n = len (a)
print ( "The number of triangles that can be formed are: " ,
numberOfTringles(a, b, c, n))
|
C#
using System.Collections.Generic;
using System;
class GFG{
static double EPSILON = 1.0842e-19;
static bool compareDoubles( double A, double B)
{
double diff = A - B;
return (diff < EPSILON) &&
(-diff < EPSILON);
}
static int numberOfTringles( int []a, int []b,
int []c, int n)
{
List< double > slope = new List< double >();
for ( int i = 0; i < n; i++)
slope.Add(( double )(a[i] * 1.0) / b[i]);
slope.Sort();
int []count = new int [n];
int k = 0;
int this_count = 1;
for ( int i = 1; i < n; i++)
{
if (compareDoubles(( double )slope[i],
( double )slope[i - 1]))
this_count++;
else
{
count[k++] = this_count;
this_count = 1;
}
}
count[k++] = this_count;
int sum1 = 0;
for ( int i = 0; i < k; i++)
sum1 += count[i];
int sum2 = 0;
int []temp = new int [n];
for ( int i = 0; i < k; i++)
{
temp[i] = count[i] * (sum1 - count[i]);
sum2 += temp[i];
}
sum2 /= 2;
int sum3 = 0;
for ( int i = 0; i < k; i++)
sum3 += count[i] * (sum2 - temp[i]);
sum3 /= 3;
return sum3;
}
public static void Main()
{
int []a = { 1, 2, 3, 4 };
int []b = { 2, 4, 5, 5 };
int []c = { 5, 7, 8, 6 };
int n = a.Length;
Console.WriteLine( "The number of triangles " +
"that can be formed are: " +
numberOfTringles(a, b, c, n));
}
}
|
Javascript
<script>
const EPSILON = 1.0842e-19;
function compareDoubles(A, B) {
var diff = A - B;
return diff < EPSILON && -diff < EPSILON;
}
function numberOfTringles(a, b, c, n) {
var slope = [];
for ( var i = 0; i < n; i++) slope.push(parseFloat(a[i] * 1.0) / b[i]);
slope.sort();
var count = new Array(n).fill(0);
var k = 0;
var this_count = 1;
for ( var i = 1; i < n; i++) {
if (compareDoubles(parseFloat(slope[i]), parseFloat(slope[i - 1])))
this_count++;
else {
count[k++] = this_count;
this_count = 1;
}
}
count[k++] = this_count;
var sum1 = 0;
for ( var i = 0; i < k; i++) sum1 += count[i];
var sum2 = 0;
var temp = new Array(n).fill(0);
for ( var i = 0; i < k; i++) {
temp[i] = count[i] * (sum1 - count[i]);
sum2 += temp[i];
}
sum2 /= 2;
var sum3 = 0;
for ( var i = 0; i < k; i++) sum3 += count[i] * (sum2 - temp[i]);
sum3 /= 3;
return sum3;
}
var a = [1, 2, 3, 4];
var b = [2, 4, 5, 5];
var c = [5, 7, 8, 6];
var n = a.length;
document.write(
"The number of triangles " +
"that can be formed are: " +
numberOfTringles(a, b, c, n)
);
</script>
|
Output:
The number of triangles that can be formed are: 2
Time Complexity: All the loops in the code are O(n). The time complexity in this implementation is thus driven by the sort function used to sort the slope array. This makes the algorithm O(nlogn).
Auxiliary Space: O(n)
Share your thoughts in the comments
Please Login to comment...