crosssolver/src/main/kotlin/be/nielandt/EdgeModel.kt

230 lines
7.6 KiB
Kotlin

package be.nielandt
/**
* 24 edge-faces (a single part of an edge), so 24 pieces that can have a color
- ----------
- | 16 |
- |19 W 17|
- | 18 |
-------------------------------------
| 12 | 00 | 04 | 08 |
|15 O 13|03 G 01|07 R_indices 05|11 B_indices 09|
| 14 | 02 | 06 | 10 |
-------------------------------------
- | 20 |
- |23 Y 21|
- | 22 |
- ----------
* white on top, green in front
*
*
*
*
*/
class EdgeModel {
val model: Array<Int>
private val F_indices = intArrayOf(13, 18, 7, 20, 3, 0, 1, 2)
private val B_indices = intArrayOf(8, 9, 10, 11, 16, 15, 22, 5)
private val L_indices = intArrayOf(3, 23, 9, 19, 12, 13, 14, 15)
private val U_indices = intArrayOf(16, 17, 18, 19, 0, 12, 8, 4)
private val D_indices = intArrayOf(2, 6, 10, 14, 20, 21, 22, 23)
private val R_indices = intArrayOf(4, 5, 6, 7, 1, 17, 11, 21)
constructor() {
// do a sanity check
val entries = mutableListOf(F_indices, B_indices, L_indices, U_indices, D_indices, R_indices).flatMap { it.asList() }.groupBy { it }.entries
// println("entries = ${entries}")
if (entries.any {
it.value.size != 2
}) {
throw RuntimeException("each index should occur exactly twice in the arrays")
}
model = arrayOf(
GREEN, GREEN, GREEN, GREEN,
RED, RED, RED, RED,
BLUE, BLUE, BLUE, BLUE,
ORANGE, ORANGE, ORANGE, ORANGE,
WHITE, WHITE, WHITE, WHITE,
YELLOW, YELLOW, YELLOW, YELLOW
)
}
constructor(randomMoves: Int) {
val edgeModel = EdgeModel()
val r: Array<Int> = randomMoves(randomMoves)
val doMoves = edgeModel.doMoves(r)
this.model = doMoves.model
}
constructor(model: Array<Int>) {
this.model = model
}
constructor(moves: List<Int>) {
val edgeModel = EdgeModel()
val newModel = edgeModel.doMoves(moves)
this.model = newModel.model
}
/**
* Do a single move and calculate the resulting edge model.
*/
fun doMove(move: Int): EdgeModel {
val copyOf = this.model.copyOf()
// execute the move
/**
* Do a non prime move. Go from 0 to 1 to 2 to 3, 4 to 5 to 6 to 7.
*/
fun nonPrime(s: IntArray) {
copyOf[s[1]] = model[s[0]]
copyOf[s[2]] = model[s[1]]
copyOf[s[3]] = model[s[2]]
copyOf[s[0]] = model[s[3]]
copyOf[s[5]] = model[s[4]]
copyOf[s[6]] = model[s[5]]
copyOf[s[7]] = model[s[6]]
copyOf[s[4]] = model[s[7]]
}
/**
* Do a prime move. Go from 3 to 2 to 1 to 0, 7 to 6 to 5 to 4.
*/
fun prime(s: IntArray) {
copyOf[s[0]] = model[s[1]]
copyOf[s[1]] = model[s[2]]
copyOf[s[2]] = model[s[3]]
copyOf[s[3]] = model[s[0]]
copyOf[s[4]] = model[s[5]]
copyOf[s[5]] = model[s[6]]
copyOf[s[6]] = model[s[7]]
copyOf[s[7]] = model[s[4]]
}
/**
* Do a double move, jump one
*/
fun double(s: IntArray) {
copyOf[s[0]] = model[s[2]]
copyOf[s[2]] = model[s[0]]
copyOf[s[1]] = model[s[3]]
copyOf[s[3]] = model[s[1]]
copyOf[s[4]] = model[s[6]]
copyOf[s[6]] = model[s[4]]
copyOf[s[5]] = model[s[7]]
copyOf[s[7]] = model[s[5]]
}
when (move) {
F -> nonPrime(F_indices)
F_ -> prime(F_indices)
F2 -> double(F_indices)
B -> nonPrime(B_indices)
B_ -> prime(B_indices)
B2 -> double(B_indices)
L -> nonPrime(L_indices)
L_ -> prime(L_indices)
L2 -> double(L_indices)
R -> nonPrime(R_indices)
R_ -> prime(R_indices)
R2 -> double(R_indices)
U -> nonPrime(U_indices)
U_ -> prime(U_indices)
U2 -> double(U_indices)
D -> nonPrime(D_indices)
D_ -> prime(D_indices)
D2 -> double(D_indices)
}
return EdgeModel(copyOf)
}
/**
* Print out the edge model.
*/
override fun toString(): String {
val trimMargin = """
| ---------
| | ${colorLetter(model[16])} |
| | ${colorLetter(model[19])} W ${colorLetter(model[17])} |
| | ${colorLetter(model[18])} |
|---------------------------------
|| ${colorLetter(model[12])} | ${colorLetter(model[0])} | ${colorLetter(model[4])} | ${colorLetter(model[8])} |
|| ${colorLetter(model[15])} O ${colorLetter(model[13])} | ${colorLetter(model[3])} G ${colorLetter(model[1])} | ${colorLetter(model[7])} R ${colorLetter(model[5])} | ${colorLetter(model[11])} B ${colorLetter(model[9])} |
|| ${colorLetter(model[14])} | ${colorLetter(model[2])} | ${colorLetter(model[6])} | ${colorLetter(model[10])} |
|---------------------------------
| | ${colorLetter(model[20])} |
| | ${colorLetter(model[23])} Y ${colorLetter(model[21])} |
| | ${colorLetter(model[22])} |
| ---------
""".trimMargin()
return trimMargin
}
fun doMoves(f: Array<Int>) : EdgeModel {
var edgeModel = this
f.forEach {
edgeModel = edgeModel.doMove(it)
}
return edgeModel
}
fun doMoves(f: Collection<Int>): EdgeModel {
var edgeModel = this
f.forEach {
edgeModel = edgeModel.doMove(it)
}
return edgeModel
}
fun doMoves(vararg f: Int): EdgeModel {
return this.doMoves(f.toList())
}
/**
* Pass any of the colors WHITE, YELLOW, RED, ...
*/
fun crossSolved(color: Int): Boolean {
return when (color) {
WHITE -> {
model[WB] == WHITE && model[WG] == WHITE && model[WO] == WHITE && model[WR] == WHITE &&
model[BW] == BLUE && model[GW] == GREEN && model[OW] == ORANGE && model[RW] == RED
}
YELLOW -> {
model[YB] == YELLOW && model[YG] == YELLOW && model[YO] == YELLOW && model[YR] == YELLOW &&
model[BY] == BLUE && model[GY] == GREEN && model[OY] == ORANGE && model[RY] == RED
}
RED -> {
model[RW] == RED && model[RG] == RED && model[RY] == RED && model[RB] == RED &&
model[WR] == WHITE && model[GR] == GREEN && model[YR] == YELLOW && model[BR] == BLUE
}
BLUE -> {
model[BW] == BLUE && model[BR] == BLUE && model[BY] == BLUE && model[BO] == BLUE &&
model[WB] == WHITE && model[RB] == RED && model[YB] == YELLOW && model[OB] == ORANGE
}
GREEN -> {
model[GW] == GREEN && model[GO] == GREEN && model[GY] == GREEN && model[GR] == GREEN &&
model[WG] == WHITE && model[OG] == ORANGE && model[YG] == YELLOW && model[RG] == RED
}
ORANGE -> {
model[OW] == ORANGE && model[OB] == ORANGE && model[OY] == ORANGE && model[OG] == ORANGE &&
model[WO] == WHITE && model[BO] == BLUE && model[YO] == YELLOW && model[GO] == GREEN
}
else -> {
throw RuntimeException()
}
}
}
}