Last active
March 10, 2023 23:50
-
-
Save narma/968462aab992fd9c4655655efb8805a4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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