Skip to main content
Commonmark migration
Source Link

#The solver:

The solver:

#The solver:

The solver:

added 3 characters in body
Source Link
Jamal
  • 34.9k
  • 13
  • 133
  • 237

I During my holiday I decided to implement a solver for those puzzles my girlfriend likes to do. They are called Takuzu, but "binero" in Dutch.

   a b c d
1. x 0 0 x
2. x x x x
3. x x x x
   a b c d
1. x 0 0 x
2. x x x x
3. x x x x

Specific questions:

I During my holiday I decided to implement a solver for those puzzles my girlfriend likes to do. They are called Takuzu, but "binero" in Dutch.

   a b c d
1. x 0 0 x
2. x x x x
3. x x x x

Specific questions

During my holiday I decided to implement a solver for those puzzles my girlfriend likes to do. They are called Takuzu, but "binero" in Dutch.

   a b c d
1. x 0 0 x
2. x x x x
3. x x x x

Specific questions:

Notice removed Draw attention by CommunityBot
Bounty Ended with no winning answer by CommunityBot
added 34 characters in body; edited tags
Source Link
Ethan Bierlein
  • 15.8k
  • 4
  • 59
  • 146

I During my holiday I decided to implement a solver for those puzzles my girlfriend likes to do. They are called Takuzu, but "binero" in Dutch.

#lang racket

(provide solve)


