package coffee.liz.rookery.algs import coffee.liz.rookery.puzzle.Notation import coffee.liz.rookery.puzzle.NxnCube /** One case of an algorithm set, with the algorithms people use for it (the first is the usual one). */ data class AlgCase(val set: String, val name: String, val group: String, val probability: Int, val algs: List) { val id: String get() = "$set:$name" /** * The cube showing this case, last layer up, as you would hold it before doing [alg]: a solved * cube with the algorithm undone. An algorithm with a net rotation (say it starts with `x`) * leaves the centres somewhere else, so colours are renamed after whichever centre they sit on. */ fun state(alg: String = algs.first()): NxnCube { val c = NxnCube(3).apply(Notation.invert(clean(alg))) val rename = IntArray(6) for (f in 0 until 6) rename[c.stickers[f * 9 + 4]] = f for (i in c.stickers.indices) c.stickers[i] = rename[c.stickers[i]] return c } /** Moves that set this case up from a solved cube. */ fun setup(alg: String = algs.first()): String = Notation.invert(clean(alg)) companion object { fun clean(alg: String) = alg.replace("(", " ").replace(")", " ").trim().replace(Regex("\\s+"), " ") } } enum class AlgStatus { NEW, LEARNING, KNOWN } object AlgSets { val names: List get() = ALG_DATA.keys.toList() fun cases(set: String): List = ALG_DATA[set].orEmpty() fun find(id: String): AlgCase? = cases(id.substringBefore(':')).firstOrNull { it.id == id } /** * The last layer seen from above, as 5x5 cells of colour indices (-1 = empty corner): the U face * in the middle and the top row of each side around it, front at the bottom. */ fun plan(c: NxnCube): Array { val s = c.stickers val g = Array(5) { IntArray(5) { -1 } } for (r in 0 until 3) for (k in 0 until 3) g[r + 1][k + 1] = s[r * 3 + k] // U for (k in 0 until 3) { g[4][k + 1] = s[2 * 9 + k] // F, left to right g[0][k + 1] = s[5 * 9 + (2 - k)] // B, seen from above g[k + 1][4] = s[1 * 9 + (2 - k)] // R, back to front g[k + 1][0] = s[4 * 9 + k] // L, back to front } return g } }