Eight Queens, minimalistic

Introduction

See also: Eight Queens Problem

Program 1

WDB:

package require Tcl 8.5
package require Tk

bind Tk <Destroy> exit
wm resizable . no no

apply {canvas {
  destroy $canvas
  pack [canvas $canvas -width 320 -height 320]
  foreach i {0 1 2 3 4 5 6 7} {
      foreach j {0 1 2 3 4 5 6 7} {
        set o [expr {($i+$j)%2 ? "odd" : "even"}]
        set coords [list [* $i 40] [* $j 40]\
                      [* [+ $i 1] 40] [* [+ $j 1] 40]]
        $canvas create rectangle $coords\
          -tags [list f $o r$j c$i]
        $canvas create text\
          [+ [* $i 40] 20] [+ [* $j 40] 20]\
          -tags [list q r$j c$i]
        $canvas bind r$j&&c$i <1> "check $j $i"
      }
    }
  foreach c {-8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7} {
      set col $c
      foreach row {0 1 2 3 4 5 6 7} {
        $canvas addtag d[+ $c 7] withtag r$row&&c$col
        incr col
      }
    }
  foreach c {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15} {
      set col $c
      foreach row {0 1 2 3 4 5 6 7} {
        $canvas addtag e$c withtag r$row&&c$col
        incr col -1
      }
    }
  $canvas itemconfigure odd\
    -fill grey\
    -outline ""
  $canvas itemconfigure even\
    -fill #ffffcc\
    -outline ""
  $canvas itemconfigure q\
    -fill navy\
    -font {Times 20 bold italic}
  bind $canvas <ButtonRelease>\
    "$canvas itemconfigure q -fill navy"
} ::tcl::mathop} .c

proc check {row col} {
  set txt [.c itemcget q&&r$row&&c$col -text]
  if {$txt ne ""} then {
    .c itemconfigure q&&r$row&&c$col -text ""
  } else {
    setQueen $row $col
  }
}

proc setQueen {row col} {
  foreach tag [.c gettags q&&r$row&&c$col] {
    regexp d(.+) $tag - d
    regexp e(.+) $tag - e
  }
  set pat q&&(r$row||c$col||d$d||e$e)
  set success true
  set els [.c find withtag $pat]
  foreach el $els {
    if {[.c itemcget $el -text] ne ""} then {
      set success false
    }
  }
  if {$success} then {
    .c itemconfigure q&&r$row&&c$col -text Q
  } else {
    .c itemconfigure $pat -fill white
  }
}

if false {
  # the "aggressive" variant:
  proc setQueen {row col} {
    foreach tag [.c gettags q&&r$row&&c$col] {
      regexp d(.+) $tag - d
      regexp e(.+) $tag - e
    }
    .c itemconfigure q&&(r$row||c$col||d$d||e$e) -text ""
    .c itemconfigure q&&r$row&&c$col -text Q
  }
}

http://wolf-dieter-busch.de/html/res/Heimatseite/img/sw/EightQueensMinimalistic.png


Program 2

Beware How Minimalistic can you go?

proc r {l} {
        global solutions
        if {[llength $l]==8} {lappend solutions $l; return $l}
        foreach g [remove $l] {
                set n [concat $l $g]
                if {[valid $n]} {
                        r $n
                }
        }
}

proc valid {l} {
        set len [llength $l]
        for {set j 0} {$j<$len} {incr j} {
                set n [lindex $l $j]
                for {set i 0} {$i<$len} {incr i} {
                        if {$i==$j} {continue}        
                        set t [lindex $l $i]
                        
                        if {[expr ($t-$n) - ($i-$j)]==0} {return 0}
                        if {[expr ($n-$t) - ($i-$j)]==0} {return 0}
                }
        }
        return 1
}

proc remove {l} {
        set ret [list]
        foreach n [list 0 1 2 3 4 5 6 7] {
                if {[lsearch $l $n]==-1} {lappend ret $n}
        }
        return $ret
} 

set solutions [list]

proc go {} {
        global solutions
        set solutions [list]
        foreach h [list 0 1 2 3 4 5 6 7] {
                r $h
        }

        #puts [join $solutions \n]
        #puts "[llength $solutions] Solutions..."
}
set index -1
proc forward {} {
        global index
        if {$index>90} {return}
        incr index
        display
}
proc back {} {
        global index
        if {$index<1} {return}
        incr index -1
        display
}
proc display {} {
        global solutions display index
        set sol [lindex $solutions $index]
        set r ""
        #set e "================\n"
        set e ""
        foreach l $sol {
                if {$l==0} {append r "Q| | | | | | | \n$e"}
                if {$l==1} {append r " |Q| | | | | | \n$e"}
                if {$l==2} {append r " | |Q| | | | | \n$e"}
                if {$l==3} {append r " | | |Q| | | | \n$e"}
                if {$l==4} {append r " | | | |Q| | | \n$e"}
                if {$l==5} {append r " | | | | |Q| | \n$e"}
                if {$l==6} {append r " | | | | | |Q| \n$e"}
                if {$l==7} {append r " | | | | | | |Q\n$e"}
        }
        set display $r
}

pack [label .l -textvariable display -width 16 -height 10 -font {Courier 12 bold}]
frame .b
button .b.b -text < -command back
button .b.f -text > -command forward
pack .b.b .b.f -in .b -side left
pack .b

set display "Searching\nfor\nsolutions"

go

forward