2016-08-07 53 views
1

我試圖用球拍解決這個難題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,定義小號,...部分)。如何改進?感謝您的評論/答覆。

+2

代碼檢查SO將會更適合。 – Sylwester

回答

1

這是寫在慣用的球拍同等計劃 - 並避免那些討厭的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)))) 
+0

這裏有很多新的功能對我來說! – rnso

+0

研究文檔,你會發現你在命令式代碼中使用的所有東西在功能代碼中都有更好,更等效的功能代碼 –

+0

甚至更​​習慣的解決方案將使用'for/list'而不是'for','cond'而不是'when',返回'row'而不是打印它,並且如果條件不滿足則返回false,這樣在整個事件周圍的一個'(過濾器標識...)'返回所有有效的可能性。 –

2

這個答案是基於@Oscar洛佩茲的回答,但修改爲使用更多的慣用功能,如filter與輔助函數,而不是for,whenprintln

這種返回值的代碼風格更有用,因爲它生成的值可以用於後面的代碼中,其中像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)) 
+0

偉大的功能解決方案。 – rnso