#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <bitset>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>
using namespace std;
#define REP(i,n) for((i)=0;(i)<(int)(n);(i)++)
#define snuke(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
#define N 9
int xx[4],yy[4];
int x[4],y[4];
bool is_concyclic(void){
int sum = 0;
int i;
REP(i,3) sum += (x[i] * x[i] + y[i] * y[i]) * (x[(i+1)%3] * y[(i+2)%3] - x[(i+2)%3] * y[(i+1)%3]);
return (sum == 0);
}
bool is_colinear(void){
int i;
for(i=1;i<=2;i++) if(x[i] * y[0] != x[0] * y[i]) return false;
return true;
}
bool is_isosceles(void){
int i;
REP(i,3){
int dx1 = x[1] - x[0];
int dx2 = x[3] - x[2];
int dy1 = y[1] - y[0];
int dy2 = y[3] - y[2];
if(dx1 * dy2 == dx2 * dy1 && (dx1 == 0 || dy1 == 0 || dx1 == dy1 || dx1 == -dy1)) return true;
int tmp = x[1]; x[1] = x[2]; x[2] = x[0]; x[0] = tmp;
tmp = y[1]; y[1] = y[2]; y[2] = y[0]; y[0] = tmp;
}
return false;
}
bool is_octagon(void){
int i;
bool ans = false;
REP(i,4){
x[i] *= 2;
y[i] *= 2;
}
for(int p=-N;p<=N;p++) for(int q=-N;q<=N;q++){
bool good = true;
REP(i,4){
int dx = abs(p - x[i]);
int dy = abs(q - y[i]);
if(min(abs(dx), abs(dy)) != min(abs(p), abs(q)) || max(abs(dx), abs(dy)) != max(abs(p), abs(q))) good = false;
}
if(good) return true;
}
REP(i,4){
x[i] /= 2;
y[i] /= 2;
}
return ans;
}
int get_x(int a, int b, int c, int d){
return d * (a * a + b * b) - b * (c * c + d * d);
}
string itos(int x){
stringstream ss;
ss << x;
return ss.str();
}
string get_greek(int p){
if(p == 5) return "α";
if(p == 13) return "β";
if(p == 17) return "γ";
if(p == 29) return "δ";
return "?";
}
int gcd(int x, int y){
return x ? gcd(y%x, x) : y;
}
string get_equation(int a, int b, int c, int d){ // three points: (0, 0), (a, b), (c, d)
int f = 2 * (a * d - b * c);
int x = get_x(a, b, c, d);
int y = -get_x(b, a, d, c);
f = abs(f);
x = abs(x);
y = abs(y);
int g = gcd(f, gcd(x, y));
f /= g;
x /= g;
y /= g;
int r = x * x + y * y;
x %= f;
y %= f;
x = min(x, f - x);
y = min(y, f - y);
if(x > y) swap(x, y);
string ans;
int coef = 1;
bool dash = false;
for(int p=2;p<=r;p++) if(r % p == 0){
int cnt = 0;
while(r % p == 0){
r /= p;
cnt++;
}
if(p % 4 != 1){
while(cnt >= 2){
cnt -= 2;
coef *= p;
}
}
if(p == 2){
if(cnt > 0) dash = true;
continue;
}
if(cnt > 0) ans += get_greek(p);
if(cnt > 1) ans += "^" + itos(cnt);
}
if(coef > 1) ans = itos(coef) + ans;
if(dash) ans = ans + '\'';
if(f > 1){
ans += '(';
ans += itos(x);
ans += ',';
ans += itos(y);
ans += ")/";
ans += itos(f);
}
return ans;
}
int unconcyclic;
int colinear;
int isosceles;
int octagon;
map <string, int> mp;
void check(void){
if(!is_concyclic()){
unconcyclic++;
} else if(is_colinear()){
colinear++;
} else if(is_isosceles()){
isosceles++;
} else if(is_octagon()){
octagon++;
} else {
string s = get_equation(xx[1] - xx[0], yy[1] - yy[0], xx[2] - xx[0], yy[2] - yy[0]);
mp[s]++;
}
}
void dfs(int pos, int hash){
if(pos == 4){
int i;
REP(i,4){
x[i] = xx[i] - xx[3];
y[i] = yy[i] - yy[3];
}
check();
} else {
for(int h=hash+1;h<N*N;h++){
xx[pos] = h / N;
yy[pos] = h % N;
dfs(pos + 1, h);
}
}
}
int main(void){
dfs(0, -1);
cout << "unconcyclic: " << unconcyclic << endl;
cout << "colinear: " << colinear << endl;
cout << "isosceles: " << isosceles << endl;
cout << "octagon: " << octagon << endl;
vector <pair <int, string> > v;
snuke(mp,itr) v.push_back(make_pair(-(itr->second), (itr->first)));
sort(v.begin(),v.end());
int i;
REP(i,v.size()) cout << v[i].second << ": " << -v[i].first << endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3N0cmVhbT4KI2luY2x1ZGUgPGZzdHJlYW0+CiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxkZXF1ZT4KI2luY2x1ZGUgPHF1ZXVlPgojaW5jbHVkZSA8c3RhY2s+CiNpbmNsdWRlIDxzZXQ+CiNpbmNsdWRlIDxtYXA+CiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDxmdW5jdGlvbmFsPgojaW5jbHVkZSA8dXRpbGl0eT4KI2luY2x1ZGUgPGJpdHNldD4KI2luY2x1ZGUgPGNtYXRoPgojaW5jbHVkZSA8Y3N0ZGxpYj4KI2luY2x1ZGUgPGN0aW1lPgojaW5jbHVkZSA8Y3N0ZGlvPgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCiNkZWZpbmUgUkVQKGksbikgZm9yKChpKT0wOyhpKTwoaW50KShuKTsoaSkrKykKI2RlZmluZSBzbnVrZShjLGl0cikgZm9yKF9fdHlwZW9mKChjKS5iZWdpbigpKSBpdHI9KGMpLmJlZ2luKCk7aXRyIT0oYykuZW5kKCk7aXRyKyspCgojZGVmaW5lIE4gOQppbnQgeHhbNF0seXlbNF07CmludCB4WzRdLHlbNF07Cgpib29sIGlzX2NvbmN5Y2xpYyh2b2lkKXsKCWludCBzdW0gPSAwOwoJaW50IGk7CglSRVAoaSwzKSBzdW0gKz0gKHhbaV0gKiB4W2ldICsgeVtpXSAqIHlbaV0pICogKHhbKGkrMSklM10gKiB5WyhpKzIpJTNdIC0geFsoaSsyKSUzXSAqIHlbKGkrMSklM10pOwoJcmV0dXJuIChzdW0gPT0gMCk7Cn0KCmJvb2wgaXNfY29saW5lYXIodm9pZCl7CglpbnQgaTsKCWZvcihpPTE7aTw9MjtpKyspIGlmKHhbaV0gKiB5WzBdICE9IHhbMF0gKiB5W2ldKSByZXR1cm4gZmFsc2U7CglyZXR1cm4gdHJ1ZTsKfQoKYm9vbCBpc19pc29zY2VsZXModm9pZCl7CglpbnQgaTsKCQoJUkVQKGksMyl7CgkJaW50IGR4MSA9IHhbMV0gLSB4WzBdOwoJCWludCBkeDIgPSB4WzNdIC0geFsyXTsKCQlpbnQgZHkxID0geVsxXSAtIHlbMF07CgkJaW50IGR5MiA9IHlbM10gLSB5WzJdOwoJCQoJCWlmKGR4MSAqIGR5MiA9PSBkeDIgKiBkeTEgJiYgKGR4MSA9PSAwIHx8IGR5MSA9PSAwIHx8IGR4MSA9PSBkeTEgfHwgZHgxID09IC1keTEpKSByZXR1cm4gdHJ1ZTsKCQoJCWludCB0bXAgPSB4WzFdOyB4WzFdID0geFsyXTsgeFsyXSA9IHhbMF07IHhbMF0gPSB0bXA7CgkJdG1wID0geVsxXTsgeVsxXSA9IHlbMl07IHlbMl0gPSB5WzBdOyB5WzBdID0gdG1wOwoJfQoJCglyZXR1cm4gZmFsc2U7Cn0KCmJvb2wgaXNfb2N0YWdvbih2b2lkKXsKCWludCBpOwoJYm9vbCBhbnMgPSBmYWxzZTsKCQoJUkVQKGksNCl7CgkJeFtpXSAqPSAyOwoJCXlbaV0gKj0gMjsKCX0KCQoJZm9yKGludCBwPS1OO3A8PU47cCsrKSBmb3IoaW50IHE9LU47cTw9TjtxKyspewoJCWJvb2wgZ29vZCA9IHRydWU7CgkJCgkJUkVQKGksNCl7CgkJCWludCBkeCA9IGFicyhwIC0geFtpXSk7CgkJCWludCBkeSA9IGFicyhxIC0geVtpXSk7CgkJCWlmKG1pbihhYnMoZHgpLCBhYnMoZHkpKSAhPSBtaW4oYWJzKHApLCBhYnMocSkpIHx8IG1heChhYnMoZHgpLCBhYnMoZHkpKSAhPSBtYXgoYWJzKHApLCBhYnMocSkpKSBnb29kID0gZmFsc2U7CgkJfQoJCQoJCWlmKGdvb2QpIHJldHVybiB0cnVlOwoJfQoJCglSRVAoaSw0KXsKCQl4W2ldIC89IDI7CgkJeVtpXSAvPSAyOwoJfQoJCglyZXR1cm4gYW5zOwp9CgppbnQgZ2V0X3goaW50IGEsIGludCBiLCBpbnQgYywgaW50IGQpewoJcmV0dXJuIGQgKiAoYSAqIGEgKyBiICogYikgLSBiICogKGMgKiBjICsgZCAqIGQpOwp9CgpzdHJpbmcgaXRvcyhpbnQgeCl7CglzdHJpbmdzdHJlYW0gc3M7CglzcyA8PCB4OwoJcmV0dXJuIHNzLnN0cigpOwp9CgpzdHJpbmcgZ2V0X2dyZWVrKGludCBwKXsKCWlmKHAgPT0gNSkgcmV0dXJuICLOsSI7CglpZihwID09IDEzKSByZXR1cm4gIs6yIjsKCWlmKHAgPT0gMTcpIHJldHVybiAizrMiOwoJaWYocCA9PSAyOSkgcmV0dXJuICLOtCI7CglyZXR1cm4gIj8iOwp9CgppbnQgZ2NkKGludCB4LCBpbnQgeSl7CglyZXR1cm4geCA/IGdjZCh5JXgsIHgpIDogeTsKfQoKc3RyaW5nIGdldF9lcXVhdGlvbihpbnQgYSwgaW50IGIsIGludCBjLCBpbnQgZCl7IC8vIHRocmVlIHBvaW50czogKDAsIDApLCAoYSwgYiksIChjLCBkKQoJaW50IGYgPSAyICogKGEgKiBkIC0gYiAqIGMpOwoJaW50IHggPSBnZXRfeChhLCBiLCBjLCBkKTsKCWludCB5ID0gLWdldF94KGIsIGEsIGQsIGMpOwoJCglmID0gYWJzKGYpOwoJeCA9IGFicyh4KTsKCXkgPSBhYnMoeSk7CgkKCWludCBnID0gZ2NkKGYsIGdjZCh4LCB5KSk7CglmIC89IGc7Cgl4IC89IGc7Cgl5IC89IGc7CgkKCWludCByID0geCAqIHggKyB5ICogeTsKCXggJT0gZjsKCXkgJT0gZjsKCXggPSBtaW4oeCwgZiAtIHgpOwoJeSA9IG1pbih5LCBmIC0geSk7CglpZih4ID4geSkgc3dhcCh4LCB5KTsKCQoJc3RyaW5nIGFuczsKCWludCBjb2VmID0gMTsKCWJvb2wgZGFzaCA9IGZhbHNlOwoJCglmb3IoaW50IHA9MjtwPD1yO3ArKykgaWYociAlIHAgPT0gMCl7CgkJaW50IGNudCA9IDA7CgkJd2hpbGUociAlIHAgPT0gMCl7CgkJCXIgLz0gcDsKCQkJY250Kys7CgkJfQoJCQoJCWlmKHAgJSA0ICE9IDEpewoJCQl3aGlsZShjbnQgPj0gMil7CgkJCQljbnQgLT0gMjsKCQkJCWNvZWYgKj0gcDsKCQkJfQoJCX0KCQkKCQlpZihwID09IDIpewoJCQlpZihjbnQgPiAwKSBkYXNoID0gdHJ1ZTsKCQkJY29udGludWU7CgkJfQoJCQoJCWlmKGNudCA+IDApIGFucyArPSBnZXRfZ3JlZWsocCk7CgkJaWYoY250ID4gMSkgYW5zICs9ICJeIiArIGl0b3MoY250KTsKCX0KCQoJaWYoY29lZiA+IDEpIGFucyA9IGl0b3MoY29lZikgKyBhbnM7CgkKCWlmKGRhc2gpIGFucyA9IGFucyArICdcJyc7CgkKCWlmKGYgPiAxKXsKCQlhbnMgKz0gJygnOwoJCWFucyArPSBpdG9zKHgpOwoJCWFucyArPSAnLCc7CgkJYW5zICs9IGl0b3MoeSk7CgkJYW5zICs9ICIpLyI7CgkJYW5zICs9IGl0b3MoZik7Cgl9CgkKCXJldHVybiBhbnM7Cn0KCmludCB1bmNvbmN5Y2xpYzsKaW50IGNvbGluZWFyOwppbnQgaXNvc2NlbGVzOwppbnQgb2N0YWdvbjsKbWFwIDxzdHJpbmcsIGludD4gbXA7Cgp2b2lkIGNoZWNrKHZvaWQpewoJaWYoIWlzX2NvbmN5Y2xpYygpKXsKCQl1bmNvbmN5Y2xpYysrOwoJfSBlbHNlIGlmKGlzX2NvbGluZWFyKCkpewoJCWNvbGluZWFyKys7Cgl9IGVsc2UgaWYoaXNfaXNvc2NlbGVzKCkpewoJCWlzb3NjZWxlcysrOwoJfSBlbHNlIGlmKGlzX29jdGFnb24oKSl7CgkJb2N0YWdvbisrOwoJfSBlbHNlIHsKCQlzdHJpbmcgcyA9IGdldF9lcXVhdGlvbih4eFsxXSAtIHh4WzBdLCB5eVsxXSAtIHl5WzBdLCB4eFsyXSAtIHh4WzBdLCB5eVsyXSAtIHl5WzBdKTsKCQltcFtzXSsrOwoJfQp9Cgp2b2lkIGRmcyhpbnQgcG9zLCBpbnQgaGFzaCl7CglpZihwb3MgPT0gNCl7CgkJaW50IGk7CgkJUkVQKGksNCl7CgkJCXhbaV0gPSB4eFtpXSAtIHh4WzNdOwoJCQl5W2ldID0geXlbaV0gLSB5eVszXTsKCQl9CgkJY2hlY2soKTsKCX0gZWxzZSB7CgkJZm9yKGludCBoPWhhc2grMTtoPE4qTjtoKyspewoJCQl4eFtwb3NdID0gaCAvIE47CgkJCXl5W3Bvc10gPSBoICUgTjsKCQkJZGZzKHBvcyArIDEsIGgpOwoJCX0KCX0KfQoKaW50IG1haW4odm9pZCl7CglkZnMoMCwgLTEpOwoJCgljb3V0IDw8ICJ1bmNvbmN5Y2xpYzogIiA8PCB1bmNvbmN5Y2xpYyA8PCBlbmRsOwoJY291dCA8PCAiY29saW5lYXI6ICIgPDwgY29saW5lYXIgPDwgZW5kbDsKCWNvdXQgPDwgImlzb3NjZWxlczogIiA8PCBpc29zY2VsZXMgPDwgZW5kbDsKCWNvdXQgPDwgIm9jdGFnb246ICIgPDwgb2N0YWdvbiA8PCBlbmRsOwoJCgl2ZWN0b3IgPHBhaXIgPGludCwgc3RyaW5nPiA+IHY7CglzbnVrZShtcCxpdHIpIHYucHVzaF9iYWNrKG1ha2VfcGFpcigtKGl0ci0+c2Vjb25kKSwgKGl0ci0+Zmlyc3QpKSk7Cglzb3J0KHYuYmVnaW4oKSx2LmVuZCgpKTsKCQoJaW50IGk7CglSRVAoaSx2LnNpemUoKSkgY291dCA8PCB2W2ldLnNlY29uZCA8PCAiOiAiIDw8IC12W2ldLmZpcnN0IDw8IGVuZGw7CgkKCXJldHVybiAwOwp9Cg==