using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Numerics; namespace Hamming { class Hammings : IEnumerable { private class LazyList { public T v; public Lazy> cont; public LazyList(T v, Lazy> cont) { this.v = v; this.cont = cont; } } private uint[] primes; private Hammings() { } // must have an argument!!! public Hammings(uint[] prms) { this.primes = prms; } private LazyList merge(LazyList xs, LazyList ys) { if (xs == null) return ys; else { var x = xs.v; var y = ys.v; if (BigInteger.Compare(x, y) < 0) { var cont = new Lazy>(() => merge(xs.cont.Value, ys)); return new LazyList(x, cont); } else { var cont = new Lazy>(() => merge(xs, ys.cont.Value)); return new LazyList(y, cont); } } } private LazyList llmult(uint mltplr, LazyList ll) { return new LazyList(mltplr * ll.v, new Lazy>(() => llmult(mltplr, ll.cont.Value))); } public IEnumerator GetEnumerator() { Func,uint,LazyList> u = (acc, p) => { LazyList r = null; var cont = new Lazy>(() => r); r = new LazyList(1, cont); r = this.merge(acc, llmult(p, r)); return r; }; yield return 1; for (var stt = primes.Aggregate(null, u); ; stt = stt.cont.Value) yield return stt.v; } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } class Program { static void Main(string[] args) { Console.WriteLine("Calculates the Hamming sequence of numbers.\r\n"); var primes = new uint[] { 5, 3, 2 }; Console.WriteLine(String.Join(" ", (new Hammings(primes)).Take(20).ToArray())); Console.WriteLine((new Hammings(primes)).ElementAt(1691 - 1)); var n = 1000000; var elpsd = -DateTime.Now.Ticks; var num = (new Hammings(primes)).ElementAt(n - 1); elpsd += DateTime.Now.Ticks; Console.WriteLine(num); Console.WriteLine("The {0}th hamming number took {1} milliseconds", n, elpsd / 10000); Console.Write("\r\nPress any key to exit:"); Console.ReadKey(true); Console.WriteLine(); } } }