Racket/Scheme解24点游戏, 初版

函数式编程真好用,

优化是啥, 能吃么2333

(如果有点兴趣, 后面我稍微给出了解释)

#lang racket
(define (co sym number)
  (cons sym number))
(define (get_sym s)
  (if (number? s)
    s
    (car s)))
(define (get_number s)
  (if (number? s)
    s
    (cdr s)))

(define (gen f a b)
  (co (list 
      (cond ((eq? f +) '+)
        ((eq? f -) '-)
        ((eq? f *) '*)
        ((eq? f /) '/))
      (get_sym a) (get_sym b))
    (f (get_number a) (get_number b))))
(define (f0 a b)
  (if (or (eq? a 'err) (eq? b 'err))
    (list 'err)
  (list 
      (gen + a b)
      (gen - a b)
      (gen - b a)
      (gen * a b)
    (if (= (get_number b) 0)
        'err
        (gen / a b))
    (if (= (get_number a) 0)
        'err
        (gen / b a)))))
(define (f1 a l)
  (if (null? l)
    '()
    (append (f0 a (car l))
      (f1 a (cdr l)))))
(define (f2 l1 l2)
  (if (null? l1)
    '()
    (append (f1 (car l1) l2)
      (f2 (cdr l1) l2))))
(define (c n)
  (cond 
    ((= n 1) '(1 2 3 4)) ; 把这里改成想要的4个数字就行
    ((= n 2) (f2 (c 1) (c 1)))
    ((= n 3) (f2 (c 1) (c 2)))
    ((= n 4) 
      (append (f2 (c 1) (c 3))
        (f2 (c 2) (c 2))))))

; 这就是答案了
(filter (lambda (x) (= (get_number x) 24))
        (filter (lambda (x) (not (eq? x 'err)))
                (c 4)))

直接算1 2 3 4有474种答案, 当然有很多是重复的

(((* 1 (* 2 (* 3 4))) . 24)
 ((/ (* 2 (* 3 4)) 1) . 24)
 ((* 1 (* 2 (* 4 3))) . 24)
 ((/ (* 2 (* 4 3)) 1) . 24)
 ((* 1 (* 3 (* 2 4))) . 24)
 ((/ (* 3 (* 2 4)) 1) . 24)
 ((* 1 (* 3 (* 4 2))) . 24)
 ((/ (* 3 (* 4 2)) 1) . 24))

要是有人看的话, 我再写点, 

基本思路是生成abcd与+-*/的所有结果, 再筛选出需要的结果, 

上面有八个函数, co, get_sym, get_number, gen, f0, f1, f2, c, 

递归地想, 四个数字的结果表可以由三个数字的结果表和一个数字得出(简称3+1)或者2+2, 

同理, 3=1+2, 2=1+1, 

这就是c函数干的事: 初次分解, 

然后, 用两个结果表生成一个结果表, 这就是个双重循环, 

然后我拆成三个函数: 列表对列表, 列表对元素, 元素对元素, 

就是f2, f1, f0三个函数, 

拿着ab, 如何生成(a+b, a-b, b-a, a*b, a/b, b/a), 应该就不用我说了吧, 

co, get_sym, get_number, 就是一数据抽象之类的对象, 无需在意, 

最后, gen函数应该改成搜索列表之类的, 而不是一个情况判断, 有空再说吧, 下次一定2333

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值