Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Counting Collinear Point Triplets in a Cartesian Plane

Tech 1

Given a collection of coordinates on a two-dimensional grid, the task requires enumerating every distinct triplet of vertices to determine how many lie on a single straight line. The brute-force methodology iterates through all valid index combinations, enforcing strictly increasing indices to eliminate duplicate evaluations and self-pairings. Geometric alignment can be verified through several mathematically equivalent approaches.

Gradient Comparison

Three vertices align when the slope between the first two matches the slope between the last two. Vertical arrangements cause division by zero if handled naively, so explicit checks for identical x-coordinates must precede any ratio calculation. Using floating-point division remains viable when vertical cases are isolated.

#include <vector>
#include <iostream>
using namespace std;

struct Coord { int h; int v; };

bool checkGradient(const Coord& a, const Coord& b, const Coord& c) {
    int dh1 = b.h - a.h, dv1 = b.v - a.v;
    int dh2 = c.h - b.h, dv2 = c.v - b.v;
    if (dh1 == 0 && dh2 == 0) return true;
    if (dh1 == 0 || dh2 == 0) return false;
    return (double)dv1 / dh1 == (double)dv2 / dh2;
}

int main() {
    int total;
    cin >> total;
    vector<Coord> grid(total);
    for(auto &pt : grid) cin >> pt.h >> pt.v;

    int matches = 0;
    for(int i = 0; i < total; ++i)
        for(int j = i + 1; j < total; ++j)
            for(int k = j + 1; k < total; ++k)
                if(checkGradient(grid[i], grid[j], grid[k])) ++matches;

    cout << matches << endl;
    return 0;
}

Vector Cross Product

By treating the points as directional segments sharing a common origin, alignment corresponds to vector parallelism. The two-dimensional cross product of vectors formed by the points yields zero precisely when they are collinear. This technique operates entirely with integer aritmhetic, avoiding precision drift.

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int pointCount;
    if(!(cin >> pointCount)) return 0;
    struct Vec { int x, y; };
    vector<Vec> pts(pointCount);
    for(int i = 0; i < pointCount; ++i) cin >> pts[i].x >> pts[i].y;

    int aligned = 0;
    for(int i = 0; i < pointCount; ++i) {
        for(int j = i + 1; j < pointCount; ++j) {
            for(int k = j + 1; k < pointCount; ++k) {
                long long cross = (long long)(pts[j].x - pts[i].x) * (pts[k].y - pts[i].y) -
                                  (long long)(pts[j].y - pts[i].y) * (pts[k].x - pts[i].x);
                if(cross == 0) aligned++;
            }
        }
    }
    cout << aligned << "\n";
    return 0;
}

Determinant Expansion

Placing the coordinates into a 3x3 matrix alongside a constant column of ones creates a system where linear dependence results in a zero determinant. Algebraically expanding this determinant produces a single linear combination of coordinate products. Evaluating this expression provides a direct integer-based test.

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<pair<int,int>> coords(n);
    for(auto& p : coords) cin >> p.first >> p.second;

    int tally = 0;
    for(int a = 0; a < n; ++a) {
        for(int b = a + 1; b < n; ++b) {
            for(int c = b + 1; c < n; ++c) {
                int xa = coords[a].first, ya = coords[a].second;
                int xb = coords[b].first, yb = coords[b].second;
                int xc = coords[c].first, yc = coords[c].second;
                long long det = (long long)xa * yb + (long long)ya * xc + (long long)xb * yc -
                                (long long)xa * yc - (long long)yb * xc - (long long)xb * ya;
                if(det == 0) tally++;
            }
        }
    }
    cout << tally << endl;
    return 0;
}

Triangle Area Evaluation

Aligned points cannot enclose a region, meaning the geometric area of the triangle they form must be exactly zero. The shoelace formula component for this calculation reduces to checking whether the weighted sum of coordinate differences equals zero. Scaling factors are irrelevant when validating against zero.

#include <iostream>
#include <vector>
using namespace std;

struct Point { int x, y; };

bool hasZeroArea(const Point& p1, const Point& p2, const Point& p3) {
    int val = p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y);
    return val == 0;
}

int main() {
    int limit;
    cin >> limit;
    vector<Point> data(limit);
    for(auto& p : data) cin >> p.x >> p.y;

    int result = 0;
    for(int i = 0; i < limit; ++i)
        for(int j = i + 1; j < limit; ++j)
            for(int k = j + 1; k < limit; ++k)
                if(hasZeroArea(data[i], data[j], data[k])) result++;

    cout << result << endl;
    return 0;
}

Each implementation maintains a cubic time complexity $O(n^3)$ due to the nested iteration over the input set. For standard problem constraints where the coordinate count remains relatively small, this computational overhead stays well within typical execution limits.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.