Sort by

recency

|

8 Discussions

|

  • + 0 comments

    I struggled with Time Limit Exceeded for n == 14 and 15 and tried to use memoization and other tricks to solve it with no luck.

    Then I realized that all of the solutions on this page are building "one queen per column" (or one queen per row) into the placement function. This solves a lot of performance issues.

  • + 0 comments

    A Clojure solution that handles all test cases.

    PERFORMANCE HINT: It pays to look at the "environment" link at the bottom of the page! My code was a bit too slow to handle case 4 (14), and it seems one bottleneck in union-ing sets. The test environment includes a library called int-map which is significantly faster and solved the problem.

    (ns superqueens
        (:require [clojure.data.int-map :as i]))
    
    (def N (Integer/parseInt (read-line)))
    ; (def N 14)
    
    (defn between [v1 v2 v]
        (and (<= v1 v) (<= v v2)))
    
    (defn between-xy [v1x v1y v2x v2y px py]
        (and (between v1x v2x px) (between v1y v2y py)))
    
    (defn blocked [qx qy x y]
        (or
            (= x qx)
            (= (- x qx) (- y qy))
            (= (- x qx) (- qy y))
            (between-xy (- qx 2)(- qy 2) (+ qx 2)(+ qy 2) x y)))
    
    (def BLOCKERS
        (vec (for [qy (range N) qx (range N)]
            (i/int-set (for [y (range N) x (range N) :when (blocked qx qy x y)]
                   (+ x (* N y)))))))
    
    (defn place [row board]
      (if (< row N)
       (let [pmin (* N row)]
         (reduce + (for [p (range pmin (+ N pmin))
                         :when (nil? (board p))]
                     (place 
                        (inc row)
                        (i/union board (BLOCKERS p))))))
       1))
    
    (let [t0 (System/currentTimeMillis)]
      (println (place 0 (i/int-set)))
      (format "Time: %d" (- (System/currentTimeMillis) t0)))
    
  • + 0 comments

    The problem of the last test - some optimizatins. If all tests are passed except the last (timeout) - seems like your idea is ok. In my case the problem was in L-shaping. I collected all of them inside one set and passed it through the recursion. But (F# lang) the search is Log(O). I have changed 1 common storage to 2 separaged, level1 and level2. So when i checked (i,j) place - I have chacked (except lines and diagonales) only level1 set. if it was ok - add to level2 new L-shaped positions and add 2 points to new Level3 set. the next iteration is level2 as level1 and level3 as level2. Through this way every step have 3 check in Set(N) and 1 check in Set(4). Hope it is clear....

  • + 1 comment

    Well-commented code for Haskell beginners:

    import Control.Monad (guard)
    
    import qualified Data.IntSet as Set
    
    placeNSuperQueens :: Int -> Int
    placeNSuperQueens n
        = length (go Set.empty Set.empty Set.empty
                     (100, 100) -- y value of last two columns. For first column,
                                -- represents nonsense value that passes knight check.
                     n)
        where go _ _ _ _ 0
                  = return () -- If go had an extra argument that accumulated y
                              -- positions, it could return valid placements easily.
                              -- The tuple of the last two columns would then
                              -- be unnecessary. It currently returns unit as this
                              -- information is not needed.
              go horizontals diagonals antidiagonals (y1, y2) left = do
                  y <- [1..n]
                  let x = n - left
                      -- These next two variables are key. To the right, a mapping
                      -- from board position to diagonals (\) and antidiagonals (/).
                      currentDiagonal = y - x
                      currentAntidiagonal = y + x
                  -- Perform knight checks first, as they are quicker.
                  guard $ abs (y2 - y) /= 2 
                  guard $ abs (y1 - y) /= 1
                  -- Queen operations use sets, and are thus slower.
                  -- We want to discard failing placements quickly.
                  guard $ y `Set.notMember` horizontals
                  guard $ currentDiagonal `Set.notMember` diagonals
                  guard $ currentAntidiagonal `Set.notMember` antidiagonals
                  go (Set.insert y horizontals)
                     (Set.insert currentDiagonal diagonals)
                     (Set.insert currentAntidiagonal antidiagonals)
                     (y2, y)
                     (left - 1)
    
    main :: IO ()
    main = interact $ show . placeNSuperQueens . read
    
  • + 1 comment

    Not sure that my solution is right, but:

    n = 14: it takes nearly 4 to 5 seconds to compute all queens n = 15: it takes nearly 39 seconds to compute all queens

    If I am right, then, my solution should pass all tests for all integers in range [8, 14], not for 15.

    Is it correct that #5 testcase use 14 as input?