94 lines
2.6 KiB
Kotlin
94 lines
2.6 KiB
Kotlin
package be.nielandt
|
|
|
|
import kotlin.math.min
|
|
|
|
/**
|
|
* Counter for X digits of a given base.
|
|
*/
|
|
open class Counter(size: Int, val base: Int = 10) {
|
|
|
|
/**
|
|
* Empty counter, all 0 values for each digit.
|
|
*/
|
|
protected var counter: Array<Int> = Array(size) { 0 }
|
|
|
|
/**
|
|
* The last (highest significance) index that overflowed and has been changed in the counter. Could be null, if it never overflowed.
|
|
* Start with saying that everything changed.
|
|
*/
|
|
var lastModifiedIndex: Int = 0
|
|
|
|
/**
|
|
* Increase the counter.
|
|
*
|
|
* @return true if the increase happened, false if we hit the ceiling.
|
|
*/
|
|
open fun increase(): Boolean {
|
|
if (atMax()) {
|
|
return false
|
|
}
|
|
for (i in this.counter.size - 1 downTo 0) {
|
|
this.counter[i]++
|
|
this.lastModifiedIndex = i
|
|
if (this.counter[i] == base) {
|
|
this.counter[i] = 0
|
|
} else {
|
|
// keep track of the digit index we're breaking on.
|
|
break
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
fun increaseAndSkipInvalid(): Boolean {
|
|
var lmi = lastModifiedIndex
|
|
var last = increase()
|
|
lmi = min(lastModifiedIndex, lmi)
|
|
// are we having an invalid situation? this would be two consecutive moves on the same face
|
|
while (containsConsecutiveSameFaceMoves() && !atMax()) {
|
|
last = increase()
|
|
lmi = min(lastModifiedIndex, lmi)
|
|
}
|
|
// we have to set the lastmodified index to the lowest point that it got to... otherwise we might be skipping some cases
|
|
this.lastModifiedIndex = lmi
|
|
return last
|
|
}
|
|
|
|
/**
|
|
* Are there two moves in the current counter / chain that act on the same face? This would be F+F2 for example.
|
|
*/
|
|
private fun containsConsecutiveSameFaceMoves(): Boolean {
|
|
for (i in 1 until this.counter.size) {
|
|
val current = Move.values()[this.counter[i]]
|
|
val previous = Move.values()[this.counter[i - 1]]
|
|
if (current sameFace previous)
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* How many digits does this counter contain?
|
|
*/
|
|
fun size(): Int {
|
|
return this.counter.size
|
|
}
|
|
|
|
/**
|
|
* Get the digit at the given index.
|
|
*/
|
|
fun digit(index: Int): Int {
|
|
return counter[index]
|
|
}
|
|
|
|
override fun toString(): String = this.counter.joinToString(".")
|
|
|
|
/**
|
|
* Have we reached the maximum value?
|
|
*/
|
|
fun atMax(): Boolean {
|
|
return counter.all {
|
|
it == this.base - 1
|
|
}
|
|
}
|
|
} |