using System;
using System.Collections.Generic;
using System.Threading;
namespace A323183 {
///
/// Cf. http://tilings.math.uni-bielefeld.de/substitution/equithirds/
///
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 generation = new HashSet();
generation.Add(p);
p.Visited = true;
for (int g = 0; ; g++) {
HashSet newGeneration = new HashSet();
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();
this.atThirdNeighbors = new Dictionary();
}
public bool Visited { get; set; }
public bool Border { get; set; }
public long Index { get; private set; }
public HashSet 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 atThirdNeighbors;
private static long Counter = 0;
}
}