pseudohkoo / src / pseudohkoo / core.clj

(ns pseudohkoo.core)
(require 'clojure.set)

(defn extract-slice [vec index]
  ; extracts a three item slice from vec which corresponds to the slice of 3x3 box index is within
  ; this needs a better description!
  (let [start-index (* 3 (quot index 3))]
    (subvec vec start-index (+ start-index 3))))

(defn get-box [grid row-index column-index]
  ; return set of values of 3x3 box containing given location
  (set (flatten (map
		 (fn [row] (extract-slice row column-index))
		 (extract-slice grid row-index)))))

(defn get-column [grid column-index]
  ; returns the specified column from the grid
  (map (fn [row] (nth row column-index)) grid))

(defn get-row [grid row-index]
  ; returns the specified row from the grid, or [] if row out-of-bounds
  (nth grid row-index []))

(defn update-row [row column-index new-value]
  ; returns a copy of row with the indicated column set to new-value
  (let [head (take column-index row)
	tail (nthnext row (+ column-index 1))]
    (concat head [new-value] tail)))

(defn get-cell [grid row-index column-index]
  ; returns the value of the grid cell at the given location, or nil if out-of-bounds
  (nth (get-row grid row-index) column-index nil))

(defn refine-row [row]
  ; return a row with non-definite values rfined, where possible
  (let [required-values (set (range 1 (+ (count row) 1)))
	current-values  (set row)
	missing-values  (clojure.set/difference required-values current-values)]
    (map (fn [cell]
	   (if (nil? cell)
	     (if (= 1 (count missing-values))
	       (first missing-values)
	       (vec missing-values))

(defn refine-grid [grid]
  ; return a "refined" grid - replacing nil cells with definite or possible values as appropriate 
  (map refine-row grid))

(defn row-complete? [row]
  ; returns true if row has been completed or false if not
  (let [required-values (set (range 1 (+ (count row) 1)))]
    (= required-values (set row))))

(defn grid-complete? [grid]
  ; returns true if grid is finished or false if not
  (reduce (fn [x y] (and x y)) (map row-complete? grid)))