Scala ãŽįˇ´įŋã¨ããĻããĒãšããŽãĒãæščĄ¨č¨ãŽįˇ´įŋã¨ããĻã 10.1 N ã¯ãŖãŧãŗåéĄ (The N-Queens Problem) ãããŖãĻã. 大é¨åã¯ãããĢæ¸ããĻããã¨ããã ããŠãčĒåãŽč§Ŗįã¨ããĻ
import scala.math._
import scala.collection.mutable.{Queue, Set}
import scala.collection.immutable._
import scala.util.Random
object Main {
def queens(n: Int): List[List[Int]] = {
def isSafe(c: Int, qs: List[Int], d: Int): Boolean = {
qs match {
case List() => true
case q::qs if c+d == q || c-d == q || c == q => false
case q::qs => isSafe(c, qs, d+1)
}
}
def sub(k: Int): List[List[Int]] = {
if (k == 0) return List(List())
for { qs <- sub(k-1)
c <- Range(0, n)
if isSafe(c, qs, 1) }
yield c::qs
}
sub(n)
}
def show(n: Int, qs: List[Int]) {
for (i <- Range(0, n)) {
for (j <- Range(0, n)) {
print('.')
if (qs(i) == j) print('q')
else print('_')
}
println("")
}
}
def main(args: Array[String]) {
for (n <- Range(4, 16)) {
val ans = queens(n)
println(n, ans.length)
}
/*
for (ls <- ans) {
for (x <- ls) print(x + " ")
println("")
show(n, ls)
}
*/
}
}
æ¨Ąį¯č§Ŗįã ã¨æã. å¤å ¸åéĄã ã. č¨įŽéãŽä¸éãæ¸ŦãŖãĻãŋããã¨ãĢãã.
éˇã n
ãŽãĒãšããŽæĢå°žããäŊãŖãĻãããã¨ãĢæã. æĢå°žãŽčĻį´ 㯠n
éããã (åļį´ããĒããŽã§ 0..(n-1)
ãŽäŊãããĻãč¯ã). æĢå°žãã2ã¤įŽãŽčĻį´ ãĢã¤ããĻã¯ã æĢå°žãŽčĻį´ n
éããããããĢã¤ããĻã ãã¯ã 0..(n-1)
㎠n
éãã isSafe
ãĢããŖãĻčŠĻããĻãåéĄãĒãããŽãæŦĄãĢéã. isSafe
ã¯éˇããĢæ¯äžããč¨įŽéã ãããããã§ã¯ 1
.
ããŽãããĢããĻãč¨įŽéãŽä¸éã¨ããĻã¯ã
\(n \times n * 1 \times n * 2 \times \ldots \times n * (n-1) = n^n * (n-1)!\)
ãŖãĻãĒå
ˇå. åŽéãĢã¯ãisSafe
ãŽé¨åã§æįŠãŖãĻčĄããã¨ãĢãĒããŽã§ãããŖã¨å°ãã. åŽéãæįĩįãĢåžãããįããŽæ°ã¯ããŖã¨ããŖã¨å°ãã.
(4,2)
(5,10)
(6,4)
(7,40)
(8,92)
(9,352)
(10,724)
(11,2680)
(12,14200)
(13,73712)
ã¨ã¯ãã n=13
ããããããã¤ããĒããŽã§ã éŠåŊãĒäŊæã§ãã㨠O(n!)
ããĒãŖãĻæãŖãĄãã.
ã°ã°ãŖãããããĢčĻã¤ããŖã.
2ã¤ãã¯åŽļãããĸã¯ãģãšã§ããĒããŖããã§ã 1ã¤ããčĒãã§ãŋã. æĩãčĒãŋã§čĒãã ããŠã čĻãããĢ Figure 1 ã¨ãããã¨ããã.
ãã ãã
ã¨ããéãããã.
įãã¯įĸēããĢãŠãã [0 .. n-1]
ãŽįŊŽæã§ãã. ãĸãĢã´ãĒãēã ã¯į°ĄåãĢ
qs
ãįæããqs[i]
㨠qs[j]
ãŽįŊŽæãã¯ã¤ãŧãŗãŽčĄįĒãæ¸ãããĒãããããqs
ãĢã¯ã¤ãŧãŗãŽčĄįĒããĒããã°ãããčŋããĻįĩäēæį´ãĢåŽčŖ
ããã¨äģĨä¸éã. ãã ããįĄéãĢãŧãé¨åã¯1000åãŽä¸éãã¤ãã. List[Int]
㯠Array[Int]
ãĢãã.
import scala.math._
import scala.collection.mutable.{Queue, Set}
import scala.collection.immutable._
import scala.util.Random
object Main {
def queens(n: Int, uplimit: Int = 1000): Option[Array[Int]] = {
def collision(qs: Array[Int]): Int = { // čĄįĒãŽæ°ãæ°ãã
var c = 0
for (i <- Range(0, n-1)) {
for (j <- Range(i+1, n)) {
val d = j - i
if (qs(i) == qs(j) || qs(i) == qs(j) - d || qs(i) == qs(j) + d) c += 1
}
}
c
}
var tryNumber = 0
for (t <- Range(0, uplimit)) {
tryNumber = t + 1
val qs = Random shuffle Range(0, n) toArray;
var c = collision(qs)
for (i <- Range(0, n-1)) {
val tmp = qs(i)
for (j <- Range(i+1, n)) {
qs(i) = qs(j)
qs(j) = tmp
val c2 = collision(qs)
if (c2 >= c) { // when swap doesn't reduce
qs(j) = qs(i)
qs(i) = tmp
} else {
c = c2
}
}
}
if (c == 0) {
println("čŠĻčĄåæ°: " + tryNumber)
return Some(qs)
}
}
return None
}
def show(n: Int, qs: Array[Int]) {
for (i <- Range(0, n)) {
for (j <- Range(0, n)) {
print('.')
if (qs(i) == j) print('q')
else print('_')
}
println("")
}
}
def main(args: Array[String]) {
val n = 10;
val ans = queens(n)
ans match {
case Some(qs) => show(n, qs)
case None => println("no answers")
}
}
}
ãŗãŧãã¯ããĒãéˇããĒãŖã.
čŠĻčĄåæ°: 257
._._._._._.q._._._._
._._._.q._._._._._._
._.q._._._._._._._._
._._._._._._._.q._._
._._.q._._._._._._._
._._._._._._.q._._._
._._._._._._._._._.q
.q._._._._._._._._._
._._._._._._._._.q._
._._._._.q._._._._._
įĸēããĢåããĻãããčŠĻčĄåæ°ã¯ãããžã§å¤§ãããĒããããĢãæãã. ä¸åãŽæŊčĄãŽč¨įŽé㯠\(O(n^4)\) ã ããŠãĒ. \(n=12\) ãããããã1000åãŽãĢãŧãã§ã¯æĒãããĒãŖãĻãã.
ä¸ã¤ãŽããŠãŗãã ãĢįæããįŊŽæãĢã¤ããĻã swap
ãä¸åēĻã§ãčĄãŖãããŽããããå°ãįļããĻčŠĻãã¨ããããĨãŧãĒãšããŖã¯ãšãå°å
Ĩãã.
import scala.math._
import scala.collection.mutable.{Queue, Set}
import scala.collection.immutable._
import scala.util.Random
object Main {
def queens(n: Int, uplimit: Int = 1000): Option[Array[Int]] = {
def collision(qs: Array[Int]): Int = { // čĄįĒãŽæ°ãæ°ãã
var c = 0
for (i <- Range(0, n-1)) {
for (j <- Range(i+1, n)) {
val d = j - i
if (qs(i) == qs(j) || qs(i) == qs(j) - d || qs(i) == qs(j) + d) c += 1
}
}
c
}
var tryNumber = 0
for (t <- Range(0, uplimit)) {
val qs = Random shuffle Range(0, n) toArray;
var c = collision(qs)
var grad = true
while (grad) {
tryNumber += 1
var performed = 0
for (i <- Range(0, n-1)) {
val tmp = qs(i)
for (j <- Range(i+1, n)) {
qs(i) = qs(j)
qs(j) = tmp
val c2 = collision(qs)
if (c2 >= c) { // when swap doesn't reduce
qs(j) = qs(i)
qs(i) = tmp
} else {
c = c2
performed += 1
}
}
}
if (performed == 0) grad = false
if (c == 0) {
println(tryNumber)
return Some(qs)
}
}
}
return None
}
def show(n: Int, qs: Array[Int]) {
for (i <- Range(0, n)) {
for (j <- Range(0, n)) {
print('.')
if (qs(i) == j) print('q')
else print('_')
}
println("")
}
}
def main(args: Array[String]) {
val n = 12;
val ans = queens(n, 1000000)
if (ans == None) println("None")
}
}
\(n=12\) ã§ãŽčŠĻčĄåæ°
% for i in `seq 10`; do scala test.scala; done
3955
1754
51
1140
1155
88
2479
307
370
1471
čĢæãŽčĄ¨ã ã¨ããŖã¨å°ãĒãããŖãĻããŊãããŠ. äŊãéãŖãããĒ.