using System;
using System.Collections.Generic;
using System.Threading;

namespace A323183 {
    /// <summary>
    /// Cf. http://tilings.math.uni-bielefeld.de/substitution/equithirds/
    /// </summary>
    class Program {
        static void Main(string[] args) {
            Point[] abc = new Point[3];
            for (int i = 0; i < abc.Length; i++) {
                abc[i] = new Point() {
                    Border = true
                };
            }

            int depth = Depth;
            if (args.Length == 1) {
                depth = int.Parse(args[0]);
            }
            Blue(depth, abc[0], abc[1], abc[2]);

            foreach (Point near in Point.Center.Neighbors) {
                if (near.Neighbors.Count == 4) {
                    Compute(near);
                    break;
                }
            }
        }

        const double Radius = 100000;
        const int Depth = 10;

        static void Compute(Point p) {
            HashSet<Point> generation = new HashSet<Point>();
            generation.Add(p);
            p.Visited = true;

            for (int g = 0; ; g++) {
                HashSet<Point> newGeneration = new HashSet<Point>();
                foreach (Point current in generation) {
                    if (current.Border) {
                        return;
                    }

                    foreach (Point neighbor in current.Neighbors) {
                        if (!neighbor.Visited) {
                            neighbor.Visited = true;
                            newGeneration.Add(neighbor);
                        }
                    }
                }
                Console.WriteLine("{0} {1}", g, generation.Count);
                generation = newGeneration;
            }
        }

        static void Blue(int depth, Point a, Point b, Point c) {
            if (depth-- > 0) {
                Point m = Point.Middle(a, b, c);

                Yellow(depth, m, a, b);
                Yellow(depth, m, b, c);
                Yellow(depth, m, c, a);
            } else {
                Triangle("blue", a, b, c);
            }
        }

        static void Yellow(int depth, Point a, Point b, Point c) {
            if (depth-- > 0) {
                Point bb = b.AtThirdDistance(c);
                Point cc = c.AtThirdDistance(b);

                Yellow(depth, bb, a, b);
                Yellow(depth, cc, a, c);
                Blue(depth, a, bb, cc);
            } else {
                Triangle("LemonChiffon", a, b, c);
            }
        }

        static void Triangle(string color, Point a, Point b, Point c) {
            a.Join(b);
            b.Join(c);
            c.Join(a);
        }
    }

    class Point {
        public Point() {
            this.Index = Interlocked.Increment(ref Counter);
            this.Neighbors = new HashSet<Point>();
            this.atThirdNeighbors = new Dictionary<Point, Point>();
        }
        public bool Visited { get; set; }
        public bool Border { get; set; }
        public long Index { get; private set; }
        public HashSet<Point> Neighbors { get; private set; }

        public static Point Middle(Point a, Point b, Point c) {
            Point middle = new Point();
            if (Center == null) {
                Center = middle;
            }
            return middle;
        }
        public static Point Center { get; private set; }

        public Point AtThirdDistance(Point other) {
            Point atThird = null;
            if (!this.atThirdNeighbors.TryGetValue(other, out atThird)) {
                this.atThirdNeighbors[other] = atThird = new Point() {
                    Border = this.Border & other.Border
                };
            }
            return atThird;
        }

        public void Join(Point other) {
            this.Neighbors.Add(other);
            other.Neighbors.Add(this);
        }

        public override int GetHashCode() {
            return (int)this.Index ^ (int)(this.Index >> 32);
        }

        public override bool Equals(object obj) {
            Point other = obj as Point;
            if (other == null) {
                return false;
            } else {
                return this.Index == other.Index;
            }
        }

        private Dictionary<Point, Point> atThirdNeighbors;
        private static long Counter = 0;
    }
}