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 "bits/stdc++.h"
//#include <iostream>
//#include <vector>
//#include <string>
using namespace std;
#define repi(i,a,b) for(int i=(a), i##_len=(b); i<i##_len; ++i)
#define rep(i,n) repi(i,0,n)
#define repi_(i,a,b) for(int i=(a), i##_len=(b); i<=i##_len; ++i)
#define rep_(i,n) repi_(i,0,n)
#define all(x) (x).begin(),(x).end()
#define vsort(v) sort((v).begin(), (v).end())
#define gsort(v) tsort(v); reverse((v).begin(), (v).end())
#define vrev(v) reverse((v).begin(), (v).end())
#define siz(v) ((int)(v).size())
#define ers(v, n) (v).erase((v).begin() + n)
#define cnt(v, n) count(all(v), n)
#define vmin(v) *min_element(v.begin(), v.end())
#define vmax(v) *max_element(v.begin(), v.end())
#define el "\n"
#define sp " "
#define co(x) cout<<(x)<<el
#define coc(c, a, b) if(c)co((a));else co((b))
#define cosp(x) cout<<(x)<<' '
#define YES(c) coc(c,"YES", "NO")
#define Yes(c) coc(c,"Yes", "No")
#define yes(c) coc(c,"yes", "no")
#define POSSIBLE(c) coc(c, "POSSIBLE", "IMPOSSIBLE")
#define Possible(c) coc(c, "Possible", "Impossible")
#define possible(c) coc(c, "possible", "impossible")
#define inf INT_MAX
#ifdef tqktmp_2
#define gc() getchar(); getchar()
#else
#define gc() 1
#endif
const unsigned int bf0 = (1 << 0);
const unsigned int bf1 = (1 << 1);
const unsigned int bf2 = (1 << 2);
const unsigned int bf3 = (1 << 3);
const unsigned int bf4 = (1 << 4);
const unsigned int bf5 = (1 << 5);
const unsigned int bf6 = (1 << 6);
const unsigned int bf7 = (1 << 7);

typedef long long lint;
typedef vector<int> ivec; typedef vector<string> svec;

const int
	dx8[8] = { 0,1,1,1,0,-1,-1,-1 },
	dy8[8] = { 1,1,0,-1,-1,-1,0,1 },
	dx4[4] = { 0,1,0,-1 },
	dy4[4] = { 1,0,-1,0 };

template<class T>inline bool maxi(T &a, const T &b) { if (a<b) { a = b; return 1; } return 0; }
template<class T>inline bool mini(T &a, const T &b) { if (b<a) { a = b; return 1; } return 0; }




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

	ivec l(3);
	lint ctr[4] = {};
	while (cin >> l[0] >> l[1] >> l[2]) {
		vsort(l);
		if (l[0] + l[1] <= l[2]) {
			cout << ctr[0] << sp << ctr[1] << sp << ctr[2] << sp << ctr[3] << el;
			gc();
			return 0;
		}
		if (l[0] * l[0] + l[1] * l[1] == l[2] * l[2])++ctr[1];
		else if (l[0] * l[0] + l[1] * l[1] > l[2] * l[2])++ctr[2];
		else ++ctr[3];
		++ctr[0];
	}
	gc();
}

C++: #include<iostream>
using namespace std;
int main(){
	int i,x,y ,z,a,b,c,ch=0,ei=0,d=0;

	for(i=0;i<100;i++)
	{
		cin>>x>>y>>z;

		if(x>=y && y>=z) 
		{
			a=x;
			b=y;
			c=z;
		}
		else if(y>=x  && x>=z)
		{
			a=y;
			b=x;
			c=z;
		}
		else //(z>=x && x>=y)
		{
			a=z;
			b=y;
			c=x;
		}

		if(b+c<=a)
		{
			break;
		}  

		a = a*a;
		b = b*b;
		c = c*c;

		if (a-(b+c)<0)
		{
			ei+=1;
		}

		if (a-(b+c)>0)
		{
			d+=1;
		}

		if(a == b+c)
		{
			ch+=1;
		}

		
	}

	cout<<ch+d+ei<<" "<<ch<<" "<<ei<<" "<<d<<endl;



	return 0;
}

