<|instruction|>
Solve the below problem. The solution should start with an abridged problem statement. Then key observations. Then full solution based on the observations. Then C++ and Python implementations with comments.

227. The art to the broad masses!
time limit per test: 0.25 sec.
memory limit per test: 4096 KB
input: standard
output: standard



Little known abstract artist Madzinsky-Kalevich painted one more masterpiece. He painted N arcs of circles on the rectangular sheet of paper. Radiuses of all arcs do not exceed 10^3. To increase popularity of the masterpiece he decided to include the quantity of arc crosses in the title of the picture. Your task is to help the artist.

Input
The first line of the input contains integer N (1 <= N <= 50). The following N lines contain the descriptions of arcs. Each description is the sequence of three points. The first two are the end points of arc and the third is a intermediate point. All coordinates are integer numbers with the absolute values not greater than 1000.

Output
Write the amount of different cross points of arcs M to the first line of the output. The following M lines should contain coordinates of crosses in ascending order of x-coordinates. If tie, output coordinates in order of increasing y-coordinates. The computed coordinates should be exact to three digits after the decimal point. If there is infinity number of crosses, print 'Infinity' (quotes added for clarity) on the single line. It is guaranteed that in the case of finite number of crosses the distance between any two different crosses will be not less than 0.005.

Sample test(s)

Input
3
7 4 7 -4 3 0
2 2 6 2 4 0
0 4 0 -4 4 0

Output
4
3.009 0.263
3.500 -1.936
3.500 1.936
4.000 0.000
Author:	Ilya V. Elterman
Resource:	
Date:

<|response|>
## 1. Abridged problem statement

You are given `N` arcs, `1 ≤ N ≤ 50`.

Each arc is described by three integer points:

- first point: one endpoint,
- second point: the other endpoint,
- third point: an intermediate point lying on the intended arc.

Find all different intersection points of the arcs.

Print them sorted by increasing `x`, then increasing `y`, with exactly three digits after the decimal point.

If infinitely many intersection points exist, print:

```text
Infinity
```

If the number of intersections is finite, any two different intersection points are guaranteed to be at least `0.005` apart.

---

## 2. Key observations needed to solve the problem

### Observation 1: Three non-collinear points define one circle

For an arc described by points `A`, `B`, `C`:

- `A` and `B` are endpoints,
- `C` is an intermediate point on the arc.

If `A`, `B`, `C` are not collinear, they define a unique circle.

The chord `AB` splits the circle into two arcs. The intermediate point `C` tells which side is used.

A point `P` on the same circle belongs to the arc iff:

- `P` is on the same side of line `AB` as `C`, or
- `P` lies on line `AB`, meaning it is one of the endpoints.

### Observation 2: Collinear input becomes a segment

If `A`, `B`, `C` are collinear, the arc degenerates into the segment `AB`.

So we need to handle both:

- circular arcs,
- straight segments.

### Observation 3: Pairwise checking is enough

`N ≤ 50`, so there are at most:

```text
50 * 49 / 2 = 1225
```

pairs of arcs.

Each pair can be processed in constant time.

### Observation 4: Infinite intersections happen only by overlap

There are infinitely many intersections if two arcs overlap along a positive-length part.

This can happen in two cases:

1. Two collinear segments overlap in a segment.
2. Two circular arcs lie on the same circle and their angular intervals overlap with positive length.

Otherwise, two arcs have at most two intersection points.

### Observation 5: Duplicate intersection points must be removed

The same point can be produced by multiple pairs of arcs.

The statement guarantees different finite intersection points are at least `0.005` apart, so using a small tolerance like `1e-3` is safe for deduplication.

---

## 3. Full solution approach based on the observations

For each input arc:

1. Let its points be `A`, `B`, `C`.
2. If they are collinear, store it as a segment.
3. Otherwise:
   - compute the circumcenter of triangle `ABC`,
   - compute the radius,
   - store it as a circular arc.

Then check every pair of processed arcs.

There are three main pair types.

---

### Case 1: Segment vs segment

Let the segments be `AB` and `CD`.

If their supporting lines are not parallel:

- compute the line-line intersection,
- keep it only if it lies on both segments.

If they are parallel:

- if they are on different lines, they do not intersect,
- if they are on the same line:
  - project both segments onto one axis,
  - if the overlap has positive length, answer is `Infinity`,
  - if they touch at exactly one endpoint, add that point.

