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. Linux/Unix分配进程ID的方法以及源代码实现

    在Linux/Unix系统中.每一个进程都有一个非负整型表示的唯一进程ID.尽管是唯一的.可是进程的ID能够重用.当一个进程终止后,其进程ID就能够再次使用了. 大多数Linux/Unix系统採用延迟 ...

  2. UVA 10700 Camel trading 无括号的表达式 贪心

    题意:给出只包含数字和+*的表达式,你可以自己安排每一个运算的顺序,让你找出表达式可能得到的最大值和最小值. 很明显,先乘后加是最小值,先加后乘能得到最大值. 其实不是很明显... 证明下: 数字的范 ...

  3. 【CSS】瀑布流布局的两种方式:传统多列浮动和绝对定位布局

    传统多列浮动 各列固定宽度,并且左浮动: 一列中的数据块为一组,列中的每个数据块依次排列即可: 更多数据加载时,需要分别插入到不同的列上: 优点: (1)布局简单,应该说没啥特别的难点: (2)不用明 ...

  4. iOS正則表達式(一)

    什么是正則表達式? 正則表達式是对字符串操作的一种逻辑公式. 作用? 在iOS开发中我们通常使用正則表達式来匹配给定的字符串是否符合我们的业务逻辑,比方说用户注冊帐号仅仅能是手机号或者邮箱等.我们还能 ...

  5. 修改MySQL数据文件的位置

    1:查看MySQL服务名称 2:管理员启动控制台 3:修改配置文件my.ini中数据文件的位置,[注]修改完成之后要把响应的数据文件从旧目录拷贝到新目录当中. 4:重新启动服务 5:登录数据库查看数据 ...

  6. 全局安装 vue

    通过npm命令安装vuejs在用 Vue.js 构建大型应用时推荐使用 NPM 安装,NPM 能很好地和诸如 Webpack 或Browserify 的 CommonJS 模块打包器配合使用.(以下操 ...

  7. jquery局部打印插件使用

    基于jquery库的jquery.PrintArea.js插件源代码为: (function ($) { var printAreaCount = 0; $.fn.printArea = functi ...

  8. 第14章1节《MonkeyRunner源代码剖析》 HierarchyViewer实现原理-面向控件编程VS面向坐标编程

    到此为止我们描写叙述的MonkeyRunner相应用的点击拖放等操作都是直接通过指定坐标点来实现的.比方以下触摸一个坐标点为(60,90)的按钮的脚本样例: 1 device.touch(60,900 ...

  9. eclipse tomcat路径更改后启动报错

      eclipse tomcat路径更改后启动报错 CreateTime--2018年5月3日14:48:22 Author:Marydon 1.情景还原 2.原因 本地的tomcat路径修改后,ec ...

  10. spring MVC之构造ModelAndView对象

    spring MVC之构造ModelAndView对象 ---------- 构造ModelAndView对象 当控制器处理完请求时,通常会将包含视图名称或视图对象以及一些模型属性的ModelAndV ...