Problem:
Problem D:
Area Separation
Mr. Yamada Springfield Tanaka は、国家区画整理事業局局長補佐代理という大任を任されていた。
			現在、彼の国は大規模な区画整理の最中であり、この区画整理をスムーズに終わらせることができたならば彼の昇進は間違いなしであるとされている。
ところが、そんな彼の出世を快く思わない者も多くいるのだ。 そんな人間の 1 人に、Mr.Sato Seabreeze Suzuki がいた。
			彼は、ことあるごとに Mr. Yamada の足を引っ張ろうと画策してきた。 今回も Mr. Sato は足を引っ張るために、実際の区画整理を担当している組織に圧力をかけて、区画整理の結果を非常に分かりにくいものにしてしまった。
そのため、Mr. Yamada に渡された結果は、 ある正方形の土地をどの直線で分割したかという情報のみになっていた。
			最低限、その正方形の土地がいくつに分割されたかだけでも分からなければ、Mr. Yamada は昇進どころか解雇されること間違いなしである。
あなたの仕事は、(-100,-100)、(100,-100)、(100,100)、(-100,100) を頂点とする正方形領域が、与えられた
n
本の直線によっていくつに分割されているかを調べるプログラムを書いて、Mr. Yamada を解雇の危機から救うことである。
Input
入力は複数のテストケースからなる。
それぞれのテストケースの最初の行では、直線数を表す整数
n
が与えられる（1 <=
n
<= 100）。 その後の
n
行にはそれぞれ 4 つの整数
x
1
、
y
1
、
x
2
、
y
2
が含まれる。
			これらの整数は直線上の相異なる 2 点 (
x
1
,
y
1
) と (
x
2
,
y
2
) を表す。
			与えられる 2 点は常に正方形の辺上の点であることが保証されている。 与えられる
n
本の直線は互いに異なり、直線同士が重なることはない。 また、直線が正方形の辺と重なることもない。
入力の終了は
n
= 0 で表される。
Output
それぞれのテストケースについて、
n
本の直線によって分割された領域の数を 1 行で出力せよ。
なお、距離が 10
-10
未満の 2 点は一致するとみなしてよい。 また、|PQ| < 10
-10
、|QR| < 10
-10
でかつ |PR| >= 10
-10
となるような交点の組 P、Q、R は存在しない。
Sample Input
2
-100 -20 100 20
-20 -100 20 100
2
-100 -20 -20 -100
20 100 100 20
0
Output for the Sample Input
4
3

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;

typedef complex<double> P;
const double EPS = 1e-12;
#define EQ(n,m) (abs((n)-(m)) < EPS)

double cross(P a, P b) {
	return (conj(a)*b).imag();
}

P crosspointLL(P a1, P a2, P b1, P b2) {
	double d1 = cross(b2 - b1, b1 - a1);
	double d2 = cross(b2 - b1, a2 - a1);
	assert(!(EQ(d1, 0) && EQ(d2, 0)));
	if (EQ(d2, 0)) return P(-1000, -1000);
	return a1 + d1 / d2 * (a2 - a1);
}

