Go: package main

import (
	"fmt"
	"sort"
)

// TriangleKind kind of triangle
type TriangleKind int

const (
	// Nothing not triangle
	Nothing TriangleKind = iota
	// RightTriangle the right triangle
	RightTriangle
	// SharpTriangle the sharp triangle
	SharpTriangle
	// ObtuseTriangle the obtuse triangle
	ObtuseTriangle
) // const for Triangle kind

type result struct {
	rTriangle int
	sTriangle int
	oTriangle int
}

func (res *result) String() string {
	return fmt.Sprintf("%d %d %d %d", res.rTriangle+res.sTriangle+res.oTriangle, res.rTriangle, res.sTriangle, res.oTriangle)
}

func checkTriangleType(a int, b int, c int) TriangleKind {
	p := []int{a, b, c}
	sort.Sort(sort.IntSlice(p))
	if !(p[0]+p[1] > p[2] && p[1]+p[2] > p[0] && p[2]+p[0] > p[1]) {
		return Nothing
	}

	c = (p[0] * p[0]) + (p[1] * p[1]) - (p[2] * p[2])
	if c == 0 {
		return RightTriangle
	}
	if c > 0 {
		return SharpTriangle
	}
	return ObtuseTriangle
}

func main() {
	var res = new(result)
	var a, b, c int
	var hasNext = true
	for hasNext {
		fmt.Scanf("%d %d %d", &a, &b, &c)
		switch checkTriangleType(a, b, c) {
		case Nothing:
			hasNext = false
		case RightTriangle:
			res.rTriangle++
		case SharpTriangle:
			res.sTriangle++
		case ObtuseTriangle:
			res.oTriangle++
		}
	}
	fmt.Println(res.String())
}

C++: #include <vector> 
#include <list> 
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <queue>
using namespace std;

//conversion
//------------------------------------------
inline int toInt(string s) { int v; istringstream sin(s); sin >> v; return v; }
template<class T> inline string toString(T x) { ostringstream sout; sout << x; return sout.str(); }

//math
//-------------------------------------------
template<class T> inline T sqr(T x) { return x * x; }

//typedef
//------------------------------------------
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef long long LL;

//container util
//------------------------------------------
#define ALL(a)  (a).begin(),(a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define MP make_pair
#define SZ(a) int((a).size())
#define EACH(i,c) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define EXIST(s,e) ((s).find(e)!=(s).end())
#define SORT(c) sort((c).begin(),(c).end())

//repetition
//------------------------------------------
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)

//constant
//--------------------------------------------
const double EPS = 1e-10;
const double PI = acos(-1.0);

//clear memory
#define CLR(a) memset((a), 0 ,sizeof(a))

//debug
#define dump(x)  cerr << #x << '=' << (x) << endl;
#define debug(x) cerr << #x << '=' << (x) << '('<<'L' << __LINE__ << ')' << ' ' << __FILE__ << endl;

//
//bool is_chokaku(int a, int b, int c) {
//	return (a*a + b * b == c * c);
//}
int num_t = 0;
int num_ei = 0;
int num_don = 0;
int num_cyokaku = 0;

//最大角の大きさで三角形を決める
// 0　鋭角　1 鈍角　２　直角
double yogen(int c, int b, int a) {

	return double(b * b + c * c - a * a) / double(2 * b*c);
}

void tri(int a, int b, int c) {
	double yo = yogen(a, b, c);

	if (abs(yo) < EPS) {
		num_cyokaku++;
	}
	else if (yo < 0) {
		num_don++;
	}
	else if (yo > 0) {
		num_ei++;
	}
}
int main() {

	vector<int> a(3);
	while (true)
	{
		cin >> a[0] >> a[1] >> a[2];
		sort(ALL(a), less<int>());
		if (a[2] < a[0] + a[1]) {
			num_t++;
			tri(a[0], a[1], a[2]);
		}
		else {
			cout << num_t << " " << num_cyokaku << " " << num_ei << " " << num_don << endl;
			break;
		}
	}


}

C++: #include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <utility>
#include <iomanip>

#define ll long long int
#define pb push_back
#define mk make_pair
#define pq priority_queue

using namespace std;
typedef pair<int, int> P;
typedef pair<ll, int> Pl;
const int inf = 1e9;
const ll linf = 1LL << 50;

bool check(int a, int b, int c){
		return max(a, max(b, c)) < (a + b + c) - max(a, max(b, c));
}

int main(int argc, char const* argv[])
{
	int a, b, c;
	int tyo = 0, don = 0, ei = 0;
	while(true){
			cin >> a >> b >> c;
			if(check(a, b, c)){
					int emax = max(a, max(b, c));
					int emin = min(a, min(b, c));
					int emid = a + b + c - emax - emin;
					if(emax * emax == emin * emin + emid * emid)tyo++;
					else if(emax * emax > emin * emin + emid * emid)don++;
					else if(emax * emax < emin * emin + emid * emid)ei++;
			}else{
					cout << tyo + don + ei << " " << tyo << " " << ei << " " << don << endl;
					return 0;
			}
	}
	return 0;
}

C++: #include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int a,b,c,d;
int x,y,z;
int main(void){
  bool f = false;
  while(cin >> x >> y >> z){
    if(x < y) swap(x,y);
    if(x < z) swap(x,z);
    if(f || x >= y+z){
      f = true;
      continue;
    }
    a++;
    if(x*x < y*y+z*z) b++;
    else if(x*x == y*y+z*z) c++;
    else d++;
  }
  printf("%d %d %d %d",a,c,b,d);
}

C++: #include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#include <utility>
#include <iomanip>
#include <algorithm>
#include <functional>
using namespace std;

typedef long long ll;
typedef vector<int> vint;
typedef vector<long long> vll;
typedef pair<int,int> pint;
typedef pair<long long, long long> pll;

#define MP make_pair
#define PB push_back
#define ALL(s) (s).begin(),(s).end()
#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P) 
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P) 
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P) 
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s; }



int a[3];

int main() {
    int t = 0, just = 0, ei = 0, don = 0;
    while (cin >> a[0] >> a[1] >> a[2]) {
        sort(a, a+3);
        if (a[2] >= a[0] + a[1]) break;
        
        ++t;
        if (a[2]*a[2] == a[0]*a[0] + a[1]*a[1]) ++just;
        else if (a[2]*a[2] > a[0]*a[0] + a[1]*a[1]) ++don;
        else ++ei;
    }
    
    cout << t << " " << just << " " << ei << " " << don << endl;
    return 0;
}

C++: #include <iostream>
#include <algorithm>
 
using namespace std;
 
int a[3];
int cnt[4];
 
bool calc(){
  for(int i=0;i<3;i++){
    if(a[i] + a[(i+1)%3] <= a[(i+2)%3]) return false;
  }
  cnt[0]++;
  if(a[0] * a[0] + a[1] * a[1] == a[2] * a[2]) cnt[1]++;
  if(a[0] * a[0] + a[1] * a[1] > a[2] * a[2]) cnt[2]++;
  if(a[0] * a[0] + a[1] * a[1] < a[2] * a[2]) cnt[3]++;
  return true;
}
 
main(){
  fill(cnt, cnt+4, 0);
  bool f = true;
  while(cin >> a[0] >> a[1] >> a[2]){
    sort(a, a+3);
    if(f){
      if(!calc()) f = false;
    }
  }
  for(int i=0;i<4;i++){
    if(i) cout << ' ';
    cout << cnt[i];
  }
  cout << endl;
}