;; Defines the variable we us as empty.
(define x 'x)


;; Check if a given value is an unknown.
(define (unknown? x) 
  (equal? x 'x))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;; INDEXING ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Returns the value on the given position, false if the position is invalid.
(define (get binero coords)
  (let ((dim (length binero))
        (x (car coords))
        (y (cdr coords)))
    (if (or (> 0 x) (> 0 y) (<= dim x) (<= dim y))
        #f
        (list-ref (list-ref binero (cdr coords)) (car coords)))))

;; Updates the value at the given position (non-destructive).
;; Does not update if position is invalid.
(define (binero-set! binero coords value)
  (define (list-replace lst nth value)
    (cond
      ((null? lst) lst)
      ((eq? 0 nth) (cons value (cdr lst)))
      (else (cons (car lst) (list-replace (cdr lst) (- nth 1) value)))))
  (let ((x (car coords))
        (y (cdr coords)))
    (cond
      ((null? binero) binero)
      ((eq? 0 y)
       (cons (list-replace (car binero) (car coords) value)
             (cdr binero)))
      (else
       (cons (car binero)
             (binero-set! (cdr binero) (cons (car coords) (- (cdr coords) 1)) value))))))


;;; (0,0) is top left corner.
(define (left-of coord)
  (cons (- (car coord) 1) (cdr coord)))

(define (right-of coord)
  (cons (+ (car coord) 1) (cdr coord)))

(define (top-of coord)
  (cons (car coord) (- (cdr coord) 1)))

(define (below-of coord)
  (cons (car coord) (+ (cdr coord) 1)))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;; HELPERS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Prints a binero with each row on a new line.
(define (display-binero binero)
  (if (not (or (equal? #f binero) (null? binero)))
      (begin (display (car binero))
             (newline)
             (display-binero (cdr binero)))
      '()))

(define (certain-value binero coord)
  (let* ((curr   (get binero coord))
         (left   (get binero (left-of coord)))
         (lleft  (get binero (left-of (left-of coord))))
         (right  (get binero (right-of coord)))
         (rright (get binero (right-of (right-of coord))))
         (above  (get binero (top-of coord)))
         (aabove (get binero (top-of (top-of coord))))
         (below  (get binero (below-of coord)))
         (bbelow (get binero (below-of (below-of coord)))))
    (cond
      ;; Already filled in.
      ((not (unknown? curr))
       curr)
      ;; Two left values are the same.
      ((and (eq? lleft left) (member left '(1 0)))
       (abs (- left 1)))
      ;; Two right values are the same.
      ((and (eq? rright right) (member right '(1 0)))
       (abs (- right 1)))
      ;; Two top values are the same.
      ((and (eq? above aabove) (member above '(1 0)))
       (abs (- above 1)))
      ;; Two bottom values are the same.
      ((and (eq? below bbelow) (member below '(1 0)))
       (abs (- below 1)))
      ;; Bottom and top are the same.
      ((and (eq? below above) (member below '(1 0)))
       (abs (- below 1)))
      ;; Left and right are the same.
      ((and (eq? left right) (member left '(1 0)))
       (abs (- left 1)))    
      (else curr))))

(define (solve-certainties binero)
  (let ((dim (length binero)))
    (let row-loop ((y 0)
                   (b binero))
      (if (< y dim)
          (let col-loop ((x 0)
                         (bb b))
            (if (< x dim)
                (let* ((coords (cons x y))
                       (new-value (certain-value bb coords))
                       (new-binero (binero-set! bb coords new-value)))
                  (col-loop (+ x 1) new-binero))
                (row-loop (+ y 1) bb)))
          b))))

(define (solve binero)
  (let ((pass (solve-certainties binero)))
    (if (equal? pass binero)
        pass
        (solve pass))))
#lang racket

(provide solve)


;; Defines the variable we us as empty.
(define x 'x)


;; Check if a given value is an unknown.
(define (unknown? x) 
  (equal? x 'x))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;; INDEXING ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Returns the value on the given position, false if the position is invalid.
(define (get binero coords)
  (let ((dim (length binero))
        (x (car coords))
        (y (cdr coords)))
    (if (or (> 0 x) (> 0 y) (<= dim x) (<= dim y))
        #f
        (list-ref (list-ref binero (cdr coords)) (car coords)))))

;; Updates the value at the given position (non-destructive).
;; Does not update if position is invalid.
(define (binero-set! binero coords value)
  (define (list-replace lst nth value)
    (cond
      ((null? lst) lst)
      ((eq? 0 nth) (cons value (cdr lst)))
      (else (cons (car lst) (list-replace (cdr lst) (- nth 1) value)))))
  (let ((x (car coords))
        (y (cdr coords)))
    (cond
      ((null? binero) binero)
      ((eq? 0 y)
       (cons (list-replace (car binero) (car coords) value)
             (cdr binero)))
      (else
       (cons (car binero)
             (binero-set! (cdr binero) (cons (car coords) (- (cdr coords) 1)) value))))))


;;; (0,0) is top left corner.
(define (left-of coord)
  (cons (- (car coord) 1) (cdr coord)))

(define (right-of coord)
  (cons (+ (car coord) 1) (cdr coord)))

(define (top-of coord)
  (cons (car coord) (- (cdr coord) 1)))

(define (below-of coord)
  (cons (car coord) (+ (cdr coord) 1)))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;; HELPERS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Prints a binero with each row on a new line.
(define (display-binero binero)
  (if (not (or (equal? #f binero) (null? binero)))
      (begin (display (car binero))
             (newline)
             (display-binero (cdr binero)))
      '()))

(define (certain-value binero coord)
  (let* ((curr   (get binero coord))
         (left   (get binero (left-of coord)))
         (lleft  (get binero (left-of (left-of coord))))
         (right  (get binero (right-of coord)))
         (rright (get binero (right-of (right-of coord))))
         (above  (get binero (top-of coord)))
         (aabove (get binero (top-of (top-of coord))))
         (below  (get binero (below-of coord)))
         (bbelow (get binero (below-of (below-of coord)))))
    (cond
      ;; Already filled in.
      ((not (unknown? curr))
       curr)
      ;; Two left values are the same.
      ((and (eq? lleft left) (member left '(1 0)))
       (abs (- left 1)))
      ;; Two right values are the same.
      ((and (eq? rright right) (member right '(1 0)))
       (abs (- right 1)))
      ;; Two top values are the same.
      ((and (eq? above aabove) (member above '(1 0)))
       (abs (- above 1)))
      ;; Two bottom values are the same.
      ((and (eq? below bbelow) (member below '(1 0)))
       (abs (- below 1)))
      ;; Bottom and top are the same.
      ((and (eq? below above) (member below '(1 0)))
       (abs (- below 1)))
      ;; Left and right are the same.
      ((and (eq? left right) (member left '(1 0)))
       (abs (- left 1)))    
      (else curr))))

(define (solve-certainties binero)
  (let ((dim (length binero)))
    (let row-loop ((y 0)
                   (b binero))
      (if (< y dim)
          (let col-loop ((x 0)
                         (bb b))
            (if (< x dim)
                (let* ((coords (cons x y))
                       (new-value (certain-value bb coords))
                       (new-binero (binero-set! bb coords new-value)))
                  (col-loop (+ x 1) new-binero))
                (row-loop (+ y 1) bb)))
          b))))

(define (solve binero)
  (let ((pass (solve-certainties binero)))
    (if (equal? pass binero)
        pass
        (solve pass))))

During my holiday I decided to implement a solver for those puzzles my girlfriend likes to do. They are called Takuzu, but "binero" in Dutch.

#lang racket

(provide solve)


;; Defines the variable we us as empty.
(define x 'x)


;; Check if a given value is an unknown.
(define (unknown? x) 
  (equal? x 'x))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;; INDEXING ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Returns the value on the given position, false if the position is invalid.
(define (get binero coords)
  (let ((dim (length binero))
        (x (car coords))
        (y (cdr coords)))
    (if (or (> 0 x) (> 0 y) (<= dim x) (<= dim y))
        #f
        (list-ref (list-ref binero (cdr coords)) (car coords)))))

;; Updates the value at the given position (non-destructive).
;; Does not update if position is invalid.
(define (binero-set! binero coords value)
  (define (list-replace lst nth value)
    (cond
      ((null? lst) lst)
      ((eq? 0 nth) (cons value (cdr lst)))
      (else (cons (car lst) (list-replace (cdr lst) (- nth 1) value)))))
  (let ((x (car coords))
        (y (cdr coords)))
    (cond
      ((null? binero) binero)
      ((eq? 0 y)
       (cons (list-replace (car binero) (car coords) value)
             (cdr binero)))
      (else
       (cons (car binero)
             (binero-set! (cdr binero) (cons (car coords) (- (cdr coords) 1)) value))))))


;;; (0,0) is top left corner.
(define (left-of coord)
  (cons (- (car coord) 1) (cdr coord)))

(define (right-of coord)
  (cons (+ (car coord) 1) (cdr coord)))

(define (top-of coord)
  (cons (car coord) (- (cdr coord) 1)))

(define (below-of coord)
  (cons (car coord) (+ (cdr coord) 1)))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;; HELPERS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Prints a binero with each row on a new line.
(define (display-binero binero)
  (if (not (or (equal? #f binero) (null? binero)))
      (begin (display (car binero))
             (newline)
             (display-binero (cdr binero)))
      '()))

(define (certain-value binero coord)
  (let* ((curr   (get binero coord))
         (left   (get binero (left-of coord)))
         (lleft  (get binero (left-of (left-of coord))))
         (right  (get binero (right-of coord)))
         (rright (get binero (right-of (right-of coord))))
         (above  (get binero (top-of coord)))
         (aabove (get binero (top-of (top-of coord))))
         (below  (get binero (below-of coord)))
         (bbelow (get binero (below-of (below-of coord)))))
    (cond
      ;; Already filled in.
      ((not (unknown? curr))
       curr)
      ;; Two left values are the same.
      ((and (eq? lleft left) (member left '(1 0)))
       (abs (- left 1)))
      ;; Two right values are the same.
      ((and (eq? rright right) (member right '(1 0)))
       (abs (- right 1)))
      ;; Two top values are the same.
      ((and (eq? above aabove) (member above '(1 0)))
       (abs (- above 1)))
      ;; Two bottom values are the same.
      ((and (eq? below bbelow) (member below '(1 0)))
       (abs (- below 1)))
      ;; Bottom and top are the same.
      ((and (eq? below above) (member below '(1 0)))
       (abs (- below 1)))
      ;; Left and right are the same.
      ((and (eq? left right) (member left '(1 0)))
       (abs (- left 1)))    
      (else curr))))

(define (solve-certainties binero)
  (let ((dim (length binero)))
    (let row-loop ((y 0)
                   (b binero))
      (if (< y dim)
          (let col-loop ((x 0)
                         (bb b))
            (if (< x dim)
                (let* ((coords (cons x y))
                       (new-value (certain-value bb coords))
                       (new-binero (binero-set! bb coords new-value)))
                  (col-loop (+ x 1) new-binero))
                (row-loop (+ y 1) bb)))
          b))))

(define (solve binero)
  (let ((pass (solve-certainties binero)))
    (if (equal? pass binero)
        pass
        (solve pass))))

I During my holiday I decided to implement a solver for those puzzles my girlfriend likes to do. They are called Takuzu, but "binero" in Dutch.

#lang racket

(provide solve)


;; Defines the variable we us as empty.
(define x 'x)


;; Check if a given value is an unknown.
(define (unknown? x) 
  (equal? x 'x))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;; INDEXING ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Returns the value on the given position, false if the position is invalid.
(define (get binero coords)
  (let ((dim (length binero))
        (x (car coords))
        (y (cdr coords)))
    (if (or (> 0 x) (> 0 y) (<= dim x) (<= dim y))
        #f
        (list-ref (list-ref binero (cdr coords)) (car coords)))))

;; Updates the value at the given position (non-destructive).
;; Does not update if position is invalid.
(define (binero-set! binero coords value)
  (define (list-replace lst nth value)
    (cond
      ((null? lst) lst)
      ((eq? 0 nth) (cons value (cdr lst)))
      (else (cons (car lst) (list-replace (cdr lst) (- nth 1) value)))))
  (let ((x (car coords))
        (y (cdr coords)))
    (cond
      ((null? binero) binero)
      ((eq? 0 y)
       (cons (list-replace (car binero) (car coords) value)
             (cdr binero)))
      (else
       (cons (car binero)
             (binero-set! (cdr binero) (cons (car coords) (- (cdr coords) 1)) value))))))


;;; (0,0) is top left corner.
(define (left-of coord)
  (cons (- (car coord) 1) (cdr coord)))

(define (right-of coord)
  (cons (+ (car coord) 1) (cdr coord)))

(define (top-of coord)
  (cons (car coord) (- (cdr coord) 1)))

(define (below-of coord)
  (cons (car coord) (+ (cdr coord) 1)))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;; HELPERS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Prints a binero with each row on a new line.
(define (display-binero binero)
  (if (not (or (equal? #f binero) (null? binero)))
      (begin (display (car binero))
             (newline)
             (display-binero (cdr binero)))
      '()))

(define (certain-value binero coord)
  (let* ((curr   (get binero coord))
         (left   (get binero (left-of coord)))
         (lleft  (get binero (left-of (left-of coord))))
         (right  (get binero (right-of coord)))
         (rright (get binero (right-of (right-of coord))))
         (above  (get binero (top-of coord)))
         (aabove (get binero (top-of (top-of coord))))
         (below  (get binero (below-of coord)))
         (bbelow (get binero (below-of (below-of coord)))))
    (cond
      ;; Already filled in.
      ((not (unknown? curr))
       curr)
      ;; Two left values are the same.
      ((and (eq? lleft left) (member left '(1 0)))
       (abs (- left 1)))
      ;; Two right values are the same.
      ((and (eq? rright right) (member right '(1 0)))
       (abs (- right 1)))
      ;; Two top values are the same.
      ((and (eq? above aabove) (member above '(1 0)))
       (abs (- above 1)))
      ;; Two bottom values are the same.
      ((and (eq? below bbelow) (member below '(1 0)))
       (abs (- below 1)))
      ;; Bottom and top are the same.
      ((and (eq? below above) (member below '(1 0)))
       (abs (- below 1)))
      ;; Left and right are the same.
      ((and (eq? left right) (member left '(1 0)))
       (abs (- left 1)))    
      (else curr))))

(define (solve-certainties binero)
  (let ((dim (length binero)))
    (let row-loop ((y 0)
                   (b binero))
      (if (< y dim)
          (let col-loop ((x 0)
                         (bb b))
            (if (< x dim)
                (let* ((coords (cons x y))
                       (new-value (certain-value bb coords))
                       (new-binero (binero-set! bb coords new-value)))
                  (col-loop (+ x 1) new-binero))
                (row-loop (+ y 1) bb)))
          b))))

(define (solve binero)
  (let ((pass (solve-certainties binero)))
    (if (equal? pass binero)
        pass
        (solve pass))))
Tweeted twitter.com/#!/StackCodeReview/status/631032704037990400
Notice added Draw attention by Christophe De Troyer
Bounty Started worth 50 reputation by Christophe De Troyer
added 6 characters in body
Source Link
Loading
edited tags
Link
200_success
  • 144.2k
  • 22
  • 188
  • 473
Loading
edited tags
Link
200_success
  • 144.2k
  • 22
  • 188
  • 473
Loading
added 75 characters in body
Source Link
Loading
added 4 characters in body
Source Link
Loading
Source Link
Loading