From 60b2b3bb1aafac95ffb88cbf039afc707558a511 Mon Sep 17 00:00:00 2001 From: Joachim Date: Sat, 25 Aug 2018 10:48:39 +0200 Subject: [PATCH] ok, let's try and improve the skip solution --- src/main/kotlin/be/nielandt/Counter.kt | 12 ++---- .../be/nielandt/CounterSkipSameFaces.kt | 41 +++++++++++++++++++ src/main/kotlin/be/nielandt/CrossSolver.kt | 9 ++-- .../kotlin/be/nielandt/CrossSolverUpgraded.kt | 4 -- .../be/nielandt/CrossSolverUpgradedSkip.kt | 7 +--- .../kotlin/be/nielandt/EdgeModelFactory.kt | 4 +- 6 files changed, 54 insertions(+), 23 deletions(-) create mode 100644 src/main/kotlin/be/nielandt/CounterSkipSameFaces.kt diff --git a/src/main/kotlin/be/nielandt/Counter.kt b/src/main/kotlin/be/nielandt/Counter.kt index 58f0e25..551b30c 100644 --- a/src/main/kotlin/be/nielandt/Counter.kt +++ b/src/main/kotlin/be/nielandt/Counter.kt @@ -5,29 +5,25 @@ import kotlin.math.min /** * Counter for X digits of a given base. */ -class Counter(size: Int, val base: Int = 10) { +open class Counter(size: Int, val base: Int = 10) { /** * Empty counter, all 0 values for each digit. */ - private var counter: Array = Array(size) { 0 } + protected var counter: Array = 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. */ - private var lastModifiedIndex: Int = 0 - - fun getLastModifiedIndex(): Int { - return this.lastModifiedIndex - } + var lastModifiedIndex: Int = 0 /** * Increase the counter. * * @return true if the increase happened, false if we hit the ceiling. */ - fun increase(): Boolean { + open fun increase(): Boolean { if (atMax()) { return false } diff --git a/src/main/kotlin/be/nielandt/CounterSkipSameFaces.kt b/src/main/kotlin/be/nielandt/CounterSkipSameFaces.kt new file mode 100644 index 0000000..dcf921f --- /dev/null +++ b/src/main/kotlin/be/nielandt/CounterSkipSameFaces.kt @@ -0,0 +1,41 @@ +package be.nielandt + +import kotlin.math.min + +/** + * Counter for X digits of a given base. Skips situations where faces are the same. + */ +class CounterSkipSameFaces(size: Int, base: Int = 10): Counter(size, base) { + + /** + * Increase the counter. + * + * @return true if the increase happened, false if we hit the ceiling. + */ + override fun increase(): Boolean { + var lmi = lastModifiedIndex + var last = super.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 = super.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 + } +} \ No newline at end of file diff --git a/src/main/kotlin/be/nielandt/CrossSolver.kt b/src/main/kotlin/be/nielandt/CrossSolver.kt index f561198..fca6f0b 100644 --- a/src/main/kotlin/be/nielandt/CrossSolver.kt +++ b/src/main/kotlin/be/nielandt/CrossSolver.kt @@ -67,17 +67,20 @@ fun main(args: Array) { // scramble random - val moves = Move.random(20) + val moves = Move.random(10) println("Scramble: $moves") val scrambledModel = EdgeModel(moves) println(scrambledModel) - val baseSolve = CrossSolverBase().solveCrossesTimed(scrambledModel) - CrossSolver.printResults(baseSolve) +// val baseSolve = CrossSolverBase().solveCrossesTimed(scrambledModel) +// CrossSolver.printResults(baseSolve) val upgradedSolve = CrossSolverUpgraded().solveCrossesTimed(scrambledModel) CrossSolver.printResults(upgradedSolve) + val upgradedSolveSkip = CrossSolverUpgradedSkip().solveCrossesTimed(scrambledModel) + CrossSolver.printResults(upgradedSolveSkip) + // val allCrossMoveCountUpgradedSkip = allCrossMoveCountUpgradedSkip(scrambledModel) // allCrossMoveCountUpgradedSkip.forEach { color, moves -> // println("skip upgrade cross for color: ${color} in ${moves.size}: ${moves.joinToString(" ")}") diff --git a/src/main/kotlin/be/nielandt/CrossSolverUpgraded.kt b/src/main/kotlin/be/nielandt/CrossSolverUpgraded.kt index 3e8ff1c..042f0ab 100644 --- a/src/main/kotlin/be/nielandt/CrossSolverUpgraded.kt +++ b/src/main/kotlin/be/nielandt/CrossSolverUpgraded.kt @@ -1,16 +1,12 @@ package be.nielandt -import java.time.Instant - /** * This solver avoids redoing edgemodel manipulations. Should be equivalent to X nested for loops. */ class CrossSolverUpgraded : CrossSolver() { override fun solveCrosses(edgeModel: EdgeModel): Map> { - val start = Instant.now() val moveCounts = mutableMapOf>() - for (moveCount in 1..8) { println("all cross move count upgrade doing $moveCount") // build a counter of moveCount big diff --git a/src/main/kotlin/be/nielandt/CrossSolverUpgradedSkip.kt b/src/main/kotlin/be/nielandt/CrossSolverUpgradedSkip.kt index 12d21f0..af9a634 100644 --- a/src/main/kotlin/be/nielandt/CrossSolverUpgradedSkip.kt +++ b/src/main/kotlin/be/nielandt/CrossSolverUpgradedSkip.kt @@ -7,16 +7,12 @@ class CrossSolverUpgradedSkip : CrossSolver() { override fun solveCrosses(edgeModel: EdgeModel): Map> { val moveCounts = mutableMapOf>() - for (moveCount in 1..8) { println("all cross move count upgrade doing $moveCount") // build a counter of moveCount big - val counter = Counter(moveCount, Move.values().size) - // TODO skip the counter + val counter = CounterSkipSameFaces(moveCount, Move.values().size) val edgeModelFactory = EdgeModelFactory(edgeModel, counter) - println("moveCounts = ${moveCounts}") - while (edgeModelFactory.hasNext()) { // get the next model, using the internal counter which simply iterates over possible combinations of moves val next = edgeModelFactory.getNext() @@ -34,7 +30,6 @@ class CrossSolverUpgradedSkip : CrossSolver() { } // break if we have found hem all if (moveCounts.keys.size == 6) { -// println("counter.skipInvalidCount = ${counter.skipInvalidCount}") return moveCounts } } diff --git a/src/main/kotlin/be/nielandt/EdgeModelFactory.kt b/src/main/kotlin/be/nielandt/EdgeModelFactory.kt index 869b8d7..00d1b7a 100644 --- a/src/main/kotlin/be/nielandt/EdgeModelFactory.kt +++ b/src/main/kotlin/be/nielandt/EdgeModelFactory.kt @@ -28,12 +28,12 @@ class EdgeModelFactory(val original: EdgeModel, val counter: Counter) { fun getNext(): EdgeModel { // the counter was increased, hooray - val lastOverflowIndex = counter.getLastModifiedIndex() + val lastOverflowIndex = counter.lastModifiedIndex // we only need to redo everything starting from the lastoverflowindex // these are our moves, but we can salvage everything up to lastoverflowindex val moves = Move.combo(counter) // we have a history to work with... only redo what's necessary - for (i in counter.getLastModifiedIndex() until counter.size()) { + for (i in counter.lastModifiedIndex until counter.size()) { var start: EdgeModel = if (i == 0) original else