Quantcast
Channel: Jive Syndication Feed
Viewing all articles
Browse latest Browse all 10881

Solving the Eight Queens problem using SAP HANA

$
0
0

I was inspired by Wenjun Zhou who wrote Play the game of life with SAP HANA to have a little fun and solve the Eight Queens problem using SAP HANA.

 

The Eight Queens is a classic problem in computer science: how can we place eight queens on a chess board, so that none of them can take each other? This is often taught to computer scientists, because it requires use of a backtracking algorithm to solve. I learnt this in a Modula-3 course back in the mid-90s. Here's a picture of the solution thanks to Eight queens puzzle - Wikipedia, the free encyclopedia

 

Screen Shot 2014-11-05 at 5.17.08 PM.png

It turns out that there are exactly 92 solutions to this problem on an 8x8 board. I can still remember my Modula-3 program spitting out solutions on a Sun UNIX server. The SQL Server Pro folks, wrote a blog Use T-SQL to Solve the Classic Eight Queens Puzzle which I then adapted to SQLScript. It's quite elegant, because it first only considers solutions where the queens are in distinct columns. This massively reduces the result space from n^n to n! (40320 for an 8x8 board).


It's even more fascinating if you do a PlanViz on this, because it only materializes 1704 rows at the most - it doesn't materialize the whole 40320 result set before it filters. Another example of the efficiency of the HANA column store engine.


I wrote a little piece to create an array of size N to represent the rows, which would be generic, but I couldn't figure out a way to recurse like you can in T-SQL. Can anyone see a more elegant solution?

 

DROPPROCEDURE queens;

CREATEPROCEDURE queens ()

  LANGUAGE SQLSCRIPT

  SQL SECURITY INVOKER

  READS SQL DATA AS

BEGIN

 

DECLARE v_queens INTEGER ARRAY;

DECLARE v_n INTEGER;

 

FOR v_n IN 1 .. 8 DO

  v_queens[:v_n] := :v_n;

ENDFOR;

 

queens = UNNEST(:v_queens) AS (n);

 

SELECT a.n AS a, b.n AS b, c.n AS c, d.n AS D,

       e.n AS e, f.n AS f, g.n AS g, h.n AS h

  FROM :queens AS a

  JOIN :queens AS b

    ON b.n <> a.n

   and (b.n - a.n) NOTIN (-1, +1)

  JOIN :queens AS c

    ON c.n NOTIN (a.n, b.n)

   AND (c.n - a.n) NOTIN (-2, +2)

   AND (c.n - b.n) NOTIN (-1, +1)

  JOIN :queens AS d

    ON d.n NOTIN (a.n, b.n, c.n)

   AND (d.n - a.n) NOTIN (-3, +3)

   AND (d.n - b.n) NOTIN (-2, +2)

   AND (d.n - c.n) NOTIN (-1, +1)

  JOIN :queens AS e

    ON e.n NOTIN (a.n, b.n, c.n, d.n)

   AND (e.n - a.n) NOTIN (-4, +4)

   AND (e.n - b.n) NOTIN (-3, +3)

   AND (e.n - c.n) NOTIN (-2, +2)

   AND (e.n - d.n) NOTIN (-1, +1)

  JOIN :queens AS f

    ON f.n NOTIN (a.n, b.n, c.n, d.n, e.n)

   AND (f.n - a.n) NOTIN (-5, +5)

   AND (f.n - b.n) NOTIN (-4, +4)

   AND (f.n - c.n) NOTIN (-3, +3)

   AND (f.n - d.n) NOTIN (-2, +2)

   AND (f.n - e.n) NOTIN (-1, +1)

  JOIN :queens AS g

    ON g.n NOTIN (a.n, b.n, c.n, d.n, e.n, f.n)

   AND (g.n - a.n) NOTIN (-6, +6)

   AND (g.n - b.n) NOTIN (-5, +5)

   AND (g.n - c.n) NOTIN (-4, +4)

   AND (g.n - d.n) NOTIN (-3, +3)

   AND (g.n - e.n) NOTIN (-2, +2)

   AND (g.n - f.n) NOTIN (-1, +1)

  JOIN :queens AS h

    ON h.n NOTIN (a.n, b.n, c.n, d.n, e.n, f.n, g.n)

   AND (h.n - a.n) NOTIN (-7, +7)

   AND (h.n - b.n) NOTIN (-6, +6)

   AND (h.n - c.n) NOTIN (-5, +5)

   AND (h.n - d.n) NOTIN (-4, +4)

   AND (h.n - e.n) NOTIN (-3, +3)

   AND (h.n - f.n) NOTIN (-2, +2)

   AND (h.n - g.n) NOTIN (-1, +1)

ORDERBY a, b, c, d, e, f, g;

 

END;

 

CALL queens();


Unfortunately there are some extremely efficient solutions to the N Queens problem like Jeff Somers's N Queens Solutions using C++, and the SQL solution can't compare to these for this type of problem. I tried running a 16x16 version of this and it was extremely slow.


Still, it was a little fun. I hope you enjoy.


Viewing all articles
Browse latest Browse all 10881

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>