#define _USE_MATH_DEFINES
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
#include <cfloat>
#include <ctime>
#include <cassert>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <numeric>
#include <list>

using namespace std;
typedef long long ll;
typedef pair<int, int> Pii;
typedef pair<ll, ll> Pll;

#define FOR(i,n) for(int i = 0; i < (n); i++)
#define sz(c) ((int)(c).size())
#define ten(x) ((int)1e##x)
#define tenll(x) ((ll)1e##x)


const double EPS(1e-8);
const double PI = acos(-1.0);

#pragma region 基本要素(struct,typedef)

typedef double T;

struct P {
	T x, y;
	P() : x(0), y(0) {}
	P(const T& x, const T& y) : x(x), y(y) {}
	P operator+(const P &a)const { return P(x + a.x, y + a.y); }
	P& operator+=(const P &a) { x += a.x; y += a.y; return *this; }
	P operator-(const P &a)const { return P(x - a.x, y - a.y); }
	P& operator-=(const P &a) { x -= a.x; y -= a.y; return *this; }
	P operator*(const T a)const { return P(a*x, a*y); }
	P& operator*=(const T a) { x *= a; y *= a; return *this; }
	P operator/(const T a)const { return P(x / a, y / a); }
	P& operator/=(const T a) { x /= a; y /= a; return *this; }

	//比較用
	bool operator<(const P &a)const { return (x != a.x) ? (x < a.x) : (y < a.y); }

};

struct S {
	P a, b;
	S() {}
	S(const P& a, const P& b) : a(a), b(b) {}
};

struct L {
	P a, b;
	L() {}
	L(const P& a, const P& b) : a(a), b(b) {}
};

struct C {
	P c;
	T r;
	C() {}
	C(const P &c, T& r) : c(c), r(r) {}
};

#pragma endregion 

#pragma region 基本要素(関数)

T SQ(T x) { return x*x; }
T dist2(const P &a, const P &b) { return SQ(a.x - b.x) + SQ(a.y - b.y); }
T abs2(const P& p) { return SQ(p.x) + SQ(p.y); }
double abs(const P& p) { return sqrt(abs2(p)); }
T dot(const P& a, const P& b) { return a.x*b.x + a.y*b.y; }
T cross(const P& a, const P& b) { return a.x*b.y - a.y*b.x; }
P rot(const P& a, const double theta) {
	return P(a.x*cos(theta) - a.y*sin(theta),a.x*sin(theta) + a.y*cos(theta));
}
double arg(const P &a) { double t = atan2(a.y, a.x); return t<0 ? t + 2 * PI : t; }

enum { CCW = 1, CW = -1, ON = 0 };
int ccw(const P &a, P b, P c) {
	b -= a; c -= a;
	double rdir = cross(b, c);
	double len = abs(b) * abs(c); //誤差対策 (速度がやばい時は外すか、二乗に置き換える)
	if (rdir> EPS * len) return CCW; //cがabより上(反時計周り)
	if (rdir<-EPS * len) return CW; // cがabより下(時計周り)
	return ON; // a,b,cが一直線上
}

#pragma endregion

#pragma region 入出力

std::ostream& operator<<(std::ostream& os, const P& point) { return (os << '(' << point.x << ',' << point.y << ')'); }
std::ostream& operator<<(std::ostream& os, const S& seg) { return (os << '{' << seg.a << ',' << seg.b << '}'); }
std::istream& operator>>(std::istream& is, P& point) { return (is >> point.x >> point.y); }

#pragma endregion

//交点が存在するかどうか
bool intersected(const S &S1, const S &S2) {
	if (max(S1.a.x, S1.b.x) + EPS<min(S2.a.x, S2.b.x)
		|| max(S1.a.y, S1.b.y) + EPS<min(S2.a.y, S2.b.y)
		|| max(S2.a.x, S2.b.x) + EPS<min(S1.a.x, S1.b.x)
		|| max(S2.a.y, S2.b.y) + EPS<min(S1.a.y, S1.b.y)) return false;
	return ccw(S1.a, S1.b, S2.a)*ccw(S1.a, S1.b, S2.b) <= 0
		&& ccw(S2.a, S2.b, S1.a)*ccw(S2.a, S2.b, S1.b) <= 0;
}

#pragma region 距離

//線分と点の距離(2乗)
double dist2(const S &S, const P &p) {
	if (dot(S.b - S.a, p - S.a) <= 0) return dist2(p, S.a);
	if (dot(S.a - S.b, p - S.b) <= 0) return dist2(p, S.b);
	return (double)SQ(cross(S.b - S.a, p - S.a)) / dist2(S.a, S.b);
}

