beat speed, down to 14 seconds now (see crosssolveriteratorupgraded
This commit is contained in:
parent
f7a2e30832
commit
200fd4e85f
@ -32,6 +32,7 @@ open abstract class CrossSolver {
|
|||||||
*
|
*
|
||||||
* - no changes: base times: 72s, 29s, 61s
|
* - no changes: base times: 72s, 29s, 61s
|
||||||
* - changed list<int> in edgemodel to intarray: 51s, 21s, 35s
|
* - 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>) {
|
fun main(args: Array<String>) {
|
||||||
|
|
||||||
@ -82,20 +83,24 @@ fun main(args: Array<String>) {
|
|||||||
val usedModel = EdgeModel.withMoves(moves)
|
val usedModel = EdgeModel.withMoves(moves)
|
||||||
println(usedModel)
|
println(usedModel)
|
||||||
|
|
||||||
// val baseSolve = CrossSolverBase().solveCrossesTimed(usedModel)
|
|
||||||
// CrossSolver.printResults(baseSolve)
|
|
||||||
|
|
||||||
val upgradedSolve = CrossSolverUpgraded().solveCrossesTimed(usedModel)
|
val upgradedSolve = CrossSolverUpgraded().solveCrossesTimed(usedModel)
|
||||||
CrossSolver.printResults(upgradedSolve)
|
CrossSolver.printResults(upgradedSolve)
|
||||||
//
|
|
||||||
val upgradedSolveSkip = CrossSolverUpgradedSkip().solveCrossesTimed(usedModel)
|
val upgradedSolveSkip = CrossSolverUpgradedSkip().solveCrossesTimed(usedModel)
|
||||||
CrossSolver.printResults(upgradedSolveSkip)
|
CrossSolver.printResults(upgradedSolveSkip)
|
||||||
|
|
||||||
val solveCrossesTimed = CrossSolverIterator().solveCrossesTimed(usedModel)
|
val solveCrossesTimed = CrossSolverIterator().solveCrossesTimed(usedModel)
|
||||||
CrossSolver.printResults(solveCrossesTimed)
|
CrossSolver.printResults(solveCrossesTimed)
|
||||||
|
|
||||||
|
val s3 = CrossSolverIteratorUpgraded().solveCrossesTimed(usedModel)
|
||||||
|
CrossSolver.printResults(s3)
|
||||||
|
|
||||||
// val allCrossMoveCountUpgradedSkip = allCrossMoveCountUpgradedSkip(scrambledModel)
|
// val allCrossMoveCountUpgradedSkip = allCrossMoveCountUpgradedSkip(scrambledModel)
|
||||||
// allCrossMoveCountUpgradedSkip.forEach { color, moves ->
|
// allCrossMoveCountUpgradedSkip.forEach { color, moves ->
|
||||||
// println("skip upgrade cross for color: ${color} in ${moves.size}: ${moves.joinToString(" ")}")
|
// println("skip upgrade cross for color: ${color} in ${moves.size}: ${moves.joinToString(" ")}")
|
||||||
// }
|
// }
|
||||||
|
// val baseSolve = CrossSolverBase().solveCrossesTimed(usedModel)
|
||||||
|
// CrossSolver.printResults(baseSolve)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
44
src/main/kotlin/be/nielandt/CrossSolverIteratorUpgraded.kt
Normal file
44
src/main/kotlin/be/nielandt/CrossSolverIteratorUpgraded.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
66
src/main/kotlin/be/nielandt/EdgeModelFactoryIterator.kt
Normal file
66
src/main/kotlin/be/nielandt/EdgeModelFactoryIterator.kt
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,5 @@
|
|||||||
package be.nielandt.iterator
|
package be.nielandt.iterator
|
||||||
|
|
||||||
import be.nielandt.decodeMove
|
|
||||||
|
|
||||||
class ValidClassMoveIterator(val size: Int) : Iterator<IntArray> {
|
class ValidClassMoveIterator(val size: Int) : Iterator<IntArray> {
|
||||||
|
|
||||||
// current level of the iterator
|
// current level of the iterator
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user