Scheme 在球拍中解谜

Scheme 在球拍中解谜,scheme,racket,Scheme,Racket,我试着用球拍解这个谜 一人犯罪,有5名嫌疑人。每个 在测谎仪下询问嫌疑犯他们认为谁犯了罪 他们的答覆如下: 测谎仪显示 每个嫌疑犯都说了一个谎言和一个真相。谁犯了罪 以下是我的代码: (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;

我试着用球拍解这个谜

一人犯罪,有5名嫌疑人。每个 在测谎仪下询问嫌疑犯他们认为谁犯了罪

他们的答覆如下:

测谎仪显示 每个嫌疑犯都说了一个谎言和一个真相。谁犯了罪

以下是我的代码:

(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)))
输出表明Matt犯了罪:

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

它可以工作,但代码是必需的,功能性不强(尤其是define t、define s、…part)。如何改进?谢谢你的评论/回答

这是一个用惯用的Racket编写的等效程序,避免了所有那些讨厌的
集合
列出了在编写功能样式代码时不受欢迎的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))))

此答案基于@Oscar Lopez的答案,但修改为使用更惯用的功能,如带有辅助函数的
过滤器
,而不是
for
when
println

这种返回值的代码样式更有用,因为它生成的值可以在以后的代码中使用,在以后的代码中,像
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? : (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))

代码审查,所以将是一个更好的适合。许多新的功能在这里为我!研究文档,你会发现你在命令式代码中使用的所有东西在函数式代码中都有一个更好、更精简的等价物一个更惯用的解决方案将使用
for/list
而不是
for
cond
而不是
when
,返回
行而不是打印它,如果条件不满足,则返回false,这样整个事件周围的
(筛选器标识…
)将返回所有有效的可能性。@AlexKnauth:如果您输入该选项作为答案,则会更清楚。另请参阅。功能性解决方案很棒。
#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))