Classify: class { - _iter; - _state: "homo"; - _majority: null; - _minority: null; initialize: method(_iter) {} + classify: method(n: null) { return each_classify(n).to_a.back; } + each_classify: method(n: null) fiber { iter: n ? _iter.take(n) : _iter; iter.with_index {|i,it| this.(_state)(i, it); if (_state == "hetero") { break; } } } - homo: method(i, it) { if (_majority && _majority != it) { _minority = it; if (i < 2) { _state = "quasi_homo0"; yield ["?", _majority, _minority]; } else { _state = "quasi_homo"; yield ["quasi_homo", _majority, _minority]; } } else { _majority = it; yield ["homo", it]; } } - quasi_homo0: method(i, it) { if (it == _majority || it == _minority) { if (it == _minority) { _majority, _minority = _minority, _majority; } yield ["quasi_homo", _majority, _minority]; _state = "quasi_homo"; } else { hetero(i, it); } } - quasi_homo: method(i, it) { if (it == _majority) { yield ["quasi_homo", _majority, _minority]; } else { hetero(i, it); } } - hetero: method(i, it) { _state = "hetero"; yield ["hetero", null]; } } Classify([1,1,1,1,1].each).classify.p; //=> [homo,1] Classify([1,2,1,1,1].each).classify.p; //=> [quasi_homo,1,2] Classify([2,1,1,1,1].each).classify.p; //=> [quasi_homo,1,2] Classify([2,2,1,1,1].each).classify.p; //=> [hetero,null] Classify([2,4,1,1,1].each).classify.p; //=> [hetero,null] Classify([1,2,3,4,5].each).classify.p; //=> [hetero,null] Classify([2,1,1,1,3].each).each_classify { it.p; } //=> [homo,2] //=> [?,2,1] //=> [quasi_homo,1,2] //=> [quasi_homo,1,2] //=> [hetero,null] Classify([1,1,3].cycle).classify(5).p; //=> [quasi_homo,1,3] Classify([1,1,3].cycle).classify(6).p; //=> [hetero,null] Classify([1,2,3].cycle).classify.p; //=> [hetero,null]