int main() {
	while(true) {
		int n;
		cin >> n;
		if (n == 0) break;
		vector<P> line_start(n), line_end(n);
		for (int i = 0; i<n; i++) {
			int x1, y1, x2, y2;
			cin >> x1 >> y1 >> x2 >> y2;
			line_start[i] = P(x1, y1);
			line_end[i] = P(x2, y2);
		}

		int ans = 1;
		for (int i = 0; i<n; i++) {
			vector<P> cross_points;
			for (int j = 0; j<i; j++) {
				P cp = crosspointLL(line_start[i], line_end[i], line_start[j], line_end[j]);
				if (cp.real() < -100 + EPS || cp.real() + EPS > 100 || cp.imag() < -100 + EPS || cp.imag() + EPS > 100) continue;
				bool exist = false;
				for (auto p : cross_points) {
					if (EQ(cp, p)) {
						exist = true;
						break;
					}
				}
				if (!exist) {
					cross_points.push_back(cp);
				}
			}
			ans += 1 + cross_points.size();
		}
		cout << ans << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3348
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long double ld;
typedef long long ll;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef pair<ll,ll> pi;
#define FOR(i,l,r) for(auto i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
#define F first
#define S second
pair<ld,ld>intersection(pi x,pi y,pi z,pi w){
    ll a=x.S-y.S,b=y.F-x.F,p=a*x.F+b*x.S;
    ll c=z.S-w.S,d=w.F-z.F,q=c*z.F+d*z.S;
    ll det=a*d-b*c;
    if(!det)return make_pair(-1000,-1000);
    return make_pair((ld)(d*p-b*q)/det,(ld)(-c*p+a*q)/det);
}
int main(){
    while(1){
        ll N;cin>>N;
        if(!N)return 0;
        vector<pair<pi,pi>>A(N);
        REP(i,N)cin>>A[i].F.F>>A[i].F.S>>A[i].S.F>>A[i].S.S;
        ll ans=1;
        REP(i,N){
            set<pair<ld,ld>>P;
            REP(j,i){
                auto p=intersection(A[j].F,A[j].S,A[i].F,A[i].S);
                if(abs(p.F)>=100||abs(p.S)>=100)continue;
                P.insert(p);
            }
            ans+=P.size()+1;
        }
        cout<<ans<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3360
final_rank: 9

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

using T = double;
const T eps = 1e-12;
using Point = complex<T>;
using Poly = vector<Point>;
#define X real()
#define Y imag()
template <typename T> inline bool eq(const T &a, const T &b) {
    return fabs(a - b) < eps;
}
bool cmp(const Point &a, const Point &b) {
    auto sub = [&](Point a) {
        return (a.Y < 0 ? -1 : (a.Y == 0 && a.X >= 0 ? 0 : 1));
    };
    if (sub(a) != sub(b))
        return sub(a) < sub(b);
    return a.Y * b.X < a.X * b.Y;
}
struct Line {
    Point a, b, dir;
    Line() {}
    Line(Point _a, Point _b) : a(_a), b(_b), dir(b - a) {}
    Line(T A, T B, T C) {
        if (eq(A, .0)) {
            a = Point(0, C / B), b = Point(1 / C / B);
        } else if (eq(B, .0)) {
            a = Point(C / A, 0), b = Point(C / A, 1);
        } else {
            a = Point(0, C / B), b = Point(C / A, 0);
        }
    }
};
struct Segment : Line {
    Segment() {}
    Segment(Point _a, Point _b) : Line(_a, _b) {}
};
struct Circle {
    Point p;
    T r;
    Circle() {}
    Circle(Point _p, T _r) : p(_p), r(_r) {}
};

istream &operator>>(istream &is, Point &p) {
    T x, y;
    is >> x >> y;
    p = Point(x, y);
    return is;
}
ostream &operator<<(ostream &os, Point &p) {
    os << fixed << setprecision(12) << p.X << ' ' << p.Y;
    return os;
}
Point unit(const Point &a) {
    return a / abs(a);
}
T dot(const Point &a, const Point &b) {
    return a.X * b.X + a.Y * b.Y;
}
T cross(const Point &a, const Point &b) {
    return a.X * b.Y - a.Y * b.X;
}
Point rot(const Point &a, const T &theta) {
    return Point(cos(theta) * a.X - sin(theta) * a.Y,
                 sin(theta) * a.X + cos(theta) * a.Y);
}
Point rot90(const Point &a) {
    return Point(-a.Y, a.X);
}
T arg(const Point &a, const Point &b, const Point &c) {
    double ret = acos(dot(a - b, c - b) / abs(a - b) / abs(c - b));
    if (cross(a - b, c - b) < 0)
        ret = -ret;
    return ret;
}

Point Projection(const Line &l, const Point &p) {
    T t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + (l.a - l.b) * t;
}
Point Projection(const Segment &l, const Point &p) {
    T t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + (l.a - l.b) * t;
}
Point Reflection(const Line &l, const Point &p) {
    return p + (Projection(l, p) - p) * 2.;
}
int ccw(const Point &a, Point b, Point c) {
    b -= a;
    c -= a;
    if (cross(b, c) > eps)
        return 1; // ccw

    if (cross(b, c) < -eps)
        return -1; // cw

    if (dot(b, c) < 0)
        return 2; // c,a,b

    if (norm(b) < norm(c))
        return -2; // a,b,c

    return 0;      // a,c,b

}
bool isOrthogonal(const Line &a, const Line &b) {
    return eq(dot(a.b - a.a, b.b - b.a), .0);
}
bool isParallel(const Line &a, const Line &b) {
    return eq(cross(a.b - a.a, b.b - b.a), .0);
}
bool isIntersect(const Segment &a, const Segment &b) {
    return ccw(a.a, a.b, b.a) * ccw(a.a, a.b, b.b) <= 0 and
           ccw(b.a, b.b, a.a) * ccw(b.a, b.b, a.b) <= 0;
}
int isIntersect(const Circle &a, const Circle &b) {
    T d = abs(a.p - b.p);
    if (d > a.r + b.r + eps)
        return 4;
    if (eq(d, a.r + b.r))
        return 3;
    if (eq(d, abs(a.r - b.r)))
        return 1;
    if (d < abs(a.r - b.r) - eps)
        return 0;
    return 2;
}
T Dist(const Line &a, const Point &b) {
    Point c = Projection(a, b);
    return abs(c - b);
}
T Dist(const Segment &a, const Point &b) {
    if (dot(a.b - a.a, b - a.a) < eps)
        return abs(b - a.a);
    if (dot(a.a - a.b, b - a.b) < eps)
        return abs(b - a.b);
    return abs(cross(a.b - a.a, b - a.a)) / abs(a.b - a.a);
}
T Dist(const Segment &a, const Segment &b) {
    if (isIntersect(a, b))
        return .0;
    T res = min({Dist(a, b.a), Dist(a, b.b), Dist(b, a.a), Dist(b, a.b)});
    return res;
}
Point Intersection(const Line &a, const Line &b) {
    T d1 = cross(a.b - a.a, b.b - b.a);
    T d2 = cross(a.b - a.a, a.b - b.a);
    if (eq(d1, 0.) and eq(d2, 0.))
        return b.a;
    return b.a + (b.b - b.a) * (d2 / d1);
}
Poly Intersection(const Circle &a, const Line &b) {
    Poly res;
    T d = Dist(b, a.p);
    if (d > a.r + eps)
        return res;
    Point h = Projection(b, a.p);
    if (eq(d, a.r)) {
        res.push_back(h);
        return res;
    }
    Point e = unit(b.b - b.a);
    T ph = sqrt(a.r * a.r - d * d);
    res.push_back(h - e * ph);
    res.push_back(h + e * ph);
    return res;
}
Poly Intersection(const Circle &a, const Segment &b) {
    Line c(b.a, b.b);
    Poly sub = Intersection(a, c);
    double xmi = min(b.a.X, b.b.X), xma = max(b.a.X, b.b.X);
    double ymi = min(b.a.Y, b.b.Y), yma = max(b.a.Y, b.b.Y);
    Poly res;
    rep(i, 0, sub.size()) {
        if (xmi <= sub[i].X + eps and sub[i].X - eps <= xma and
            ymi <= sub[i].Y + eps and sub[i].Y - eps <= yma) {
            res.push_back(sub[i]);
        }
    }
    return res;
}
Poly Intersection(const Circle &a, const Circle &b) {
    Poly res;
    int mode = isIntersect(a, b);
    T d = abs(a.p - b.p);
    if (mode == 4 or mode == 0)
        return res;
    if (mode == 3) {
        T t = a.r / (a.r + b.r);
        res.push_back(a.p + (b.p - a.p) * t);
        return res;
    }
    if (mode == 1) {
        if (b.r < a.r - eps) {
            res.push_back(a.p + (b.p - a.p) * (a.r / d));
        } else {
            res.push_back(b.p + (a.p - b.p) * (b.r / d));
        }
        return res;
    }
    T rc = (a.r * a.r + d * d - b.r * b.r) / d / 2.;
    T rs = sqrt(a.r * a.r - rc * rc);
    if (a.r - abs(rc) < eps)
        rs = 0;
    Point e = unit(b.p - a.p);
    res.push_back(a.p + rc * e + rs * e * Point(0, 1));
    res.push_back(a.p + rc * e + rs * e * Point(0, -1));
    return res;
}
Poly HalfplaneIntersection(vector<Line> &H) {
    sort(ALL(H), [&](Line &l1, Line &l2) { return cmp(l1.dir, l2.dir); });
    auto outside = [&](Line &L, Point p) -> bool {
        return cross(L.dir, p - L.a) < -eps;
    };
    deque<Line> deq;
    int sz = 0;
    rep(i, 0, SZ(H)) {
        while (sz > 1 and
               outside(H[i], Intersection(deq[sz - 1], deq[sz - 2]))) {
            deq.pop_back();
            sz--;
        }
        while (sz > 1 and outside(H[i], Intersection(deq[0], deq[1]))) {
            deq.pop_front();
            sz--;
        }
        if (sz > 0 and fabs(cross(H[i].dir, deq[sz - 1].dir)) < eps) {
            if (dot(H[i].dir, deq[sz - 1].dir) < 0) {
                return {};
            }
            if (outside(H[i], deq[sz - 1].a)) {
                deq.pop_back();
                sz--;
            } else
                continue;
        }
        deq.push_back(H[i]);
        sz++;
    }

    while (sz > 2 and outside(deq[0], Intersection(deq[sz - 1], deq[sz - 2]))) {
        deq.pop_back();
        sz--;
    }
    while (sz > 2 and outside(deq[sz - 1], Intersection(deq[0], deq[1]))) {
        deq.pop_front();
        sz--;
    }
    if (sz < 3)
        return {};
    deq.push_back(deq.front());
    Poly ret;
    rep(i, 0, sz) ret.push_back(Intersection(deq[i], deq[i + 1]));
    return ret;
}

T Area(const Poly &a) {
    T res = 0;
    int n = a.size();
    rep(i, 0, n) res += cross(a[i], a[(i + 1) % n]);
    return fabs(res / 2.);
}
T Area(const Poly &a, const Circle &b) {
    int n = a.size();
    if (n < 3)
        return .0;
    auto rec = [&](auto self, const Circle &c, const Point &p1,
                   const Point &p2) {
        Point va = c.p - p1, vb = c.p - p2;
        T f = cross(va, vb), res = .0;
        if (eq(f, .0))
            return res;
        if (max(abs(va), abs(vb)) < c.r + eps)
            return f;
        if (Dist(Segment(p1, p2), c.p) > c.r - eps)
            return c.r * c.r * arg(vb * conj(va));
        auto u = Intersection(c, Segment(p1, p2));
        Poly sub;
        sub.push_back(p1);
        for (auto &x : u)
            sub.push_back(x);
        sub.push_back(p2);
        rep(i, 0, sub.size() - 1) res += self(self, c, sub[i], sub[i + 1]);
        return res;
    };
    T res = .0;
    rep(i, 0, n) res += rec(rec, b, a[i], a[(i + 1) % n]);
    return fabs(res / 2.);
}
T Area(const Circle &a, const Circle &b) {
    T d = abs(a.p - b.p);
    if (d >= a.r + b.r - eps)
        return .0;
    if (d <= abs(a.r - b.r) + eps) {
        T r = min(a.r, b.r);
        return M_PI * r * r;
    }
    T ath = acos((a.r * a.r + d * d - b.r * b.r) / d / a.r / 2.);
    T res = a.r * a.r * (ath - sin(ath * 2) / 2.);
    T bth = acos((b.r * b.r + d * d - a.r * a.r) / d / b.r / 2.);
    res += b.r * b.r * (bth - sin(bth * 2) / 2.);
    return fabs(res);
}
bool isConvex(const Poly &a) {
    int n = a.size();
    int cur, pre, nxt;
    rep(i, 0, n) {
        pre = (i - 1 + n) % n;
        nxt = (i + 1) % n;
        cur = i;
        if (ccw(a[pre], a[cur], a[nxt]) == -1)
            return 0;
    }
    return 1;
}
int isContained(const Poly &a,
                const Point &b) { // 0:not contain,1:on edge,2:contain

    bool res = 0;
    int n = a.size();
    rep(i, 0, n) {
        Point p = a[i] - b, q = a[(i + 1) % n] - b;
        if (p.Y > q.Y)
            swap(p, q);
        if (p.Y < eps and eps < q.Y and cross(p, q) > eps)
            res ^= 1;
        if (eq(cross(p, q), .0) and dot(p, q) < eps)
            return 1;
    }
    return (res ? 2 : 0);
}
Poly ConvexHull(Poly &a) {
    sort(ALL(a), [](const Point &p, const Point &q) {
        return (eq(p.Y, q.Y) ? p.X < q.X : p.Y < q.Y);
    });
    a.erase(unique(ALL(a)), a.end());
    int n = a.size(), k = 0;
    Poly res(n * 2);
    for (int i = 0; i < n; res[k++] = a[i++]) {
        while (k >= 2 and
               cross(res[k - 1] - res[k - 2], a[i] - res[k - 1]) < eps)
            k--;
    }
    for (int i = n - 2, t = k + 1; i >= 0; res[k++] = a[i--]) {
        while (k >= t and
               cross(res[k - 1] - res[k - 2], a[i] - res[k - 1]) < eps)
            k--;
    }
    res.resize(k - 1);
    return res;
}
T Diam(const Poly &a) {
    int n = a.size();
    int x = 0, y = 0;
    rep(i, 1, n) {
        if (a[i].Y > a[x].Y)
            x = i;
        if (a[i].Y < a[y].Y)
            y = i;
    }
    T res = abs(a[x] - a[y]);
    int i = x, j = y;
    do {
        if (cross(a[(i + 1) % n] - a[i], a[(j + 1) % n] - a[j]) < 0)
            i = (i + 1) % n;
        else
            j = (j + 1) % n;
        chmax(res, abs(a[i] - a[j]));
    } while (i != x or j != y);
    return res;
}
Poly Cut(const Poly &a, const Line &l) {
    int n = a.size();
    Poly res;
    rep(i, 0, n) {
        Point p = a[i], q = a[(i + 1) % n];
        if (ccw(l.a, l.b, p) != -1)
            res.push_back(p);
        if (ccw(l.a, l.b, p) * ccw(l.a, l.b, q) < 0)
            res.push_back(Intersection(Line(p, q), l));
    }
    return res;
}

T Closest(Poly &a) {
    int n = a.size();
    if (n <= 1)
        return 0;
    sort(ALL(a), [&](Point a, Point b) {
        return (eq(a.X, b.X) ? a.Y < b.Y : a.X < b.X);
    });
    Poly buf(n);
    auto rec = [&](auto self, int lb, int rb) -> T {
        if (rb - lb <= 1)
            return (T)INF;
        int mid = (lb + rb) >> 1;
        auto x = a[mid].X;
        T res = min(self(self, lb, mid), self(self, mid, rb));
        inplace_merge(a.begin() + lb, a.begin() + mid, a.begin() + rb,
                      [&](auto p, auto q) { return p.Y < q.Y; });
        int ptr = 0;
        rep(i, lb, rb) {
            if (abs(a[i].X - x) >= res)
                continue;
            rep(j, 0, ptr) {
                auto sub = a[i] - buf[ptr - 1 - j];
                if (sub.Y >= res)
                    break;
                chmin(res, abs(sub));
            }
            buf[ptr++] = a[i];
        }
        return res;
    };
    return rec(rec, 0, n);
}

Circle Incircle(const Point &a, const Point &b, const Point &c) {
    T A = abs(b - c), B = abs(c - a), C = abs(a - b);
    Point p(A * a.X + B * b.X + C * c.X, A * a.Y + B * b.Y + C * c.Y);
    p /= (A + B + C);
    T r = Dist(Line(a, b), p);
    return Circle(p, r);
}
Circle Circumcircle(const Point &a, const Point &b, const Point &c) {
    Line l1((a + b) / 2., (a + b) / 2. + (b - a) * Point(0, 1));
    Line l2((b + c) / 2., (b + c) / 2. + (c - b) * Point(0, 1));
    Point p = Intersection(l1, l2);
    return Circle(p, abs(p - a));
}
Poly tangent(const Point &a, const Circle &b) {
    return Intersection(b, Circle(a, sqrt(norm(b.p - a) - b.r * b.r)));
}
vector<Line> tangent(const Circle &a, const Circle &b) {
    vector<Line> res;
    T d = abs(a.p - b.p);
    if (eq(d, 0.))
        return res;
    Point u = unit(b.p - a.p);
    Point v = u * Point(0, 1);
    for (int t : {-1, 1}) {
        T h = (a.r + b.r * t) / d;
        if (eq(h * h, 1.)) {
            res.push_back(Line(a.p + (h > 0 ? u : -u) * a.r,
                               a.p + (h > 0 ? u : -u) * a.r + v));
        } else if (1 > h * h) {
            Point U = u * h, V = v * sqrt(1 - h * h);
            res.push_back(Line(a.p + (U + V) * a.r, b.p - (U + V) * (b.r * t)));
            res.push_back(Line(a.p + (U - V) * a.r, b.p - (U - V) * (b.r * t)));
        }
    }
    return res;
}

/**
 * @brief Geometry
 */

int main() {
while(1) {
    int N;
    cin >> N;
    if (N == 0) return 0;
    vector<Point> VP1, VP2;
    vector<Segment> SL;
    vector<Line> L;
    rep(i,0,N) {
        double A, B, C, D;
        cin >> A >> B >> C >> D;
        Point P1(A,B), P2(C,D);
        VP1.push_back(P1), VP2.push_back(P2);
        Segment l(P1,P2);
        SL.push_back(l);
        Line ll(P1,P2);
        L.push_back(ll);
    }
    int ANS = 1;
    rep(i,0,N) {
        vector<pair<double,double>> VD;
        VD.push_back({VP1[i].real(),VP1[i].imag()});
        VD.push_back({VP2[i].real(),VP2[i].imag()});
        rep(j,0,i) {
            if (!isIntersect(SL[i],SL[j])) continue;
            Point PP = Intersection(L[i],L[j]);
            VD.push_back({PP.real(),PP.imag()});
        }
        UNIQUE(VD);
        ANS += (int)(VD.size()) - 1;
        rep(j,0,(int)(VD.size())-1) {
            if ((VD[j].first-VD[j+1].first)*(VD[j].first-VD[j+1].first)+(VD[j].second-VD[j+1].second)*(VD[j].second-VD[j+1].second)<1e-10) ANS--;
        }
    }
    cout << ANS << endl;
}
}
accuracy: 1
time_ms: 10
memory_kb: 3568
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (long long i = 0; i < (long long)(n); i++)
#define rrep(i,start,end) for (long long i = start;i >= (long long)(end);i--)
#define repn(i,end) for(long long i = 0; i <= (long long)(end); i++)
#define reps(i,start,end) for(long long i = start; i < (long long)(end); i++)
#define repsn(i,start,end) for(long long i = start; i <= (long long)(end); i++)
#define each(p,a) for(auto &p:a)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<long long> vll;
typedef vector<pair<long long ,long long>> vpll;
typedef vector<vector<long long>> vvll;
typedef set<ll> sll;
typedef map<long long , long long> mpll;
typedef pair<long long ,long long> pll;
typedef tuple<long long , long long , long long> tpl3;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (int)x.size()
// << std::fixed << std::setprecision(10)
const ll INF = 1LL << 60;
const ld EPS = 1e-9;
 
inline ll lfloor(ll x,ll m){return (x - ((x % m+ m)%m))/m;}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {0,0,1,-1,1,1,-1,-1};
vector<ll> _yo = {1,-1,0,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
  
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;

// for AOJ or ICPC or etc..
// 全部が0だったらtrueを返す
template<class Tp> bool zero (const Tp &x) {return x == 0;}
template<class Tp, class... Args> bool zero (const Tp &x, const Args& ...args) {return zero(x) and zero(args...);}



//参考 https://github.com/saphmitchy/deliair-lib
// 型名
// R:Real, P:Point, L:Line, S:Segment, C:Circle, VP:vector<Point>

#define X(p) real(p)
#define Y(p) imag(p)

using R = ld;
using P = complex<R>;
using VP = vector<P>;

//const R EPS = 1e-9; // ここは適宜調節する,いつものやつから消す
const R pi = acos(-1.0);

int sgn(R a) {
    return (a < -EPS) ? -1 : (a > EPS) ? 1 : 0;
} // 符号関数

bool eq(R a, R b) {//実数の一致判定
    return sgn(b - a) == 0;
}

P operator*(P p, R d) {//ベクトルのd倍
    return P(X(p) * d, Y(p) * d);
}

P operator/(P p, R d) {//ベクトルの1/d倍
    return p * (1 / d);
}

istream &operator>>(istream &is, P &p) {
    // R a, b; // 入力が小数
    int a, b; // 入力が整数
    is >> a >> b;
    p = P(a, b);
    return is;
}

ostream &operator<<(ostream &os, P p) {
    return os << X(p) << ' ' << Y(p);
}

R getarg(P b,P a){//ベクトルbはベクトルaを何radian回転させる必要があるか
  assert(sgn(abs(a)) != 0);//長さが0はだめ
  return arg(b/a);
}

bool cp_x(P p, P q) {//ベクトルの比較x軸で比較->y軸で比較
    if (!eq(X(p), X(q)))
        return X(p) < X(q);
    return Y(p) < Y(q);
}

bool cp_y(P p, P q) {//ベクトルの比較y軸で比較->x軸で比較
    if (!eq(Y(p), Y(q)))
        return Y(p) < Y(q);
    return X(p) < X(q);
}

struct L {//直線ab
    P a, b;
    L() {}
    L(P a, P b) : a(a), b(b) {}

    // 入出力（必要なら）
    friend ostream &operator<<(ostream &os, L &l) {
        return os << l.a << ' ' << l.b;
    }
    friend istream &operator>>(istream &is, L &l) {
        return is >> l.a >> l.b;
    }
};

struct S : L {//線分ab
    S() {}
    S(P a, P b) : L(a, b) {}
};

struct C {//中心p 半径rの円
    P p;
    R r;
    C() {}
    C(P p, R r) : p(p), r(r) {}
};

P rot(P p, R t) {//ベクトルの回転
    return p * P(cos(t), sin(t));
}

//2つのベクトルの内積
R dot(P p, P q) {
    return X(p) * X(q) + Y(p) * Y(q);
}

//2つのベクトルの外積
R det(P p, P q) {
    return X(p) * Y(q) - Y(p) * X(q);
}

// https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_1_C&lang=jp
int ccw(P a, P b, P c) { // 線分 ab に対する c の位置関係 
    b -= a, c -= a;//ベクトルab,ベクトルacにした
    if (sgn(det(b, c)) == 1)//外積右ねじ正
        return +1; // COUNTER_CLOCKWISE a,b,cが反時計回り
    if (sgn(det(b, c)) == -1)
        return -1; // CLOCKWISE
    if (dot(b, c) < 0.0)
        return +2; // ONLINE_BACK
    if (norm(b) < norm(c))
        return -2; // ONLINE_FRONT
    return 0;      // ON_SEGMENT
}

bool para(L a, L b) { // 平行判定
    return eq(det(a.b - a.a, b.b - b.a), 0.0);
}

bool orth(L a, L b) { // 垂直判定
    return eq(dot(a.b - a.a, b.b - b.a), 0.0);
}

P proj(L l, P p) { // 垂線の足
    R t = dot(p - l.a, l.b - l.a) / norm(l.b - l.a);
    return l.a + (l.b - l.a) * t;
}

// これいる？
// P proj(S s, P p) {
//     R t = dot(p - s.a, s.b - s.a) / norm(s.b - s.a);
//     return s.a + (s.b - s.a) * t;
// }

P refl(L l, P p) { // 線対称の位置にある点
    return p + (proj(l, p) - p) * 2.0;
}

bool inter(L l, P p) { // 交点を持つか判定
    return abs(ccw(l.a, l.b, p)) != 1;
}

bool inter(S s, P p) {
    return ccw(s.a, s.b, p) == 0;
}

bool inter(L l, L m) {
    if (!eq(det(l.b - l.a, m.b - m.a), 0.0))
        return true;
    return eq(det(l.b - l.a, m.b - l.a), 0.0);
}

bool inter(L l, S s) {
    return sgn(det(l.b - l.a, s.a - l.a) * det(l.b - l.a, s.b - l.a)) <= 0;
}

bool inter(S s, L l) {
    return inter(l, s);
}

bool inter(S s, S t) {
    if (ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) > 0)
        return false;
    return ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

R dist(P p, P q) {
    return abs(q - p);
}

R dist(L l, P p) {
    return abs(p - P(proj(l, p)));
}

R dist(S s, P p) {
    P h = proj(s, p);
    if (inter(s, h))
        return abs(h - p);
    return min(abs(s.a - p), abs(s.b - p));
}

R dist(L l, L m) {
    return inter(l, m) ? 0.0 : dist(l, m.a);
}

R dist(S s, S t) {
    if (inter(s, t))
        return 0.0;
    return min({dist(s, t.a), dist(s, t.b), dist(t, s.a), dist(t, s.b)});
}

R dist(L l, S s) {
    if (inter(l, s))
        return 0.0;
    return min(dist(l, s.a), dist(l, s.b));
}

R dist(S s, L l) {
    return dist(l, s);
}

bool inter(C c, L l) {
    return sgn(c.r - dist(l, c.p)) >= 0;
}

bool inter(C c, P p) {
    return eq(abs(p - c.p), c.r);
}

// 共通接線の本数
// 交点なし:4
// 外接:3
// 2点で交わる:2
// 内接:1
// 一方がもう一方を内包:0
int inter(C c1, C c2) {
    if (c1.r < c2.r)
        swap(c1, c2);
    R d = abs(c1.p - c2.p);
    int a = sgn(d - c1.r - c2.r);
    if (a >= 0)
        return 3 + a;
    return 1 + sgn(d - c1.r + c2.r);
}

VP crosspoint(L l, L m) {
    VP ret;
    if (!inter(l, m))
        return ret;
    R A = det(l.b - l.a, m.b - m.a);
    R B = det(l.b - l.a, l.b - m.a);
    if (eq(A, 0.0) && eq(B, 0.0)) {
        ret.emplace_back(m.a);
    } else {
        ret.emplace_back(m.a + (m.b - m.a) * B / A);
    }
    return ret;
}

VP crosspoint(S s, S t) {
    return inter(s, t) ? crosspoint(L(s), L(t)) : VP();
}

VP crosspoint(C c, L l) {//円と直線の交点
    P h = proj(l, c.p);
    P e = (l.b - l.a) / abs(l.b - l.a);
    VP ret;
    if (!inter(c, l))
        return ret;
    if (eq(dist(l, c.p), c.r)) {
        ret.emplace_back(h);
    } else {
        R b = sqrt(c.r * c.r - norm(h - c.p));
        ret.push_back(h + e * b), ret.push_back(h - e * b);
    }
    return ret;
}

VP crosspoint(C c, S s) {//円と線分の交点
    P h = proj(s, c.p);
    P e = (s.b - s.a) / abs(s.b - s.a);
    VP ret;
    if (!inter(c, s))
        return ret;
    if (eq(dist(s, c.p), c.r)) {
        ret.emplace_back(h);
    } else {
        R b = sqrt(c.r * c.r - norm(h - c.p));
        if(ccw(s.a,s.b,h - e * b) == 0){//s.aに近い方から線分上なら追加する
          ret.push_back(h - e * b);
        }
        if(ccw(s.a,s.b,h + e * b)==0){
          ret.push_back(h + e * b);
        }
    }
    return ret;
}

VP crosspoint(C c1, C c2) {//2つの円の交わる点
    R d = abs(c1.p - c2.p);
    R a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
    R t = atan2(Y(c2.p) - Y(c1.p), X(c2.p) - X(c1.p));
    VP ret;
    if (inter(c1, c2) % 4 == 0) // 交わらないとき
        return ret;
    if (eq(a, 0.0)) {
        ret.emplace_back(P(c1.p + rot(P(c1.r, 0.0), t)));
    } else {
        P p1 = c1.p + rot(P(c1.r, 0.0), t + a);
        P p2 = c1.p + rot(P(c1.r, 0.0), t - a);
        ret.emplace_back(p1), ret.emplace_back(p2);
    }
    return ret;
}

VP cut(VP p, L l, bool border = true) { // 直線が多角形に切り取られる区間
    int n = sz(p);
    p.emplace_back(p[0]), p.emplace_back(p[1]);
    VP ret;
    rep(i, n) {
        if (!eq(dist(l, p[i]), 0) && !eq(dist(l, p[i + 1]), 0)) {
            S s(p[i], p[i + 1]);
            if (eq(dist(l, s), 0)) {
                auto res = crosspoint(l, s);
                ret.emplace_back(res[0]);
            }
        }
        if (eq(dist(l, p[i + 1]), 0)) {
            if ((eq(dist(l, p[i]), 0) || eq(dist(l, p[i + 2]), 0)) && !border)
                continue;
            S s(p[i], p[i + 2]);
            if (eq(dist(l, s), 0))
                ret.emplace_back(p[i + 1]);
        }
    }
    return ret;
}

VP rectangle(S s, R r) { // sを軸とした幅rの長方形
    P d = (s.a - s.b) * P(0, 1);
    d *= r / sqrt(norm(d));
    return VP{s.a + d, s.a - d, s.b - d, s.b + d};
}

L vertical_bisector(P p, P q) { // 垂直二等分線
    L l;
    l.a = (p + q) * 0.5;
    l.b = l.a + rot(q - p, pi * 0.5);
    return l;
}

L angle_bisector(P a,P b,P c){//角abcの二等分線(角bの２等分線)
  L l;
  l.a = b;
  R ang = atan2(Y(c-b),X(c-b)) - atan2(Y(a-b),X(a-b));//なす角
  ang/=2.0;
  l.b = l.a + rot(a-b,ang);
  return l;
}

C Apollonius(P p, P q, R a, R b) { // アポロニウスの円
    P p1 = (p * b + q * a) / (a + b), p2 = (-p * b + q * a) / (a - b);
    C c;
    c.p = (p1 + p2) * 0.5;
    c.r = abs(p1 - p2) * 0.5;
    return c;
}

R area(VP p) { // 多角形の面積
    R ret = 0.0;
    int n = sz(p);
    rep(i, n) ret += det(p[i], p[(i + 1) % n]);
    return abs(ret * 0.5);
}

int in_polygon(VP p, P q) { // IN:2, ON:1, OUT:0
    int n = sz(p);
    int ret = 0;
    rep(i, n) {
        P a = p[i] - q, b = p[(i + 1) % n] - q;
        if (eq(det(a, b), 0.0) && sgn(dot(a, b)) <= 0)
            return 1;
        if (Y(a) > Y(b))
            swap(a, b);
        if (sgn(Y(a)) <= 0 && sgn(Y(b)) == 1 && sgn(det(a, b)) == 1)
            ret ^= 2;
    }
    return ret;
}

VP tangent(C c, P p) { // 点 p を通る円 c の接線と c の接点
    return crosspoint(c, C(p, sqrt(norm(p - c.p) - c.r * c.r)));
}

vector<L> tangent(C c1, C c2) { // 共通接線
    vector<L> ret;
    if (c1.r < c2.r)
        swap(c1, c2);
    R r = abs(c2.p - c1.p);
    if (eq(r, 0.0))
        return ret;
    P u = (c2.p - c1.p) / r;
    P v = rot(u, pi * 0.5);
    for (R s : {1.0, -1.0}) {
        R h = (c1.r + c2.r * s) / r;
        if (eq(abs(h), 1.0)) {
            ret.emplace_back(c1.p + u * c1.r, c1.p + (u + v) * c1.r);
        } else if (abs(h) < 1.0) {
            P uu = u * h, vv = v * sqrt(1.0 - h * h);
            ret.emplace_back(c1.p + (uu + vv) * c1.r, c2.p - (uu + vv) * c2.r * s);
            ret.emplace_back(c1.p + (uu - vv) * c1.r, c2.p - (uu - vv) * c2.r * s);
        }
    }
    return ret;
}

VP convex_hull(VP p) { // 凸包
    sort(all(p), cp_x);
    p.erase(unique(all(p)), end(p));
    int n = sz(p), k = 0;
    if (n == 1)
        return p;
    VP ch(2 * n);
    for (int i = 0; i < n; ch[k++] = p[i++]) {
        while (k >= 2 && sgn(det(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1])) <= 0)
            k--;
    }
    for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]) {
        while (k >= t && sgn(det(ch[k - 1] - ch[k - 2], p[i] - ch[k - 1])) <= 0)
            k--;
    }
    ch.resize(k - 1);
    return ch;
}

R closest_pair(VP p) { // 最近点対の距離
    if (sz(p) <= 1)
        return 1e18;
    sort(all(p), cp_x);
    VP memo(sz(p));

    function<R(int, int)> rec = [&](int l, int r) {
        if (r - l <= 1)
            return R(1e18);
        int m = (l + r) >> 1;
        R x = X(p[m]);
        R ret = min(rec(l, m), rec(m, r));
        inplace_merge(p.begin() + l, p.begin() + m, p.begin() + r, cp_y);
        int cnt = 0;
        reps(i, l, r) {
            if (abs(X(p[i]) - x) >= ret)
                continue;
            rep(j, cnt) {
                P d = p[i] - memo[cnt - j - 1];
                if (Y(d) >= ret)
                    break;
                chmin(ret, abs(d));
            }
            memo[cnt++] = p[i];
        }
        return ret;
    };

    return rec(0, sz(p));
}

R farthest_pair(VP p) {//最遠点対の距離
  VP ps = convex_hull(p);
  ll n = ps.size();
  if(n == 2){//凸包が潰れてる
    return dist(ps[0],ps[1]);
  }
  ll i = 0,j = 0;
  rep(k,n){//x軸方向に最も遠い点対を求める
    if(cp_x(ps[k],ps[i]))i = k;
    if(cp_x(ps[j],ps[k]))j = k;
  }
  R ret = 0;
  ll si = i,sj = j;
  while(i != sj || j != si){//180度反転しきるまで
    ret = max(ret,dist(ps[i],ps[j]));
    if(det(ps[(i+1)%n] - ps[i],ps[(j+1)%n]-ps[j]) < 0){
      i = (i + 1) % n;
    }else{
      j = (j + 1) % n;
    }
  }
  return ret;
}

// 原点, 点 a, 点 b とで囲まれる領域の面積 (三角形 ver と扇型 ver)
R calc_element(P a, P b, R cr,bool triangle){
  if(triangle)return det(a,b)/2;
  else{
    P tmp = b * (P(X(a),-Y(a)));
    R ang = atan2(Y(tmp),X(tmp));
    return cr * cr * ang/2;
  }
}

// 円 C と、三角形 ((0, 0), ia, ib) との共通部分の面積
R common_area(C c, P ia,P ib){
  P a = ia - c.p , b = ib - c.p;
  if(eq(abs(a-b),0))return 0;
  bool isin_a = (sgn(c.r - abs(a))>= 0);
  bool isin_b = (sgn(c.r - abs(b))>= 0);
  if(isin_a && isin_b)return calc_element(a,b,c.r,true);//aもbも円の中

  C oc(P(0,0),c.r);
  S seg(a,b);
  VP cr = crosspoint(oc,seg);
  if(cr.empty())return calc_element(a,b,c.r,false);
  P s = cr[0],t = cr.back();
  return calc_element(s,t,c.r,true) + calc_element(a,s,c.r,isin_a) + calc_element(t,b,c.r,isin_b);

}


R common_area(C c, VP vp){// 円cと多角形の共通部分の面積
  R ret = 0;
  ll n = vp.size();
  rep(i,n){
    ret += common_area(c,vp[i],vp[(i+1)%n]);
  }
  return ret;
}

R common_area(C p, C q) {// 円と円の共通部分の面積
    R d = abs(p.p - q.p);
    if (d >= p.r + q.r - EPS) return 0;
    else if (d <= abs(p.r - q.r) + EPS) return min(p.r, q.r) * min(p.r, q.r) * pi;
    R pcos = (p.r*p.r + d*d - q.r*q.r) / (p.r*d*2);
    R pang = acosl(pcos);
    R parea = p.r*p.r*pang - p.r*p.r*sin(pang*2)/2;
    R qcos = (q.r*q.r + d*d - p.r*p.r) / (q.r*d*2);
    R qang = acosl(qcos);
    R qarea = q.r*q.r*qang - q.r*q.r*sin(qang*2)/2;
    return parea + qarea;
}

vector<VP> divisions(vector<L> lf, R lim = 1e9) {
    vector<L> ls;
    each(l, lf) {
        bool ok = true;
        each(m, ls) {
            if (para(l, m) & inter(l, m.a)) {
                ok = false;
                break;
            }
        }
        if (ok)
            ls.emplace_back(l);
    }
    VP lc{P(-lim, -lim), P(lim, -lim), P(lim, lim), P(-lim, lim)};
    rep(i, 4) ls.emplace_back(lc[i], lc[(i + 1) % 4]);
    int m = sz(ls);
    VP ps;
    vector<vector<int>> lp(m);
    rep(i, m) {
        reps(j, i + 1, m) {
            each(p, crosspoint(ls[i], ls[j])) {
                if (max(abs(X(p)), abs(Y(p))) < lim + EPS) {
                    lp[i].emplace_back(sz(ps)), lp[j].emplace_back(sz(ps));
                    ps.emplace_back(p);
                }
            }
        }
    }
    int n = sz(ps);
    vector<int> id(n, -1), to;
    vector<R> rg;
    vector<vector<pair<R, int>>> li(n);
    rep(i, m) {
        sort(all(lp[i]), [&ps](int a, int b) { return cp_x(ps[a], ps[b]); });
        vector<int> q;
        rep(j, sz(lp[i])) {
            int me = id[lp[i][j]], st = j;
            auto np = ps[lp[i][j]];
            while (j + 1 < sz(lp[i])) {
                if (abs(ps[lp[i][j + 1]] - np) < EPS) {
                    j++;
                    if (id[lp[i][j]] != -1)
                        me = id[lp[i][j]];
                } else
                    break;
            }
            if (me == -1)
                me = lp[i][st];
            reps(k, st, j + 1) id[lp[i][k]] = me;
            q.emplace_back(me);
        }
        rep(i, sz(q) - 1) {
            P d = ps[q[i + 1]] - ps[q[i]];
            R s = atan2(Y(d), X(d)), t = atan2(-Y(d), -X(d));
            int x = q[i], y = q[i + 1];
            li[x].emplace_back(s, sz(to));
            li[x].emplace_back(s + pi * 2, sz(to));
            to.emplace_back(y), rg.emplace_back(t);
            li[y].emplace_back(t, sz(to));
            li[y].emplace_back(t + pi * 2, sz(to));
            to.emplace_back(x), rg.emplace_back(s);
        }
    }
    rep(i, n) sort(all(li[i]));
    vector<bool> u(sz(to), false);
    vector<VP> ret;
    rep(i, n) {
        each(l, li[i]) {
            int ns = l.second;
            if (u[ns])
                continue;
            VP nv;
            int no = ns;
            bool ok = true;
            while (1) {
                if (sz(nv) > 1) {
                    P x = nv[sz(nv) - 2], y = nv[sz(nv) - 1], z = ps[to[no]];
                    int c = ccw(x, y, z);
                    if (c == 1)
                        ok = false;
                    if (c != -1)
                        nv.pop_back();
                }
                nv.emplace_back(ps[to[no]]);
                u[no] = true;
                no = upper_bound(all(li[to[no]]), pair(rg[no] + EPS, -1))->second;
                if (no == ns)
                    break;
            }
            if (ok)
                ret.emplace_back(nv);
        }
    }
    return ret;
}
//ref https://github.com/drken1215/algorithm/blob/master/Geometry/arg_sort.cpp
//verify https://atcoder.jp/contests/abc139/submissions/me
//点列を偏角ソート
void arg_sort(VP &v){
  //原点=0,(pi,2pi] = -1  (0pi,pi] = 1
  auto sign = [&](const P &p){
    if(sgn(X(p)) == 0 && sgn(Y(p)) == 0){
      return 0;
    }else if(sgn(Y(p)) == -1 || (sgn(Y(p)) == 0 && sgn(X(p)) == 1)){
      return -1;
    }else{
      return 1;
    }
  };
  auto cp = [&](const P &p,const P &q){
    if(sign(p) != sign(q)){
      return sign(p) < sign(q);
    }else{//外積>0で判定
      //同じ向きのときは未定義必要に応じて決める
      return X(p) * Y(q) - Y(p) * X(q) > 0;
    }
  };
  sort(v.begin(),v.end(),cp);
}


// 変数をちゃんと全部受け取る！
void solve(ll n){
  vector<L> vl;
  rep(i,n){
    LL(x1,y1,x2,y2);
    L l(P(x1,y1),P(x2,y2));
    vl.push_back(l);
  }
  P p1(-100,-100),p2(100,-100),p3(100,100),p4(-100,100);
  L l1(p1,p2),l2(p2,p3),l3(p3,p4),l4(p4,p1);
  vl.push_back(l1);vl.push_back(l2);vl.push_back(l3);vl.push_back(l4);

  vector<VP> div = divisions(vl,1e10);
  VP poli = {p1,p2,p3,p4};
  ll cnt = 0;
  rep(i,div.size()){
    bool is_in = true;
    each(p,div[i]){
      if(in_polygon(poli,p) == 0){
        is_in = false;
      }
    }
    if(is_in)cnt++;
    
  }
  cout << cnt << endl;
}
 
int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  while(true){
    LL(n);//変数数調整
    if(zero(n))break;
    solve(n);
  }
}
accuracy: 1
time_ms: 220
memory_kb: 7028
final_rank: 20

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
using namespace std;

#define equals(a,b) (fabs((a)-(b))<EPS)

const double EPS = 1e-10;
const double PI = asinl(1) * 2;

struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator+(Point p) {return Point(x+p.x,y+p.y);}
    Point operator-(Point p) {return Point(x-p.x,y-p.y);}
    Point operator*(double k){return Point(x*k,y*k);}
    Point operator/(double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}

    bool operator<(const Point &p) const{
        return x!=p.x?x<p.x:y<p.y;
        //grid-point only
        //return !equals(x,p.x)?x<p.x:!equals(y,p.y)?y<p.y:0;
    }

    bool operator==(const Point &p) const{
        return fabs(x-p.x)<EPS and fabs(y-p.y)<EPS;
    }
};

