编程解决谁是凶手的问题

编程解决谁是凶手的问题

编程解决谁是凶手的问题

1 简介

使用代码来解决小学问题,具体题目如下图。

https://img2018.cnblogs.com/blog/1545892/202001/1545892-20200131220437229-836456330.jpg

图1  谁是凶手

2 具体实现

主要在于条件判断。每句话所指的都不是说话者自身;只有无辜者说真话,并且至少有一句话是无辜者说的。

(defn permutations
  "计算排列"
  [s]
  (lazy-seq
   (if (seq (rest s))
     (apply concat (for [x s]
                     (map #(cons x %) (permutations (remove #{x} s)))))
     [s])))

(permutations [1 2 3])
;; => ((1 2 3) (1 3 2) (2 1 3) (2 3 1) (3 1 2) (3 2 1))

;; 所有可能结果的集合
(def results (map zipmap (cycle [guys]) (permutations [:凶手 :帮凶 :无辜者])))

;; 要检测的语句
(def exps {:甲 #(not= (:甲 %) :帮凶)
           :乙 #(not= (:乙 %) :凶手)
           :丙 #(not= (:丙 %) :无辜者)})

(def guys (set (keys exps)))

(doseq [r results]
  (let [good-guy (:无辜者 (clojure.set/map-invert r))]
    ;;找到正确答案的条件
    (when (and (not ((exps good-guy) r)) 
               ;; 只有无辜者说真话,因此关于无辜者自己的话(另外的人说的)必须为假

               (some #(% r) (->> (disj guys good-guy)
                                 (select-keys exps)
                                 vals))                
               ;; 与无辜者不相关的话至少有一个为真
               )
      (println "result:" r "
"
               "甲不是帮凶:" ((:甲 exps) r) "
"
               "乙不是凶手:" ((:乙 exps) r) "
"
               "丙不是无辜者:" ((:丙 exps) r)))))


result: {:乙 :帮凶, :甲 :凶手, :丙 :无辜者} 
 甲不是帮凶: true 
 乙不是凶手: true 
 丙不是无辜者: false
nil

作者: ntestoc

Created: 2020-01-31 五 22:04

原文地址:https://www.cnblogs.com/ntestoc/p/12246965.html