<commit_before>(defpackage :kakuro
  (:documentation "Solver for kakuro puzzles")
  (:use :cl)
  (:export :cell :blank-cell :constraint-cell :wall-cell :puzzle
           :read-puzzle :solve-puzzle
           #+sbcl :main))

(in-package :kakuro)

(defconstant +max-digit+ 9)

(defun ways (sum len &optional other-cells)
  "calculate the ways to sum up to `sum` using `len` terms, optionally with already-marked cells"
  (defun ways-aux (sum len max-term)
    (cond
      ((minusp sum) '())
      ((and (zerop sum) (= len 0)) (list '()))
      ((zerop sum) '())
      (t
       (loop for term from 1 upto (min sum max-term)
          nconc (mapcar (lambda (way) (cons term way))
                        (ways-aux (- sum term) (1- len) (1- term)))))))
  (loop
     with ways = (mapcar #'nreverse (ways-aux sum len +max-digit+))
     for cell in other-cells
     for mark = (mark cell)
     if mark
     do (setf ways (delete-if-not (lambda (way) (find mark way)) ways))
     finally (return ways)))

(defun make-all-candidates ()
  "list all candidate entries"
  (loop for i from 1 upto +max-digit+ collect i))

(defclass cell ()
  ((x :accessor x :initarg :x :type (integer 0 *)
      :documentation "x-coordinate of the cell, origin top-left, going down")
   (y :accessor y :initarg :y :type (integer 0 *)
      :documentation "y-coordinate of the cell, origin top-left, going right")
   (puzzle :accessor puzzle :initarg :puzzle :type puzzle
           :documentation "puzzle to which this cell belongs")))

(defclass constraint-cell (cell)
  ((horiz :accessor horiz :initarg :horiz :initform nil
          :documentation "horizontal sum constraint")
   (verti :accessor verti :initarg :verti :initform nil
          :documentation "vertical sum constraint"))
  (:documentation "cell representing a constraint on the sum of other cells"))

(defmethod print-object ((c constraint-cell) stream)
  (format stream "(~a ~a)" (verti c) (horiz c)))

(defclass blank-cell (cell)
  ((horiz :accessor horiz :initarg :horiz :initform nil :type constraint-cell
          :documentation "horizontal constraint cell")
   (verti :accessor verti :initarg :verti :initform nil :type constraint-cell
          :documentation "vertical constraint cell")
   (mark :accessor mark :initarg :mark :initform nil
         :documentation "number written in the cell"))
  (:documentation "cell representing a player-fillable entry with constraints"))

(defmethod print-object ((b blank-cell) stream)
  (format stream "~a" (or (mark b) " ")))

(defclass wall-cell (cell)
  ()
  (:documentation "cell representing a wall with no constraint or entry"))<commit_msg>output blank cell as 'b'<commit_after>(defpackage :kakuro
  (:documentation "Solver for kakuro puzzles")
  (:use :cl)
  (:export :cell :blank-cell :constraint-cell :wall-cell :puzzle
           :read-puzzle :solve-puzzle
           #+sbcl :main))

(in-package :kakuro)

(defconstant +max-digit+ 9)

(defun ways (sum len &optional other-cells)
  "calculate the ways to sum up to `sum` using `len` terms, optionally with already-marked cells"
  (defun ways-aux (sum len max-term)
    (cond
      ((minusp sum) '())
      ((and (zerop sum) (= len 0)) (list '()))
      ((zerop sum) '())
      (t
       (loop for term from 1 upto (min sum max-term)
          nconc (mapcar (lambda (way) (cons term way))
                        (ways-aux (- sum term) (1- len) (1- term)))))))
  (loop
     with ways = (mapcar #'nreverse (ways-aux sum len +max-digit+))
     for cell in other-cells
     for mark = (mark cell)
     if mark
     do (setf ways (delete-if-not (lambda (way) (find mark way)) ways))
     finally (return ways)))

(defun make-all-candidates ()
  "list all candidate entries"
  (loop for i from 1 upto +max-digit+ collect i))

(defclass cell ()
  ((x :accessor x :initarg :x :type (integer 0 *)
      :documentation "x-coordinate of the cell, origin top-left, going down")
   (y :accessor y :initarg :y :type (integer 0 *)
      :documentation "y-coordinate of the cell, origin top-left, going right")
   (puzzle :accessor puzzle :initarg :puzzle :type puzzle
           :documentation "puzzle to which this cell belongs")))

(defclass constraint-cell (cell)
  ((horiz :accessor horiz :initarg :horiz :initform nil
          :documentation "horizontal sum constraint")
   (verti :accessor verti :initarg :verti :initform nil
          :documentation "vertical sum constraint"))
  (:documentation "cell representing a constraint on the sum of other cells"))

(defmethod print-object ((c constraint-cell) stream)
  (format stream "(~a ~a)" (verti c) (horiz c)))

(defclass blank-cell (cell)
  ((horiz :accessor horiz :initarg :horiz :initform nil :type constraint-cell
          :documentation "horizontal constraint cell")
   (verti :accessor verti :initarg :verti :initform nil :type constraint-cell
          :documentation "vertical constraint cell")
   (mark :accessor mark :initarg :mark :initform nil
         :documentation "number written in the cell"))
  (:documentation "cell representing a player-fillable entry with constraints"))

(defmethod print-object ((b blank-cell) stream)
  (format stream "~a" (or (mark b) "b")))

(defclass wall-cell (cell)
  ()
  (:documentation "cell representing a wall with no constraint or entry"))
{'fraction_non_alphanumeric': 0.1272486271539481, 'fraction_numerical': 0.0030297292179511455, 'mean_word_length': 3.3295081967213114, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2433834', 'n_tokens_mistral': 1692, 'n_tokens_neox': 1601, 'n_words': 614}