在 Racket 中解决难题 [英] Solving a puzzle in Racket

查看:90
本文介绍了在 Racket 中解决难题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<块引用>

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

他们的回答如下:

Terry:不是卡尔,是史蒂夫史蒂夫:不是马特,不是卡尔马特:是卡尔,不是特里本:是马特,是史蒂夫卡尔:是本,不是特里

<块引用>

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

以下是我的代码:

(define (oneof a b)(或(和a(不是b))(和b(不是a))))(对于((i 5))(定义临时列表(列表#f #f #f #f #f));制作一个所有虚假的临时清单;(set!templist (list-set templist i #t)) ;在这个循环中一一保持为真;(定义 t (list-ref templist 0)) ;按照上面的名单分配每个人(一个一个地保持真实)(定义 s (list-ref templist 1))(定义 m (list-ref templist 2))(定义 b (list-ref templist 3))(定义 c (list-ref templist 4))(when ; 测试所有语句是否符合上述赋值:(和(其中一个(不是 c) s);特里的声明(oneof (not m) (not c)) ;史蒂夫的声明(一个c(不是t));马特的声明(其中一个);本的声明(一个 b (不是 t))) ;卡尔的声明(println (list "t" "s" "m" "b" "c")) ;如果所有语句都适合,则打印分配;(println 临时表)))

输出表明马特犯了罪:

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

它可以工作,但代码是命令式的,功能不是很强大(尤其是定义 t、定义 s、...部分).如何改进?感谢您的评论/回答.

解决方案

这是一个用惯用的 Racket 编写的等效程序 - 避免所有那些讨厌的 set!list-ref 在编写函数式代码时不受欢迎:

<代码>;生成具有可能性的矩阵(定义(生成矩阵 n)(for/list [(i (in-range n))](构建列表 n (λ (j) (= i j)))));迭代每一行(for [(row (make-matrix 5))];将每一行解包成相应的变量(match-let ([(list t s m b c) row]);不要重新发明轮子,`oneof`被称为`xor`(当 (和 (xor (not c) s)(异或(非 m)(非 c))(异或 c(不是 t))(异或毫秒)(xor b (不是 t)))(println '(t s m b c))(println 行)))))

I tried to solve this puzzle https://puzzling.stackexchange.com/questions/40094/who-committed-the-crime using Racket.

A crime has been carried out by one person, there are 5 suspects. Each suspect is asked under polygraph who they think committed the crime.

Their answers are as follows:

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 

The polygraph showed that each suspect told one lie and one truth. Who committed the crime?

Following is my code:

(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)))

Output indicates Matt committed the crime:

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

It works but the code is imperative and not very functional (especially define t, define s, ... part). How can it can be improved? Thanks for your comments/answers.

解决方案

This is an equivalent program written in idiomatic Racket - and avoiding all those pesky set! and list-ref which are frowned upon when writing functional-style code:

; 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))))

这篇关于在 Racket 中解决难题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