#include <bits/stdc++.h>

using ld = long double;
using point = std::complex<ld>;
using polygon = std::vector<point>;

constexpr ld eps = 1e-10;
constexpr ld pi = std::acos(-1.0);

bool comp(point a, point b) {
    return std::real(a) < std::real(b) || (std::real(a) <= std::real(b) && std::imag(a) < std::imag(b));
}

std::vector<point> unique(std::vector<point> ps) {
    std::sort(std::begin(ps), std::end(ps), comp);
    std::vector<point> res;
    for(auto& p : ps) {
        if(res.empty() || abs(res.back() - p) > eps) {
            res.push_back(p);
        }
    }
    return res;
}

ld dot(point const& a, point const& b) {
    return std::real(std::conj(a) * b);
}
ld cross(point const& a, point const& b) {
    return std::imag(std::conj(a) * b);
}

int ccw(point a, point b, point c) {
    b -= a; c -= a;
    if(cross(b, c) > eps) return 1;            // a -> b -> c : counterclockwise
    if(cross(b, c) < -eps) return -1;          // a -> b -> c : clockwise
    if(dot(b, c) < 0) return 2;                // c -> a -> b : line
    if(std::norm(b) < std::norm(c)) return -2; // a -> b -> c : line
    return 0;                                  // a -> c -> b : line
}

struct segment {
    segment() : a(0, 0), b(0, 0) {}
    segment(point a, point b) : a(a), b(b) {}
    point a, b;
};

struct line {
    line() : a(0, 0), b(0, 0) {}
    line(point a, point b) : a(a), b(b) {}
    line(segment s) : a(s.a), b(s.b) {}
    point a, b;
};

struct circle {
    circle() : p(point(0, 0)), r(0) {}
    circle(point p_, long double r_) : p(p_), r(r_) {}
    point p;
    long double r;
};

bool isis_ll(line l, line m) {
    return cross(l.b - l.a, m.b - m.a) < eps;
}