---

### Case 2: Segment vs circular arc

Intersect the segment's supporting line with the circle.

A line and a circle may have:

- no intersection,
- one tangent point,
- two intersection points.

For each candidate point, keep it only if:

1. it lies on the segment,
2. it lies on the circular arc.

---

### Case 3: Circular arc vs circular arc

If their supporting circles are different:

- compute circle-circle intersections,
- keep only points belonging to both arcs.

If their supporting circles are the same:

- convert each arc to an angular interval on the circle,
- if their angular intervals overlap with positive length, print `Infinity`,
- otherwise they can only share endpoints, so test all endpoints.

---

### Final steps

After processing all pairs:

1. If any infinite overlap was found, print `Infinity`.
2. Otherwise:
   - remove duplicate points,
   - sort points by `x`, then by `y`,
   - print the number of points and their coordinates.

Complexity:

```text
Time:   O(N^2)
Memory: O(N^2)
```

---

## 4. C++ implementation with detailed comments

```cpp
#include <bits/stdc++.h>
using namespace std;

const double EPS = 1e-9;
const double PI = acos(-1.0);
const double FULL = 2.0 * PI;

struct Point {
    double x, y;

    Point(double x = 0, double y = 0) : x(x), y(y) {}

    Point operator + (const Point& other) const {
        return Point(x + other.x, y + other.y);
    }

    Point operator - (const Point& other) const {
        return Point(x - other.x, y - other.y);
    }

    Point operator * (double k) const {
        return Point(x * k, y * k);
    }

    Point operator / (double k) const {
        return Point(x / k, y / k);
    }

    double dot(const Point& other) const {
        return x * other.x + y * other.y;
    }

    double cross(const Point& other) const {
        return x * other.y - y * other.x;
    }

    double norm2() const {
        return x * x + y * y;
    }

    double norm() const {
        return sqrt(norm2());
    }

    Point unit() const {
        return *this / norm();
    }

    Point perp() const {
        return Point(-y, x);
    }

    double angle() const {
        return atan2(y, x);
    }
};

istream& operator >> (istream& in, Point& p) {
    return in >> p.x >> p.y;
}

struct Arc {
    bool is_segment;

    Point a, b, c;

    Point center;
    double r;
};

struct CrossingResult {
    bool infinite = false;
    vector<Point> points;
};

int sign(double x) {
    if (x > EPS) return 1;
    if (x < -EPS) return -1;
    return 0;
}

int ccw(const Point& a, const Point& b, const Point& c) {
    return sign((b - a).cross(c - a));
}

bool point_on_segment(const Point& a, const Point& b, const Point& p) {
    return ccw(a, b, p) == 0 &&
           p.x >= min(a.x, b.x) - EPS &&
           p.x <= max(a.x, b.x) + EPS &&
           p.y >= min(a.y, b.y) - EPS &&
           p.y <= max(a.y, b.y) + EPS;
}

Point line_line_intersection(
    const Point& a1,
    const Point& b1,
    const Point& a2,
    const Point& b2
) {
    Point d1 = b1 - a1;
    Point d2 = b2 - a2;

    double t = (a2 - a1).cross(d2) / d1.cross(d2);

    return a1 + d1 * t;
}

Point circumcenter(const Point& a, const Point& b, const Point& c) {
    Point mid_ab = (a + b) / 2.0;
    Point mid_ac = (a + c) / 2.0;

    Point dir_ab = (b - a).perp();
    Point dir_ac = (c - a).perp();

    return line_line_intersection(
        mid_ab, mid_ab + dir_ab,
        mid_ac, mid_ac + dir_ac
    );
}

double normalize_angle(double a) {
    a = fmod(a, FULL);

    if (a < 0) {
        a += FULL;
    }

    return a;
}

Arc make_arc(const Point& a, const Point& b, const Point& c) {
    Arc arc;

    arc.a = a;
    arc.b = b;
    arc.c = c;

    if (ccw(a, b, c) == 0) {
        arc.is_segment = true;
    } else {
        arc.is_segment = false;
        arc.center = circumcenter(a, b, c);
        arc.r = (a - arc.center).norm();
    }

    return arc;
}

/*
    Assumes p lies on the same supporting circle.

    The chord AB divides the circle into two arcs.
    Point p belongs to the desired arc if it is on the same side
    of line AB as the intermediate point C, or if it lies on AB.
*/
bool on_circle_arc(const Arc& arc, const Point& p) {
    double side_c = (arc.b - arc.a).cross(arc.c - arc.a);
    double side_p = (arc.b - arc.a).cross(p - arc.a);

    if (fabs(side_p) < EPS) {
        return true;
    }

    return (side_c > 0) == (side_p > 0);
}

/*
    Convert a circular arc to a counterclockwise angular interval.

    Returns:
        start angle,
        angular length.
*/
pair<double, double> arc_interval(const Arc& arc) {
    double ang_a = (arc.a - arc.center).angle();
    double ang_b = (arc.b - arc.center).angle();
    double ang_c = (arc.c - arc.center).angle();

    double span_b = normalize_angle(ang_b - ang_a);
    double span_c = normalize_angle(ang_c - ang_a);

    /*
        If C is met while going counterclockwise from A to B,
        then the arc is A -> B.
        Otherwise it is the other arc, B -> A.
    */
    if (span_c <= span_b) {
        return {ang_a, span_b};
    } else {
        return {ang_b, FULL - span_b};
    }
}

/*
    For two arcs on the same circle, compute positive angular overlap.

    If the returned value is positive, they share infinitely many points.
*/
double arc_overlap(const Arc& x, const Arc& y) {
    auto [start_x, len_x] = arc_interval(x);
    auto [start_y, len_y] = arc_interval(y);

    /*
        Work in a coordinate system where arc x starts at angle 0.
    */
    double shift = normalize_angle(start_y - start_x);

    double overlap = 0.0;

    auto add_overlap = [&](double l, double r) {
        double left = max(l, 0.0);
        double right = min(r, len_x);

        if (right > left) {
            overlap += right - left;
        }
    };

    if (shift + len_y <= FULL) {
        add_overlap(shift, shift + len_y);
    } else {
        /*
            Interval y wraps around 2*pi, so split it.
        */
        add_overlap(shift, FULL);
        add_overlap(0.0, shift + len_y - FULL);
    }

    return overlap;
}

/*
    Intersect an infinite line AB with a circle.
*/
vector<Point> line_circle_intersection(
    const Point& a,
    const Point& b,
    const Point& center,
    double r
) {
    Point dir = (b - a).unit();

    /*
        Foot of perpendicular from center to the line.
    */
    Point foot = a + dir * (center - a).dot(dir);

    double dist = (center - foot).norm();

    if (dist > r + EPS) {
        return {};
    }

    double h2 = r * r - dist * dist;

    if (h2 < 0) {
        h2 = 0;
    }

    double h = sqrt(h2);

    if (h < EPS) {
        return {foot};
    }

    return {
        foot + dir * h,
        foot - dir * h
    };
}

/*
    Intersect two circles.
*/
vector<Point> circle_circle_intersection(
    const Point& c1,
    double r1,
    const Point& c2,
    double r2
) {
    Point d = c2 - c1;
    double dist = d.norm();

    /*
        No intersections if circles are separate, nested, or concentric.
    */
    if (dist > r1 + r2 + EPS ||
        dist < fabs(r1 - r2) - EPS ||
        dist < EPS) {
        return {};
    }

    double a = (r1 * r1 - r2 * r2 + dist * dist) / (2.0 * dist);
    double h2 = r1 * r1 - a * a;

    if (h2 < -EPS) {
        return {};
    }

    if (h2 < 0) {
        h2 = 0;
    }

    Point base = c1 + d.unit() * a;
    Point perp = d.perp().unit();

    double h = sqrt(h2);

    if (h < EPS) {
        return {base};
    }

    return {
        base + perp * h,
        base - perp * h
    };
}

CrossingResult intersect_arcs(const Arc& x, const Arc& y) {
    CrossingResult result;

    /*
        Case 1: segment vs segment.
    */
    if (x.is_segment && y.is_segment) {
        Point d1 = x.b - x.a;
        Point d2 = y.b - y.a;

        /*
            Parallel supporting lines.
        */
        if (fabs(d1.cross(d2)) < EPS) {
            /*
                Different lines.
            */
            if (ccw(x.a, x.b, y.a) != 0) {
                return result;
            }

            /*
                Same line. Project onto direction of first segment.
            */
            Point u = d1.unit();

            double len_x = (x.b - x.a).dot(u);

            double p1 = (y.a - x.a).dot(u);
            double p2 = (y.b - x.a).dot(u);

            double lo = max(0.0, min(p1, p2));
            double hi = min(len_x, max(p1, p2));

            if (hi > lo + EPS) {
                result.infinite = true;
            } else if (hi > lo - EPS) {
                result.points.push_back(x.a + u * ((lo + hi) / 2.0));
            }

            return result;
        }

        /*
            Non-parallel lines intersect in exactly one point.
        */
        Point p = line_line_intersection(x.a, x.b, y.a, y.b);

        if (point_on_segment(x.a, x.b, p) &&
            point_on_segment(y.a, y.b, p)) {
            result.points.push_back(p);
        }

        return result;
    }

    /*
        Case 2: segment vs circular arc.
    */
    if (x.is_segment != y.is_segment) {
        const Arc& seg = x.is_segment ? x : y;
        const Arc& cir = x.is_segment ? y : x;

        vector<Point> candidates = line_circle_intersection(
            seg.a,
            seg.b,
            cir.center,
            cir.r
        );

        for (const Point& p : candidates) {
            if (point_on_segment(seg.a, seg.b, p) &&
                on_circle_arc(cir, p)) {
                result.points.push_back(p);
            }
        }

        return result;
    }

    /*
        Case 3: circular arc vs circular arc.
    */

    /*
        Same supporting circle.
    */
    if ((x.center - y.center).norm() < 1e-6 &&
        fabs(x.r - y.r) < 1e-6) {

        if (arc_overlap(x, y) > 1e-7) {
            result.infinite = true;
            return result;
        }

        /*
            If there is no positive overlap, they may only share endpoints.
        */
        vector<Point> endpoints = {x.a, x.b, y.a, y.b};

        for (const Point& p : endpoints) {
            if (on_circle_arc(x, p) && on_circle_arc(y, p)) {
                result.points.push_back(p);
            }
        }

        return result;
    }

    /*
        Different supporting circles.
    */
    vector<Point> candidates = circle_circle_intersection(
        x.center,
        x.r,
        y.center,
        y.r
    );

    for (const Point& p : candidates) {
        if (on_circle_arc(x, p) && on_circle_arc(y, p)) {
            result.points.push_back(p);
        }
    }

    return result;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;

    vector<Arc> arcs;

    for (int i = 0; i < n; i++) {
        Point a, b, c;
        cin >> a >> b >> c;

        arcs.push_back(make_arc(a, b, c));
    }

    bool has_infinite = false;
    vector<Point> all_points;

    /*
        Process all pairs.
    */
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            CrossingResult res = intersect_arcs(arcs[i], arcs[j]);

            if (res.infinite) {
                has_infinite = true;
            }

            for (const Point& p : res.points) {
                all_points.push_back(p);
            }
        }
    }

    if (has_infinite) {
        cout << "Infinity\n";
        return 0;
    }

    /*
        Deduplicate intersection points.
    */
    vector<Point> unique_points;

    for (const Point& p : all_points) {
        bool duplicate = false;

        for (const Point& q : unique_points) {
            if ((p - q).norm() < 1e-3) {
                duplicate = true;
                break;
            }
        }

        if (!duplicate) {
            unique_points.push_back(p);
        }
    }

    sort(unique_points.begin(), unique_points.end(),
         [](const Point& a, const Point& b) {
             if (fabs(a.x - b.x) > 1e-6) {
                 return a.x < b.x;
             }
             return a.y < b.y;
         });

    cout << unique_points.size() << '\n';
    cout << fixed << setprecision(3);

    for (Point p : unique_points) {
        /*
            Avoid printing -0.000.
        */
        if (fabs(p.x) < 5e-4) {
            p.x = 0;
        }

        if (fabs(p.y) < 5e-4) {
            p.y = 0;
        }

        cout << p.x << ' ' << p.y << '\n';
    }

    return 0;
}
```

