class Space : IEnumerable<Space> { public object Filler { get { return filler ?? (filler = Top.create()); } } public Space Upper { get; protected set; } public Space Top => Upper?.Top ?? this; private Func<object> create; private object filler; public int[] Chain { get; set; } public int[] Dementions { get; } Space[] all; static Random r { get; } = new Random(); public Space(int i, params int[] indexes) : this(() => r.Next(2), i, indexes) { } public Space(Func<object> create, int i, params int[] indexes) : this(new int[0], new[] { i }.Concat(indexes).ToArray()) { this.create = create; } private Space(int[] chain, params int[] indexes) { Chain = chain; Dementions = indexes; var i = indexes[0]; all = new Space[i]; var chains = Enumerable.Range(0, i).Select(e => chain.Concat(new int[] { e }).ToArray()).ToArray(); if (indexes.Length == 1) { while (i-- > 0) { all[i] = new Space(chains[i]); all[i].Upper = this; } } else { var _indexes = indexes.Skip(1).ToArray(); while (i-- > 0) { all[i] = new Space(chains[i], _indexes); all[i].Upper = this; } } filler = all; } private Space(int[] chain) { Chain = chain; } public Space this[int i, params int[] indexes] { get { if (all == null) { return (Filler as Space)?[i, indexes]; } if (indexes.Length == 0) { return all[i]; } return all[i][indexes[0], indexes.Skip(1).ToArray()]; } } public override string ToString() { return all?.Aggregate(string.Empty, (a, s) => a + s + ',').Trim(',') ?? Filler.ToString(); } public override bool Equals(object obj) { if (GetType() != obj?.GetType()) { return false; } return GetHashCode() == obj.GetHashCode(); } public override int GetHashCode() { if (Upper == null) { return base.GetHashCode(); } return Top.GetHashCode() - Chain.GetHashCode(); } public IEnumerator<Space> GetEnumerator() { return ((IEnumerable<Space>)all).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<Space>)all).GetEnumerator(); } }