bool sort_x(Point a,Point b){
    return a.x!=b.x?a.x<b.x:a.y<b.y;
}

bool sort_y(Point a,Point b){
    return a.y!=b.y?a.y<b.y:a.x<b.x;
}

typedef Point Vector;
typedef vector<Point> Polygon;

struct Segment{
    Point p1,p2;
    Segment(){}
    Segment(Point p1, Point p2):p1(p1),p2(p2){}
};
typedef Segment Line;

struct Circle{
    Point c;
    double r;
    Circle(){}
    Circle(Point c,double r):c(c),r(r){}
};

double norm(Vector a){
    return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
    return sqrt(norm(a));
}

double dot(Vector a,Vector b){
    return a.x*b.x+a.y*b.y;
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

Point orth(Point p){return Point(-p.y,p.x);}

bool isOrthogonal(Vector a,Vector b){
    return equals(dot(a,b),0.0);
}

bool isOrthogonal(Point a1,Point a2,Point b1,Point b2){
    return isOrthogonal(a1-a2,b1-b2);
}

bool isOrthogonal(Segment s1,Segment s2){
    return equals(dot(s1.p2-s1.p1,s2.p2-s2.p1),0.0);
}

bool isParallel(Vector a,Vector b){
    return equals(cross(a,b),0.0);
}

bool isParallel(Point a1,Point a2,Point b1,Point b2){
    return isParallel(a1-a2,b1-b2);
}

bool isParallel(Segment s1,Segment s2){
    return equals(cross(s1.p2-s1.p1,s2.p2-s2.p1),0.0);
}

Point project(Segment s,Point p){
    Vector base=s.p2-s.p1;
    double r=dot(p-s.p1,base)/norm(base);
    return s.p1+base*r;
}

Point reflect(Segment s,Point p){
    return p+(project(s,p)-p)*2.0;
}

double arg(Vector p){
    return atan2(p.y,p.x);
}

Vector polar(double a,double r){
    return Point(cos(r)*a,sin(r)*a);
}

// COUNTER CLOCKWISE
static const int CCW_COUNTER_CLOCKWISE = 1;
static const int CCW_CLOCKWISE = -1;
static const int CCW_ONLINE_BACK = 2;
static const int CCW_ONLINE_FRONT = -2;
static const int CCW_ON_SEGMENT = 0;

int ccw(Point p0,Point p1,Point p2){
    Vector a = p1-p0;
    Vector b = p2-p0;
    if(cross(a,b) > EPS) return CCW_COUNTER_CLOCKWISE;
    if(cross(a,b) < -EPS) return CCW_CLOCKWISE;
    if(dot(a,b) < -EPS) return CCW_ONLINE_BACK;
    if(a.norm()<b.norm()) return CCW_ONLINE_FRONT;
    return CCW_ON_SEGMENT;
}

bool intersectSS(Point p1,Point p2,Point p3,Point p4){
    return (ccw(p1,p2,p3)*ccw(p1,p2,p4) <= 0 and
            ccw(p3,p4,p1)*ccw(p3,p4,p2) <= 0 );
}

bool intersectSS(Segment s1,Segment s2){
    return intersectSS(s1.p1,s1.p2,s2.p1,s2.p2);
}

bool intersectPS(Polygon p,Segment l){
    int n=p.size();
    for(int i=0;i<n;++i)
        if(intersectSS(Segment(p[i],p[(i+1)%n]),l)) return 1;
    return 0;
}

double getDistanceLP(Line l,Point p){
    return fabs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1));
}

double getDistanceSP(Segment s,Point p){
    if(dot(s.p2-s.p1,p-s.p1) < 0.0 ) return abs(p-s.p1);
    if(dot(s.p1-s.p2,p-s.p2) < 0.0 ) return abs(p-s.p2);
    return getDistanceLP(s,p);
}

double getDistanceSS(Segment s1,Segment s2){
    if(intersectSS(s1,s2)) return 0.0;
    return min(
            min(getDistanceSP(s1,s2.p1),getDistanceSP(s1,s2.p2)),
            min(getDistanceSP(s2,s1.p1),getDistanceSP(s2,s1.p2)));
}

// intercsect of circles
static const int ICC_SEPERATE = 4;
static const int ICC_CIRCUMSCRIBE = 3;
static const int ICC_INTERSECT = 2;
static const int ICC_INSCRIBE = 1;
static const int ICC_CONTAIN = 0;

int intersectCC(Circle c1,Circle c2){
    if(c1.r<c2.r) swap(c1,c2);
    double d=abs(c1.c-c2.c);
    double r=c1.r+c2.r;
    if(equals(d,r)) return ICC_CIRCUMSCRIBE;
    if(d>r) return ICC_SEPERATE;
    if(equals(d+c2.r,c1.r)) return ICC_INSCRIBE;
    if(d+c2.r<c1.r) return ICC_CONTAIN;
    return ICC_INTERSECT;
}

bool intersectSC(Segment s,Circle c){
    return getDistanceSP(s,c.c)<=c.r;
}

int intersectCS(Circle c,Segment s){
    if(norm(project(s,c.c)-c.c)-c.r*c.r>EPS) return 0;
    double d1=abs(c.c-s.p1),d2=abs(c.c-s.p2);
    if(d1<c.r+EPS and d2<c.r+EPS) return 0;
    if((d1<c.r-EPS and d2>c.r+EPS)
       or (d1>c.r+EPS and d2<c.r-EPS)) return 1;
    Point h=project(s,c.c);
    if(dot(s.p1-h,s.p2-h)<0) return 2;
    return 0;
}

Point getCrossPointSS(Segment s1,Segment s2){
    for(int k=0;k<2;++k){
        if(getDistanceSP(s1,s2.p1)<EPS) return s2.p1;
        if(getDistanceSP(s1,s2.p2)<EPS) return s2.p2;
        swap(s1,s2);
    }
    Vector base=s2.p2-s2.p1;
    double d1=fabs(cross(base,s1.p1-s2.p1));
    double d2=fabs(cross(base,s1.p2-s2.p1));
    double t=d1/(d1+d2);
    return s1.p1+(s1.p2-s1.p1)*t;
}

Point getCrossPointLL(Line l1,Line l2){
    double a=cross(l1.p2-l1.p1,l2.p2-l2.p1);
    double b=cross(l1.p2-l1.p1,l1.p2-l2.p1);
    if(fabs(a)<EPS and fabs(b)<EPS) return l2.p1;
    return l2.p1+(l2.p2-l2.p1)*(b/a);
}

Polygon getCrossPointCL(Circle c,Line l){
    Polygon ps;
    Point pr=project(l,c.c);
    Vector e=(l.p2-l.p1)/abs(l.p2-l.p1);
    if(equals(getDistanceLP(l,c.c),c.r)){
        ps.emplace_back(pr);
        return ps;
    }
    double base=sqrt(c.r*c.r-norm(pr-c.c));
    ps.emplace_back(pr+e*base);
    ps.emplace_back(pr-e*base);
    return ps;
}

Polygon getCrossPointCS(Circle c,Segment s){
    Line l(s);
    Polygon res=getCrossPointCL(c,l);
    if(intersectCS(c,s)==2) return res;
    if(res.size()>1u){
        if(dot(l.p1-res[0],l.p2-res[0])>0) swap(res[0],res[1]);
        res.pop_back();
    }
    return res;
}


Polygon getCrossPointCC(Circle c1,Circle c2){
    Polygon p(2);
    double d=abs(c1.c-c2.c);
    double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
    double t=arg(c2.c-c1.c);
    p[0]=c1.c+polar(c1.r,t+a);
    p[1]=c1.c+polar(c1.r,t-a);
    return p;
}

// IN:2 ON:1 OUT:0
int contains(Polygon g,Point p){
    int n=g.size();
    bool x=false;
    for(int i=0;i<n;++i){
        Point a=g[i]-p,b=g[(i+1)%n]-p;
        if(fabs(cross(a,b)) < EPS and dot(a,b) < EPS) return 1;
        if(a.y>b.y) swap(a,b);
        if(a.y < EPS and EPS < b.y and cross(a,b) > EPS )
            x = !x;
    }
    return (x?2:0);
}

// BEGIN IGNORE
Polygon andrewScan(Polygon s){
    Polygon u,l;
    if(s.size()<3) return s;
    sort(s.begin(),s.end());
    u.push_back(s[0]);
    u.push_back(s[1]);
    l.push_back(s[s.size()-1]);
    l.push_back(s[s.size()-2]);
    for(int i=2;i<(int)s.size();++i){
        for(int n=u.size();
            n>=2 and ccw(u[n-2],u[n-1],s[i])!=CCW_CLOCKWISE;
            n--){
            u.pop_back();
        }
        u.push_back(s[i]);
    }
    for(int i=s.size()-3;i>=0;i--){
        for(int n=l.size();
            n>=2 and ccw(l[n-2],l[n-1],s[i])!=CCW_CLOCKWISE;
            n--){
            l.pop_back();
        }
        l.push_back(s[i]);
    }
    reverse(l.begin(),l.end());
    for(int i=u.size()-2;i>=1;i--) l.push_back(u[i]);
    return l;
}
// END IGNORE

Polygon convex_hull(Polygon ps){
    int n=ps.size();
    sort(ps.begin(),ps.end(),sort_y);
    int k=0;
    Polygon qs(n*2);
    for(int i=0;i<n;++i){
        while(k>1 and cross(qs[k-1]-qs[k-2],ps[i]-qs[k-1])<0)
            k--;
        qs[k++]=ps[i];
    }
    for(int i=n-2,t=k;i>=0;i--){
        while(k>t and cross(qs[k-1]-qs[k-2],ps[i]-qs[k-1])<0)
            k--;
        qs[k++]=ps[i];
    }
    qs.resize(k-1);
    return qs;
}

double diameter(Polygon s){
    Polygon p=s;
    int n=p.size();
    if(n==2) return abs(p[0]-p[1]);
    int i=0,j=0;
    for(int k=0;k<n;++k){
        if(p[i]<p[k]) i=k;
        if(!(p[j]<p[k])) j=k;
    }
    double res=0;
    int si=i,sj=j;
    while(i!=sj or j!=si){
        res=max(res,abs(p[i]-p[j]));
        if(cross(p[(i+1)%n]-p[i],p[(j+1)%n]-p[j])<0.0){
            i=(i+1)%n;
        }else{
            j=(j+1)%n;
        }
    }
    return res;
}

bool isConvex(Polygon p){
    bool f=1;
    int n=p.size();
    for(int i=0;i<n;++i){
        int t=ccw(p[(i+n-1)%n],p[i],p[(i+1)%n]);
        f&=t!=CCW_CLOCKWISE;
    }
    return f;
}

double area(Polygon s){
    double res=0;
    for(int i=0;i<(int)s.size();++i){
        res+=cross(s[i],s[(i+1)%s.size()])/2.0;
    }
    return res;
}

double area(Circle c1,Circle c2){
    double d=abs(c1.c-c2.c);
    if(c1.r+c2.r<=d+EPS) return 0;
    if(d<=fabs(c1.r-c2.r)){
        double r=min(c1.r,c2.r);
        return PI*r*r;
    }
    double res=0;
    for(int k=0;k<2;++k){
        double rc=(d*d+c1.r*c1.r-c2.r*c2.r)/(2*d*c1.r);
        double th=acosl(rc)*2;
        res+=(th-sinl(th))*c1.r*c1.r/2;
        swap(c1,c2);
    }
    return res;
}

Polygon convexCut(Polygon p,Line l){
    Polygon q;
    for(int i=0;i<(int)p.size();++i){
        Point a=p[i],b=p[(i+1)%p.size()];
        if(ccw(l.p1,l.p2,a)!=-1) q.push_back(a);
        if(ccw(l.p1,l.p2,a)*ccw(l.p1,l.p2,b)<0)
            q.push_back(getCrossPointLL(Line(a,b),l));
    }
    return q;
}

Line bisector(Point p1,Point p2){
    Circle c1=Circle(p1,abs(p1-p2)),c2=Circle(p2,abs(p1-p2));
    Polygon p=getCrossPointCC(c1,c2);
    if(cross(p2-p1,p[0]-p1)>0) swap(p[0],p[1]);
    return Line(p[0],p[1]);
}

Vector translate(Vector v,double theta){
    Vector res;
    res.x=cos(theta)*v.x-sin(theta)*v.y;
    res.y=sin(theta)*v.x+cos(theta)*v.y;
    return res;
}

vector<Line> corner(Line l1,Line l2){
    vector<Line> res;
    if(isParallel(l1,l2)){
        double d=getDistanceLP(l1,l2.p1)/2.0;
        Vector v1=l1.p2-l1.p1;
        v1=v1/v1.abs()*d;
        Point p=l2.p1+translate(v1,90.0*(PI/180.0));
        double d1=getDistanceLP(l1,p);
        double d2=getDistanceLP(l2,p);
        if(fabs(d1-d2)>d){
            p=l2.p1+translate(v1,-90.0*(PI/180.0));
        }
        res.push_back(Line(p,p+v1));
    }else{
        Point p=getCrossPointLL(l1,l2);
        Vector v1=l1.p2-l1.p1,v2=l2.p2-l2.p1;
        v1=v1/v1.abs();
        v2=v2/v2.abs();
        res.push_back(Line(p,p+(v1+v2)));
        res.push_back(
                Line(p,p+translate(v1+v2,90.0*(PI/180.0))));
    }
    return res;
}

