import std.typecons;
import std.stdio;
T gcd(T)(T a, T b) {
	if (a % b == 0) return b;
	return gcd(b, a % b);
}
struct Rat(T) {
	import std.math : abs;
	T n, d;
	this(T n_, T d_) {
		if (d_ == 0) {
			n = 1;
			d = 0;
		} else if (n_ == 0) {
			d = 1;
			n = 0;
		} else {
			auto c = gcd(abs(n_), abs(d_));
			bool neg = (n_ < 0) ^ (d_ < 0);
			n = abs(n_ / c);
			d = abs(d_ / c);
			if (neg) {
				n = -n;
			}
		}
	}
	Rat!T opBinary(string op)(T o) if (op == "*"){
		if (d == 0) {
			return this;
		}
		return Rat!T(n * o, d);
	}
	Rat!T opBinary(string op)(T o) if (op == "/"){
		if (d == 0) {
			return this;
		}
		return Rat!T(n, d * o);
	}
	Rat!T opBinary(string op)(T o) if (op == "+"){
		if (d == 0) {
			return this;
		}
		return Rat!T(n + d * o, d);
	}
	bool opEqual(Rat!T o) {
		return n == o.n && d == o.d;
	}
}
int[2][50] points;
void main() {
	bool[Tuple!(Rat!long, Rat!long)] lines;
	int n;
	scanf("%d ", &n);

	foreach(i; 0..n) {
		scanf("%d %d ", &points[i][0], &points[i][1]);
	}

	debug writeln(points);

	foreach(i; 0..n) {
		foreach(j; 0..i) {
			auto t = Rat!long(points[i][1]-points[j][1], points[i][0]-points[j][0]);
			auto d = t.d ? (t * -points[i][0]) + points[i][1] : Rat!long(points[i][0], 1);
			debug writeln(t, d, t == d);
			lines[tuple(t, d)] = true;
		}
	}

	debug writeln(lines);
	int[Rat!long] tgroup;
	foreach(t, d; lines.byKey) {
		tgroup[t]++;
	}
	long ans = lines.length * (lines.length - 1) / 2;
	foreach(t; tgroup.byKey) {
		ans -= tgroup[t] * (tgroup[t]-1) / 2;
	}
	writeln(ans);
}