//線分と点の距離
double dist(const S &S, const P &p) { return sqrt(dist2(S, p)); }

//線分と線分の距離
double dist(const S &S1, const S &S2) {
	if (intersected(S1, S2)) return 0;
	return sqrt(min(min(dist2(S1, S2.a), dist2(S1, S2.b)),
		min(dist2(S2, S1.a), dist2(S2, S1.b))));
}

//直線と点の距離
double dist(const L &L, const P &p) {
	return sqrt((double)SQ(cross(L.b - L.a, p - L.a)) / dist2(L.a, L.b));
}

//a -- bの間の円が入った時の、a - b間の距離
//円の間に
double geodist(P a, P b, const C &c) {
	double r = c.r;
	S s(a, b);
	if (dist(s, c.c)>r)
		return abs(a - b);

	a -= c.c;
	b -= c.c;

	double L1 = abs(a);
	double t1 = arg(a) + acos(r / L1); if (t1<0) t1 += 2 * PI;
	double t2 = arg(a) - acos(r / L1); if (t2<0) t2 += 2 * PI;

	double L2 = abs(b);
	double t3 = arg(b) + acos(r / L2); if (t3<0) t3 += 2 * PI;
	double t4 = arg(b) - acos(r / L2); if (t4<0) t4 += 2 * PI;

	double theta = 2 * PI;
	theta = min(theta, min(abs(t1 - t4), 2 * PI - abs(t1 - t4)));
	theta = min(theta, min(abs(t2 - t3), 2 * PI - abs(t2 - t3)));
	return sqrt(L1*L1 - r*r) + sqrt(L2*L2 - r*r) + r*theta;
}

#pragma endregion

#pragma region 面積

//多角形の面積
double area(const vector<P>& v) {
	double ans = 0;
	for (int i = 2; i < (int)v.size(); i++) {
		ans += cross(v[i - 1] - v[0], v[i] - v[0]);
	}
	return abs(ans) / 2;
}

//三角形の面積
double area(const P &a, const P &b, const P &c) {
	return abs(cross(b - a, c - a)) / 2;
}

#pragma endregion

#pragma region 包含

//凸包
vector<P> convex_hull(vector<P>& ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<P> ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
	while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;

	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--]) // upper-hull
	while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;

	ch.resize(k - 1);

	return ch;
}

//線分の内包判定
//1. AB の 両方の点が多角形に内包されている
//2. ABと多角形の交点がない

//凸でない多角形に頂点が含まれるかどうか
enum { POLY_OUT = -1, POLY_ON = 0, POLY_IN = 1 };
int contains(vector<P>& poly, const P& p) {
	bool in = false;
	FOR(i, sz(poly)) {
		P a = poly[i] - p, b = poly[(i + 1) % sz(poly)] - p;
		if (a.y > b.y) swap(a, b);
		if (a.y <= 0 && 0 < b.y)
			if (cross(a, b) < 0) in = !in;

		if (cross(a, b) == 0 && dot(a, b) <= 0) return POLY_ON;
	}
	return in ? POLY_IN : POLY_OUT;
}

//三角形abcにpが含まれているかどうか(線上の場合も含む)
bool cover(const P& a, const P& b, const P& c, const P& p) {
	return area(a, b, c) + EPS >= area(a, b, p) + area(a, c, p) + area(b, c, p);
}

#pragma endregion

#pragma region 交点

//円同士の交点
int intersect(const C &C1, const C &C2, P* p = NULL, P *q = NULL) {
	double r1 = C1.r, r2 = C2.r;
	P p1 = C1.c, p2 = C2.c;

	double d = abs(p1 - p2);
	if (d<EPS && abs(r1 - r2)<EPS) { // C1==C2
		return -1;
	} else if (r1 + r2<d - EPS || d + EPS<abs(r1 - r2)) {
		return 0;
	} else {
		double a = (r1*r1 - r2*r2 + d*d) / (2 * d);
		double h = sqrt(max(r1*r1 - a*a, 0.0));
		P tmp1 = p1 + (p2 - p1)*a / d;
		P tmp2 = (p2 - p1)*h / d;
		if (abs(tmp2)<EPS) {
			if (p&&q) *p = *q = tmp1;
			return 1;
		} else {
			if (p&&q) {
				*p = P(tmp1.x - tmp2.y, tmp1.y + tmp2.x);
				*q = P(tmp1.x + tmp2.y, tmp1.y - tmp2.x);
			}
			return 2;
		}
	}
}

// l : ax+by+c=0 に変換
inline void calc_abc(const L &l, double &a, double &b, double &c) {
	a = l.a.y - l.b.y;
	b = l.b.x - l.a.x;
	c = l.a.x*l.b.y - l.b.x*l.a.y;
}

