From 80179e9b68c5ba405584d3ac60b13abe4f5d36f9 Mon Sep 17 00:00:00 2001 From: Joachim Date: Mon, 27 Aug 2018 22:31:02 +0200 Subject: [PATCH] Cross solver iterator seems to be working. --- src/main/kotlin/be/nielandt/CrossSolver.kt | 6 +- .../kotlin/be/nielandt/CrossSolverBase.kt | 7 +-- .../kotlin/be/nielandt/CrossSolverIterator.kt | 48 ++++++++++++++++ .../kotlin/be/nielandt/CrossSolverUpgraded.kt | 6 +- .../be/nielandt/CrossSolverUpgradedSkip.kt | 6 +- src/main/kotlin/be/nielandt/EdgeModel.kt | 20 +++---- src/main/kotlin/be/nielandt/Move.kt | 4 +- .../kotlin/be/nielandt/counter/Counter.kt | 2 +- .../be/nielandt/counter/CounterBasic.kt | 9 +++ .../be/nielandt/counter/CounterBuffer.kt | 4 +- .../be/nielandt/counter/CounterTiered.kt | 14 ++--- .../iterator/ValidClassMoveIterator.kt | 57 +++++++++++++++++++ .../be/nielandt/iterator/ValidMoveIterator.kt | 5 +- 13 files changed, 148 insertions(+), 40 deletions(-) create mode 100644 src/main/kotlin/be/nielandt/CrossSolverIterator.kt create mode 100644 src/main/kotlin/be/nielandt/iterator/ValidClassMoveIterator.kt diff --git a/src/main/kotlin/be/nielandt/CrossSolver.kt b/src/main/kotlin/be/nielandt/CrossSolver.kt index 5fce47c..e10ab1a 100644 --- a/src/main/kotlin/be/nielandt/CrossSolver.kt +++ b/src/main/kotlin/be/nielandt/CrossSolver.kt @@ -7,9 +7,9 @@ open abstract class CrossSolver { /** * Solve all crosses, look for a minimal set of moves for each color's cross. */ - abstract fun solveCrosses(edgeModel: EdgeModel): Map> + abstract fun solveCrosses(edgeModel: EdgeModel): Map - fun solveCrossesTimed(edgeModel: EdgeModel): Map> { + fun solveCrossesTimed(edgeModel: EdgeModel): Map { val now = Instant.now() val solveCrosses = solveCrosses(edgeModel) val between = Duration.between(now, Instant.now()) @@ -18,7 +18,7 @@ open abstract class CrossSolver { } companion object { - fun printResults(results: Map>) { + fun printResults(results: Map) { println("results: ") results.forEach { color, moveList -> println("> color ${colorLetter(color)}, moves (${moveList.size}) ${moveList.map { it -> decodeMove(it) }}") diff --git a/src/main/kotlin/be/nielandt/CrossSolverBase.kt b/src/main/kotlin/be/nielandt/CrossSolverBase.kt index df2c8c0..10dfa1f 100644 --- a/src/main/kotlin/be/nielandt/CrossSolverBase.kt +++ b/src/main/kotlin/be/nielandt/CrossSolverBase.kt @@ -1,14 +1,13 @@ package be.nielandt -import be.nielandt.counter.CounterBasic import be.nielandt.counter.CounterTieredFactory class CrossSolverBase : CrossSolver() { /** * Solve the minimal cross for all colors. */ - override fun solveCrosses(edgeModel: EdgeModel): Map> { - val moveCounts = mutableMapOf>() + override fun solveCrosses(edgeModel: EdgeModel): Map { + val moveCounts = mutableMapOf() for (moveCount in 1..8) { // build a counter of moveCount big @@ -24,7 +23,7 @@ class CrossSolverBase : CrossSolver() { if (!moveCounts.containsKey(color)) { val crossSolved = afterMoves.crossSolved(color) if (crossSolved) { - moveCounts[color] = counter.counter.toList() + moveCounts[color] = counter.counter.copyOf() } } } diff --git a/src/main/kotlin/be/nielandt/CrossSolverIterator.kt b/src/main/kotlin/be/nielandt/CrossSolverIterator.kt new file mode 100644 index 0000000..f28b0ad --- /dev/null +++ b/src/main/kotlin/be/nielandt/CrossSolverIterator.kt @@ -0,0 +1,48 @@ +package be.nielandt + +import be.nielandt.iterator.ValidClassMoveIterator + +class CrossSolverIterator : CrossSolver() { + /** + * Solve the minimal cross for all colors. + */ + override fun solveCrosses(edgeModel: EdgeModel): Map { + val moveCounts = mutableMapOf() + + for (moveCount in 1..8) { + // build a counter of moveCount big + println("crossSolverIterator doing $moveCount") + val iterator = ValidClassMoveIterator(moveCount) + + // count up, each state of the counter corresponds to a combination of moves + while (iterator.hasNext()) { + val moves = iterator.next() + // execute the moves + val afterMoves = edgeModel.doMoves(moves.toList()) + // check crosses that have not been found yet + (0..5).forEach { color -> + if (!moveCounts.containsKey(color)) { + val crossSolved = afterMoves.crossSolved(color) + if (crossSolved) { + moveCounts[color] = moves + } + } + } + if (moveCounts.keys.size == 6) { + return@solveCrosses moveCounts + } + } + } + return moveCounts + } + +} + +fun main(args: Array) { + val start = EdgeModel().doMoves(randomMoves(20)) + val solver = CrossSolverIterator() + val solveCrossesTimed = solver.solveCrossesTimed(start) + solveCrossesTimed.forEach { t, u -> + println("t $t u ${u.map { decodeMove(it) }}") + } +} \ No newline at end of file diff --git a/src/main/kotlin/be/nielandt/CrossSolverUpgraded.kt b/src/main/kotlin/be/nielandt/CrossSolverUpgraded.kt index ce6f69a..5dc5133 100644 --- a/src/main/kotlin/be/nielandt/CrossSolverUpgraded.kt +++ b/src/main/kotlin/be/nielandt/CrossSolverUpgraded.kt @@ -7,8 +7,8 @@ import be.nielandt.counter.CounterBasic */ class CrossSolverUpgraded : CrossSolver() { - override fun solveCrosses(edgeModel: EdgeModel): Map> { - val moveCounts = mutableMapOf>() + 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 @@ -25,7 +25,7 @@ class CrossSolverUpgraded : CrossSolver() { val crossSolved = next.crossSolved(color) if (crossSolved) { // what is the move combination we're looking at? - moveCounts[color] = counter.counter.toList() + moveCounts[color] = counter.counter.copyOf() } } } diff --git a/src/main/kotlin/be/nielandt/CrossSolverUpgradedSkip.kt b/src/main/kotlin/be/nielandt/CrossSolverUpgradedSkip.kt index 5730500..cddc863 100644 --- a/src/main/kotlin/be/nielandt/CrossSolverUpgradedSkip.kt +++ b/src/main/kotlin/be/nielandt/CrossSolverUpgradedSkip.kt @@ -7,8 +7,8 @@ import be.nielandt.counter.CounterSkip */ class CrossSolverUpgradedSkip : CrossSolver() { - override fun solveCrosses(edgeModel: EdgeModel): Map> { - val moveCounts = mutableMapOf>() + 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 @@ -25,7 +25,7 @@ class CrossSolverUpgradedSkip : CrossSolver() { val crossSolved = next.crossSolved(color) if (crossSolved) { // what is the move combination we're looking at? - moveCounts[color] = counter.counter.toList() + moveCounts[color] = counter.counter.copyOf() } } } diff --git a/src/main/kotlin/be/nielandt/EdgeModel.kt b/src/main/kotlin/be/nielandt/EdgeModel.kt index 3120441..985d75d 100644 --- a/src/main/kotlin/be/nielandt/EdgeModel.kt +++ b/src/main/kotlin/be/nielandt/EdgeModel.kt @@ -57,8 +57,8 @@ class EdgeModel { constructor(randomMoves: Int) { val edgeModel = EdgeModel() - val r: Array = randomMoves(randomMoves) - val doMoves = edgeModel.doMoves(r) + val r: IntArray = randomMoves(randomMoves) + val doMoves = edgeModel.doMoves(r.toList()) this.model = doMoves.model } @@ -171,14 +171,6 @@ class EdgeModel { return trimMargin } - fun doMoves(f: Array) : EdgeModel { - var edgeModel = this - f.forEach { - edgeModel = edgeModel.doMove(it) - } - return edgeModel - } - fun doMoves(f: Collection): EdgeModel { var edgeModel = this f.forEach { @@ -187,8 +179,12 @@ class EdgeModel { return edgeModel } - fun doMoves(vararg f: Int): EdgeModel { - return this.doMoves(f.toList()) + fun doMoves(f: IntArray): EdgeModel { + var edgeModel = this + f.forEach { + edgeModel = edgeModel.doMove(it) + } + return edgeModel } /** diff --git a/src/main/kotlin/be/nielandt/Move.kt b/src/main/kotlin/be/nielandt/Move.kt index 549fbbf..e6a9750 100644 --- a/src/main/kotlin/be/nielandt/Move.kt +++ b/src/main/kotlin/be/nielandt/Move.kt @@ -91,9 +91,9 @@ fun parseMove(s: String): Int { } } -fun randomMoves(amount: Int): Array { +fun randomMoves(amount: Int): IntArray { val rgen = Random() - return Array(amount) { + return IntArray(amount) { rgen.nextInt(18) } } diff --git a/src/main/kotlin/be/nielandt/counter/Counter.kt b/src/main/kotlin/be/nielandt/counter/Counter.kt index 2a0061a..75db173 100644 --- a/src/main/kotlin/be/nielandt/counter/Counter.kt +++ b/src/main/kotlin/be/nielandt/counter/Counter.kt @@ -12,7 +12,7 @@ open abstract class Counter(size: Int, val base: Int = 18) { /** * Empty counter, all 0 values for each digit. */ - var counter: Array = Array(size) { 0 } + var counter: IntArray = IntArray(size) { 0 } /** * The last (highest significance) index that overflowed and has been changed in the counter. Could be null, if it never overflowed. diff --git a/src/main/kotlin/be/nielandt/counter/CounterBasic.kt b/src/main/kotlin/be/nielandt/counter/CounterBasic.kt index a5bbf72..3787684 100644 --- a/src/main/kotlin/be/nielandt/counter/CounterBasic.kt +++ b/src/main/kotlin/be/nielandt/counter/CounterBasic.kt @@ -61,3 +61,12 @@ class CounterBasic(size: Int) : Counter(size, 18) { } } + +fun main(args: Array) { + val counterBasic = CounterBasic(7) + var count = 0 + while(counterBasic.increase()) + count++ + println("count = ${count}") + +} diff --git a/src/main/kotlin/be/nielandt/counter/CounterBuffer.kt b/src/main/kotlin/be/nielandt/counter/CounterBuffer.kt index ebef94d..7401712 100644 --- a/src/main/kotlin/be/nielandt/counter/CounterBuffer.kt +++ b/src/main/kotlin/be/nielandt/counter/CounterBuffer.kt @@ -7,14 +7,14 @@ import be.nielandt.classOf */ class CounterBuffer(size: Int) : Counter(size, 18) { - val buffer = mutableListOf>() + val buffer = mutableListOf() init { // initialise the buffer of valid counters val counterBasic = CounterBasic(size) do { if (counterBasic.isValid()) { - buffer.add(counterBasic.counter) + buffer.add(counterBasic.counter.copyOf()) } } while (counterBasic.increase()) println("Init of counter buffer, ${buffer.size} valid combos") diff --git a/src/main/kotlin/be/nielandt/counter/CounterTiered.kt b/src/main/kotlin/be/nielandt/counter/CounterTiered.kt index 8a58d5b..2563454 100644 --- a/src/main/kotlin/be/nielandt/counter/CounterTiered.kt +++ b/src/main/kotlin/be/nielandt/counter/CounterTiered.kt @@ -9,7 +9,7 @@ import be.nielandt.decodeMove */ class CounterTiered : Counter(8) { - private val moveIterator: Iterator> = listOf>().iterator() + private val moveIterator: Iterator = listOf().iterator() override fun increase(): Boolean { if (!this.moveIterator.hasNext()) @@ -22,10 +22,10 @@ class CounterTiered : Counter(8) { return !this.moveIterator.hasNext() } - private class MoveIterator(val classes: List>) : Iterator> { + private class MoveIterator(val classes: List) : Iterator { var currentClassIndex = 0 - lateinit var currentMoves: Iterator> + lateinit var currentMoves: Iterator init { @@ -34,11 +34,11 @@ class CounterTiered : Counter(8) { } private fun doClass(index: Int) { - val fillIn = fillIn(0, classes[index], Array(classes.size) { 0 }) + val fillIn = fillIn(0, classes[index], IntArray(classes.size) { 0 }) currentMoves = fillIn.toList().iterator() } - override fun next(): Array { + override fun next(): IntArray { val next = currentMoves.next() if (!currentMoves.hasNext()) { nextClass() @@ -97,8 +97,8 @@ const val D2 = 15 const val L2 = 16 const val R2 = 17 */ -fun fillIn(index: Int, classes: List, moveList: Array): List> { - val result = mutableListOf>() +fun fillIn(index: Int, classes: IntArray, moveList: IntArray): List { + val result = mutableListOf() // if the movelist is complete, finish it if (index == classes.size) { diff --git a/src/main/kotlin/be/nielandt/iterator/ValidClassMoveIterator.kt b/src/main/kotlin/be/nielandt/iterator/ValidClassMoveIterator.kt new file mode 100644 index 0000000..76555cc --- /dev/null +++ b/src/main/kotlin/be/nielandt/iterator/ValidClassMoveIterator.kt @@ -0,0 +1,57 @@ +package be.nielandt.iterator + +import be.nielandt.decodeMove + +class ValidClassMoveIterator(val size: Int) : Iterator { + + // current level of the iterator + var classesIterator = ValidClassesIterator(size) + var movesIterator: ValidMoveIterator + + init { + this.movesIterator = ValidMoveIterator(classesIterator.next()) + } + + override fun hasNext(): Boolean { + // check if we have another move in the move iterator + return if (this.movesIterator.hasNext()) { + true + } else { + // the moves iterator does not has any more juice, move to the next class + if (!this.classesIterator.hasNext()) { + false + } else { + nextClass() + this.movesIterator.hasNext() + } + } + } + + override fun next(): IntArray { + // check if there's a valid move left + if (!this.movesIterator.hasNext()) { + nextClass() + } + // now we're sure there's something left + return this.movesIterator.next() + } + + /** + * Bump the 'current class'. This means we have a new moves iterator at our disposal. + */ + private fun nextClass() { + val next = this.classesIterator.next() + this.movesIterator = ValidMoveIterator(next) + } +} + +fun main(args: Array) { + val validClassMoveIterator = ValidClassMoveIterator(8) + var count=0 + while (validClassMoveIterator.hasNext()) { + validClassMoveIterator.next() +// println("Arrays.toString(validClassMoveIterator.next()) = ${validClassMoveIterator.next().map { decodeMove(it) }}") + count++ + } + println("count = ${count}") +} \ No newline at end of file diff --git a/src/main/kotlin/be/nielandt/iterator/ValidMoveIterator.kt b/src/main/kotlin/be/nielandt/iterator/ValidMoveIterator.kt index b600c78..ab7ba38 100644 --- a/src/main/kotlin/be/nielandt/iterator/ValidMoveIterator.kt +++ b/src/main/kotlin/be/nielandt/iterator/ValidMoveIterator.kt @@ -19,7 +19,7 @@ class ValidMoveIterator(val classes: List) : Iterator { // create the variable counter: if a class is 'alone', it can iterate over all 6 values. otherwise, each part can iterate over 3 val intArray = IntArray(classes.size) var i = 0 - while (i < classes.size - 1) { + while (i < classes.size) { if (i < classes.size - 1 && classes[i] == classes[i + 1]) { intArray[i] = 3 intArray[i + 1] = 3 @@ -36,12 +36,11 @@ class ValidMoveIterator(val classes: List) : Iterator { override fun next(): IntArray { val next = this.expansionCounter.next() - println("Expansioncounter next = ${Arrays.toString(next)}") // translate this state into a list of moves var i = 0 while (i < next.size) { // process the double situation - if (classes[i] == classes[i + 1]) { + if (i < classes.size-1 && classes[i] == classes[i + 1]) { // so, we're in the same state, the first counter will get the 'low' value, the second the 'high' value // for class FB, that would be F and B respectively // class 0 (FB) has to expand to 0,6,12 (F,F_F2) and 1,7,13 (B,B_,B2) respectively