Polygon tangent(Circle c1,Point p2){
    Circle c2=Circle(p2,sqrt(norm(c1.c-p2)-c1.r*c1.r));
    Polygon p=getCrossPointCC(c1,c2);
    sort(p.begin(),p.end());
    return p;
}

vector<Line> tangent(Circle c1,Circle c2){
    vector<Line> ls;
    if(c1.r<c2.r) swap(c1,c2);
    double g=norm(c1.c-c2.c);
    if(equals(g,0)) return ls;
    Point u=(c2.c-c1.c)/sqrt(g);
    Point v=orth(u);
    for(int s=1;s>=-1;s-=2){
        double h=(c1.r+s*c2.r)/sqrt(g);
        if(equals(1-h*h,0)){
            ls.emplace_back(c1.c+u*c1.r,c1.c+(u+v)*c1.r);
        }else if(1-h*h>0){
            Point uu=u*h,vv=v*sqrt(1-h*h);
            ls.emplace_back(
                    c1.c+(uu+vv)*c1.r,c2.c-(uu+vv)*c2.r*s);
            ls.emplace_back(
                    c1.c+(uu-vv)*c1.r,c2.c-(uu-vv)*c2.r*s);
        }
    }

    return ls;
}

double closest_pair(Polygon &a,int l=0,int r=-1){
    if(r<0){
        r=a.size();
        sort(a.begin(),a.end(),sort_x);
    }
    if(r-l<=1) return abs(a[0]-a[1]);
    int m=(l+r)>>1;
    double x=a[m].x;
    double d=min(closest_pair(a,l,m),closest_pair(a,m,r));
    inplace_merge(a.begin()+l,a.begin()+m,a.begin()+r,sort_y);

    Polygon b;
    for(int i=l;i<r;++i){
        if(fabs(a[i].x-x)>=d) continue;
        for(int j=0;j<(int)b.size();++j){
            double dy=a[i].y-next(b.rbegin(),j)->y;
            if(dy>=d) break;
            d=min(d,abs(a[i]-*next(b.rbegin(),j)));
        }
        b.emplace_back(a[i]);
    }
    return d;
}

vector<vector<int>>
segmentArrangement(vector<Segment> &ss, Polygon &ps){
    int n=ss.size();
    for(int i=0;i<n;++i){
        ps.emplace_back(ss[i].p1);
        ps.emplace_back(ss[i].p2);
        for(int j=i+1;j<n;++j)
            if(intersectSS(ss[i],ss[j]))
                ps.emplace_back(getCrossPointSS(ss[i],ss[j]));
    }
    sort(ps.begin(),ps.end());
    ps.erase(unique(ps.begin(),ps.end()),ps.end());

    vector<vector<int> > G(ps.size());
    for(int i=0;i<n;++i){
        vector<pair<double,int> > ls;
        for(int j=0;j<(int)ps.size();++j)
            if(getDistanceSP(ss[i],ps[j])<EPS)
                ls.emplace_back(make_pair(norm(ss[i].p1-ps[j]),j));

        sort(ls.begin(),ls.end());
        for(int j=0;j+1<(int)ls.size();++j){
            int a=ls[j].second,b=ls[j+1].second;
            G[a].emplace_back(b);
            G[b].emplace_back(a);
        }
    }
    for(auto &v:G){
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
    }
    return G;
}

struct EndPoint{
    Point p;
    int seg,st;
    EndPoint(){}
    EndPoint(Point p,int seg,int st):p(p),seg(seg),st(st){}
    bool operator<(const EndPoint &ep)const{
        if(p.y==ep.p.y) return st<ep.st;
        return p.y<ep.p.y;
    }
};

int manhattan_intersection(
        vector<Segment> ss,const int INF){
    const int BTM = 0;
    const int LFT = 1;
    const int RGH = 2;
    const int TOP = 3;

    int n=ss.size();
    vector<EndPoint> ep;
    for(int i=0;i<n;++i){
        if(ss[i].p1.y==ss[i].p2.y){
            if(ss[i].p1.x>ss[i].p2.x) swap(ss[i].p1,ss[i].p2);
            ep.emplace_back(ss[i].p1,i,LFT);
            ep.emplace_back(ss[i].p2,i,RGH);
        }else{
            if(ss[i].p1.y>ss[i].p2.y) swap(ss[i].p1,ss[i].p2);
            ep.emplace_back(ss[i].p1,i,BTM);
            ep.emplace_back(ss[i].p2,i,TOP);
        }
    }
    sort(ep.begin(),ep.end());

    set<int> bt;
    bt.insert(INF);

    int cnt=0;
    for(int i=0;i<n*2;++i){
        if(ep[i].st==TOP){
            bt.erase(ep[i].p.x);
        }else if(ep[i].st==BTM){
            bt.emplace(ep[i].p.x);
        }else if(ep[i].st==LFT){
            auto b=bt.lower_bound(ss[ep[i].seg].p1.x);
            auto e=bt.upper_bound(ss[ep[i].seg].p2.x);
            cnt+=distance(b,e);
        }
    }

    return cnt;
}

double area(Polygon ps,Circle c){
    if(ps.size()<3u) return 0;
    function<double(Circle, Point, Point)> dfs=
            [&](Circle c,Point a,Point b){
                Vector va=c.c-a,vb=c.c-b;
                double f=cross(va,vb),res=0;
                if(equals(f,0.0)) return res;
                if(max(abs(va),abs(vb))<c.r+EPS) return f;
                Vector d(dot(va,vb),cross(va,vb));
                if(getDistanceSP(Segment(a,b),c.c)>c.r-EPS)
                    return c.r*c.r*atan2(d.y,d.x);
                auto u=getCrossPointCS(c,Segment(a,b));
                if(u.empty()) return res;
                if(u.size()>1u and dot(u[1]-u[0],a-u[0])>0)
                    swap(u[0],u[1]);
                u.emplace(u.begin(),a);
                u.emplace_back(b);
                for(int i=1;i<(int)u.size();++i)
                    res+=dfs(c,u[i-1],u[i]);
                return res;
            };
    double res=0;
    for(int i=0;i<(int)ps.size();++i)
        res+=dfs(c,ps[i],ps[(i+1)%ps.size()]);
    return res/2;
}


using ll = long long;
using i64 = long long;
using pll = pair<ll,ll>;
using plll = pair<pll,ll>;
using pii =pair<int,int>;

constexpr ll mod = 998244353;

int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int dX[4]={1,0,-1,0};
int dY[4]={0,-1,0,1};


using Graph =vector<vector<ll>>;


int main(){
    while (true){
        int n;
        cin>>n;
        if (n==0)break;
        vector<Segment> Segs;
        int ans=1;
        for (int i=0; i<n; i++){
            double x1,y1,x2,y2;
            cin>>x1>>y1>>x2>>y2;
            Point p1={x1,y1};
            Point p2={x2,y2};
            Segment s={p1,p2};

            vector<Point> vec;
            vec.push_back(p1);
            vec.push_back(p2);
            for (auto v: Segs){
                if (intersectSS(v,s)){
                    vec.push_back(getCrossPointSS(v,s));

                }
            }
            int sans=vec.size()-1;
            sort(vec.begin(),vec.end(),[](auto& a, auto& b){
                if (a.x==b.x)return a.y<b.y;
                return a.x<b.x;});
            int cnt=1;
            for (int j=1; j<vec.size(); j++){
                if (vec[j]==vec[j-1]){
                    cnt++;
                }
                else{
                    sans-=cnt-1;
                    cnt=1;
                }
            }
            sans-=cnt-1;

            ans+=sans;
            //cout<<' '<<ans<<endl;
            Segs.emplace_back(p1,p2);



        }
        cout<<ans<<endl;



    }
}
accuracy: 1
time_ms: 10
memory_kb: 3480
final_rank: 12

code_snippet: #include <bits/stdc++.h>

#include <algorithm>
#include <cmath>
#include <iterator>
#include <utility>
#include <vector>

using Real = long double;
constexpr Real EPS = 1e-10;
const Real PI = std::acos(-1);

int sign(Real x) {
    return x < -EPS ? -1 : x > EPS ? 1 : 0;
}

bool eq(Real lhs, Real rhs) {
    return sign(rhs - lhs) == 0;
}

bool lte(Real lhs, Real rhs) {
    return sign(rhs - lhs) >= 0;
}

bool lt(Real lhs, Real rhs) {
    return sign(rhs - lhs) > 0;
}

bool gte(Real lhs, Real rhs) {
    return lte(rhs, lhs);
}

bool gt(Real lhs, Real rhs) {
    return lt(rhs, lhs);
}

struct Point {
    Real x;
    Real y;
    Point(Real x = 0, Real y = 0): x(x), y(y) {}
    Point& operator+=(Point rhs) {
        this->x += rhs.x;
        this->y += rhs.y;
        return *this;
    }
    Point& operator-=(Point rhs) {
        this->x -= rhs.x;
        this->y -= rhs.y;
        return *this;
    }
    Point& operator*=(Real k) {
        this->x *= k;
        this->y *= k;
        return *this;
    }
    Point& operator/=(Real k) {
        this->x /= k;
        this->y /= k;
        return *this;
    }
    friend Point operator+(Point lhs, Point rhs) {
        return lhs += rhs;
    }
    friend Point operator-(Point lhs, Point rhs) {
        return lhs -= rhs;
    }
    friend Point operator*(Point p, Real k) {
        return p *= k;
    }
    friend Point operator/(Point p, Real k) {
        return p /= k;
    }
    friend Point operator*(Real k, Point p) {
        return p * k;
    }
    friend Point operator/(Real k, Point p) {
        return p / k;
    }
    friend bool operator==(Point lhs, Point rhs) {
        return eq(lhs.x, rhs.x) && eq(lhs.y, rhs.y);
    }
    friend bool operator<(Point lhs, Point rhs) {
        if (eq(lhs.x, rhs.x)) return lt(lhs.y, rhs.y);
        return lt(lhs.x, rhs.x);
    }
    friend bool operator>(Point lhs, Point rhs) {
        return rhs < lhs;
    }
};

using Points = std::vector<Point>;
using Polygon = Points;
using Vector = Point;

Real norm(Vector p) {
    return p.x * p.x + p.y * p.y;
}

Real abs(Vector p) {
    return std::sqrt(norm(p));
}

Real dot(Vector lhs, Vector rhs) {
    return lhs.x * rhs.x + lhs.y * rhs.y;
}

Real cross(Vector lhs, Vector rhs) {
    return lhs.x * rhs.y - lhs.y * rhs.x;
}

int ccw(Point p0, Point p1, Point p2) {
    Vector a = p1 - p0;
    Vector b = p2 - p0;

    if (cross(a, b) > EPS) return 1;

    if (cross(a, b) < -EPS) return -1;

    if (dot(a, b) < 0) return 2;

    if (norm(a) < norm(b)) return -2;

    return 0;
}

struct Circle {
    Real r;
    Point c;
    Circle() {}
    Circle(Real r, Point c): r(r), c(c) {}
};

struct Segment {
    Segment() {}
    Segment(Point p0, Point p1): p0(p0), p1(p1) {}
    Point p0, p1;
};

struct Line {
    Line() {}
    Line(Point p0, Point p1): p0(p0), p1(p1) {}
    explicit Line(Segment s): p0(s.p0), p1(s.p1) {}
    Point p0, p1;
};

Real distance(Point lhs, Point rhs) {
    return abs(rhs - lhs);
}

Real distance(Line l, Point p) {
    return std::abs(cross(l.p1 - l.p0, p - l.p0)) / abs(l.p1 - l.p0);
}

Real distance(Segment s, Point p) {
    if (dot(s.p1 - s.p0, p - s.p0) < 0) {
        return distance(p, s.p0);
    }
    if (dot(s.p0 - s.p1, p - s.p1) < 0) {
        return distance(p, s.p1);
    }
    return distance(Line(s), p);
}

bool intersect(Segment lhs, Segment rhs) {
    return ccw(lhs.p0, lhs.p1, rhs.p0) * ccw(lhs.p0, lhs.p1, rhs.p1) <= 0
           && ccw(rhs.p0, rhs.p1, lhs.p0) * ccw(rhs.p0, rhs.p1, lhs.p1) <= 0;
}

bool intersect(Segment s, Point p) {
    return ccw(s.p0, s.p1, p) == 0;
}

Real distance(Segment lhs, Segment rhs) {
    if (intersect(lhs, rhs)) {
        return Real(0);
    }
    return std::min({distance(lhs, rhs.p0), distance(lhs, rhs.p1), distance(rhs, lhs.p0), distance(rhs, lhs.p1)});
}

bool parallel(Vector lhs, Vector rhs) {
    return eq(cross(lhs, rhs), 0);
}

bool parallel(Segment lhs, Segment rhs) {
    return parallel(lhs.p0 - lhs.p1, rhs.p0 - rhs.p1);
}

bool parallel(Line lhs, Line rhs) {
    return parallel(lhs.p0 - lhs.p1, rhs.p0 - rhs.p1);
}

Point crosspoint(Line lhs, Line rhs) {
    Real a = cross(lhs.p1 - lhs.p0, rhs.p1 - rhs.p0);
    Real b = cross(lhs.p1 - lhs.p0, lhs.p1 - rhs.p0);
    return rhs.p0 + (rhs.p1 - rhs.p0) * b / a;
}

bool intersect(Line l, Segment s) {
    return ccw(l.p0, l.p1, s.p0) * ccw(l.p0, l.p1, s.p1) <= 0;
}

bool intersect(Circle c, Line l) {
    return lte(distance(l, c.c), c.r);
}

bool intersect(Circle c, Point p) {
    return eq(distance(c.c, p), c.r);
}

bool intersect(Circle c, Segment s) {
    return lte(distance(s, c.c), c.r);
}

int intersect(Circle lhs, Circle rhs) {
    if (gt(lhs.r, rhs.r)) std::swap(lhs, rhs);
    Real d = distance(lhs.c, rhs.c);
    if (lt(lhs.r + rhs.r, d)) return 4;
    if (eq(lhs.r + rhs.r, d)) return 3;
    if (gt(lhs.r + d, rhs.r)) return 2;
    if (eq(lhs.r + d, rhs.r)) return 1;
    return 0;
}

bool orthogonal(Vector lhs, Vector rhs) {
    return eq(dot(lhs, rhs), 0);
}

bool orthogonal(Segment lhs, Segment rhs) {
    return orthogonal(lhs.p0 - lhs.p1, rhs.p0 - rhs.p1);
}

bool orthogonal(Line lhs, Line rhs) {
    return orthogonal(lhs.p0 - lhs.p1, rhs.p0 - rhs.p1);
}

Point crosspoint(Segment lhs, Segment rhs) {
    Real d0 = distance(Line(lhs.p0, lhs.p1), rhs.p0);
    Real d1 = distance(Line(lhs.p0, lhs.p1), rhs.p1);
    return rhs.p0 + (rhs.p1 - rhs.p0) * (d0 / (d0 + d1));
}

Real arg(Vector p) {
    return std::atan2(p.y, p.x);
}

Vector polar(Real a, Real r) {
    return Point(std::cos(r) * a, std::sin(r) * a);
}

Point rotate(Point p, Real t) {
    Point v = polar(1, t);
    return Point(p.x * v.x - p.y * v.y, p.x * v.y + p.y * v.x);
}

Real angle(Point p0, Point p1, Point p2) {
    Real a = arg(p0 - p1);
    Real b = arg(p2 - p1);
    if (gt(a, b)) std::swap(a, b);
    return std::min(b - a, 2 * PI - (b - a));
}

Points crosspoint(Circle lhs, Circle rhs) {
    Real d = abs(lhs.c - rhs.c);
    if (eq(d, lhs.r + rhs.r)) return {lhs.c + lhs.r * (rhs.c - lhs.c) / d};
    Real a = std::acos((lhs.r * lhs.r + d * d - rhs.r * rhs.r) / (2 * lhs.r * d));
    Real t = arg(rhs.c - lhs.c);
    return {lhs.c + polar(lhs.r, t + a), lhs.c + polar(lhs.r, t - a)};
}

Point projection(Segment s, Point p) {
    Vector a = p - s.p0;
    Vector b = s.p1 - s.p0;
    Real t = dot(a, b) / norm(b);
    return s.p0 + t * b;
}

Point projection(Line l, Point p) {
    Vector a = p - l.p0;
    Vector b = l.p1 - l.p0;
    Real t = dot(a, b) / norm(b);
    return l.p0 + t * b;
}

Point reflection(Segment s, Point p) {
    return p + (projection(s, p) - p) * Real(2);
}

Point reflection(Line l, Point p) {
    return p + (projection(l, p) - p) * Real(2);
}

Points crosspoint(Circle c, Line l) {
    Vector p = projection(l, c.c);
    Real t = std::sqrt(c.r * c.r - norm(c.c - p));
    if (eq(t, 0)) return {p};
    Vector e = (l.p1 - l.p0) / abs(l.p1 - l.p0);
    return {p + t * e, p + -t * e};
}

Real area(Polygon poly) {
    int n = poly.size();
    Real result = 0;
    for (int i = 0; i < n; i++) {
        result += cross(poly[i], poly[(i + 1) % n]);
    }
    return result / 2;
}

Real perimeter(Polygon poly) {
    int n = poly.size();
    Real result = 0;
    for (int i = 0; i < n; i++) {
        result += abs(poly[i] - poly[(i + 1) % n]);
    }
    return result;
}

bool convex(Polygon poly) {
    int n = poly.size();
    for (int i = 0; i < n; i++) {
        if (ccw(poly[i], poly[(i + 1) % n], poly[(i + 2) % n]) == -1) return false;
    }
    return true;
}

int contain(Polygon poly, Point p) {
    int n = poly.size();
    bool parity = false;
    for (int i = 0; i < n; i++) {
        Point a = poly[i] - p;
        Point b = poly[(i + 1) % n] - p;
        if (gt(a.y, b.y)) std::swap(a, b);
        if (lte(a.y, 0) && lt(0, b.y) && lt(cross(a, b), 0)) parity ^= true;
        if (eq(cross(a, b), 0) && lte(dot(a, b), 0)) return 1;
    }
    return (parity ? 2 : 0);
}

Polygon convex_hull(Points points) {
    std::sort(points.begin(), points.end(), [](Point lhs, Point rhs) {
        if (eq(lhs.x, rhs.x)) return lt(lhs.y, rhs.y);
        return lt(lhs.x, rhs.x);
    });
    int n = points.size();
    Points lower, upper;
    lower.push_back(points[n - 1]);
    lower.push_back(points[n - 2]);
    upper.push_back(points[0]);
    upper.push_back(points[1]);
    for (int i = n - 3; i >= 0; i--) {
        for (int m = lower.size(); m >= 2 && ccw(lower[m - 2], lower[m - 1], points[i]) >= 0; m--) {
            lower.pop_back();
        }
        lower.push_back(points[i]);
    }
    for (int i = 2; i < n; i++) {
        for (int m = upper.size(); m >= 2 && ccw(upper[m - 2], upper[m - 1], points[i]) >= 0; m--) {
            upper.pop_back();
        }
        upper.push_back(points[i]);
    }
    std::reverse(lower.begin(), lower.end());
    std::copy(std::next(upper.rbegin()), std::prev(upper.rend()), std::back_inserter(lower));
    return lower;
}

Polygon convex_cut(Polygon poly, Line l) {
    int n = poly.size();
    Polygon res;
    for (int i = 0; i < n; i++) {
        Point a = poly[i];
        Point b = poly[(i + 1) % n];
        if (ccw(l.p0, l.p1, a) != -1) res.push_back(a);
        if (ccw(l.p0, l.p1, a) * ccw(l.p0, l.p1, b) == -1) {
            res.push_back(crosspoint(l, Line(a, b)));
        }
    }
    return res;
}

