我尝试使用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,...部分)。怎么可以改进?感谢您的意见/解答。
答案 0 :(得分:2)
这个答案基于@Oscar Lopez的答案,但修改为使用更多惯用功能,例如filter
辅助函数而不是for
,when
和println
这种返回值的代码样式更有用,因为它生成的值可以在以后的代码中使用,其中像println
这样的命令行为将更不可重复使用。
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))))