---

## 5. Python implementation with detailed comments

```python
import sys
import math


EPS = 1e-9
PI = math.pi
FULL = 2.0 * PI


class Point:
    def __init__(self, x=0.0, y=0.0):
        self.x = float(x)
        self.y = float(y)

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

    def __sub__(self, other):
        return Point(self.x - other.x, self.y - other.y)

    def __mul__(self, k):
        return Point(self.x * k, self.y * k)

    def __truediv__(self, k):
        return Point(self.x / k, self.y / k)

    def dot(self, other):
        return self.x * other.x + self.y * other.y

    def cross(self, other):
        return self.x * other.y - self.y * other.x

    def norm2(self):
        return self.x * self.x + self.y * self.y

    def norm(self):
        return math.sqrt(self.norm2())

    def unit(self):
        return self / self.norm()

    def perp(self):
        return Point(-self.y, self.x)

    def angle(self):
        return math.atan2(self.y, self.x)


class Arc:
    def __init__(self):
        self.is_segment = False

        self.a = None
        self.b = None
        self.c = None

        self.center = None
        self.r = 0.0


def sign(x):
    if x > EPS:
        return 1
    if x < -EPS:
        return -1
    return 0


def ccw(a, b, c):
    """
    Orientation of triangle ABC.
    """
    return sign((b - a).cross(c - a))


def point_on_segment(a, b, p):
    """
    Check whether point p lies on closed segment AB.
    """
    return (
        ccw(a, b, p) == 0
        and min(a.x, b.x) - EPS <= p.x <= max(a.x, b.x) + EPS
        and min(a.y, b.y) - EPS <= p.y <= max(a.y, b.y) + EPS
    )


def line_line_intersection(a1, b1, a2, b2):
    """
    Intersection of two non-parallel infinite lines.
    """
    d1 = b1 - a1
    d2 = b2 - a2

    t = (a2 - a1).cross(d2) / d1.cross(d2)

    return a1 + d1 * t


def circumcenter(a, b, c):
    """
    Circumcenter of non-collinear triangle ABC.
    """
    mid_ab = (a + b) / 2.0
    mid_ac = (a + c) / 2.0

    dir_ab = (b - a).perp()
    dir_ac = (c - a).perp()

    return line_line_intersection(
        mid_ab, mid_ab + dir_ab,
        mid_ac, mid_ac + dir_ac
    )


def normalize_angle(a):
    """
    Normalize angle to [0, 2*pi).
    """
    a = math.fmod(a, FULL)

    if a < 0:
        a += FULL

    return a


def make_arc(a, b, c):
    """
    Convert input triple into either a segment or a circular arc.
    """
    arc = Arc()

    arc.a = a
    arc.b = b
    arc.c = c

    if ccw(a, b, c) == 0:
        arc.is_segment = True
    else:
        arc.is_segment = False
        arc.center = circumcenter(a, b, c)
        arc.r = (a - arc.center).norm()

    return arc


def on_circle_arc(arc, p):
    """
    Check whether p belongs to circular arc.

    Assumes p lies on the same supporting circle.
    """
    side_c = (arc.b - arc.a).cross(arc.c - arc.a)
    side_p = (arc.b - arc.a).cross(p - arc.a)

    if abs(side_p) < EPS:
        return True

    return (side_c > 0) == (side_p > 0)


def arc_interval(arc):
    """
    Convert a circular arc to a counterclockwise angular interval.

    Returns:
        start_angle, length
    """
    ang_a = (arc.a - arc.center).angle()
    ang_b = (arc.b - arc.center).angle()
    ang_c = (arc.c - arc.center).angle()

    span_b = normalize_angle(ang_b - ang_a)
    span_c = normalize_angle(ang_c - ang_a)

    if span_c <= span_b:
        return ang_a, span_b

    return ang_b, FULL - span_b


def arc_overlap(x, y):
    """
    Compute angular overlap length of two arcs on the same circle.
    Positive overlap means infinitely many common points.
    """
    start_x, len_x = arc_interval(x)
    start_y, len_y = arc_interval(y)

    shift = normalize_angle(start_y - start_x)

    overlap = 0.0

    def add_overlap(l, r):
        nonlocal overlap

        left = max(l, 0.0)
        right = min(r, len_x)

        if right > left:
            overlap += right - left

    if shift + len_y <= FULL:
        add_overlap(shift, shift + len_y)
    else:
        add_overlap(shift, FULL)
        add_overlap(0.0, shift + len_y - FULL)

    return overlap


def line_circle_intersection(a, b, center, r):
    """
    Intersect infinite line AB with circle.
    """
    direction = (b - a).unit()

    foot = a + direction * (center - a).dot(direction)

    dist = (center - foot).norm()

    if dist > r + EPS:
        return []

    h2 = r * r - dist * dist

    if h2 < 0:
        h2 = 0.0

    h = math.sqrt(h2)

    if h < EPS:
        return [foot]

    return [
        foot + direction * h,
        foot - direction * h
    ]


def circle_circle_intersection(c1, r1, c2, r2):
    """
    Intersect two circles.
    """
    d = c2 - c1
    dist = d.norm()

    if (
        dist > r1 + r2 + EPS
        or dist < abs(r1 - r2) - EPS
        or dist < EPS
    ):
        return []

    a = (r1 * r1 - r2 * r2 + dist * dist) / (2.0 * dist)
    h2 = r1 * r1 - a * a

    if h2 < -EPS:
        return []

    if h2 < 0:
        h2 = 0.0

    base = c1 + d.unit() * a
    perp = d.perp().unit()

    h = math.sqrt(h2)

    if h < EPS:
        return [base]

    return [
        base + perp * h,
        base - perp * h
    ]


def intersect_arcs(x, y):
    """
    Intersect two arcs.

    Returns:
        infinite, points
    """
    infinite = False
    points = []

    # Case 1: segment vs segment.
    if x.is_segment and y.is_segment:
        d1 = x.b - x.a
        d2 = y.b - y.a

        # Parallel supporting lines.
        if abs(d1.cross(d2)) < EPS:
            # Different lines.
            if ccw(x.a, x.b, y.a) != 0:
                return False, []

            # Same line: project onto direction of first segment.
            u = d1.unit()

            len_x = (x.b - x.a).dot(u)

            p1 = (y.a - x.a).dot(u)
            p2 = (y.b - x.a).dot(u)

            lo = max(0.0, min(p1, p2))
            hi = min(len_x, max(p1, p2))

            if hi > lo + EPS:
                return True, []

            if hi > lo - EPS:
                points.append(x.a + u * ((lo + hi) / 2.0))

            return False, points

        # Non-parallel lines.
        p = line_line_intersection(x.a, x.b, y.a, y.b)

        if point_on_segment(x.a, x.b, p) and point_on_segment(y.a, y.b, p):
            points.append(p)

        return False, points

    # Case 2: segment vs circular arc.
    if x.is_segment != y.is_segment:
        seg = x if x.is_segment else y
        cir = y if x.is_segment else x

        candidates = line_circle_intersection(
            seg.a,
            seg.b,
            cir.center,
            cir.r
        )

        for p in candidates:
            if point_on_segment(seg.a, seg.b, p) and on_circle_arc(cir, p):
                points.append(p)

        return False, points

    # Case 3: circular arc vs circular arc.

    # Same supporting circle.
    if (x.center - y.center).norm() < 1e-6 and abs(x.r - y.r) < 1e-6:
        if arc_overlap(x, y) > 1e-7:
            return True, []

        # No positive overlap: only shared endpoints are possible.
        for p in [x.a, x.b, y.a, y.b]:
            if on_circle_arc(x, p) and on_circle_arc(y, p):
                points.append(p)

        return False, points

    # Different supporting circles.
    candidates = circle_circle_intersection(
        x.center,
        x.r,
        y.center,
        y.r
    )

    for p in candidates:
        if on_circle_arc(x, p) and on_circle_arc(y, p):
            points.append(p)

    return False, points


def solve():
    data = sys.stdin.read().strip().split()

    if not data:
        return

    it = iter(data)

    n = int(next(it))

    arcs = []

    for _ in range(n):
        a = Point(float(next(it)), float(next(it)))
        b = Point(float(next(it)), float(next(it)))
        c = Point(float(next(it)), float(next(it)))

        arcs.append(make_arc(a, b, c))

    all_points = []
    has_infinite = False

    # Process all pairs of arcs.
    for i in range(n):
        for j in range(i + 1, n):
            infinite, points = intersect_arcs(arcs[i], arcs[j])

            if infinite:
                has_infinite = True

            all_points.extend(points)

    if has_infinite:
        print("Infinity")
        return

    # Deduplicate points.
    unique = []

    for p in all_points:
        duplicate = False

        for q in unique:
            if (p - q).norm() < 1e-3:
                duplicate = True
                break

        if not duplicate:
            unique.append(p)

    # Sort by x, then y.
    unique.sort(key=lambda p: (p.x, p.y))

    print(len(unique))

    for p in unique:
        # Avoid printing -0.000.
        x = 0.0 if abs(p.x) < 5e-4 else p.x
        y = 0.0 if abs(p.y) < 5e-4 else p.y

        print(f"{x:.3f} {y:.3f}")


if __name__ == "__main__":
    solve()
```