Line bisector(Point p0, Point p1, Point p2) {
    return Line(p1, p1 + polar(1, angle(p0, p1, p2) / 2));
}

Circle incircle(Point p0, Point p1, Point p2) {
    Point c = crosspoint(bisector(p0, p1, p2), bisector(p1, p2, p0));
    Real r = std::abs(2 * area({p0, p1, p2}) / perimeter({p0, p1, p2}));
    return Circle(r, c);
}

Line perpendicular(Line l, Point p) {
    Vector v = l.p1 - l.p0;
    return Line(p, p + Vector(-v.y, v.x));
}

Line perpendicular_bisector(Segment s) {
    return perpendicular(Line(s), (s.p0 + s.p1) / 2);
}

Circle circumscribed_circle(Point p0, Point p1, Point p2) {
    Point c = crosspoint(perpendicular_bisector(Segment(p0, p1)), perpendicular_bisector(Segment(p0, p2)));
    return Circle(distance(p0, c), c);
}

Real area(Circle c) {
    return c.r * c.r * PI;
}

Points tangent(Circle c, Point p) {
    return crosspoint(c, Circle(std::sqrt(norm(c.c - p) - c.r * c.r), p));
}

const Real L = 100;

bool on_square(Point p) {
    return eq(p.x, L) || eq(p.x, -L) || eq(p.y, L) || eq(p.y, -L);
}

int solve() {
    int n;
    std::cin >> n;
    if (n == 0) return 1;
    using Segments = std::vector<Segment>;
    Segments segments;
    int ans = 1;
    for (int i = 0; i < n; i++) {
        Point p, q;
        std::cin >> p.x >> p.y;
        std::cin >> q.x >> q.y;
        Segment s(p, q);
        Points cp;
        for (auto& t: segments) {
            if (intersect(s, t)) {
                cp.push_back(crosspoint(s, t));
            }
        }
        std::sort(cp.begin(), cp.end());
        cp.erase(std::unique(cp.begin(), cp.end()), cp.end());
        int cur = 0;
        for (auto& p: cp) {
            if (!on_square(p)) cur++;
        }
        ans += cur + 1;
        segments.push_back(s);
    }
    std::cout << ans << std::endl;
    return 0;
}

int main() {
    while (!solve())
        ;
}
accuracy: 1
time_ms: 10
memory_kb: 3552
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define rrep(i, a, n) for(int i = a; i >= n; i--)
#define inr(l, x, r) (l <= x && x < r)
#define ll long long
#define ld long double

constexpr int IINF = 1001001001;
constexpr ll INF = 9e18;

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

namespace geometry {
    using D = long double;
    using Point = std::complex<D>;
    const D EPS = 1e-10;
    const D PI = std::acos(D(-1));

    istream &operator>>(istream &is, Point &p) {
        D a, b;
        is >> a >> b;
        p = Point(a, b);
        return is;
    }

    // d 倍する
    Point operator*(Point p, D d) {
    return Point(p.real() * d, p.imag() * d);
    }
    // 等しいかどうか（誤差で判定）
    inline bool equal(D a, D b) { return fabs(a - b) < EPS; }

    // 単位ベクトル
    Point unit_vector(Point a) { return a / abs(a); };

    // 法線ベクトル (逆向きがよければ (0, -1) をかける)
    Point normal_vector(Point a, D dir=1) { return a * Point(0, dir); }

    // 内積：a・b = |a||b|cosΘ
    D dot(Point a, Point b){
        return (a.real() * b.real() + a.imag() * b.imag());
    }

    // 外積：a×b = |a||b|sinΘ (外積の大きさではないか？)
    D cross(Point a, Point b){
        return (a.real() * b.imag() - a.imag() * b.real());
    }

    // 反時計回りに theta 回転
    Point rotate(Point a, D theta) {
        D c = cos(theta), s = sin(theta);
        return Point(c * a.real() - s * a.imag(), s * a.real() + c * a.imag());
    }

    // 直線 
    struct Line {
        Point a, b;
        Line() = default;
        Line(Point a_, Point b_) : a(a_), b(b_) { assert(a_ != b_); };
        // Ax+By=C
        Line(D A, D B, D C){
            if(equal(A, 0)){
                a = Point(0, C/B), b = Point(1, C/B);
            }else if(equal(B, 0)){
                b = Point(C/A, 0), a = Point(C/A, 1);
            }else{
                a = Point(0, C/B), b = Point(C/A, 0);
            }
        }
    };

    // 線分（Line と同じ）
    struct Segment : Line {
        Segment() = default;
        Segment(Point a_, Point b_) : Line(a_, b_) {};
    };


    // 射影：直線（線分）に 点p から引いた垂線の足を求める
    Point projection(Line l, Point p){
        D t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
        return l.a + (l.a - l.b) * t;
    }
    Point projection(Segment l, Point p){
        D t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
        return l.a + (l.a - l.b) * t;
    }

    // 反射：直線を対象軸として 点p と線対称の位置にある点を求める
    Point reflection(Line l, Point p){
        return p + (projection(l, p)-p) * 2.0;
    }

    // 3点 a, b, c の位置関係
    // reference: https://sen-comp.hatenablog.com/entry/2020/03/12/145742#iSP3%E7%82%B9%E3%81%AE%E4%BD%8D%E7%BD%AE%E9%96%A2%E4%BF%82
    int ccw(Point a, Point b, Point c){
        b -= a, c -= a;
        // 点 a, b, c が
        if(cross(b, c) >  EPS) return  1; // 反時計回りのとき
        if(cross(b, c) < -EPS) return -1; // 時計回りのとき
        
        // 同一直線上にある場合
        if(dot(b, c) < 0) return 2;      // c, a, b の順
        if(norm(b) < norm(c)) return -2; // a, b, c の順
        return 0;                        // a, c, b の順
    }
    
    // 垂直（内積 == 0）
    bool is_vertical(Line a, Line b){
        return equal(dot(a.b - a.a, b.b - b.a), 0);
    }

    // 平行（外積 == 0）
    bool is_parallel(Line a, Line b){
        return equal(cross(a.b - a.a, b.b - b.a), 0);
    }

    // 線分の交差判定（線分 s に対して, 線分 t の端点が反対側にあればよい）
    bool is_intersect(Segment s, Segment t){
        return (ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0) && 
               (ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0);
    }

    // 交点（交差する前提）
    Point cross_point(Line s, Line t){
        D d1 = cross(s.b - s.a, t.b - t.a);
        D d2 = cross(s.b - s.a, s.b - t.a);
        // s, t が一致する場合（適当な１点を返す）
        if(equal(abs(d1), 0) && equal(abs(d2), 0)) return t.a; 
        
        return t.a + (t.b - t.a) * (d2/d1);
    }
    Point cross_point(Segment s, Segment t) {
        assert(is_intersect(s, t)); // 交差する前提
        return cross_point(Line(s), Line(t));
    }

    // 線分と点の距離（点p から線分のどこかへの最短距離）
    D dist_segment_point(Segment l, Point p){
        if(dot(l.b - l.a, p - l.a) < EPS) abs(p - l.a);
        if(dot(l.a - l.b, p - l.b) < EPS) abs(p - l.b);
        return abs(cross(l.b - l.a, p - l.a)) / abs(l.b - l.a);
    }
    // 線分と線分の距離
    D dist_segment_segment(Segment s, Segment t){
        if(is_intersect(s, t)) return 0.0;
        D res = min({
            dist_segment_point(s, t.a),
            dist_segment_point(s, t.b),
            dist_segment_point(t, s.a),
            dist_segment_point(t, s.b),
        });
        return res;
    }

    // Todo : 円, 多角形
};
using namespace geometry;


