using System; using System.Collections; public abstract class IntSequence: IEnumerable { public abstract IEnumerator GetEnumerator(); public abstract int Min {get;} public abstract int Max {get;} } public class IntInterval: IntSequence{ private int from, to; public IntInterval(int from, int to){ this.from = from; this.to = to; } public override int Min{ get {return Math.Min(from,to);} } public override int Max{ get {return Math.Max(from,to);} } public override IEnumerator GetEnumerator (){ return new IntervalEnumerator(this); } private class IntervalEnumerator: IEnumerator{ private readonly IntInterval interval; private int idx; public IntervalEnumerator (IntInterval i){ this.interval = i; idx = -1; // position enumerator outside range } public Object Current{ get {return (interval.from < interval.to) ? interval.from + idx : interval.from - idx;} } public bool MoveNext (){ if ( idx < Math.Abs(interval.to - interval.from)) {idx++; return true;} else {return false;} } public void Reset(){ idx = -1; } } } public class IntSingular: IntSequence{ private int it; public IntSingular(int it){ this.it = it; } public override int Min{ get {return it;} } public override int Max{ get {return it;} } public override IEnumerator GetEnumerator (){ return new SingularEnumerator(this); } private class SingularEnumerator: IEnumerator{ private readonly IntSingular ints; private int idx; public SingularEnumerator (IntSingular ints){ this.ints = ints; idx = -1; // position enumerator outside range } public Object Current{ get {return ints.it;} } public bool MoveNext (){ if (idx == -1) {idx++; return true;} else {return false;} } public void Reset(){ idx = -1; } } } // Binary sequence: Exactly two subsequences. public class IntCompSeq: IntSequence{ private IntSequence s1, s2; public IntCompSeq(IntSequence s1, IntSequence s2) { this.s1 = s1; this.s2 = s2; } public override int Min{ get {return Math.Min(s1.Min,s2.Min);} } public override int Max{ get {return Math.Max(s1.Max, s2.Max);} } public override IEnumerator GetEnumerator (){ return new CompositeEnumerator(this); } private class CompositeEnumerator: IEnumerator{ private IntSequence s1, s2; private int idx; // 0: not started. // 1: s1 is current. 2: s2 is current. private IEnumerator idxEnumerator; public CompositeEnumerator (IntCompSeq outerIntCompSeq){ this.s1 = outerIntCompSeq.s1; this.s2 = outerIntCompSeq.s2; idx = 0; // 0: outside. 1: at s1. 2: at s2 idxEnumerator = null; } public Object Current{ get {return idxEnumerator.Current;} } public bool MoveNext (){ if (idx == 0){ // At start position. idx = 1; idxEnumerator = s1.GetEnumerator(); return idxEnumerator.MoveNext(); } else if (idx == 1){ // At left sequence bool hasMoved1 = idxEnumerator.MoveNext(); if (hasMoved1) return true; else{ idxEnumerator = s2.GetEnumerator(); idx = 2; return idxEnumerator.MoveNext(); } } else if (idx == 2) { // At right sequence bool hasMoved2 = idxEnumerator.MoveNext(); if (hasMoved2) return true; else return false; } else return false; } public void Reset(){ idx = 0; } } }