Functional programming scheme中的可变数据返回对,其中right元素是匹配条件的最大后缀

Functional programming scheme中的可变数据返回对,其中right元素是匹配条件的最大后缀,functional-programming,scheme,racket,mutable,Functional Programming,Scheme,Racket,Mutable,我有一个定义“sort left list”,它是根据每对的左元素排序的对列表。左元素必须是非负整数,右分量可以是任何类型的值 我必须写一个程序mkjump,它以非负整数的排序列表作为参数, 排序lst=(x1…xn)并返回左排序列表: sort left list=((x1.y1)…(xn.yn))这样:yi是sort left list的最大后缀, ((xj.yj)…(xn.yn))其中xk>所有xk的(xi)^2。例如: >(define lst (list 2 3 4 15

我有一个定义“sort left list”,它是根据每对的左元素排序的对列表。左元素必须是非负整数,右分量可以是任何类型的值

我必须写一个程序mkjump,它以非负整数的排序列表作为参数, 排序lst=(x1…xn)并返回左排序列表: sort left list=((x1.y1)…(xn.yn))这样:yi是sort left list的最大后缀, ((xj.yj)…(xn.yn))其中xk>所有xk的(xi)^2。例如:

   >(define lst (list 2 3 4 15 16 17))
   >(mkjump lst)
   >lst
    ( (2 (15) (16) (17))
    (3 (15) (16) (17))
    (4 (17))
    (15)
    (16)
    (17) )
res中的第6个元素是(x6.y6),其中x6=17,y6=null。res中的第三个元素是(x3.y3), 其中x3=4,y3是包含(x6.y6)的列表,该列表是res的最大后缀,其中xk>(xi)^2 对于所有xk


怎么写呢?

我在麻省理工学院的计划中这样做了,希望它在racket中也能起作用。我假设您实际上不必使用突变,因为您的示例并不依赖于它

(define (square x) (* x x))

(define (mkjump lst)
  (if (null? lst)
      '()
      (cons (cons (car lst) (wrapper (car lst) (cdr lst)))
        (mkjump (cdr lst)))))

(define (wrapper item lst)
  (modmap (lambda (x) 
         (if (< (square item) x)
             (list x)
             #f))
         lst))

(define (modmap proc lst)
  (cond ((null? lst) '())
        ((proc (car lst)) (cons (proc (car lst)) (modmap proc (cdr lst))))
        (else (modmap proc (cdr lst))))) 
(定义(正方形x)(*x))
(定义(mkjump lst)
(如果(空?lst)
'()
(cons(cons(车辆lst)(包装器(车辆lst)(cdr lst)))
(mkjump(cdrlst(()())))
(定义(包装项目lst)
(modmap(lambda(x)
(如果(<(方形项目)x)
(列表十)
#f) )
(lst)
(定义(modmap proc lst)
(cond((null?lst)“”())
((程序(车辆lst))(cons(程序(车辆lst))(modmap程序(cdr lst)))
(其他(modmap proc(cdrlst(()())))

如前所述,执行工作不需要可变状态。然而,如果你真的想使用它们,你可以很容易地改变基恩的解决方案,以得到你想要的。首先,您必须以尾部递归的方式翻译他的代码。您可以从
mkjump

(define (mkjump lst) (reverse (mkjump-tr lst '())))

(define (mkjump-tr lst sol)
  (if (null? lst)
      sol
      (mkjump-tr (cdr lst) 
                 (cons (cons (car lst) (wrapper (car lst) (cdr lst)))
                       sol)) ))
(define (mkjump lst)
  (let ((elt 'undefined)
        (lst lst)
        (sol '()))
  (do () 
    ((null? lst) (reverse sol))
    (set! elt (car lst))
    (set! lst (cdr lst))
    (set! sol (cons (cons elt (wrapper elt lst)) sol))
    )))
然后您可以更改
modmap

(define (modmap proc lst) (reverse (modmap-tr proc lst '())))

(define (modmap-tr proc lst sol)
  (cond ((null? lst) sol)
        ((proc (car lst)) (modmap-tr proc 
                                     (cdr lst) 
                                     (cons (proc (car lst)) sol) ))
        (else (modmap-tr proc (cdr lst) sol)))) 
尾部递归
mkjump tr
将在迭代过程中转换。这是因为它可以被看作是一个while循环。这使您能够使用
do
构造创建此循环。这样
mkjump tr
就可以写为

(define (mkjump-tr lst sol)
  (do ((lst lst (cdr lst))
       (sol sol (cons (cons (car lst) (wrapper (car lst) (cdr lst)))
                       sol)) )
    ((null? lst) sol)
    ))
modmap tr
可以翻译为

(define (modmap-tr proc lst sol)
  (do ((lst lst (cdr lst))
       (sol sol (if (proc (car lst)) (cons (proc (car lst)) sol) sol)) )
    ((null? lst) sol)
    ))
但是由于我们没有递归形式,我们可以在前面的函数
mkjump
modmap
中直接编写这些
do
。所以我们得到了

(define (mkjump lst) 
  (do ((lst lst (cdr lst))
       (sol '() (cons (cons (car lst) (wrapper (car lst) (cdr lst)))
                       sol)) )
    ((null? lst) (reverse sol))
    ))

(define (modmap proc lst) 
  (do ((lst lst (cdr lst))
       (sol '() (if (proc (car lst)) (cons (proc (car lst)) sol) sol)) )
    ((null? lst) (reverse sol))
    ))
您可以看到一些细微的变化:
reverse
sol
之前添加,并且在这两种情况下,
sol
都由空列表初始化

最后,如果你真的想看看
do
-循环结构来添加它们。以下是
mkjump

(define (mkjump lst) (reverse (mkjump-tr lst '())))

(define (mkjump-tr lst sol)
  (if (null? lst)
      sol
      (mkjump-tr (cdr lst) 
                 (cons (cons (car lst) (wrapper (car lst) (cdr lst)))
                       sol)) ))
(define (mkjump lst)
  (let ((elt 'undefined)
        (lst lst)
        (sol '()))
  (do () 
    ((null? lst) (reverse sol))
    (set! elt (car lst))
    (set! lst (cdr lst))
    (set! sol (cons (cons elt (wrapper elt lst)) sol))
    )))
我将允许您更改
modmap
。最后两次修改混淆了算法背后的思想。因此,以这种方式改变它们是一个坏主意,因为它们不会改善任何东西。然而,第一次修改可能是个好主意。因此,我建议您保留第一次修改


这是您所期望的吗?

为什么这需要可变数据?因为在运行此代码后,如果我运行lst,它将返回(2 3 4 15 16 17),所以我认为必须使用set!。。。我从可变数据问题中得到了这个问题,这并不意味着你需要可变数据。重要的是
mkjump
返回正确答案,而不是更改
lst
,除非您的作业明确要求
lst
也更改。您不能仅使用set!。你需要用一辆二手车!和/或设置cdr!如果你想改变传递到过程中的列表,这是家庭作业吗?如果是的话,应该这样标记。谢谢,但我在命令式编程中需要它,比如使用set!设置cdr!设置汽车!可以我会考虑如何使用set实现这一点!