Racket 版本的 24 点实现

#lang racket

; Author: woodfox
; Date: Oct 11, 2014 ; ==================== 1. Non-determinism implementation for Racket ==================
; refer to <On Lisp> by Paul Graham
(define *paths* '())
(define failsym '@)
(define (choose choices)
(if (null? choices)
(fail)
(call-with-current-continuation
(lambda (cc)
(set! *paths*
(cons (lambda ()
(cc (choose (cdr choices))))
*paths*))
(car choices)))))
(define fail '())
(call-with-current-continuation
(lambda (cc)
(set! fail
(lambda ()
(if (null? *paths*)
(cc failsym)
(let ((p1 (car *paths*)))
(set! *paths* (cdr *paths*))
(p1)))))))
; ==================== Non-determinism implementation ENDs ============== ; ========= 2. implement permute function ==================================
; refer to: http://stackoverflow.com/questions/4180101/creating-an-n-sized-permutation-with-scheme-using-only-basic-constructs
(define (seq start end)
(if (= start end)
(list end) ; if start and end are the same number, we are done
(cons start (seq (+ start 1) end)))) (define (insert cdrList n carItem)
(if (= 0 n)
(cons carItem cdrList) ; if n is 0, prepend carItem to cdrList
(cons (car cdrList)
(insert (cdr cdrList) (- n 1) carItem)))) ; (map (lambda (n)
; (insert '(b c) n 'a))
; '(0 1 2)) -> output of seq function given n = 2, which is length of '(b c)
; '((a b c) (b a c) (b c a)) ---> will be the output (define (permute mylist)
(if (null? mylist)
'(())
(apply append (map (lambda (plist)
(map (lambda (n)
(insert plist n (car mylist)))
(seq 0 (length plist))))
(permute (cdr mylist)))))) ;(permute '(a b c)) ; ========= permute function implemenetation END ========= ; ================ Calculate 24 implementation ===================
(define operators '(+ - * /)) (define-syntax-rule (mytest a b c d f1 f2 f3)
(let ((combinations (list `(,f3 (,f1 ,a ,b) (,f2 ,c ,d))
`(,f3 (,f2 (,f1 ,a ,b) ,c) ,d)
`(,f3 (,f2 ,a (,f1 ,b ,c)) ,d)
`(,f3 ,a (,f2 (,f1 ,b ,c) ,d))
`(,f3 ,a (,f2 ,b (,f1 ,c ,d))))))
(let ((expr (choose combinations)))
(with-handlers ([exn:fail:contract:divide-by-zero?
(lambda (exn) (fail))])
(if (= 24 (eval expr))
(displayln expr)
(fail)))))) (define (calc24 nums)
(let ((nums2 (choose (permute nums))))
(let ((a (car nums2))
(b (cadr nums2))
(c (caddr nums2))
(d (cadddr nums2))
(f1 (choose operators))
(f2 (choose operators))
(f3 (choose operators)))
(mytest a b c d f1 f2 f3))))

真正跟 24点逻辑相关的是最后一小段, “Calculate 24 implementation” 注释开始后的代码,代码不多。

前面都是准备工作,一小段代码实现了不确定性计算的自动回溯功能;

另一小段代码是实现了全排列的辅助函数。

测试:

欢迎使用 DrRacket, 版本 5.3.3 [3m].
语言: racket; memory limit: 128 MB.
> (calc24 '(4 5 6 7))
(* 4 (+ (- 5 6) 7))
> (fail)
(* 4 (- 5 (- 6 7)))
> (fail)
(* (+ (- 5 6) 7) 4)
> (calc24 '(3 3 8 8))
(/ 8 (- 3 (/ 8 3)))
>

每次调用可以输出一个解。如果想要更多的解,执行一次 (fail) 函数就可以了,每执行一次会自动回溯,找到下一个解,直到无解为止。

在用 '(3 3 8 8) 这个例子尝试的时候,顺带发现了前面 Haskell 版本写的一个 bug, 即:

想当然的以为全排列后每次取到的4个数应该不一样,因此把有重复数字的情况都排除掉了,求不到解。

这个 Racket 版本在做的时候,顺带修正了这个 bug.

回头晚一点把 Haskell 的也 fix 一下。

完毕。

Racket 版本的 24 点实现的更多相关文章

  1. C# 版本的24点实现

    C# 版本的24点实现. 已经实现基本功能,可以正确的算 3, 3, 8, 8 这类组合. 稍加修改就可以支持任意数目的操作数和操作符组合形成的四则运算表达式,不限于24点. 代码还比较简单粗糙,晚一 ...

  2. 团队作业4--第一次项目冲刺(Alpha版本)预备工作

    小组说明 我们组是从周一开始对项目进行研究讨论并编程的,因为我们看截止日期是周日,就从周一才开始,起步晚了,是我们认识上的失误,导致我们周一周二的步伐没有协调好,项目进展的不稳定,但是我们在上周末并不 ...

  3. ESP-IDF版本2.1.1

    版本2.1.1是一个错误修复版本.它包括对KRACK和BlueBorne漏洞的修复. 版本2.1.1的文档可在http://esp-idf.readthedocs.io/en/v2.1.1/上找到. ...

  4. Android 7.0以上版本 系统解决拍照的问题 exposed beyond app through ClipData.Item.getUri()

    解决方案1: android.os.FileUriExposedException: file:///storage/emulated/0/ilive/images/photophoto.jpeg e ...

  5. 交叉编译OpenCV的Android版本

    交叉编译OpenCV的Android版本 OpenCV作为一个强大的图像处理库,在Android上也有强大的应用. OpenCV官网提供了SDK的下载,可以直接下载使用 OpenCV官网地址:http ...

  6. selenium:chromedriver与chrome版本的对应关系

    转自:http://blog.csdn.NET/huilan_same/article/details/51896672 再使用selenium打开chrome浏览器的时候,需要用chromedriv ...

  7. 四、10分钟ToPandas_0.24.2

    # Author:Zhang Yuan整理,版本Pandas0.24.2 # 0. 习惯上,我们会按下面格式引入所需要的包: import pandas as pd import numpy as n ...

  8. OpenCV.3.4.6_VS2015&cmake编译x86版本的bin&lib

    ZC:<<OpenCV3编程入门>> 的 2.2.2 中也有该内容的讲解 1.参考网址:opencv3.3.0+vs2015+cmake编译opencv x86 - wowo的 ...

  9. PDF 文件编写器 C# 类库(版本 1.28.0)使用详解

    PDF File Writer 是一个 C# .NET 类库,允许应用程序创建 PDF 文件. PDF File Writer C# 类库使 .NET 应用程序能够生成 PDF 文档.该库使应用程序免 ...

随机推荐

  1. 安装--->Tomcat监控工具Probe

    1.Porbe介绍 psi-probe用于对Tomcat进行监控,比tomcat的manager强大很多. 2.下载 probe-2.3.3.zip  或者  probe.war 3.将下载好的war ...

  2. 策略模式(Strategy)简介

    一.策略模式(Strategy)简介 策略模式是行为模式. 行为模式:规定了各个对象应该具备的职责以及对象间的通信模式,它很好的规范了对象间调用和数据传递方式 策略模式适合于算法经常变化的情况 算法的 ...

  3. 解决sqlplus: command not found

    export ORACLE_BASE=/u01/app/oracle export ORACLE_HOME=$ORACLE_BASE/product//db_1 su - root ln -s $OR ...

  4. MSSQL语句批量替换表中某列字段内容的某个字符

    UPdate 表 Set 字段名=REPLACE(字段名,'查找目标字符','要替换的字符') 比如:在Products表中把字段CharCode中含有ch-的字符全部替换为dw- UPDATE Pr ...

  5. python学习笔记之基础数据和控制

    注释: 单行注释 # 多行注释'''    ''' 注意:当注释中有汉字时需要在python文件的第一行添加如下内容之一:#coding:gbk或#coding:utf-8或##-*- coding ...

  6. J2EE项目集成SAP的BO报表

    网上的方案: 每个用户在自己的J2EE系统的用户登陆的同时登陆bo系统,这做法的缺点是登陆bo速度慢,而且如果J2EE用户比较多的话会在bo服务器生成很多的token. 最佳方案(自己研究): 1.调 ...

  7. 判断是否为SIM卡联系人

    判断是否为SIM卡联系人 在AsyncQueryContacts类中. private List<TxrjAccount> accounts = new ArrayList<Txrj ...

  8. 【laravel5.4】中jquery的post Ajax提交

    1.post的ajax需要提交csrf_token字段,进行安全过滤 <meta name="csrf-token" content="{{ csrf_token( ...

  9. get请求乱码情况

    编写一个RegistServlet处理用户的Get请求数据 public void doGet(HttpServletRequest request, HttpServletResponse resp ...

  10. js 随机变换图片

    <div style="position:absolute;left:40%;top:10%;border-style:dotted"> <img src=&qu ...