Solving N-Queens in Clojure

Slides:



Advertisements
Similar presentations
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 5. 2 List Utilities Scheme built-in procedures –(list x y z...) –(list-ref lst index) –(length lst) –(append.
Advertisements

8 Queens. Problem: Placing 8 queens on a chessboard such that they don’t attack each other Three different Prolog programs are suggessted as solutions.
PROLOG 8 QUEENS PROBLEM.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
Techniques for Dealing with Hard Problems Backtrack: –Systematically enumerates all potential solutions by continually trying to extend a partial solution.
Stacks CS 3358 – Data Structures. What is a stack? It is an ordered group of homogeneous items of elements. Elements are added to and removed from the.
P Chapter 6 introduces the stack data type. p Several example applications of stacks are given in that chapter. p This presentation shows another use called.
The N-Queens Problem lab01.
Clojure Template Tail Recursion. Hello, Factorial! The factorial function is everybody’s introduction to recursion (defn factorial-1 [n] (if (zero? n)
Backtracking What is backtracking?
ITERATIVE CONSTRUCTS: DOLIST Dolist is an iterative construct (a loop statement) consisting of a variable declaration and a body The body states what happens.
Contents Introduction Related problems Constructions –Welch construction –Lempel construction –Golomb construction Special properties –Periodicity –Nonattacking.
Stacks (Revised and expanded from CIT 591). What is a stack? A stack is a Last In, First Out (LIFO) data structure Anything added to the stack goes on.
Clojure 3 Recursion, Higher-order-functions 27-Aug-15.
 1 Loop and Set operations. Creating a loop Loops are used to repeat a computation. Let’s see the example of factorial computation. Let’s compute 10!
Data Structures Using C++ 2E Chapter 6 Recursion.
Slide Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley.
Copyright © 2011 Pearson Education, Inc. Publishing as Prentice Hall.
Vlad Furash & Steven Wine.  Problem surfaced in 1848 by chess player Max Bezzel as 8 queens (regulation board size)  Premise is to place N queens on.
Data Structures Using C++ 2E Chapter 6 Recursion.
Recursion Chapter 5.
Functional Programming in Scheme and Lisp. Overview In a functional programming language, functions are first class objects. You can create them, put.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
Back Tracking Project Due August 11, 1999 N-queens: –A classic puzzle for chess buffs is the N- Queens problem. Simply stated: is it possible to place.
HISTORY The problem was originally proposed in 1848 by the chess player Max Bezzel, and over the years, many mathematicians, including Gauss have worked.
Clojure 4 Sequences 20-Oct-15. Clojure errors (NO_SOURCE_FILE:12) Useless--just means you’re running from the REPL shell java.lang.Exception: EOF while.
Vectors and Matrices In MATLAB a vector can be defined as row vector or as a column vector. A vector of length n can be visualized as matrix of size 1xn.
Contents of Chapter 7 Chapter 7 Backtracking 7.1 The General method
Two Dimensional Arrays
Clojure 2 Feb 7,
Data Structures Using C++ 2E1 Recursion and Backtracking: DFS Depth first search (a way to traverse a tree or graph) Backtracking can be regarded as a.
Feb 7, 2015 Thinking in Clojure. Jumping in We’ll quickly go through Clojure’s data types, some basic functions, and basic syntax Then we’ll get to the.
Two Dimensional Arrays. Two-dimensional Arrays Declaration: int matrix[4][11]; 4 x 11 rows columns
Iterators CS Chakrabarti What is an iterator?  Thus far, the only data structure over which we have iterated was the array for (int ix = 0;
Algorithmics - Lecture 131 LECTURE 13: Backtracking.
PROGRAMMING LANGUAGES: PROLOG, CLOJURE, F# Jared Wheeler.
1 Chapter 4: Creating Simple Queries 4.1 Introduction to the Query Task 4.2 Selecting Columns and Filtering Rows 4.3 Creating New Columns with an Expression.
The 8-queens problem CS 5010 Program Design Paradigms “Bootcamp” Lesson TexPoint fonts used in EMF. Read the TexPoint manual before you delete this.
Backtracking & Brute Force Optimization Intro2CS – weeks
Introduction to State Space Search
N- Queens Solution with Genetic Algorithm By Mohammad A. Ismael.
1 FP Foundations, Scheme In Text: Chapter Chapter 14: FP Foundations, Scheme Mathematical Functions Def: A mathematical function is a mapping of.
An Analysis of the n- Queens problem Saleem Karamali.
Fall 2016 Images from Sebesta: Copyright © 2012 Addison-Wesley. All rights reserved. The mind is everything. What you think you become. Buddha.
 Chapter 7 introduces the stack data type.  Several example applications of stacks are given in that chapter.  This presentation shows another use called.
Lets and Loops Tail Recursion.
Lecture 5 of Computer Science II
CS1020 – Data Structures And Algorithms 1 AY Semester 2
Intro to Computer Science II
Lecture 16 Streams continue Infinite Streams מבוא מורחב - שיעור 16.
CS1371 Introduction to Computing for Engineers
COP4020 Programming Languages
Sit-In Lab 1 Ob-CHESS-ion
CS 213: Data Structures and Algorithms
6.001 SICP Data abstractions
Recursion Copyright (c) Pearson All rights reserved.
Important Concepts from Clojure
Important Concepts from Clojure
Clojure to Haskell (It’s mostly syntax).
Analysis and design of algorithm
Clojure 4 Sequences 27-Nov-18.
FP Foundations, Scheme In Text: Chapter 14.
Clojure 4 Sequences 5-Dec-18.
adapted from Recursive Backtracking by Mike Scott, UT Austin
Recursion, Higher-order-functions
Important Concepts from Clojure
Today’s topics Abstractions Procedural Data
Clojure 2 22-Apr-19.
Clojure 3 1-Jun-19.
Presentation transcript:

Solving N-Queens in Clojure

The N-Queens Problem The classic 8-queens problem is that of placing 8 queens on a chessboard so that no pair is attacking. Franz Nauck in 1850 extended the chess problem to n-queens problem on an n×n board. S. Günther proposed a method of finding solutions by using matrix determinants. Edsger Dijkstra used this problem in 1972 to illustrate the power of what he called structured programming.

Solution Design Let us represent solution using vectors of column locations. [5 3 6 0 7 1 4 2] is the solution above We can write a generator that adds a queen to a new row as long as it is non-attacking. A simple recursive generator function n-queens will Take each solution to n-1 queens problem and apply map which-queen is function to computes list of possible additions (we’ll use list comprehensions/for simplicity) map the conjall using which queen to add to each partial solution So n_queens() will take 2 parameters, the number of queens n (same as # rows) and m (or number of cols) of the board.

Pattern for n-queens coming from allchains solution (defn allchains [n m] (cond (= n 0) '(()) :else (apply concat (map (fn [it] (conjall (range 1 (inc m)) it)) (allchains (dec n) m))))) (defn n-queens [n m] (= n 0) '([]) (which-queens it m) it)) (n-queens (dec n) m))))

Recall conjall for generating collections conj is the standard op for building collections in Clojure. conj returns a new collection with the new item 'added'. The 'addition' may happen at different 'places' depending on the concrete type. user=> (conj [1 2 3] 4) => [1 2 3 4] user=> (conj '(1 2 3) 4) => (4 1 2 3) We write conjall with input a vector vec and a list lst… and returns a collection of all conj’s of lst elements onto the vec. (defn conjall [lst vec] (cond (empty? lst) '() :else (conj (conj vec (first lst)) (conjall (rest lst1) vec))) ;(conjall '(4 5 6) [ 1 2 ]) ; => ([1 2 4] [1 2 5] [1 2 6])

List Comprehension using for List comprehension uses for for generating lists. Takes a vector of one or more binding-form/collection-expr pairs, each followed by zero or more modifiers, and yields a lazy sequence of evaluations of expr. (for [x (range 6) y (range 5) :let [z (* x y)] :when (odd? z)] (list x y)) ;=> ((1 1) (1 3) (3 1) (3 3) (5 1) (5 3)) :when iterates over the bindings, but only evaluates the body of the loop when the condition is true. :while iterates over the bindings and evaluates the body until the condition is false: (for [x (range 20) :when (not= x 10)] x) ; =>(0 1 2 3 4 5 6 7 8 9 11 12 13 14 15 16 17 18 19) (for [x (range 20) :while (not= x 10)] x) ; => (0 1 2 3 4 5 6 7 8 9)

Which-queens to add? ; for each possible col x return x ; if all other queens in partial sol psol are non-attacking (defn which-queens [psol m] (for [x (range m) :when (not-any? true? (for [i (range (count psol)) :let [pi (psol i)]] (or ;check if pi and x share col or diagonal (= pi x) (= (- (count psol) i) (Math/abs (- x pi)))) )) ] x))

That all! 92 solutions (defn n-queens [n m] (cond (= n 0) '([]) :else (apply concat (map (fn [it] (conjall (which-queens it m) it)) (n-queens (dec n) m)))) user=> (count (n-queens 8 8)) 92 user=> (n-queens 8 8) ([0 4 7 5 2 6 1 3] [0 5 7 2 6 3 1 4] [0 6 3 5 7 1 4 2] [0 6 4 7 1 3 5 2] [1 3 5 7 2 0 6 4] [1 4 6 0 2 7 5 3] [1 4 6 3 0 7 5 2] [1 5 0 6 3 7 2 4] [1 5 7 2 0 3 6 4] [1 6 2 5 7 4 0 3] [1 6 4 7 0 3 5 2] [1 7 5 0 2 4 6 3] [2 0 6 4 7 1 3 5] [2 4 1 7 0 6 3 5] [2 4 1 7 5 3 6 0] [2 4 6 0 3 1 7 5] [2 4 7 3 0 6 1 5] [2 5 1 4 7 0 6 3] [2 5 1 6 0 3 7 4] [2 5 1 6 4 0 7 3] [2 5 3 0 7 4 6 1] [2 5 3 1 7 4 6 0] [2 5 7 0 3 6 4 1] [2 5 7 0 4 6 1 3] [2 5 7 1 3 0 6 4] [2 6 1 7 4 0 3 5] [2 6 1 7 5 3 0 4] [2 7 3 6 0 5 1 4] [3 0 4 7 1 6 2 5] [3 0 4 7 5 2 6 1] [3 1 4 7 5 0 2 6] [3 1 6 2 5 7 0 4] [3 1 6 2 5 7 4 0] [3 1 6 4 0 7 5 2] [3 1 7 4 6 0 2 5] [3 1 7 5 0 2 4 6] [3 5 0 4 1 7 2 6] [3 5 7 1 6 0 2 4] [3 5 7 2 0 6 4 1] [3 6 0 7 4 1 5 2] [3 6 2 7 1 4 0 5] [3 6 4 1 5 0 2 7] [3 6 4 2 0 5 7 1] [3 7 0 2 5 1 6 4] [3 7 0 4 6 1 5 2] [3 7 4 2 0 6 1 5] [4 0 3 5 7 1 6 2] [4 0 7 3 1 6 2 5] [4 0 7 5 2 6 1 3] [4 1 3 5 7 2 0 6] [4 1 3 6 2 7 5 0] [4 1 5 0 6 3 7 2] [4 1 7 0 3 6 2 5] [4 2 0 5 7 1 3 6] [4 2 0 6 1 7 5 3] [4 2 7 3 6 0 5 1] [4 6 0 2 7 5 3 1] [4 6 0 3 1 7 5 2] [4 6 1 3 7 0 2 5] [4 6 1 5 2 0 3 7] [4 6 1 5 2 0 7 3] [4 6 3 0 2 7 5 1] [4 7 3 0 2 5 1 6] [4 7 3 0 6 1 5 2] [5 0 4 1 7 2 6 3] [5 1 6 0 2 4 7 3] [5 1 6 0 3 7 4 2] [5 2 0 6 4 7 1 3] [5 2 0 7 3 1 6 4] [5 2 0 7 4 1 3 6] [5 2 4 6 0 3 1 7] [5 2 4 7 0 3 1 6] [5 2 6 1 3 7 0 4] [5 2 6 1 7 4 0 3] [5 2 6 3 0 7 1 4] [5 3 0 4 7 1 6 2] [5 3 1 7 4 6 0 2] [5 3 6 0 2 4 1 7] [5 3 6 0 7 1 4 2] [5 7 1 3 0 6 4 2] [6 0 2 7 5 3 1 4] [6 1 3 0 7 4 2 5] [6 1 5 2 0 3 7 4] [6 2 0 5 7 4 1 3] [6 2 7 1 4 0 5 3] [6 3 1 4 7 0 2 5] [6 3 1 7 5 0 2 4] [6 4 2 0 5 7 1 3] [7 1 3 0 6 4 2 5] [7 1 4 2 0 6 3 5] [7 2 0 5 1 4 6 3] [7 3 0 2 5 1 6 4])

Isomorph Rejection Problem Not all of the 92 solutions found can be considered unique, in the sense that rotating or flipping the board around can result in another solution found in the set. 8 transformations that map the chess-board to itself; 4 rotations of 90 degrees, and 4 reflections --the so-called dihedral group D8 of automorphisms of the square. A solution (based on perfect hashing) is to consider each solution of N-Queens as a base N+1 number. We can generate solutions in numeric order, and test if a solution is isomorphic to a previously found solution if and only if one of the 8 transformations produces a solution, which is numerically (or, more generally, lexicographically) less than the original We can lexicographically compare solutions as follows… user=> (compare [0 4 7 5 2 6 1 3] [7 1 3 0 6 4 2 5]) -1

Working with immutability is sometimes difficult (This may not be best work around) To work in an immutable fashion we will expand and collapse each vector using a list of [row-index col-index] pairs as intermediate solution. ; (def a (first (n-queens 8 8)) (defn expand [sol] (map vector (range 8) sol) ) ;(expand a) ;=>([0 7] [1 3] [2 0] [3 2] [4 5] [5 1] [6 6] [7 4]) If [i j] is a queen in sol, then [j 7-i] is a queen in (rotate sol) If [i j] is a queen in sol, then [i 7-j] is a queen in (reflect sol) (defn rotate [sol] ( map (fn[x] (let [[ i j] x] (vector j (- 7 i)))) sol)) (defn reflect [sol] ( map (fn[x] (let [[ i j] x] (vector i (- 7 j)))) sol))

Expand and Collapse Transformed Solutions (reflect (expand a)) ;=> ([0 7] [1 3] [2 0] [3 2] [4 5] [5 1] [6 6] [7 4]) ; (sort (rotate (expand a))) ;=> ([0 7] [1 1] [2 3] [3 0] [4 6] [5 4] [6 2] [7 5]) (defn collapse [p] (into [] (map (fn[ij] (last ij)) p))) ;(collapse '([0 7] [1 1] [2 3] [3 0] [4 6] [5 4] [6 2] [7 5])) ;=> [7 1 3 0 6 4 2 5]

into lets you take anything seq'able Take a list, vector, map, set, sorted-map and an empty container you want filled. (into [] '(1 2 3 4)) ==> [1 2 3 4] "have a lazy list and want a vector" into #{} [1 2 3 4]) ==> #{1 2 3 4} "have a vector and want a set" > (into {} #{[1 2] [3 4]}) ==> {3 4, 1 2} "have a set of vectors want a map" > (into #{} [{1 2} {3 4}]) ==> #{{1 2} {3 4}} "have a vector of maps want a set of maps"

Here is a potential solution (defn non-iso [n] (filter canonical-pred? (n-queens n n))

Homework #3 How many orbits/non-iso solutions? How many are full (size 8) and degenerate? Catalog the fixed configurations of 8 symmetries. Write clojure program to produce list of all canonical (non-isomorphic) solution vectors.