From 200fd4e85f1abaf3dfa4f2d12c2982438f99b4ae Mon Sep 17 00:00:00 2001 From: Joachim Date: Tue, 28 Aug 2018 20:14:29 +0200 Subject: [PATCH] beat speed, down to 14 seconds now (see crosssolveriteratorupgraded --- src/main/kotlin/be/nielandt/CrossSolver.kt | 11 +++- .../nielandt/CrossSolverIteratorUpgraded.kt | 44 +++++++++++++ .../be/nielandt/EdgeModelFactoryIterator.kt | 66 +++++++++++++++++++ .../iterator/ValidClassMoveIterator.kt | 2 - 4 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 src/main/kotlin/be/nielandt/CrossSolverIteratorUpgraded.kt create mode 100644 src/main/kotlin/be/nielandt/EdgeModelFactoryIterator.kt diff --git a/src/main/kotlin/be/nielandt/CrossSolver.kt b/src/main/kotlin/be/nielandt/CrossSolver.kt index 5c88849..e0c0d0f 100644 --- a/src/main/kotlin/be/nielandt/CrossSolver.kt +++ b/src/main/kotlin/be/nielandt/CrossSolver.kt @@ -32,6 +32,7 @@ open abstract class CrossSolver { * * - no changes: base times: 72s, 29s, 61s * - changed list in edgemodel to intarray: 51s, 21s, 35s + * - new version, optimised now avoid recalc: 47s, 21s, 34s, 14s, (401592291, 147023415, 67382002, 67381995) */ fun main(args: Array) { @@ -82,20 +83,24 @@ fun main(args: Array) { val usedModel = EdgeModel.withMoves(moves) println(usedModel) -// val baseSolve = CrossSolverBase().solveCrossesTimed(usedModel) -// CrossSolver.printResults(baseSolve) val upgradedSolve = CrossSolverUpgraded().solveCrossesTimed(usedModel) CrossSolver.printResults(upgradedSolve) -// + val upgradedSolveSkip = CrossSolverUpgradedSkip().solveCrossesTimed(usedModel) CrossSolver.printResults(upgradedSolveSkip) val solveCrossesTimed = CrossSolverIterator().solveCrossesTimed(usedModel) CrossSolver.printResults(solveCrossesTimed) + + val s3 = CrossSolverIteratorUpgraded().solveCrossesTimed(usedModel) + CrossSolver.printResults(s3) + // val allCrossMoveCountUpgradedSkip = allCrossMoveCountUpgradedSkip(scrambledModel) // allCrossMoveCountUpgradedSkip.forEach { color, moves -> // println("skip upgrade cross for color: ${color} in ${moves.size}: ${moves.joinToString(" ")}") // } +// val baseSolve = CrossSolverBase().solveCrossesTimed(usedModel) +// CrossSolver.printResults(baseSolve) } diff --git a/src/main/kotlin/be/nielandt/CrossSolverIteratorUpgraded.kt b/src/main/kotlin/be/nielandt/CrossSolverIteratorUpgraded.kt new file mode 100644 index 0000000..8484cf5 --- /dev/null +++ b/src/main/kotlin/be/nielandt/CrossSolverIteratorUpgraded.kt @@ -0,0 +1,44 @@ +package be.nielandt + +import be.nielandt.iterator.ValidClassMoveIterator + +/** + * This solver avoids redoing edgemodel manipulations. Should be equivalent to X nested for loops. + */ +class CrossSolverIteratorUpgraded : CrossSolver() { + + override fun solveCrosses(edgeModel: EdgeModel): Map { + val moveCounts = mutableMapOf() + var iteratorCount = 0 + for (moveCount in 1..8) { + println("all cross move count upgrade doing $moveCount") + // build a counter of moveCount big + val counter = ValidClassMoveIterator(moveCount) + val edgeModelFactory = EdgeModelFactoryIterator(edgeModel, counter) + + while (edgeModelFactory.hasNext()) { + // get the next model, using the internal counter which simply iterates over possible combinations of moves + val next = edgeModelFactory.getNext() + iteratorCount++ + + // check crosses that have not been found yet + (0..5).forEach { color -> + if (!moveCounts.containsKey(color)) { + val crossSolved = next.crossSolved(color) + if (crossSolved) { + // what is the move combination we're looking at? + moveCounts[color] = edgeModelFactory.movesOfCurrent().copyOf() + } + } + } + // break if we have found hem all + if (moveCounts.keys.size == 6) { + println("iteratorCount = $iteratorCount") + return moveCounts + } + } + } + println("had to do it all... iteratorCount = $iteratorCount") + return moveCounts + } +} \ No newline at end of file diff --git a/src/main/kotlin/be/nielandt/EdgeModelFactoryIterator.kt b/src/main/kotlin/be/nielandt/EdgeModelFactoryIterator.kt new file mode 100644 index 0000000..87f922b --- /dev/null +++ b/src/main/kotlin/be/nielandt/EdgeModelFactoryIterator.kt @@ -0,0 +1,66 @@ +package be.nielandt + +/** + * This thing helps us to create edgemodels using a counter. The advantage is that the edgemodel doesn't need to be calculated + * completely from scratch: previous states are kept, so if, e.g., the third digit changes in the counter (of length 5), + * the previous state that was calculated using the first two states is used to perform move 3,4,5 on. + * + * This is probably equivalent to 8 nested for loops, you'd be able to keep track of temporary solutions there too.... + */ +class EdgeModelFactoryIterator(val original: EdgeModel, val counter: Iterator) { + // keep a modified version of the edgemodel for each digit in the counter, from left to right + private val history: MutableList = mutableListOf() + private var previous:IntArray + private var lastMoves: IntArray + + init { + // init the history + val firstOne = counter.next() + lastMoves = firstOne + this.history.add(original.doMove(firstOne[0])) + for (i in 1 until firstOne.size) { + this.history.add(this.history.last().doMove(firstOne[i])) + } + // keep track of the 'previous move that was performed' + previous = firstOne + } + + fun hasNext(): Boolean { + return counter.hasNext() + } + + fun movesOfCurrent() : IntArray { + return previous + } + + fun getNext(): EdgeModel { + // the next set of moves + val moves = counter.next() + this.lastMoves = moves + // figure out the first index that differs + val lastModifiedIndex = firstDifferingIndex(previous, moves) + // we only need to redo everything starting from the lastoverflowindex + // these are our moves, but we can salvage everything up to lastoverflowindex + // we have a history to work with... only redo what's necessary + for (i in lastModifiedIndex until moves.size) { + var start: EdgeModel = if (i == 0) + original + else + history[i - 1] + history[i] = start.doMove(moves[i]) + } + // bump the previous value + previous = moves + // the last item in the history is now the edgemodel we need to test... + return history.last() + } + + private fun firstDifferingIndex(previous: IntArray, moves: IntArray): Int { + previous.forEachIndexed { index, i -> + if(previous[index] != moves[index]) + return index + } + // nothing changed.. that's probably impossible + throw IllegalStateException() + } +} \ No newline at end of file diff --git a/src/main/kotlin/be/nielandt/iterator/ValidClassMoveIterator.kt b/src/main/kotlin/be/nielandt/iterator/ValidClassMoveIterator.kt index 76555cc..f240108 100644 --- a/src/main/kotlin/be/nielandt/iterator/ValidClassMoveIterator.kt +++ b/src/main/kotlin/be/nielandt/iterator/ValidClassMoveIterator.kt @@ -1,7 +1,5 @@ package be.nielandt.iterator -import be.nielandt.decodeMove - class ValidClassMoveIterator(val size: Int) : Iterator { // current level of the iterator