在Racket中解决一个难题

时间:2016-08-07 16:49:01

标签: scheme racket

我尝试使用Racket来解决这个难题https://puzzling.stackexchange.com/questions/40094/who-committed-the-crime

  犯罪已经由一人进行,有5名犯罪嫌疑人。每   根据测谎仪询问嫌疑人他们认为犯了什么罪。

     

他们的答案如下:

Terry : It wasn't Carl, It was Steve 
Steve : It wasn't Matt, It wasn't Carl 
Matt : It was Carl, It wasn't Terry 
Ben : It was Matt, It was Steve 
Carl : It was Ben, It wasn't Terry 
  

测谎仪表明了这一点   每个嫌犯都说了一个谎言和一个真相。谁犯了罪?

以下是我的代码:

(define (oneof a b)
  (or (and a (not b)) (and b (not a))))

(for ((i 5))
  (define templist (list #f #f #f #f #f))  ; make a temporary list of all false; 
  (set! templist (list-set templist i #t)) ; one by one keep one as true in this loop; 
  (define t (list-ref templist 0))   ; allocate each person according to above list (one kept true one by one)
  (define s (list-ref templist 1))
  (define m (list-ref templist 2))
  (define b (list-ref templist 3))
  (define c (list-ref templist 4))

  (when                              ; test if all statements fit with above assignment: 
    (and
     (oneof  (not c) s)              ; Terry's statement
     (oneof  (not m) (not c))        ; Steve's statement
     (oneof  c (not t))              ; Matt's statement
     (oneof  m s)                    ; Ben's statement
     (oneof  b (not t)))             ; Carl's statement
    (println (list "t" "s" "m" "b" "c"))  ; print allocation if all statement fit in; 
    (println templist)))

输出表明马特犯了罪:

'("t" "s" "m" "b" "c")
'(#f #f #t #f #f)

它可以工作但是代码是必要的而且功能不是很强大(特别是定义t,定义s,...部分)。怎么可以改进?感谢您的意见/解答。

2 个答案:

答案 0 :(得分:2)

这个答案基于@Oscar Lopez的答案,但修改为使用更多惯用功能,例如filter辅助函数而不是forwhenprintln

这种返回值的代码样式更有用,因为它生成的值可以在以后的代码中使用,其中像println这样的命令行为将更不可重复使用。

@Oscar Lopez的make-matrix函数生成了一个可能的初始列表,但是我们必须过滤掉那些不可能的,并且只留下那些可能的。写下来:

;; If there are no valid solutions, this will be an empty list,
;; if there's one, this will be a list of one element,
;; and if there are more, this will include all of them.
(filter valid-solution? (make-matrix 5))

;; Wish list:
;; valid-solution? : (Listof Boolean) -> Boolean

现在我们只需添加valid-solution?

的定义
;; valid-solution? : (Listof Boolean) -> Boolean
;; Given a list containing booleans for whether Terry, Steve, Matt, Ben, and Carl did it,
;; this determines whether that combination is possible under the constraints in the problem.
(define (valid-solution? row)
  ; unpack each row into the corresponding variables
  (match-define (list t s m b c) row)
  ; don't reinvent the wheel, `oneof` is called `xor`
  (and (xor (not c) s)
       (xor (not m) (not c))
       (xor c (not t))
       (xor m s)
       (xor b (not t))))

就是这样。包括make-matrix在内的完整计划是:

#lang racket

;; make-matrix : Natural -> (Listof (Listof Boolean))
;; generate a matrix with possibilities
(define (make-matrix n)
  (for/list ([i (in-range n)])
    (build-list n (λ (j) (= i j)))))

;; valid-solution? : (Listof Boolean) -> Boolean
;; Given a list containing booleans for whether Terry, Steve, Matt, Ben, and Carl did it,
;; this determines whether that combination is possible under the constraints in the problem.
(define (valid-solution? row)
  ; unpack each row into the corresponding variables
  (match-define (list t s m b c) row)
  ; don't reinvent the wheel, `oneof` is called `xor`
  (and (xor (not c) s)
       (xor (not m) (not c))
       (xor c (not t))
       (xor m s)
       (xor b (not t))))

;; If there are no valid solutions, this will be an empty list,
;; if there's one, this will be a list of one element,
;; and if there are more, this will include all of them.
(filter valid-solution? (make-matrix 5))

答案 1 :(得分:1)

这是一个用惯用的Racket编写的等效程序 - 避免在编写功能样式代码时不赞成的所有那些讨厌的set!list-ref

; generate a matrix with possibilities
(define (make-matrix n)
  (for/list [(i (in-range n))]
    (build-list n (λ (j) (= i j)))))

; iterate over each row
(for [(row (make-matrix 5))]
  ; unpack each row into the corresponding variables
  (match-let ([(list t s m b c) row])
    ; don't reinvent the wheel, `oneof` is called `xor`
    (when (and (xor (not c) s)
               (xor (not m) (not c))
               (xor c (not t))
               (xor m s)
               (xor b (not t)))
      (println '(t s m b c))
      (println row))))