//PからLへの垂線の足
P perp_foot(const P &p, const L &l) {
	double a, b, c;
	calc_abc(l, a, b, c);
	return p - P(a, b) * ((a*p.x + b*p.y + c) / (a*a + b*b));
}

//円と直線の交点
int intersect(const C &c, const L &l, P *p = NULL, P *q = NULL) {
	P m = perp_foot(c.c, l);
	double d2 = abs2(c.c - m);
	if (c.r*c.r + EPS<d2)   return 0;
	else if (abs(c.r*c.r - d2)<EPS) {
		if (p&&q)    *p = *q = m;
		return 1;
	} else {
		if (p&&q) {
			P v;
			double n0 = abs2(l.a - m), n1 = abs2(l.b - m);
			if (n0<n1)    v = l.b - m, n0 = n1;
			else        v = l.a - m;
			v *= sqrt((c.r*c.r - d2) / n0);
			*p = m + v, *q = m - v;
		}
		return 2;
	}
}

//円と線分の交点
int intersect(const C &c, const S &s, P *p = NULL, P *q = NULL) {
	P pp, qq;
	int n = intersect(c, L(s.a, s.b), &pp, &qq);
	if (n == 0)    return 0;
	else if (n == 1) {
		if (dot(pp - s.a, pp - s.b)<EPS) {
			if (p&&q)    *p = *q = pp;
			return 1;
		}
		return 0;
	} else {
		bool bp = (dot(pp - s.a, pp - s.b)<EPS);
		bool bq = (dot(qq - s.a, qq - s.b)<EPS);
		if (bp&&bq) {
			if (p&&q)    *p = pp, *q = qq;
			return 2;
		}
		if (bp || bq) {
			if (p&&q)    *p = (bp ? pp : qq);
			return 1;
		}
		return 0;
	}
}

//直線の交点
P intersect(const L &L1, const L &L2) {
	double a1 = cross(L1.b - L1.a, L2.b - L2.a);
	double a2 = cross(L1.b - L1.a, L1.b - L2.a);
	if (abs(a1)<EPS) return L1.a;
	return L2.a + (L2.b - L2.a) * (a2 / a1);
}

//角ABC の二等分線,A + pはBC上の辺に存在する
P bisect_angle(P A, P B, P C) {
	A -= B; C -= B;
	double alen = abs(A), clen = abs(C);
	P p = (A * clen + C * alen) / (alen + clen);
	return p;
}

//三角形ABCにおいて、AからBCへの垂線の長さ
double perp_len(P A, P B, P C) {
	return 2 * area(A, B, C) / abs(B - C);
}

//三角形の内心
P inner_center(P A, P B, P C) {
	P bis1 = bisect_angle(A, B, C);
	P bis2 = bisect_angle(B, A, C);
	L l1(B, B + bis1), l2(A, A + bis2);
	return intersect(l1, l2);
}

#pragma endregion


int main() {
	int x1, x2, x3, y1, y2, y3;
	while (cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3) {
		if (!x1&&!x2&&!x3&&!y1&&!y2&&!y3) break;
		double A = hypot(x2 - x3, y2 - y3);
		double B = hypot(x3 - x1, y3 - y1);
		double C = hypot(x1 - x2, y1 - y2);
		double a1 = acos((B*B + C*C - A*A) / (2 * B*C)) / 2;
		double a2 = acos((C*C + A*A - B*B) / (2 * C*A)) / 2;
		double a3 = acos((A*A + B*B - C*C) / (2 * A*B)) / 2;
		double cotA = cos(a1) / sin(a1);
		double cotB = cos(a2) / sin(a2);
		double cotC = cos(a3) / sin(a3);

		double s = (A + B + C) / 2;
		double S = sqrt(s*(s - A)*(s - B)*(s - C));
		double r1, r2, r3;
		double l = 0, r = S / (A+B+C) * 2;
		FOR(_, 50) {
			r1 = (l + r) / 2;
			double p = r1 * cotA;
			r2 = (-sqrt(r1) + sqrt(r1 - cotB * (p - C))) / cotB;
			r2 *= r2;
			r3 = (-sqrt(r1) + sqrt(r1 - cotC * (p - B))) / cotC;
			r3 *= r3;
			double cur_A = r2*cotB + r3*cotC + 2 * sqrt(r2*r3);
			if (cur_A < A) r = r1;
			else l = r1;
		}
		printf("%.10f %.10f %.10f\n", r1, r2, r3);
	}
}

Measured memory_bytes: 1260