bool isis_ls(line l, segment s) {
    return (cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

bool isis_lp(line l, point p) {
    return (std::abs(cross(l.b - p, l.a - p)) < eps);
}

bool isis_sp(segment s, point p) {
    return (std::abs(s.a - p) + std::abs(s.b - p) - std::abs(s.b - s.a) < eps);
}

bool isis_ss(segment s, segment t) {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0
        && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

point proj(line l, point p) {
    long double t = dot(p - l.a, l.a - l.b) / std::norm(l.a - l.b);
    return l.a + t * (l.a - l.b);
}

point is_ll(line s, line t) {
    point sv = s.b - s.a, tv = t.b - t.a;
    assert(cross(sv, tv) != 0);
    return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}

point is_ss(segment s1, segment s2) {
    assert(isis_ss(s1, s2));
    point sv = s1.b - s1.a, tv = s2.b - s2.a;
    if(cross(sv, tv) == 0) {
        if(std::abs(s1.a - s2.a) < eps || std::abs(s1.a - s2.b) < eps) {
            return s1.a;
        } else {
            return s1.b;
        }
    } else {
        return is_ll(line(s1), line(s2));
    }
}

long double dist_lp(line l, point p) {
    return std::abs(p - proj(l, p));
}

long double dist_ll(line l, line m) {
    return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

long double dist_ls(line l, segment s) {
    return isis_ls(l, s) ? 0 : std::min(dist_lp(l, s.a), dist_lp(l, s.b));
}

long double dist_sp(segment s, point p) {
    point r = proj(line(s), p);
    return isis_sp(s, r) ? std::abs(r - p) : std::min(std::abs(s.a - p), std::abs(s.b - p));
}

long double dist_ss(segment s, segment t) {
    if(isis_ss(s, t)) return 0;
    long double d1 = std::min(dist_sp(s, t.a), dist_sp(s, t.b));
    long double d2 = std::min(dist_sp(t, s.a), dist_sp(t, s.b));
    return std::min(d1, d2);
}

std::vector<point> is_cl(circle const& c, line const& l) {
    const ld d = dist_lp(l, c.p);
    std::vector<point> res;
    if(d > c.r) return res;
    auto p = proj(l, c.p);
    if(std::fabs(d - c.r) < eps) {
        res.push_back(p);
        return res;
    }
    const ld len = std::sqrt(c.r * c.r - d * d);
    auto vec = (l.b - l.a) / std::abs(l.b - l.a);
    res.push_back(p + vec * len);
    res.push_back(p + vec * len * point(-1, 0));
    return res;
}

std::vector<point> is_cc(circle const& c1, circle const& c2) {
    std::vector<point> res;
    ld d = std::abs(c1.p - c2.p);
    ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
    ld dfr = c1.r * c1.r - rc * rc;
    if(std::abs(dfr) < eps) {
        dfr = 0.0;
    } else if(dfr < 0.0) {
        return res;
    }

    ld rs = std::sqrt(dfr);
    point diff = (c2.p - c1.p) / d;
    res.push_back(c1.p + diff * point(rc, rs));
    if(dfr != 0.0) {
        res.push_back(c1.p + diff * point(rc, -rs));
    }
    return res;
}

ld area(polygon const& p) {
    const int N = p.size();
    ld res = 0;
    for(int i = 0; i < N; ++i) {
        res += cross(p[i], p[(i + 1) % N]);
    }
    return res / 2;
}

// 0 -> on, 1 -> in, 2 -> out
int is_in_polygon(polygon const& poly, point p) {
    const int n = poly.size();
    ld sum = 0;
    for(int i = 0; i < n; ++i) {
        point p1 = poly[i], p2 = poly[(i + 1) % n];
        if(isis_sp(segment(p1, p2), p)) {
            return 0;
        }
        sum += arg((p2 - p) / (p1 - p));
    }
    return std::abs(sum) < pi / 2 ? 2 : 1; // @todo: should check < 0.5 ?
}

// left side
polygon convex_cut(polygon const& p, line l) {
    const int N = p.size();
    polygon res;
    for(int i = 0; i < N; ++i) {
        auto a = p[i], b = p[(i + 1) % N];
        if(ccw(l.a, l.b, a) != -1) {
            res.push_back(a);
        }
        if(ccw(l.a, l.b, a) * ccw(l.a, l.b, b) < 0) {
            if(cross(a - b, l.a - l.b) == 0) continue; // cut line が辺に覆いかぶさる
            res.push_back(is_ll(line(a, b), l));
        }
    }
    return res;
}

polygon convex_hull(std::vector<point> ps) {
    std::sort(ps.begin(), ps.end(), comp);
    const int n = ps.size();
    int k = 0;
    polygon qs(2 * n);
    for(int i = 0; i < n; ++i) {
        while(k > 1 && ccw(qs[k - 2], qs[k - 1], ps[i]) <= 0) {
            k--;
        }
        qs[k++] = ps[i];
    }
    for(int i = n - 2, t = k; i >= 0; --i) {
        while(k > t && ccw(qs[k - 2], qs[k - 1], ps[i]) <= 0) {
            k--;
        }
        qs[k++] = ps[i];
    }
    qs.resize(k - 1);
    return qs;
}

bool compare_y(point const& a, point const& b) {
    return std::imag(a) < std::imag(b);
}

ld closest_pair_impl(point* a, int n) {
    if (n <= 1) return 1e20;
    int m = n / 2;
    ld x = std::real(a[m]);
    ld d = std::min(closest_pair_impl(a, m), closest_pair_impl(a + m, n - m));
    std::inplace_merge(a, a + m, a + n, compare_y);
    std::vector<point> b;
    for (int i = 0; i < n; i++) {
        if (std::abs(std::real(a[i]) - x) >= d) continue;
        for (int j = 0; j < (int)b.size(); j++) {
            ld dx = std::real(a[i]) - std::real(b[b.size() - j - 1]);
            ld dy = std::imag(a[i]) - std::imag(b[b.size() - j - 1]);
            if (dy >= d) break;
            d = std::min(d, sqrtl(dx * dx + dy * dy));
        }
        b.push_back(a[i]);
    }
    return d;
}
ld closest_pair(std::vector<point> ps) {
    std::sort(std::begin(ps), std::end(ps), comp);
    return closest_pair_impl(ps.data(), ps.size());
}

std::vector<line> tangent_cp(circle c, point p) {
    std::vector<line> res;
    point v = c.p - p;
    ld d = std::abs(v), len = std::sqrt(std::norm(v) - c.r * c.r);
    if(std::isnan(len)) {
        return res;
    }
    point v1 = v * point(len / d, c.r / d);
    point v2 = v * point(len / d, -c.r / d);
    res.push_back(line(p, p + v1));
    if(len < eps) {
        return res;
    }
    res.push_back(line(p, p + v2));
    return res;
}

std::vector<line> tangent_cc(circle c1, circle c2) {
    std::vector<line> res;
    auto average = [] (point const& p1, point const& p2, ld ratio1, ld ratio2) {
        return (p1 * ratio1 + p2 * ratio2) / (ratio1 + ratio2);
    };
    if(std::abs(c1.p - c2.p) - (c1.r + c2.r) >= 0) {
        auto center = average(c1.p, c2.p, c2.r, c1.r);
        res = tangent_cp(c1, center);
    }
    if(c1.r - c2.r != 0) {
        const point out = average(c1.p, c2.p, -c2.r, c1.r);
        const std::vector<line> tmp = tangent_cp(c1, out);
        res.insert(std::end(res), std::begin(tmp), std::end(tmp));
    } else {
        point vec = (c2.p - c1.p) / std::abs(c2.p - c1.p);
        point q1 = c1.p + vec * point(0, 1) * c1.r;
        point q2 = c1.p + vec * point(0, -1) * c1.r;
        res.emplace_back(q1, q1 + vec);
        res.emplace_back(q2, q2 + vec);
    }
    return res;
}

using namespace std;

int main() {
    ld cx1, cy1, r1, cx2, cy2, r2;
    cin >> cx1 >> cy1 >> r1 >> cx2 >> cy2 >> r2;
    circle c1(point(cx1, cy1), r1), c2(point(cx2, cy2), r2);
    auto ls = tangent_cc(c1, c2);
    vector<point> ans;
    for(auto& l : ls) {
        auto p1 = proj(l, c1.p);
        ans.push_back(p1);
    }
    ans = unique(move(ans));
    cout << setprecision(10) << fixed;
    for(auto& p : ans) {
        cout << real(p) << ' ' << imag(p) << endl;
    }
}



Measured memory_bytes: 3448