C++: #include<iostream>
#include<algorithm>
#define rep(num,num2) for(int num=0;num<num2;num++)
using namespace std;
int main()
{
    int t=0,r=0,n=0,p=0;
    while(true)
    {
        int a[3];
        rep(i,3)cin>>a[i];
        sort(a,a+3);
        if(a[1]+a[0]<=a[2])break;
        if(a[2]*a[2]==a[1]*a[1]+a[0]*a[0]){
            t++;r++;
        }
        if(a[2]*a[2]>a[1]*a[1]+a[0]*a[0]){
            t++;p++;
        }
        if(a[2]*a[2]<a[1]*a[1]+a[0]*a[0]){
            t++;n++;
        }
    }
    cout<<t<<" "<<r<<" "<<n<<" "<<p<<endl;
}

C++: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps=1e-9;

//// < "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\a.txt" > "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\b.answer"
int main() {
	vector<int>nums(4);
	while (1) {
		vector<int>vs(3);
		cin >> vs[0] >> vs[1] >> vs[2];
		sort(vs.begin(), vs.end());
		if (vs[0] + vs[1] <= vs[2]) {
			break;
		}
		else {
			int l = vs[0] * vs[0] + vs[1] * vs[1];
			int r = vs[2] * vs[2];
			if (l < r) {
				nums[3]++;
			}
			else if (l == r) {
				nums[1]++;
			}
			else {
				nums[2]++;
			}
			nums[0]++;
		}

	}
	cout << nums[0] << " " << nums[1] << " " << nums[2] << " " << nums[3] << endl;
	return 0;
}

C++: #include <iostream>
#include <complex>
#include <sstream>
#include <string>
#include <algorithm>
#include <deque>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <vector>
#include <set>
#include <limits>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;
#define REP(i, j) for(int i = 0; i < (int)(j); ++i)
#define FOR(i, j, k) for(int i = (int)(j); i < (int)(k); ++i)
#define SORT(v) sort((v).begin(), (v).end())
#define REVERSE(v) reverse((v).begin(), (v).end())
const double EPS = 1e-8;
#define EQ(a,b) (abs((a)-(b)) < EPS)
typedef complex<double> P;


int solve(vector<int> &v, vector<int> &cnt){
    SORT(v);
    if(v[0] + v[1] <= v[2]) return -1;
    if(v[0] * v[0] + v[1] * v[1] > v[2] * v[2]) return 1;
    if(v[0] * v[0] + v[1] * v[1] < v[2] * v[2]) return 2;
    return 0;
}

int main() {
  vector<int> v(3), cnt(3, 0);
  for(int i = 0; cin >>v[0] >>v[1] >>v[2]; ++i){
    int r = solve(v, cnt);
    if(r == -1){
      cout <<i;
      REP(i, 3) cout <<" " <<cnt[i];
      cout <<endl;
      break;
    }
    ++cnt[r];
  }
  return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define all(v) v.begin(), v.end()

void print_vec(vector<int> vec)
{
  cout << "[";
  for (int i = 0; i < vec.size(); i++)
  {
    cout << vec.at(i);
    if (i < vec.size() - 1)
    {
      cout << ", ";
    }
  }
  cout << "]...size: " << vec.size() << endl;
}

int main()
{
  map<string, int> hash;
  hash["right"] = 0;
  hash["acute"] = 0;
  hash["obtuse"] = 0;

  bool judge = true;
  while (judge)
  {
    int a, b, c;
    cin >> a >> b >> c;

    if (a + b <= c || b + c <= a || c + a <= b)
    {
      judge = false;
    }
    else
    {
      vector<int> vec(3);
      vec.at(0) = a * a;
      vec.at(1) = b * b;
      vec.at(2) = c * c;
      sort(all(vec));
      int x = vec.at(0);
      int y = vec.at(1);
      int z = vec.at(2);
      if (z == x + y)
      {
        hash.at("right") += 1;
      }
      else if (z < x + y)
      {
        hash.at("acute") += 1;
      }
      else
      {
        hash.at("obtuse") += 1;
      }
    }
  }

  printf("%d %d %d %d\n", hash["right"] + hash["acute"] + hash["obtuse"], hash["right"], hash["acute"], hash["obtuse"]);
}