Skip to content

Instantly share code, notes, and snippets.

@narma
Last active March 10, 2023 23:50
Show Gist options
  • Save narma/968462aab992fd9c4655655efb8805a4 to your computer and use it in GitHub Desktop.
Save narma/968462aab992fd9c4655655efb8805a4 to your computer and use it in GitHub Desktop.
#!/usr/bin/env -S scala-cli shebang
//> using scala "3.2.2"
import scala.collection.mutable
enum Color:
case Yellow
case Blue
case Red
case White
case Purple
case Green
case Empty
case Pink
import Color.*
val e = Empty
enum Operation:
case Right
case Left
case Shift
def shiftLeft[T](v: Vector[T]): Vector[T] =
Vector(v(2), v(3), v(4), v(5), v(6), v(7), v(0), v(1))
def shiftRight[T](v: Vector[T]): Vector[T] =
Vector(v(6), v(7), v(0), v(1), v(2), v(3), v(4), v(5))
def shift[T](v: Vector[T]): Vector[T] =
Vector(v(0), v(1), v(2), v(4), v(5), v(3), v(6), v(7))
val random = new scala.util.Random
def find[T](valid: Seq[T], init: Seq[T], limitOps: Int = 20, limitIterations: Int = 10000): List[Operation] = {
require(valid.size == 8)
require(init.size == 8)
var current = Vector.from(init)
val ops = mutable.ArrayBuffer.empty[Int]
ops.sizeHint(limitOps + 1)
var b = true
var iterations = 0
var found = false
while b do {
val i = random.nextInt(3)
ops.append(i)
i match
case 0 => current = shiftLeft(current)
case 1 => current = shiftRight(current)
case 2 => current = shift(current)
if (valid == current) {
b = false
found = true
// println(s"Found! Iterations taken ${iterations}}")
}
if (ops.size > limitOps && b) {
iterations = iterations + 1
ops.clear()
current = Vector.from(init)
}
if (iterations > limitIterations) {
b = false
}
}
if (found) {
ops.toList.map {
case 0 => Operation.Left
case 1 => Operation.Right
case 2 => Operation.Shift
}
} else {
List.empty
}
}
def solve[T](valid: Seq[T], init: Seq[T], startLimitFrom: Int = 30, limitIterations: Int = 200000): List[Operation] = {
var currentLimit = startLimitFrom - 1
var cont = true
var finishResult = find(valid, init, startLimitFrom, limitIterations)
while cont do {
val result = find(valid, init, currentLimit, limitIterations)
if (result.isEmpty) {
cont = false
} else {
finishResult = result
currentLimit = Math.min(currentLimit - 1, result.size - 1)
}
}
finishResult
}
val s = args.map(_.replace('-', ' ').replace(',', ' ').trim()).filter(_.nonEmpty)
if (s.size != 8*2) {
println(s"arg size should be ${8*2}")
} else {
val colors = s.map { a =>
if (a == "e") Empty
else Color.valueOf(a)
}
val valid = colors.slice(0, 8)
val init = colors.slice(8, 16)
val result = solve(valid, init)
val r = result.mkString(" ")
println(r)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment