beat speed, down to 14 seconds now (see crosssolveriteratorupgraded

This commit is contained in:
Joachim 2018-08-28 20:14:29 +02:00
parent f7a2e30832
commit 200fd4e85f
4 changed files with 118 additions and 5 deletions

View File

@ -32,6 +32,7 @@ open abstract class CrossSolver {
*
* - no changes: base times: 72s, 29s, 61s
* - changed list<int> 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<String>) {
@ -82,20 +83,24 @@ fun main(args: Array<String>) {
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)
}

View File

@ -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<Int, IntArray> {
val moveCounts = mutableMapOf<Int, IntArray>()
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
}
}

View File

@ -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<IntArray>) {
// keep a modified version of the edgemodel for each digit in the counter, from left to right
private val history: MutableList<EdgeModel> = 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()
}
}

View File

@ -1,7 +1,5 @@
package be.nielandt.iterator
import be.nielandt.decodeMove
class ValidClassMoveIterator(val size: Int) : Iterator<IntArray> {
// current level of the iterator