int main(){
    while(1){
        int n; cin >> n;
        if(n == 0) return 0;
        int ans = n+1;
        vector<Line> lines;
        rep(i, 0, n){
            Point p1, p2; cin >> p1 >> p2;
            Line newl(p1, p2);
            vector<Point> points;
            for(auto l: lines){
                if(is_parallel(l, newl)) continue;
                Point crossp = cross_point(l, newl);
                if(abs(crossp.imag())>=100 || abs(crossp.real())>=100) continue;
                bool flg = true;
                for(auto p:points){
                    if(abs(p-crossp) <= 1e-10){
                        flg = false;
                        break;
                    }
                }
                if(flg) ans++;
                points.push_back(crossp);
            }
            lines.push_back(newl);
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 3492
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define rrep(i, a, n) for(int i = a; i >= n; i--)
#define inr(l, x, r) (l <= x && x < r)
#define ll long long
#define ld long double

constexpr int IINF = 1001001001;
constexpr ll INF = 9e18;

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

namespace geometry {
    using D = long double;
    using Point = std::complex<D>;
    const D EPS = 1e-10;
    const D PI = std::acos(D(-1));

    istream &operator>>(istream &is, Point &p) {
        D a, b;
        is >> a >> b;
        p = Point(a, b);
        return is;
    }

    // d 倍する
    Point operator*(Point p, D d) {
    return Point(p.real() * d, p.imag() * d);
    }
    // 等しいかどうか（誤差で判定）
    inline bool equal(D a, D b) { return fabs(a - b) < EPS; }

    // 単位ベクトル
    Point unit_vector(Point a) { return a / abs(a); };

    // 法線ベクトル (逆向きがよければ (0, -1) をかける)
    Point normal_vector(Point a, D dir=1) { return a * Point(0, dir); }

    // 内積：a・b = |a||b|cosΘ
    D dot(Point a, Point b){
        return (a.real() * b.real() + a.imag() * b.imag());
    }

    // 外積：a×b = |a||b|sinΘ (外積の大きさではないか？)
    D cross(Point a, Point b){
        return (a.real() * b.imag() - a.imag() * b.real());
    }

    // 反時計回りに theta 回転
    Point rotate(Point a, D theta) {
        D c = cos(theta), s = sin(theta);
        return Point(c * a.real() - s * a.imag(), s * a.real() + c * a.imag());
    }

    // 直線 
    struct Line {
        Point a, b;
        Line() = default;
        Line(Point a_, Point b_) : a(a_), b(b_) { assert(a_ != b_); };
        // Ax+By=C
        Line(D A, D B, D C){
            if(equal(A, 0)){
                a = Point(0, C/B), b = Point(1, C/B);
            }else if(equal(B, 0)){
                b = Point(C/A, 0), a = Point(C/A, 1);
            }else{
                a = Point(0, C/B), b = Point(C/A, 0);
            }
        }
    };

    // 線分（Line と同じ）
    struct Segment : Line {
        Segment() = default;
        Segment(Point a_, Point b_) : Line(a_, b_) {};
    };


    // 射影：直線（線分）に 点p から引いた垂線の足を求める
    Point projection(Line l, Point p){
        D t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
        return l.a + (l.a - l.b) * t;
    }
    Point projection(Segment l, Point p){
        D t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
        return l.a + (l.a - l.b) * t;
    }

    // 反射：直線を対象軸として 点p と線対称の位置にある点を求める
    Point reflection(Line l, Point p){
        return p + (projection(l, p)-p) * 2.0;
    }

    // 3点 a, b, c の位置関係
    // reference: https://sen-comp.hatenablog.com/entry/2020/03/12/145742#iSP3%E7%82%B9%E3%81%AE%E4%BD%8D%E7%BD%AE%E9%96%A2%E4%BF%82
    int ccw(Point a, Point b, Point c){
        b -= a, c -= a;
        // 点 a, b, c が
        if(cross(b, c) >  EPS) return  1; // 反時計回りのとき
        if(cross(b, c) < -EPS) return -1; // 時計回りのとき
        
        // 同一直線上にある場合
        if(dot(b, c) < 0) return 2;      // c, a, b の順
        if(norm(b) < norm(c)) return -2; // a, b, c の順
        return 0;                        // a, c, b の順
    }
    
    // 垂直（内積 == 0）
    bool is_vertical(Line a, Line b){
        return equal(dot(a.b - a.a, b.b - b.a), 0);
    }

    // 平行（外積 == 0）
    bool is_parallel(Line a, Line b){
        return equal(cross(a.b - a.a, b.b - b.a), 0);
    }

    // 線分の交差判定（線分 s に対して, 線分 t の端点が反対側にあればよい）
    bool is_intersect(Segment s, Segment t){
        return (ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0) && 
               (ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0);
    }

    // 交点（交差する前提）
    Point cross_point(Line s, Line t){
        D d1 = cross(s.b - s.a, t.b - t.a);
        D d2 = cross(s.b - s.a, s.b - t.a);
        // s, t が一致する場合（適当な１点を返す）
        if(equal(abs(d1), 0) && equal(abs(d2), 0)) return t.a; 
        
        return t.a + (t.b - t.a) * (d2/d1);
    }
    Point cross_point(Segment s, Segment t) {
        assert(is_intersect(s, t)); // 交差する前提
        return cross_point(Line(s), Line(t));
    }

    // 線分と点の距離（点p から線分のどこかへの最短距離）
    D dist_segment_point(Segment l, Point p){
        if(dot(l.b - l.a, p - l.a) < EPS) abs(p - l.a);
        if(dot(l.a - l.b, p - l.b) < EPS) abs(p - l.b);
        return abs(cross(l.b - l.a, p - l.a)) / abs(l.b - l.a);
    }
    // 線分と線分の距離
    D dist_segment_segment(Segment s, Segment t){
        if(is_intersect(s, t)) return 0.0;
        D res = min({
            dist_segment_point(s, t.a),
            dist_segment_point(s, t.b),
            dist_segment_point(t, s.a),
            dist_segment_point(t, s.b),
        });
        return res;
    }

    // Todo : 円, 多角形
};
using namespace geometry;


int main(){
    while(1){
        int n; cin >> n;
        if(n == 0) return 0;
        int ans = n+1;
        vector<Line> lines;
        rep(i, 0, n){
            Point p1, p2; cin >> p1 >> p2;
            Line newl(p1, p2);
            vector<Point> points;
            for(auto l: lines){
                if(is_parallel(l, newl)) continue;
                Point crossp = cross_point(l, newl);
                if(abs(crossp.imag())>=100-1e-10 || abs(crossp.real())>=100-1e-10) continue;
                bool flg = true;
                for(auto p:points){
                    if(abs(p-crossp) <= 1e-10){
                        flg = false;
                        break;
                    }
                }
                if(flg) ans++;
                points.push_back(crossp);
            }
            lines.push_back(newl);
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 3476
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;
namespace geometry
{
    using ld=long double;
    const double EPS=1e-8;
    const double PI=acos(-1);
    const double INF_DOUBLE=DBL_MAX;
    bool same(double a, double b){return abs(a-b)<EPS;}
    struct point
    {
        double x,y;
        point()=default;
        point(double x, double y):x(x),y(y){}

        double norm(){return sqrt(x*x+y*y);}
        double arg(){return atan2(y,x);}
        double arg(point p, point q) // *this=Oとして∠POQを[0,π]で返す
        {
            p-=*this,q-=*this;
            double res=abs(p.arg()-q.arg());
            if(res>PI+EPS)res=2*PI-res;
            return res;
        }
        double operator*(const point& p){return x*p.x+y*p.y;} // 内積を求める
        double operator^(const point& p){return x*p.y-y*p.x;} // 外積を求める

        bool operator==(const point& p){return same(x,p.x)&&same(y,p.y);}
        bool operator!=(const point& p){return !same(x,p.x)||!same(y,p.y);}
        point operator+(const point& p){return point{x+p.x,y+p.y};}
        point operator-(const point& p){return point{x-p.x,y-p.y};}
        point operator*(const double& k){return point{x*k,y*k};}
        point operator/(const double& k){return point{x/k,y/k};}
        point& operator+=(const point& p){return *this=(*this)+p;}
        point& operator-=(const point& p){return *this=(*this)-p;}
        point& operator*=(const double& k){return *this=(*this)*k;}
        point& operator/=(const double& k){return *this=(*this)/k;}
        friend point operator*(double k, point p){return p*k;}
        void rotate(double theta) // theta回転する、thetaは弧度法
        {
            double x_=x*cos(theta)-y*sin(theta);
            double y_=x*sin(theta)+y*cos(theta);
            x=x_,y=y_;
        }
        int ccw(point q, point r) // this=:pを中心としてq,rとの位置関係
        {
            q-=*this,r-=*this;
            if((q^r)>EPS)return 1; // p,q,rが反時計回り
            if(-(q^r)>EPS)return -1; // p,q,rが時計回り
            if(-(q*r)>EPS)return 2; // r,p,qの順で同一直線上
            if(q.norm()<r.norm())return -2; // p,q,rの順で同一直線上
            return 0; // p,r,qの順で同一直線上
        }
    };
    ostream &operator<<(ostream& os, point p)
    {
        os << '(' << p.x << ',' << p.y << ')';
        return os;
    }
    const point INF_POINT=point(INF_DOUBLE,INF_DOUBLE);
    struct line // ax+by=cの形で持つ
    {
        double a,b,c;
        line()=default;
        line(double a, double b, double c):a(a),b(b),c(c){}
        // 2点
        line(point p, point q):a(q.y-p.y),b(p.x-q.x),c(p.x*q.y-p.y*q.x){}
        line(double a, point p):a(a),b(-1),c(a*p.x-p.y){} // 傾きと1点
        bool online(point p){return same(a*p.x+b*p.y,c);} // 点が線上にあるか
        // 代入
        double y(double x)
        {
            if(same(b,0))return INF_DOUBLE;
            return (c-a*x)/b;
        }
        double x(double y)
        {
            if(same(a,0))return INF_DOUBLE;
            return (c-b*y)/a;
        }
        point uni()
        {
            if(same(b,0)){return point(0,1);}
            point p(0,this->y(0)),q(1,this->y(1));
            return  (p-q)/(p-q).norm();
        }
        line normal(point p) // pを通りthisに垂直な直線
        {
            if(same(a,0))return line(1,0,p.x);
            if(same(b,0))return line(0,1,p.y);
            return line(b/a,p);
        }
        point crosspoint(line l) // 2直線の交点
        {
            if(same(a*l.b,b*l.a))return INF_POINT;
            double den=a*l.b-b*l.a;
            return point((c*l.b-b*l.c)/den,(a*l.c-c*l.a)/den);
        }
        point projection(point p) // pからthisに下した垂線の足
        {
            return this->crosspoint(this->normal(p));
        }
        point reflection(point p) // thisについてpと対称な点
        {
            point q=this->projection(p);
            return 2*q-p;
        }
        double dist(point p){return (p-this->projection(p)).norm();} // 点と直線の距離
        double angle(line l) // 2直線のなす角
        {
            
            if(same(a*l.a+b*l.b,0))return PI/2; // 直行
            if(same(a*l.b,b*l.a))return INF_DOUBLE; // 平行
            double tan=(a*l.b-b*l.a)/(a*l.a+b*l.b);
            if(-tan>EPS)tan=-tan;
            return atan(tan);
        }
    };
    struct segment
    {
        line l;
        point p,q;
        segment()=default;
        segment(point p, point q):l(line(p,q)),p(p),q(q){}
        bool cross(segment s) // 線分の交差判定
        {
            return p.ccw(q,s.p)*p.ccw(q,s.q)<=0&&s.p.ccw(s.q,p)*s.p.ccw(s.q,q)<=0;
        }
        point crosspoint(segment s) // 線部同士の交点
        {
            if(this->cross(s))return l.crosspoint(s.l);
            return INF_POINT;
        }
        double dist(point r) // 点と線分の距離
        {
            if((q-p)*(r-p)<EPS){return (r-p).norm();}
            if((p-q)*(r-q)<EPS){return (r-q).norm();}
            return l.dist(r);
        }
        double dist(segment s) // 線分同士の距離
        {
            if(this->cross(s)){return 0;}
            double res=this->dist(s.p);
            res=min(res,this->dist(s.q));
            res=min(res,s.dist(p));
            res=min(res,s.dist(q));
            return res;
        }
    };
    struct polygon
    {
        int n;
        vector<point>vertex;
        polygon()=default;
        polygon(vector<point>v):vertex(v),n(v.size()){}
        point operator[](int i){return vertex[i];}
        double area() // 面積
        {
            double res=vertex.back()^vertex[0];
            for(int i=1;i<n;i++)res+=vertex[i-1]^vertex[i];
            return res/2;
        }
        bool is_convex() // 凸性判定
        {
            int pre,cur,nxt;
            for(int i=1;i<=n;i++)
            {
                pre=i-1;
                cur=i%n;
                nxt=(i+1)%n;
                if(vertex[pre].ccw(vertex[cur],vertex[nxt])==-1){return 0;}
            }
            return 1;
        }
        int contain(point p)// 多角形に点が含まれているか、内部:2、辺上:1、外部:0
        {
            bool in=0;
            for(int i=0;i<n;i++)
            {
                point q=vertex[i]-p,r=vertex[(i+1)%n]-p;
                if(q.y>r.y)swap(q,r);
                if(q.y<EPS&&EPS<r.y&&-(q^r)>EPS)in=!in;
                if(same(q^r,0)&&(q*r)<=0)return 1;
            }
            return (in?2:0);
        }
        double diam() // 凸包の直径=最遠頂点対間距離
        {
            cout << "ok diam\n";
            int is=0,js=0;
            for(int i=1;i<n;i++)
            {
                cout << i << endl;
                if(vertex[i].y>vertex[is].y)is=i;
                if(vertex[i].y<vertex[js].y)js=i;
            }
            double res=(vertex[is]-vertex[js]).norm();
            int i,j,max_i,max_j;
            i=max_i=is;
            j=max_j=js;
            do
            {
                point pi=vertex[(i+1)%n]-vertex[i];
                point pj=vertex[(j+1)%n]-vertex[j];
                if((pi^pj)>EPS)j=(j+1)%n;
                else i=(i+1)%n;
                if((vertex[i]-vertex[j]).norm()>res)
                {
                    res=(vertex[i]-vertex[j]).norm();
                    max_i=i,max_j=j;
                }
            }while(i!=is||j!=js);
            return res;
        }
        void relabeling() // 最も下、最も左の頂点から
        {
            double min_x=INF_DOUBLE,min_y=INF_DOUBLE;
            int idx=0;
            for(int i=0;i<n;i++)
            {
                if(vertex[i].y<min_y)
                {
                    min_x=vertex[i].x;
                    min_y=vertex[i].y;
                    idx=i;
                }
                else if(same(vertex[i].y,min_y)&&vertex[i].x<min_x)
                {
                    min_x=vertex[i].x;
                    min_y=vertex[i].y;
                    idx=i;
                }
            }
            vector<point>tmp(n);
            for(int i=0;i<n;i++)tmp[i]=vertex[(idx+i)%n];
            vertex=tmp;
        }
    };
    polygon convex_hull(vector<point>v) // 凸包
    {
        int n=v.size(),k=0;
        sort(v.begin(),v.end(),[](const point& p, const point& q)
        {
            return p.x!=q.x?p.x<q.x:p.y<q.y;
        });
        vector<point>ch(2*n);
        for(int i=0;i<n;ch[k++]=v[i++])
        {
            // 同一直線上の点を含めないときは上、含めるときは下
            // while(k>=2&&((ch[k-1]-ch[k-2])^(v[i]-ch[k-1]))<EPS)k--;
            while(k>=2&&-((ch[k-1]-ch[k-2])^(v[i]-ch[k-1]))>EPS)k--;
        }
        for(int i=n-2,t=k+1;i>=0;ch[k++]=v[i--])
        {
            // while(k>=2&&((ch[k-1]-ch[k-2])^(v[i]-ch[k-1]))<EPS)k--;
            while(k>=2&&-((ch[k-1]-ch[k-2])^(v[i]-ch[k-1]))>EPS)k--;
        }
        ch.resize(k-1);
        return polygon(ch);
    }
    double closest_pair(vector<point> v) // 最近点対をO(N(logN)^2)で求める
    {
        sort(v.begin(),v.end(),[](const point& p, const point& q)
        {
            return p.x<q.x;
        });
        auto rec=[&](const auto& rec, int l, int r) -> double
        {
            if(r-l<=1)return INF_DOUBLE;
            int m=(r+l)/2;
            double x=v[m].x;
            double d=min(rec(rec,l,m),rec(rec,m,r));
            inplace_merge(v.begin()+l,v.begin()+m,v.begin()+r,[&](const point& p, const point& q)
            {
                return p.y<q.y;
            });
            vector<point>v_;
            for(int i=l;i<r;i++)
            {
                if(d-abs(v[i].x-x)<=EPS)continue;
                for(int j=v_.size()-1;j>=0;j--)
                {
                    if(d-abs(v[i].y-v_[j].y)<=EPS)break;
                    d=min(d,(v[i]-v_[j]).norm());
                }
                v_.push_back(v[i]);
            }
            return d;
        };
        return rec(rec,0,v.size());
    }
    struct circle
    {
        point p;
        double r;
        circle()=default;
        circle(point p, double r):p(p),r(r){}
        circle(point p_, point q_, point r_, bool in=0) // 三角形の外/内接円
        {
            if(in)
            {
                double a=(q_-r_).norm(),b=(r_-p_).norm(),c=(p_-q_).norm();
                p=a*p_+b*q_+c*r_;
                p/=(a+b+c);
                r=line(p_,q_).dist(p);
            }
            else
            {
                point pq=p_-q_,qr=q_-r_;
                double d=pq^qr;
                double tmp1=p_.norm()*p_.norm()-q_.norm()*q_.norm();
                double tmp2=q_.norm()*q_.norm()-r_.norm()*r_.norm();
                p=(0.5/d)*(tmp1*qr-tmp2*pq);
                swap(p.x,p.y);
                p.y=-p.y;
                r=(p-p_).norm();
            }
        }
        int count_common_tangent(circle c) // 共通接線の本数を返す
        {
            double d=(p-c.p).norm();
            if(d>r+c.r+EPS)return 4;
            if(same(d,r+c.r))return 3;
            if(same(d,abs(r-c.r)))return 1;
            if(d<abs(r-c.r)-EPS)return 0;
            return 2;
        }
        vector<point>crosspoint(line l) // 円と直線の交点
        {
            double d=l.dist(p);
            vector<point>res;
            if(d>r+EPS)return res;
            point h=l.projection(p);
            if(same(d,r))
            {
                res.push_back(h);
                return res;
            }
            point e=l.uni();
            double tmp=sqrt(r*r-d*d);
            res.push_back(h-tmp*e);
            res.push_back(h+tmp*e);
            return res;
        }
        vector<point>crosspoint(circle c) // 2円の交点
        {
            int t=this->count_common_tangent(c);
            double d=(p-c.p).norm();
            vector<point>res;
            if(t==0||t==4){return res;}
            if(t==3)
            {
                double s=r/(r+c.r);
                res.push_back(p+(c.p-p)*s);
                return res;
            }
            if(t==1)
            {
                if(c.r<r-EPS)res.push_back(p+(c.p-p)*(r/d));
                else res.push_back(c.p+(p-c.p)*(c.r/d));
                return res;
            }
            double a_=2*(p.x-c.p.x);
            double b_=2*(p.y-c.p.y);
            double c_=(p.x+c.p.x)*(p.x-c.p.x)+(p.y+c.p.y)*(p.y-c.p.y)+(r+c.r)*(c.r-r);
            return this->crosspoint(line(a_,b_,c_));
        }
        vector<point>tangent(point p_) // 点から引いた円の接点
        {
            double d=(p-p_).norm();
            if(d<r-EPS)return{};
            if(same(d,r))return{p_};
            return this->crosspoint(circle(p_,sqrt(d*d-r*r)));
        }
        vector<line> common_tangent(circle c) // 2円の共通接線
        {
            int t=this->count_common_tangent(c);
            double d=(p-c.p).norm();
            vector<line>res;
            if(t==0)return res;
            if(t==1)
            {
                point q=(this->crosspoint(c))[0];
                res.push_back(line(p,q).normal(q));
            }
            if(t==2)
            {
                //
            }
        }
    };
}
using namespace geometry;
bool solve()
{
    int N;
    cin>>N;
    if(N==0)return 0;
    vector<segment>lines(N);
    int ans=1;
    for(int i=0;i<N;i++)
    {
        point P,Q;
        cin>>P.x>>P.y>>Q.x>>Q.y;
        lines[i]=segment(P,Q);
        int cnt=1;
        vector<point>CP;
        for(int j=0;j<i;j++)
        {
            if(!lines[i].cross(lines[j]))continue;
            auto X=lines[i].crosspoint(lines[j]);
            if(same(X.x,100))continue;
            if(same(X.x,-100))continue;
            if(same(X.y,100))continue;
            if(same(X.y,-100))continue;
            if([&]
            {
                for(auto Y:CP)if(same(X.x,Y.x)&&same(X.y,Y.y))return 0;
                return 1;
            }())CP.push_back(X);
        }
        ans+=CP.size()+1;
    }
    cout<<ans<<'\n';
    return 1;
}
int main(){while(solve()){}}
accuracy: 1
time_ms: 10
memory_kb: 3456
final_rank: 11

code_snippet: // (⁠◕⁠ᴗ⁠◕⁠✿⁠)

// #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define srep(i, s, n) for (ll i = s; i < (n); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
using namespace std;
template<typename T> using vc = vector<T>;
template<typename T> using vv = vc<vc<T>>;
template<typename T> using vvv = vv<vc<T>>;
using vi = vc<int>;using vvi = vv<int>; using vvvi = vv<vi>;
using ll = long long;using vl = vc<ll>;using vvl = vv<ll>; using vvvl = vv<vl>;
using ld = long double; using vld = vc<ld>; using vvld = vc<vld>; using vvvld = vc<vvld>;
using uint = unsigned int;
using ull = unsigned long long;
const ld pi = 3.141592653589793;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
// const ll mod = 1000000007;
const ll mod = 998244353;
inline bool inside(ll y, ll x, ll H, ll W) {return 0 <= (y) and (y) < (H) and 0 <= (x) and (x) < (W); }

#define debug(var)  do{std::cout << #var << " : \n";view(var);}while(0)
template<typename T> void view(T e){cout << e << endl;}
template<typename T> void view(const vc<T>& v){for(const auto& e : v){ cout << e << " "; } cout << endl;}

using P = complex<ld>;
ld eps = 1e-10;
ll solve(int N){
    vc<P> S(N), T(N); rep(i, N){
        ld a, b, c, d; cin >> a >> b >> c >> d;
        S[i] = {a, b};
        T[i] = {c, d};
    }
    ll ans = 1;
    auto cross = [&](P a, P b){return (conj(a) * b).imag();};
    rep(i, N){
        vc<P> point;
        ll cnt = 0;
        rep(j, i){
            P iv = T[i] - S[i];
            P jv = T[j] - S[j];
            if (abs(cross(iv, jv)) < eps) continue;
            P a = S[i] + iv * cross(jv, S[j] - S[i]) / cross(jv, iv);
            if (abs(a.real()) - 100 > -eps || abs(a.imag()) - 100 > -eps) continue;
            bool flag = true;
            rep(x, len(point)) if (abs(a.real() - point[x].real()) < eps && abs(a.imag() - point[x].imag()) < eps){
                flag = false;
                break;
            }
            if (flag){
                cnt++;
                point.push_back(a);
            }
        }
        ans += cnt + 1;
    }
    return ans;
}

int main(){
    vc<ll> ans;
    while (true){
        int N; cin >> N;
        if (N == 0) break;
        ans.push_back(solve(N));
    }
    for (auto x : ans) cout << x << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3412
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<ll, ll>;
#define rep(i, a, b) for(ll i = a; i < b; ++i)
#define rrep(i, a, b) for(ll i = a; i >= b; --i)
constexpr ll inf = 4e18;
struct SetupIO {
    SetupIO() {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout << fixed << setprecision(30);
    }
} setup_io;
using Real = long double;
const Real EPS = 1e-10, PI = acos(Real(-1.0));
int sign(const Real& r) {
    if(r <= -EPS) return -1;
    if(r >= +EPS) return +1;
    return 0;
}
bool eq(const Real& a, const Real& b) {
    return sign(a - b) == 0;
}
using Point = complex<Real>;
istream& operator>>(istream& is, Point& p) {
    Real a, b;
    is >> a >> b;
    p = Point(a, b);
    return is;
}
ostream& operator<<(ostream& os, const Point& p) {
    return os << p.real() << " " << p.imag();
}
Point operator*(const Point& p, const Real& d) {
    return Point(p.real() * d, p.imag() * d);
}
Point operator/(const Point& p, const Real& d) {
    return Point(p.real() / d, p.imag() / d);
}
Point rot(const Point& p, Real theta) {
    return p * Point(cos(theta), sin(theta));
}
Real dot(const Point& p1, const Point& p2) {
    return (conj(p1) * p2).real();
}
Real cross(const Point& p1, const Point& p2) {
    return (conj(p1) * p2).imag();
}
Real dist(const Point& p1, const Point& p2) {
    return abs(p1 - p2);
}
bool comp_x(const Point& p1, const Point& p2) {
    return eq(p1.real(), p2.real()) ? p1.imag() < p2.imag() : p1.real() < p2.real();
}
bool comp_y(const Point& p1, const Point& p2) {
    return eq(p1.imag(), p2.imag()) ? p1.real() < p2.real() : p1.imag() < p2.imag();
}
bool comp_arg(const Point& p1, const Point& p2) {
    return arg(p1) < arg(p2);
}
int ccw(const Point& a, Point b, Point c) {
    b -= a;
    c -= a;
    if(sign(cross(b, c)) == 1) return 1;
    if(sign(cross(b, c)) == -1) return -1;
    if(sign(dot(b, c)) == -1) return +2;
    if(norm(b) < norm(c)) return -2;
    return 0;
}
Real closest_pair(vector<Point> ps) {
    if((int)ps.size() <= 1) return 1e18;
    sort(ps.begin(), ps.end(), comp_x);
    vector<Point> memo(ps.size());
    auto func = [&](auto& func, int l, int r) -> Real {
        if(r - l <= 1) return 1e18;
        int m = (l + r) >> 1;
        Real x = ps[m].real();
        Real res = min(func(func, l, m), func(func, m, r));
        inplace_merge(ps.begin() + l, ps.begin() + m, ps.begin() + r, comp_y);
        int cnt = 0;
        for(int i = l; i < r; ++i) {
            if(abs(ps[i].real() - x) >= res) continue;
            for(int j = 0; j < cnt; ++j) {
                Point d = ps[i] - memo[cnt - j - 1];
                if(d.imag() >= res) break;
                res = min(res, abs(d));
            }
            memo[cnt++] = ps[i];
        }
        return res;
    };
    return func(func, 0, (int)ps.size());
}
struct Line {
    Point a, b;
    Line() = default;
    Line(const Point& a, const Point& b)
        : a(a), b(b) {}
};
using Segment = Line;
bool is_parallel(const Line& a, const Line& b) {
    return eq(cross(a.b - a.a, b.b - b.a), 0.0);
}
bool is_orthogonal(const Line& a, const Line& b) {
    return eq(dot(a.b - a.a, b.b - b.a), 0.0);
}
Point projection(const Line& l, const Point& p) {
    Real t = dot(p - l.a, l.b - l.a) / norm(l.b - l.a);
    return l.a + (l.b - l.a) * t;
}
Point reflection(const Line& l, const Point& p) {
    return p + (projection(l, p) - p) * 2.0;
}
bool is_intersect_lp(const Line& l, const Point& p) {
    return abs(ccw(l.a, l.b, p)) != 1;
}
bool is_intersect_sp(const Segment& s, const Point& p) {
    return ccw(s.a, s.b, p) == 0;
}
bool is_intersect_ll(const Line& l1, const Line& l2) {
    if(!eq(cross(l1.b - l1.a, l2.b - l2.a), 0.0)) return true;
    return eq(cross(l1.b - l1.a, l2.b - l1.a), 0.0);
}
bool is_intersect_ls(const Line& l, const Segment& s) {
    return sign(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a)) <= 0;
}
bool is_intersect_sl(const Segment& s, const Line& l) {
    return is_intersect_ls(l, s);
}
bool is_intersect_ss(const Segment& s1, const Segment& s2) {
    if(ccw(s1.a, s1.b, s2.a) * ccw(s1.a, s1.b, s2.b) > 0) return false;
    return ccw(s2.a, s2.b, s1.a) * ccw(s2.a, s2.b, s1.b) <= 0;
}
vector<Point> intersection_ll(const Line& l1, const Line& l2) {
    vector<Point> res;
    if(!is_intersect_ll(l1, l2)) return res;
    Real a = cross(l1.b - l1.a, l2.b - l2.a);
    Real b = cross(l1.b - l1.a, l1.b - l2.a);
    if(eq(a, 0.0) and eq(b, 0.0)) {
        res.push_back(l2.a);
    } else {
        res.push_back(l2.a + (l2.b - l2.a) * b / a);
    }
    return res;
}
vector<Point> intersection_ss(const Segment& s1, const Segment& s2) {
    return is_intersect_ss(s1, s2) ? intersection_ll(Line(s1), Line(s2)) : vector<Point>();
}
Real dist_lp(const Line& l, const Point& p) {
    return abs(p - projection(l, p));
}
Real dist_sp(const Segment& s, const Point& p) {
    Point h = projection(s, p);
    if(is_intersect_sp(s, h)) return abs(h - p);
    return min(abs(s.a - p), abs(s.b - p));
}
Real dist_ll(const Line& l1, const Line& l2) {
    if(is_intersect_ll(l1, l2)) return 0.0;
    return dist_lp(l1, l2.a);
}
Real dist_ss(const Segment& s1, const Segment& s2) {
    if(is_intersect_ss(s1, s2)) return 0.0;
    return min({dist_sp(s1, s2.a), dist_sp(s1, s2.b), dist_sp(s2, s1.a), dist_sp(s2, s1.b)});
}
Real dist_ls(const Line& l, const Segment& s) {
    if(is_intersect_ls(l, s)) return 0.0;
    return min(dist_lp(l, s.a), dist_lp(l, s.b));
}
Real dist_sl(const Segment& s, const Line& l) {
    return dist_ls(l, s);
}
int main(void) {
    while(1) {
        int n;
        cin >> n;
        if(n == 0) break;
        vector<Segment> s(n);
        int ans = 1;
        rep(i, 0, n) {
            Point p1, p2;
            cin >> p1 >> p2;
            Point dir = p2 - p1;
            s[i] = Segment(p1 + EPS * dir, p2 - EPS * dir);
            vector<Point> cs;
            rep(j, 0, i) {
                vector<Point> c = intersection_ss(s[i], s[j]);
                if(c.empty()) continue;
                bool flag = true;
                rep(k, 0, (int)cs.size()) {
                    if(eq(cs[k].real(), c[0].real()) and eq(cs[k].imag(), c[0].imag())) {
                        flag = false;
                    }
                }
                if(flag) {
                    cs.push_back(c[0]);
                }
            }
            ans += cs.size() + 1;
        }
        cout << ans << '\n';
    }
}
accuracy: 1
time_ms: 40
memory_kb: 3480
final_rank: 17

code_snippet: #include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <vector>
#include <set>

#define EPS 1e-10
#define F first
#define S second
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

struct P {
  double x, y;
  P(double x = 0, double y = 0) : x(x), y(y) {}
  P operator+(const P &p) const { return P(x + p.x, y + p.y); }
  P operator-(const P &p) const { return P(x - p.x, y - p.y); }
  bool operator<(const P &p) const {
    return x != p.x ? x < p.x : y < p.y;
  }
};

typedef pair<P, P> Segment;

double cross(const P &a, const P &b) { return a.x * b.y - a.y * b.x; }
double norm(const P &p) { return p.x * p.x + p.y * p.y; }
double dot(const P &a, const P &b) { return a.x * b.x + a.y * b.y; }

int ccw(const P &p, const P &q, const P &r) {
  P a = q - p;
  P b = r - p;
  if (cross(a, b) > EPS)
    return COUNTER_CLOCKWISE;
  if (cross(a, b) < -EPS)
    return CLOCKWISE;
  if (dot(a, b) < -EPS)
    return ONLINE_BACK;
  if (norm(a) < norm(b))
    return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool isIntersect(const P &p1, const P &p2, const P &p3, const P &p4) {
  return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
          ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0);
}

P crosspoint(const P &p1, const P &p2, const P &p3, const P &p4) {
  double A = cross(p2 - p1, p4 - p3);
  double B = cross(p2 - p1, p2 - p3) / A;
  return P(p3.x + (p4.x - p3.x) * B, p3.y + (p4.y - p3.y) * B);
}

int main() {
  int n;
  vector<Segment> pos;
  Segment pesh;

  while (cin >> n && n) {
    int field = 1;
    pos.clear();
    for (int i = 0; i < n; i++) {
      cin >> pesh.F.x >> pesh.F.y >> pesh.S.x >> pesh.S.y;
      pos.push_back(pesh);
      set<P> exist;
      int x_counter = 0;
      for (int j = 0; j < pos.size() - 1; j++) {
        if (isIntersect(pos[j].F, pos[j].S, pos[pos.size() - 1].F,
                        pos[pos.size() - 1].S)) {
          P xp = crosspoint(pos[j].F, pos[j].S, pos[pos.size() - 1].F,
                          pos[pos.size() - 1].S);
          if (100 - fabs(xp.x) < EPS || 100 - fabs(xp.y) < EPS)
            continue;
          if (exist.insert(xp).second) {
            x_counter++;
          }
        }
      }
      field += x_counter + 1;
    }
    cout << field << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3064
final_rank: 4

code_snippet: #line 1 "2009.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/2009"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Template/IOSetting.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/Template/TypeAlias.hpp"

#include <cstdint>
#include <cstddef>

namespace zawa {

using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;

using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;

using usize = std::size_t;

} // namespace zawa
#line 4 "/home/zawatin/compro/cp-documentation/Src/Template/IOSetting.hpp"

#include <iostream>
#include <iomanip>

namespace zawa {

void SetFastIO() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
}

void SetPrecision(u32 dig) {
    std::cout << std::fixed << std::setprecision(dig);
}

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Point.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Real.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Real.hpp"

#include <cmath>
#include <cassert>

namespace zawa {

namespace geometryR2 {

using Real = long double;
constexpr Real EPS{1e-12};

namespace internal {

constexpr i32 negative{-1};
constexpr i32 zero{};
constexpr i32 positive{1};

} // namespace internal

constexpr i32 Sign(Real value) {
    if (value < -EPS) return internal::negative;
    if (value > EPS) return internal::positive;
    return internal::zero;
}

constexpr bool Zero(Real value) {
    return Sign(value) == internal::zero;
}

constexpr bool Positive(Real value) {
    return Sign(value) == internal::positive;
}

constexpr bool Negative(Real value) {
    return Sign(value) == internal::negative;
}

constexpr bool Equal(Real a, Real b) {
    return Zero(a - b);
}

constexpr bool Smaller(Real a, Real b) {
    return Negative(a - b);
}

constexpr bool Bigger(Real a, Real b) {
    return Positive(a - b);
}

constexpr Real Square(Real value) {
    return (Zero(value) ? value : value * value);
}

constexpr Real Sqrt(Real value) {
    assert(!Negative(value));
    return (Zero(value) ? value : sqrtl(value));
}

constexpr Real Abs(Real value) {
    return (Negative(value) ? -value : value);
}

} // namespace geometryR2
 
} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Angle.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Angle.hpp"

#line 6 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Angle.hpp"

namespace zawa {

namespace geometryR2 {

constexpr Real PI{acosl(-1)};
constexpr Real TAU{static_cast<Real>(2) * PI};

constexpr Real ArcToRadian(Real arc) {
    return (arc * PI) / static_cast<Real>(180);
}

constexpr Real RadianToArc(Real radian) {
    return (radian * static_cast<Real>(180)) / PI;
}

} // namespace geometryR2

} // namespace zawa
#line 5 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Point.hpp"

#line 9 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Point.hpp"

namespace zawa {

namespace geometryR2 {

class Point {
private:
    Real x_{}, y_{};
public:
    /* constructor */
    Point() = default;
    Point(Real x, Real y) : x_{x}, y_{y} {}

    /* getter, setter */
    Real x() const {
        return x_;
    }
    Real& x() {
        return x_;
    }
    Real y() const {
        return y_;
    }
    Real& y() {
        return y_;
    }

    /* operator */
    Point& operator+=(const Point& rhs) {
        x_ += rhs.x();
        y_ += rhs.y();
        return *this;
    }
    friend Point operator+(const Point& lhs, const Point& rhs) {
        return Point{lhs} += rhs;
    }
    Point operator+() const {
        return *this;
    }
    Point& operator-=(const Point& rhs) {
        x_ -= rhs.x();
        y_ -= rhs.y();
        return *this;
    }
    friend Point operator-(const Point& lhs, const Point& rhs) {
        return Point{lhs} -= rhs;
    }
    Point operator-() const {
        return Point{} - *this;
    }
    Point& operator*=(Real k) {
        x_ *= k;
        y_ *= k;
        return *this;
    }
    friend Point operator*(Real k, const Point& p) {
        return Point{p} *= k;
    }
    friend Point operator*(const Point& p, Real k) {
        return Point{p} *= k;
    }
    Point& operator/=(Real k) {
        assert(!Zero(k));
        x_ /= k;
        y_ /= k;
        return *this;
    }
    friend Point operator/(Real k, const Point& p) {
        return Point{p} /= k;
    }
    friend Point operator/(const Point& p, Real k) {
        return Point{p} /= k;
    }
    friend bool operator==(const Point& lhs, const Point& rhs) {
        return Equal(lhs.x(), rhs.x()) and Equal(lhs.y(), rhs.y());
    }
    friend bool operator!=(const Point& lhs, const Point& rhs) {
        return !Equal(lhs.x(), rhs.x()) or !Equal(lhs.y(), rhs.y());
    }
    friend bool operator<(const Point& lhs, const Point& rhs) {
        return Smaller(lhs.x(), rhs.x()) or 
            (Equal(lhs.x(), rhs.x()) and Smaller(lhs.y(), rhs.y()));
    }
    friend bool operator<=(const Point& lhs, const Point& rhs) {
        return Smaller(lhs.x(), rhs.x()) or 
            (Equal(lhs.x(), rhs.x()) and (Smaller(lhs.y(), rhs.y()) or Equal(lhs.y(), rhs.y())));
    }
    friend bool operator>(const Point& lhs, const Point& rhs) {
        return Bigger(lhs.x(), rhs.x()) or
            (Equal(lhs.x(), rhs.x()) and Bigger(lhs.y(), rhs.y()));
    }
    friend bool operator>=(const Point& lhs, const Point& rhs) {
        return Bigger(lhs.x(), rhs.x()) or
            (Equal(lhs.x(), rhs.x()) and (Bigger(lhs.y(), rhs.y()) or Equal(lhs.y(), rhs.y())));
    }
    friend std::istream& operator>>(std::istream& is, Point& p) {
        is >> p.x_ >> p.y_;
        return is;
    }
    friend std::ostream& operator<<(std::ostream& os, const Point& p) {
        os << '(' << p.x_ << ',' << p.y_ << ')';
        return os;
    }
    
    /* member function */
    Real normSquare() const {
        return Square(x_) + Square(y_);
    }
    Real norm() const {
        return Sqrt(normSquare());
    }
    void normalize() {
        assert((*this) != Point{});
        (*this) /= norm(); 
    }
    Point normalized() const {
        Point res{*this};
        res.normalize();
        return res;
    }
    Point rotated(Real radian) const {
        return Point{
            x_ * cosl(radian) - y_ * sinl(radian),
            x_ * sinl(radian) + y_ * cosl(radian)
        };
    }
    void rotate(Real radian) {
        *this = rotated(radian); 
    }
    Point rotatedByArc(Real arc) const {
        return rotated(ArcToRadian(arc));
    }
    void rotateByArc(Real arc) {
        *this = rotatedByArc(arc);
    }
    Real argument() const {
        return (Negative(y_) ? TAU : static_cast<Real>(0)) + atan2l(y_, x_);
    }
    Real argumentByArc() const {
        return RadianToArc(argument());
    }

    /* friend function */
    friend Real Dot(const Point& lhs, const Point& rhs) {
        return lhs.x() * rhs.x() + lhs.y() * rhs.y();
    }
    friend Real Cross(const Point& lhs, const Point& rhs) {
        return lhs.x() * rhs.y() - lhs.y() * rhs.x();
    }
    friend Real Argument(const Point& lhs, const Point& rhs) {
        return rhs.argument() - lhs.argument();
    }
    friend bool ArgComp(const Point& lhs, const Point& rhs) {
        return Smaller(lhs.argument(), rhs.argument());
    }
};

using Vector = Point;

} // namespace geometryR2

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Polygon.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Relation.hpp"

#line 5 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Relation.hpp"

namespace zawa {

namespace geometryR2 {

enum RELATION {
    // p0 -> p1 -> p2の順で直線上に並んでいる
    ONLINE_FRONT = -2,
    // (p1 - p0) -> (p2 - p0)が時計回りになっている
    CLOCKWISE,
    // p0 -> p2 -> p1の順で直線上に並んでいる
    ON_SEGMENT,
    // (p1 - p0) -> (p2 - p0)が反時計回りになっている
    COUNTER_CLOCKWISE,
    // p2 -> p0 -> p1、またはp1 -> p0 -> p2の順で直線上に並んでいる
    ONLINE_BACK
};

RELATION Relation(const Point& p0, const Point& p1, const Point& p2) {
    Point a{p1 - p0}, b{p2 - p0};
    if (Positive(Cross(a, b))) return COUNTER_CLOCKWISE;
    if (Negative(Cross(a, b))) return CLOCKWISE;
    if (Negative(Dot(a, b))) return ONLINE_BACK;
    if (Smaller(a.normSquare(), b.normSquare())) return ONLINE_FRONT;
    return ON_SEGMENT;
};

} // namespace geometryR2

} // namespace zawa
#line 7 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Polygon.hpp"

#include <algorithm>
#line 10 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Polygon.hpp"
#include <vector>

namespace zawa {

namespace geometryR2 {

class Polygon {
private:
    std::vector<Point> data_;
public:
    /* member */
    usize size() const {
        return data_.size();
    }

    /* constructor */
    Polygon() = default;
    Polygon(const Polygon& polygon) : data_{polygon.data_} {}
    Polygon(const std::vector<Point>& data) : data_{data} {}
    Polygon(usize n) : data_{n} {
        assert(n >= static_cast<usize>(3));
    }

    /* operator[] */
    Point& operator[](usize i) {
        assert(i < size());
        return data_[i];
    }
    const Point& operator[](usize i) const {
        assert(i < size());
        return data_[i];
    }
    Polygon& operator=(const Polygon& polygon) {
        data_ = polygon.data_;
        return *this;
    }
    friend std::istream& operator>>(std::istream& is, Polygon& polygon) {
        for (size_t i{} ; i < polygon.size() ; i++) {
            is >> polygon[i];
        }
        return is;
    }
    friend std::ostream& operator<<(std::ostream& os, const Polygon& polygon) {
        for (usize i{} ; i < polygon.size() ; i++) {
            std::cout << polygon[i] << (i + 1 == polygon.size() ? "" : " ");
        }
        return os;
    }

    /* member function */
    void orderRotate(usize i) {
        assert(i < size());
        std::rotate(data_.begin(), data_.begin() + i, data_.end());
    }
    void headMinimize() {
        auto index{std::distance(data_.begin(), std::min_element(data_.begin(), data_.end()))};
        orderRotate(index);
    }
    bool isConvex() const {
        assert(size() >= static_cast<usize>(3));
        for (usize i{} ; i < size() ; i++) {
            if (Relation(data_[i], data_[i+1==size()?0:i+1], data_[i+2>=size()?i+2-size():i+2])
                    == CLOCKWISE) {
                return false;
            }
        }
        return true;
    }
    Real area() const {
        assert(size() >= static_cast<usize>(3));
        Real res{};
        for (usize i{1} ; i < size() ; i++) {
            res += Cross(data_[i] - data_[0], data_[i+1==size()?0:i+1] - data_[0]);
        }
        return res / static_cast<Real>(2);
    }
    void pushBack(const Point& p) {
        data_.push_back(p);
    }
    void emplaceBack(Real x, Real y) {
        data_.emplace_back(x, y);
    }
};

} // namespace geometryR2

} // namespace zawa

#line 2 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Line.hpp"

#line 5 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Line.hpp"

#line 7 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Line.hpp"

namespace zawa {

namespace geometryR2 {

class Line {
private:
    Point p0_{}, p1_{};
public:
    /* constructor */
    Line() = default;
    Line(const Point& p0, const Point& p1) : p0_{p0}, p1_{p1} {}
    // y = ax + b 
    Line(Real a, Real b) : p0_{static_cast<Real>(0), b}, p1_{static_cast<Real>(1), a + b} {}

    /* getter, setter */
    const Point& p0() const {
        return p0_;
    }
    Point& p0() {
        return p0_;
    }
    const Point& p1() const {
        return p1_;
    }
    Point& p1() {
        return p1_;
    }

    /* operator */
    friend bool operator==(const Line& l0, const Line& l1) {
        return Zero(Cross(l0.p1() - l0.p0(), l1.p1() - l1.p0())) and Zero(Cross(l0.p1() - l0.p0(), l1.p1() - l0.p0()));
    }
    friend bool operator!=(const Line& l0, const Line& l1) {
        return !Zero(Cross(l0.p1() - l0.p0(), l1.p1() - l1.p0())) or !Zero(Cross(l0.p1() - l0.p0(), l1.p1() - l0.p0()));
    }

    /* member function */
    bool valid() const {
        return p0_ != p1_;
    }
    Vector slope() const {
        assert(valid());
        return Vector{p1() - p0()}.normalized();
    }
};

} // namespace geometryR2

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Intersect/LineAndLine.hpp"

#line 4 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Intersect/LineAndLine.hpp"

#line 6 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Intersect/LineAndLine.hpp"

namespace zawa {

namespace geometryR2 {

bool Intersect(const Line& l0, const Line& l1) {
    assert(l0.valid());
    assert(l1.valid());
    if (!Zero(Cross(l0.p1() - l0.p0(), l1.p1() - l1.p0()))) {
        return true;
    }
    else if (!Zero(Cross(l0.p1() - l0.p0(), l1.p0() - l0.p0()))) {
        return false;
    }
    else {
        return true;
    }
}

} // namespace geometryR2

} // namespace 
#line 2 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/CrossPoint/LineAndLine.hpp"

#line 6 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/CrossPoint/LineAndLine.hpp"

#line 8 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/CrossPoint/LineAndLine.hpp"

namespace zawa {

namespace geometryR2 {

Point CrossPoint(const Line& l0, const Line& l1) {
    assert(l0.valid());
    assert(l1.valid());
    assert(Intersect(l0, l1));
    assert(l0 != l1);
    return l0.p0() + (l0.p1() - l0.p0()) * 
        (Cross(l1.p0() - l0.p0(), l1.p1() - l1.p0()) / Cross(l0.p1() - l0.p0(), l1.p1() - l1.p0()));
}

} // namespace geometryR2

} // namespace zawa
#line 2 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Contain/PolygonContainsPoint.hpp"

#line 2 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Contain/State.hpp"

namespace zawa {

namespace geometryR2 {

enum ContainState {
    INSIDE,
    ONLINE,
    OUTSIDE
};

} // namespace geometryR2

} // namespace zawa
#line 9 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Contain/PolygonContainsPoint.hpp"

#line 11 "/home/zawatin/compro/cp-documentation/Src/GeometryR2/Contain/PolygonContainsPoint.hpp"
#include <utility>

namespace zawa {

namespace geometryR2 {

ContainState PolygonContainsPoint(const Polygon& polygon, const Point& p) {
    usize n{polygon.size()};
    assert(n >= static_cast<usize>(3));
    bool odd{};
    for (usize i{} ; i < n ; i++) {
        if (polygon[i] == p) {
            return ONLINE;
        }
        if (Relation(polygon[i], polygon[i+1==n?0:i+1], p) == ON_SEGMENT) {
            return ONLINE;
        }
        Vector a{polygon[i] - p}, b{polygon[i+1==n?0:i+1] - p};
        if (Bigger(a.y(), b.y())) std::swap(a, b);
        odd ^= !Positive(a.y()) and Positive(b.y()) and Positive(Cross(a, b));
    }
    return (odd ? INSIDE : OUTSIDE);
}

} // namespace geometryR2

} // namespace zawa
#line 10 "2009.test.cpp"

#line 13 "2009.test.cpp"
#include <set>

using namespace zawa;
using namespace geometryR2;

bool contain(const Point& p) {
    static Polygon sq(4);
    sq[0] = Point{-100, -100};
    sq[1] = Point{100, -100};
    sq[2] = Point{100, 100};
    sq[3] = Point{-100, 100};
    return PolygonContainsPoint(sq, p) == INSIDE;
}

bool solve() {
    int n; std::cin >> n;
    if (n == 0) return false;
    std::vector<Line> l;
    l.reserve(n);
    int ans{1};
    for (int _{} ; _ < n ; _++) {
        Line a;
        std::cin >> a.p0() >> a.p1();
        std::set<Point> set;
        for (const auto line : l) {
            if (!Intersect(line, a)) continue;
            Point p{CrossPoint(line, a)};
            if (contain(p)) set.insert(p);
        }
        ans += set.size() + 1;
        l.push_back(a); 
    }
    std::cout << ans << '\n';
    return true;
}

int main() {
    SetFastIO();
    for (int i{} ; solve() ; i++) {

    }
}
accuracy: 1
time_ms: 30
memory_kb: 3400
final_rank: 16

code_snippet: #include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>

#define EPS 1e-10
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

struct P {
  double x, y;
  P(double x = 0, double y = 0) : x(x), y(y) {}

  P operator-(P p) const { return P(x - p.x, y - p.y); }
  bool operator==(const P &p) const { return fabs(x - p.x) < EPS && fabs(y - p.y) < EPS; }
};

typedef std::pair<P, P> Segment;

double cross(P a, P b) { return a.x * b.y - a.y * b.x; }
double dot(P a, P b) { return a.x * b.x + a.y * b.y; }
double norm(P p) { return p.x * p.x + p.y * p.y; }

int ccw(P p, P q, P r) {
  P a = q - p;
  P b = r - p;
  if (cross(a, b) > EPS) return COUNTER_CLOCKWISE;
  if (cross(a, b) < -EPS) return CLOCKWISE;
  if (dot(a, b) < -EPS) return ONLINE_BACK;
  if (norm(a) < norm(b)) return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool isIntersect(P p1, P p2, P p3, P p4) {
  return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 && ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0);
}

P crosspoint(P p1, P p2, P p3, P p4) {
  double A = cross(p2 - p1, p4 - p3);
  double B = cross(p2 - p1, p2 - p3);
  return P(p3.x + (p4.x - p3.x) * (B / A), p3.y + (p4.y - p3.y) * (B / A));
}

int main() {
  int n;
  while (std::cin >> n && n) {
    int field = 1;
    std::vector<Segment> pos;
    for (int i = 0; i < n; i++) {
      Segment pesh;
      std::cin >> pesh.first.x >> pesh.first.y >> pesh.second.x >> pesh.second.y;
      pos.push_back(pesh);
      std::vector<P> exist;
      int x_counter = 0;
      for (int i = 0; i < int(pos.size()) - 1; i++) {
        if (isIntersect(pos[i].first, pos[i].second, pos.back().first, pos.back().second)) {
          P xp = crosspoint(pos[i].first, pos[i].second, pos.back().first, pos.back().second);
          if (100 - fabs(xp.x) < EPS || 100 - fabs(xp.y) < EPS) continue;
          if (std::find(exist.begin(), exist.end(), xp) == exist.end()) {
            x_counter++;
            exist.push_back(xp);
          }
        }
      }
      field += x_counter + 1;
    }
    std::cout << field << '\n';
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3056
final_rank: 3

code_snippet: #include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <set>
#include <vector>
#define EPS 1e-10
#define F first
#define S second
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
using namespace std;
struct P {
  double x, y;
  P(double x = 0, double y = 0) : x(x), y(y) {}
  P operator+(P p) { return P(x + p.x, y + p.y); }
  P operator-(P p) { return P(x - p.x, y - p.y); }
  P operator*(P p) { return P(x * p.x, y * p.y); }
  P operator/(P p) { return P(x / p.x, y / p.y); }
  bool operator==(const P &p) const {
    return (fabs(x - p.x) < EPS && fabs(y - p.y) < EPS);
  }
  bool operator<(const P &p) const {
    return x != p.x ? fabs(x - p.x) < EPS : fabs(y - p.y) < EPS;
  }
};
typedef pair<P, P> Segment;
double dot(P a, P b) { return a.x * b.x + a.y * b.y; }
double cross(P a, P b) { return a.x * b.y - a.y * b.x; }
double norm(P p) { return p.x * p.x + p.y * p.y; }
double abs(P p) { return sqrt(norm(p)); }
int ccw(P p, P q, P r) {
  P a = q - p;
  P b = r - p;
  if (cross(a, b) > EPS)
    return COUNTER_CLOCKWISE;
  if (cross(a, b) < -EPS)
    return CLOCKWISE;
  if (dot(a, b) < -EPS)
    return ONLINE_BACK;
  if (norm(a) < norm(b))
    return ONLINE_FRONT;
  return ON_SEGMENT;
}
bool isIntersect(P p1, P p2, P p3, P p4) {
  return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
          ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0);
}
P crosspoint(P p1, P p2, P p3, P p4) {
  double A = cross(p2 - p1, p4 - p3);
  double B = cross(p2 - p1, p2 - p3);
  P pro = p4 - p3;
  pro.x = pro.x * (B / A);
  pro.y = pro.y * (B / A);
  return p3 + pro;
}
int main() {
  int n, xx, yy, xxx, yyy, field;
  vector<Segment> pos;
  Segment pesh;
  vector<P> exist;
  P xp;
  while (cin >> n && n) {
    field = 1;
    pos.clear();
    for (int i = 0; i < n; i++) {
      cin >> xx >> yy >> xxx >> yyy;
      pesh.F.x = xx;
      pesh.F.y = yy;
      pesh.S.x = xxx;
      pesh.S.y = yyy;
      pos.push_back(pesh);
      int x_counter = 0;
      bool new_x = true;
      exist.clear();
      for (int i = 0; i < pos.size() - 1; i++) {
        new_x = true;
        if (isIntersect(pos[i].F, pos[i].S, pos[pos.size() - 1].F,
                        pos[pos.size() - 1].S)) {
          xp = crosspoint(pos[i].F, pos[i].S, pos[pos.size() - 1].F,
                          pos[pos.size() - 1].S);
          if (100 - fabs(xp.x) < EPS || 100 - fabs(xp.y) < EPS)
            continue;
          for (int j = 0; j < exist.size(); j++) {
            if (exist[j] == xp) {
              new_x = false;
              break;
            }
          }
          if (new_x) {
            x_counter++;
            exist.push_back(xp);
          }
        }
      }
      field += x_counter + 1;
    }
    cout << field << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 2992
final_rank: 2

code_snippet: #include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <vector>
#define EPS 1e-10
#define F first
#define S second
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
using namespace std;
struct P {
  double x, y;
  P(double x = 0, double y = 0) : x(x), y(y) {}
  P operator+(P p) { return P(x + p.x, y + p.y); }
  P operator-(P p) { return P(x - p.x, y - p.y); }
  P operator*(P p) { return P(x * p.x, y * p.y); }
  P operator/(P p) { return P(x / p.x, y / p.y); }
  bool operator==(const P &p) const {
    return (fabs(x - p.x) < EPS && fabs(y - p.y) < EPS);
  }
  bool operator<(const P &p) const {
    return x != p.x ? fabs(x - p.x) < EPS : fabs(y - p.y) < EPS;
  }
};
typedef pair<P, P> Segment;
double dot(P a, P b) { return a.x * b.x + a.y * b.y; }
double cross(P a, P b) { return a.x * b.y - a.y * b.x; }
double norm(P p) { return p.x * p.x + p.y * p.y; }
double abs(P p) { return sqrt(norm(p)); }
int ccw(P p, P q, P r) {
  P a = q - p;
  P b = r - p;
  if (cross(a, b) > EPS)
    return COUNTER_CLOCKWISE;
  if (cross(a, b) < -EPS)
    return CLOCKWISE;
  if (dot(a, b) < -EPS)
    return ONLINE_BACK;
  if (norm(a) < norm(b))
    return ONLINE_FRONT;
  return ON_SEGMENT;
}
bool isIntersect(P p1, P p2, P p3, P p4) {
  return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
          ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0);
}
P crosspoint(P p1, P p2, P p3, P p4) {
  double A = cross(p2 - p1, p4 - p3);
  double B = cross(p2 - p1, p2 - p3);
  P pro = p4 - p3;
  pro.x = pro.x * (B / A);
  pro.y = pro.y * (B / A);
  return p3 + pro;
}
int main() {
  int n, xx, yy, xxx, yyy, field;
  vector<Segment> pos;
  Segment pesh;
  vector<P> exist;
  P xp;
  while (cin >> n && n) {
    field = 1;
    pos.clear();
    for (int i = 0; i < n; i++) {
      cin >> xx >> yy >> xxx >> yyy;
      pesh.F.x = xx;
      pesh.F.y = yy;
      pesh.S.x = xxx;
      pesh.S.y = yyy;
      pos.push_back(pesh);
      int x_counter = 0;
      bool new_x = true;
      exist.clear();
      for (int i = 0; i < pos.size() - 1; i++) {
        new_x = true;
        if (isIntersect(pos[i].F, pos[i].S, pos[pos.size() - 1].F,
                        pos[pos.size() - 1].S)) {
          xp = crosspoint(pos[i].F, pos[i].S, pos[pos.size() - 1].F,
                          pos[pos.size() - 1].S);
          if (100 - fabs(xp.x) < EPS || 100 - fabs(xp.y) < EPS)
            continue;
          for (int j = 0; j < exist.size(); j++) {
            if (exist[j] == xp) {
              new_x = false;
              break;
            }
          }
          if (new_x) {
            x_counter++;
            exist.push_back(xp);
          }
        }
      }
      field += x_counter + 1;
    }
    cout << field << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 2984
final_rank: 1

code_snippet: #include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <vector>
#define EPS 1e-10
#define F first
#define S second
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
using namespace std;
struct P {
  double x, y;
  P(double x = 0, double y = 0) : x(x), y(y) {}
  P operator+(P p) const { return P(x + p.x, y + p.y); }
  P operator-(P p) const { return P(x - p.x, y - p.y); }
  P operator*(P p) const { return P(x * p.x, y * p.y); }
  P operator/(P p) const { return P(x / p.x, y / p.y); }
  bool operator==(const P &p) const {
    return (fabs(x - p.x) < EPS && fabs(y - p.y) < EPS);
  }
  bool operator<(const P &p) const {
    return x != p.x ? x < p.x : y < p.y;
  }
};
typedef pair<P, P> Segment;
double dot(P a, P b) { return a.x * b.x + a.y * b.y; }
double cross(P a, P b) { return a.x * b.y - a.y * b.x; }
double norm(P p) { return p.x * p.x + p.y * p.y; }
double abs(P p) { return sqrt(norm(p)); }
int ccw(P p, P q, P r) {
  P a = q - p;
  P b = r - p;
  if (cross(a, b) > EPS)
    return COUNTER_CLOCKWISE;
  if (cross(a, b) < -EPS)
    return CLOCKWISE;
  if (dot(a, b) < -EPS)
    return ONLINE_BACK;
  if (norm(a) < norm(b))
    return ONLINE_FRONT;
  return ON_SEGMENT;
}
bool isIntersect(Segment s1, Segment s2) {
  return (ccw(s1.F, s1.S, s2.F) * ccw(s1.F, s1.S, s2.S) <= 0 &&
          ccw(s2.F, s2.S, s1.F) * ccw(s2.F, s2.S, s1.S) <= 0);
}
P crosspoint(Segment s1, Segment s2) {
  double A = cross(s1.S - s1.F, s2.S - s2.F);
  double B = cross(s1.S - s1.F, s1.S - s2.F);
  P pro = s2.S - s2.F;
  pro.x = pro.x * (B / A);
  pro.y = pro.y * (B / A);
  return s2.F + pro;
}
int main() {
  int n, xx, yy, xxx, yyy, field;
  vector<Segment> pos;
  Segment pesh;
  vector<P> exist;
  P xp;
  while (cin >> n && n) {
    field = 1;
    pos.clear();
    for (int i = 0; i < n; i++) {
      cin >> xx >> yy >> xxx >> yyy;
      pesh.F.x = xx;
      pesh.F.y = yy;
      pesh.S.x = xxx;
      pesh.S.y = yyy;
      pos.push_back(pesh);
      int x_counter = 0;
      bool new_x = true;
      exist.clear();
      for (int i = 0; i < pos.size() - 1; i++) {
        new_x = true;
        if (isIntersect(pos[i], pos.back())) {
          xp = crosspoint(pos[i], pos.back());
          if (100 - fabs(xp.x) < EPS || 100 - fabs(xp.y) < EPS) continue;
          if (find(exist.begin(), exist.end(), xp) != exist.end()) {
            new_x = false;
          }
          if (new_x) {
            x_counter++;
            exist.push_back(xp);
          }
        }
      }
      field += x_counter + 1;
    }
    cout << field << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3120
final_rank: 8

code_snippet: #include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <vector>
#define EPS 1e-10
#define F first
#define S second
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
using namespace std;
struct P {
  double x, y;
  P(double x = 0, double y = 0) : x(x), y(y) {}
  P operator+(P p) const { return P(x + p.x, y + p.y); }
  P operator-(P p) const { return P(x - p.x, y - p.y); }
  P operator*(P p) const { return P(x * p.x, y * p.y); }
  P operator/(P p) const { return P(x / p.x, y / p.y); }
  bool operator==(const P &p) const {
    return (fabs(x - p.x) < EPS && fabs(y - p.y) < EPS);
  }
  bool operator<(const P &p) const {
    return x != p.x ? x < p.x : y < p.y;
  }
};
typedef pair<P, P> Segment;
double dot(P a, P b) { return a.x * b.x + a.y * b.y; }
double cross(P a, P b) { return a.x * b.y - a.y * b.x; }
double norm(P p) { return p.x * p.x + p.y * p.y; }
double abs(P p) { return sqrt(norm(p)); }
int ccw(P p, P q, P r) {
  P a = q - p;
  P b = r - p;
  if (cross(a, b) > EPS)
    return COUNTER_CLOCKWISE;
  if (cross(a, b) < -EPS)
    return CLOCKWISE;
  if (dot(a, b) < -EPS)
    return ONLINE_BACK;
  if (norm(a) < norm(b))
    return ONLINE_FRONT;
  return ON_SEGMENT;
}
bool isIntersect(Segment s1, Segment s2) {
  return (ccw(s1.F, s1.S, s2.F) * ccw(s1.F, s1.S, s2.S) <= 0 &&
          ccw(s2.F, s2.S, s1.F) * ccw(s2.F, s2.S, s1.S) <= 0);
}
P crosspoint(Segment s1, Segment s2) {
  double A = cross(s1.S - s1.F, s2.S - s2.F);
  double B = cross(s1.S - s1.F, s1.S - s2.F);
  P pro = s2.S - s2.F;
  pro.x = pro.x * (B / A);
  pro.y = pro.y * (B / A);
  return s2.F + pro;
}
int main() {
  int n, xx, yy, xxx, yyy, field;
  vector<Segment> pos;
  Segment pesh;
  vector<P> exist;
  P xp;
  while (cin >> n && n) {
    field = 1;
    pos.clear();
    for (int i = 0; i < n; i++) {
      cin >> xx >> yy >> xxx >> yyy;
      pesh.F.x = xx;
      pesh.F.y = yy;
      pesh.S.x = xxx;
      pesh.S.y = yyy;
      pos.push_back(pesh);
      int x_counter = 0;
      bool new_x = true;
      exist.clear();
      for (int i = 0; i < pos.size() - 1; i++) {
        new_x = true;
        if (isIntersect(pos[i], pos.back())) {
          xp = crosspoint(pos[i], pos.back());
          if (fabs(100 - fabs(xp.x)) < EPS || fabs(100 - fabs(xp.y)) < EPS)
            continue;
          for (int j = 0; j < exist.size(); j++) {
            if (exist[j] == xp) {
              new_x = false;
              break;
            }
          }
          if (new_x) {
            x_counter++;
            exist.push_back(xp);
          }
        }
      }
      field += x_counter + 1;
    }
    cout << field << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3104
final_rank: 6

code_snippet: #include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <vector>
#define EPS 1e-10
#define F first
#define S second
#define COUNTER_CLOCKWISE 0
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
using namespace std;
struct P {
  double x, y;
  P(double x = 0, double y = 0) : x(x), y(y) {}
  P operator+(P p) { return P(x + p.x, y + p.y); }
  P operator-(P p) { return P(x - p.x, y - p.y); }
  P operator*(P p) { return P(x * p.x, y * p.y); }
  P operator/(P p) { return P(x / p.x, y / p.y); }
  bool operator==(const P &p) const {
    return (fabs(x - p.x) < EPS && fabs(y - p.y) < EPS);
  }
  bool operator<(const P &p) const {
    return x != p.x ? fabs(x - p.x) < EPS : fabs(y - p.y) < EPS;
  }
};
typedef pair<P, P> Segment;
double dot(P a, P b) { return a.x * b.x + a.y * b.y; }
double cross(P a, P b) { return a.x * b.y - a.y * b.x; }
double norm(P p) { return p.x * p.x + p.y * p.y; }
double abs(P p) { return sqrt(norm(p)); }
int ccw(P p, P q, P r) {
  P a = q - p;
  P b = r - p;
  if (cross(a, b) > EPS)
    return COUNTER_CLOCKWISE;
  if (cross(a, b) < -EPS)
    return CLOCKWISE;
  if (dot(a, b) < -EPS)
    return ONLINE_BACK;
  if (norm(a) < norm(b))
    return ONLINE_FRONT;
  return ON_SEGMENT;
}
bool isIntersect(P p1, P p2, P p3, P p4) {
  return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
          ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0);
}
P crosspoint(P p1, P p2, P p3, P p4) {
  double A = cross(p2 - p1, p4 - p3);
  double B = cross(p2 - p1, p2 - p3);
  P pro = p4 - p3;
  pro.x = pro.x * (B / A);
  pro.y = pro.y * (B / A);
  return p3 + pro;
}
int main() {
  int n, xx, yy, xxx, yyy, field;
  vector<Segment> pos;
  Segment pesh;
  vector<P> exist;
  P xp;
  while (cin >> n && n) {
    field = 1;
    pos.clear();
    for (int i = 0; i < n; i++) {
      cin >> xx >> yy >> xxx >> yyy;
      pesh.F.x = xx;
      pesh.F.y = yy;
      pesh.S.x = xxx;
      pesh.S.y = yyy;
      pos.push_back(pesh);
      int x_counter = 0;
      bool new_x = true;
      exist.clear();
      for (int i = 0; i < pos.size() - 1; i++) {
        new_x = true;
        if (isIntersect(pos[i].F, pos[i].S, pos[pos.size() - 1].F,
                        pos[pos.size() - 1].S)) {
          xp = crosspoint(pos[i].F, pos[i].S, pos[pos.size() - 1].F,
                          pos[pos.size() - 1].S);
          if (100 - fabs(xp.x) < EPS || 100 - fabs(xp.y) < EPS)
            continue;
          for (int j = 0; j < exist.size(); j++) {
            if (exist[j] == xp) {
              new_x = false;
              break;
            }
          }
          if (new_x) {
            x_counter++;
            exist.push_back(xp);
          }
        }
      }
      field += x_counter + 1;
    }
    cout << field << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3104
final_rank: 6

code_snippet: #include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <vector>
#define EPS 1e-9
#define F first
#define S second
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
using namespace std;
struct P {
  double x, y;
  P(double x = 0, double y = 0) : x(x), y(y) {}
  P operator+(P p) { return P(x + p.x, y + p.y); }
  P operator-(P p) { return P(x - p.x, y - p.y); }
  P operator*(P p) { return P(x * p.x, y * p.y); }
  P operator/(P p) { return P(x / p.x, y / p.y); }
  bool operator==(const P &p) const {
    return (fabs(x - p.x) < EPS && fabs(y - p.y) < EPS);
  }
  bool operator<(const P &p) const {
    return x != p.x ? fabs(x - p.x) < EPS : fabs(y - p.y) < EPS;
  }
};
typedef pair<P, P> Segment;
double dot(P a, P b) { return a.x * b.x + a.y * b.y; }
double cross(P a, P b) { return a.x * b.y - a.y * b.x; }
double norm(P p) { return p.x * p.x + p.y * p.y; }
double abs(P p) { return sqrt(norm(p)); }
int ccw(P p, P q, P r) {
  P a = q - p;
  P b = r - p;
  if (cross(a, b) > EPS)
    return COUNTER_CLOCKWISE;
  if (cross(a, b) < -EPS)
    return CLOCKWISE;
  if (dot(a, b) < -EPS)
    return ONLINE_BACK;
  if (norm(a) < norm(b))
    return ONLINE_FRONT;
  return ON_SEGMENT;
}
bool isIntersect(P p1, P p2, P p3, P p4) {
  return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
          ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0);
}
P crosspoint(P p1, P p2, P p3, P p4) {
  double A = cross(p2 - p1, p4 - p3);
  double B = cross(p2 - p1, p2 - p3);
  P pro = p4 - p3;
  pro.x = pro.x * (B / A);
  pro.y = pro.y * (B / A);
  return p3 + pro;
}
int main() {
  int n, xx, yy, xxx, yyy, field;
  vector<Segment> pos;
  Segment pesh;
  vector<P> exist;
  P xp;
  while (cin >> n && n) {
    field = 1;
    pos.clear();
    for (int i = 0; i < n; i++) {
      cin >> xx >> yy >> xxx >> yyy;
      pesh.F.x = xx;
      pesh.F.y = yy;
      pesh.S.x = xxx;
      pesh.S.y = yyy;
      pos.push_back(pesh);
      int x_counter = 0;
      bool new_x = true;
      exist.clear();
      for (int i = 0; i < pos.size() - 1; i++) {
        new_x = true;
        if (isIntersect(pos[i].F, pos[i].S, pos[pos.size() - 1].F,
                        pos[pos.size() - 1].S)) {
          xp = crosspoint(pos[i].F, pos[i].S, pos[pos.size() - 1].F,
                          pos[pos.size() - 1].S);
          if (100 - fabs(xp.x) < EPS || 100 - fabs(xp.y) < EPS)
            continue;
          for (int j = 0; j < exist.size(); j++) {
            if (exist[j] == xp) {
              new_x = false;
              break;
            }
          }
          if (new_x) {
            x_counter++;
            exist.push_back(xp);
          }
        }
      }
      field += x_counter + 1;
    }
    cout << field << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3084
final_rank: 5