Scheme 球拍累加器列表函数

Scheme 球拍累加器列表函数,scheme,racket,Scheme,Racket,我正在制作2048游戏的一个具体步骤,你可能已经玩过了。网上有很多网站 基本上,该函数所做的全部工作是: 1) 所有空格移到后面 2)如果前两个数字相等,则它会加倍并每隔两个数字检查一次 以下是我一直坚持的步骤的说明: 设计一个向左滑动功能,以便使用APS(累加器传递样式)辅助程序在给定行上运行一次传递。您需要维护两个蓄能器。第一个累加器记住最后一个未合并的数字。最初,这个值为false,这意味着我们还没有看到一个数字。第二个累加器是我们在遇到空白时将其堆积起来的地方(空白是“-”),最简单的方

我正在制作2048游戏的一个具体步骤,你可能已经玩过了。网上有很多网站

基本上,该函数所做的全部工作是: 1) 所有空格移到后面 2)如果前两个数字相等,则它会加倍并每隔两个数字检查一次

以下是我一直坚持的步骤的说明:

设计一个向左滑动功能,以便使用APS(累加器传递样式)辅助程序在给定行上运行一次传递。您需要维护两个蓄能器。第一个累加器记住最后一个未合并的数字。最初,这个值为false,这意味着我们还没有看到一个数字。第二个累加器是我们在遇到空白时将其堆积起来的地方(空白是“-”),最简单的方法是使用列表来实现此目的,因此,其初始值为空

一次完成:起初,您可能会认为在解决方案中使用累加器是个好主意。但是秩序也有问题。您可以使用类似(append solution(list number))的方法将新元素添加到当前解决方案的末尾,但该append操作是递归的,所需时间与解决方案列表的长度成比例。如果可以的话,我们肯定希望在APS递归期间避免非平凡的操作。相反,您可以决定在当前解决方案的前面添加新的数字(使用cons),目的是在最后反转解决方案。这肯定比append方法好。缺点是需要对数据进行第二次传递才能进行反转。我们希望一次完成这项工作,而且我们能够做到。因此,最简单、最快的方法就是在退出递归时,以正确的顺序构造解决方案

我在这里添加了一组检查期望值,以便您可以看到它在做什么:

(check-expect (slide-row-left '(2 2 4 -))(list 4 4 '- '-))
(check-expect (slide-row-left '(2 2 - 4))(list 4 4 '- '-))
(check-expect (slide-row-left '(2 - 2 4))(list 4 4 '- '-))
(check-expect (slide-row-left '(- 2 2 4))(list 4 4 '- '-))

(check-expect (slide-row-left '(2 2 2 2))(list 4 4 '- '-))
(check-expect (slide-row-left '(4 2 2 2))(list 4 4 2 '-))
(check-expect (slide-row-left '(2 4 2 2))(list 2 4 4 '-))
(check-expect (slide-row-left '(2 2 4 2))(list 4 4 2 '-))
(check-expect (slide-row-left '(2 2 4 4))(list 4 8 '- '-))
好的,这就是我所拥有的:

(define (blank? item) (equal? item '-))

(define (slide-row-left b)
  (blank-help (slide-row-left/help b false) '()))

(define (slide-row-left/help ls acc)
  (cond [(empty? ls) acc]
        [(not (equal? (first ls) (first (rest ls)))) 
         (slide-row-left/help (rest (rest ls)) 
           (cons (first (rest ls)) (cons (first ls) acc)))]
        [else (slide-row-left/help (rest (rest ls)) acc)]))

(define (blank-help ls acc)
  (cond [(empty? ls) acc]
        [(blank? (first ls)) (blank-help (rest ls) (cons (first ls) acc))]     
        [else (cons (first ls) (blank-help (rest ls) acc))]))
左侧的第一个累加器幻灯片行/help创建一个不合并的数字列表。它检查第一个数字和第二个数字是否不相等,并将它们添加到列表中。如果它们相等(这意味着它们合并为原始数量的两倍),那么它只是递归。第二个累加器空白有助于将所有空白区域推到列表的末尾,所以所有的数字都向左移动。 问题是,我不知道如何使用这些来合并片段,尤其是在一次传递中


我今晚就要出发了,希望你们明天能回复。任何帮助都太好了。这也是针对ISL+

的,我想我发现了您的问题。坦率地说,你还没有完全到达那里。赋值清楚地表明,您必须在从递归返回时建立结果。这是因为您不希望在程序结束时
反转
,或者在执行尾部递归时执行
追加

以下是解释每种方法的几个示例:

;; Using an accumulator
(define (double ls acc)
  (if (empty? ls)
      acc
      (double (rest ls) (cons (* 2 (first ls)) acc))))

(double '(1 2 3) '())
;; = '(6 4 2)
;; So you could reverse the result: (reverse '(1 2 3) '()))
;; but this requires looping over the list again!

;; Using append
(define (double2 ls acc)
  (if (empty? ls)
      acc
      (double2 (rest ls) (append acc (list (* 2 (first ls)))))))

(double2 '(1 2 3) '())
;; = '(2 4 6)
;; But the append operation is very expensive and you don't want that!

(define (double3 ls)
  (if (empty? ls)
      '()
      (cons (* 2 (first ls)) (double3 (rest ls)))))

(double3 '(1 2 3))
;; Cons *after* the recursive call.
;; Requires more memory though, becuase you can not do tail call optimisation!
;; Info: http://c2.com/cgi/wiki?TailRecursion
因此,对于功能的不同输入
向左滑动行/help

案例1:前两个数字相等

输入:
”(2 2 4-
结果:
'(4'-')

这里要做的是对前两个元素求和(4)。然后,您需要计算列表的其余部分。列表的其余部分现在还应该包含一个额外的空白,因为两个元素相加会使列表缩短一个元素。因此,在递归调用中将新的空白传递给
acc
值。因此,您首先要做的是计算列表的其余部分。因此,使用
(drop ls 2)
(cons'-acc)
递归调用。这将从列表中删除前2个元素。一旦你把结果拿回来(结果将是
'(4'-')
,你只需
cons
你前面的总和。这将导致总结果
'(4'-')

案例2:前两个数字不同

输入:
”(42)
结果:
'(4 4 2'-)

如果前两个数字不同,我们将无能为力。我们将从列表中删除第一个数字(
4
),这将给您留下
”(2)
。不能删除前两个元素,因为第二个和第三个元素可能可以求和。记住第一个元素并递归调用函数以计算结果的其余部分。函数返回并给出
'(4 2'-)
。现在您需要做的就是
cons
返回到它前面的第一个元素,产生
'(4 4 2'-)

案例3:第一个元素为空白

输入:
”(-24)
结果:
'(4'-')

如果第一个数字是空的,你就不能用它做任何事情。你可能会认为,在这个例子中,<强>>2 < /强>适用,但它不是。一个空白应该放在你的解决方案的后面。但是你怎么能做到呢?简单的说,你把空白放在你的累加器中。你很快就会看到,累加器基本上是你的列表的末尾。所以,从列表中去掉空白,这就给你留下了<代码>(2 2 4)<代码>。把“代码>”-<代码>放在累加器前面,这使得累加器等于<代码>('-')并执行递归调用。因此,你用列表<代码>(2 2 4)< /C>和累加器<代码>('-')< /C> >调用它。递归调用将产生<代码>(4'-'-)。因此,你不必再在它前面做任何事情,这只是你的结果

案例4:第二个元素为空白

输入:
”(2-24)
结果:
'(4'-')

如果第二个数字是空的,情况就有点复杂了。你必须从列表中删去空白。所以你需要<代码>(2 2 4)< /C>。你可以做<代码>(CONS(第一个LS)(REST(LSD))<代码>。空白可以再次,不被丢弃。你需要它把它放在列表的末尾。我在哪里

#lang racket

;; A shorthand for (first (rest ls))
(define (second ls) (first (rest ls)))

(define (blank? item) (equal? item '-))

(define (slide-row-left b)
  (blank-help (slide-row-left/help b '()) '()))

(define (slide-row-left/help ls acc)
  (cond [(empty? ls) acc]
        [(= (length ls) 1) (cons (first ls) acc)]
        ;; When the first element is blank (e.g., '(- 2 4))
        ;; -> Discard the blank
        ;; -> call the function on the rest of the list.
        [(blank? (first ls))
         (slide-row-left/help (rest ls) (cons (first ls) acc))]
        ;; When the second element is blank (e.g., '(2 - 2 4))
        ;; -> Discard the second element
        ;; -> Run the function again with the entire list (without the blank)
        [(blank? (second ls))
         (slide-row-left/help (cons (first ls) (drop ls 2)) (cons (second ls) acc))]        
        ;; If the first two elements are not equal:
        ;; -> drop 1 element from the list
        ;; -> cons this element to the result of the recursive call
        [(not (equal? (first ls) (second ls)))
         (let  ([fst (first ls)]
                [snd (second ls)]
                [rst (rest ls)]) 
           (cons fst (slide-row-left/help rst acc)))]

        ;; If the first two elements are the same:
        ;; -> drop 2 elements from the list
        ;; -> Sum them
        ;; -> cons the sum in front of the recursive call
        [else
         (let  ([fst (first ls)]
                [snd (second ls)]
                [rst (drop ls 2)]) 
           (cons (* 2 snd) (slide-row-left/help rst (cons '- acc))))]))


(define (blank-help ls acc)
  (cond [(empty? ls) acc]
        [(blank? (first ls)) (blank-help (rest ls) (cons (first ls) acc))]     
        [else (cons (first ls) (blank-help (rest ls) acc))]))

(define (check-expect x y)
  (display x)
  (display y)
  (equal? x y))

(check-expect (slide-row-left '(2 2 4 -))(list 4 4 '- '-))
(check-expect (slide-row-left '(2 2 - 4))(list 4 4 '- '-))
(check-expect (slide-row-left '(2 - 2 4))(list 4 4 '- '-))
(check-expect (slide-row-left '(- 2 2 4))(list 4 4 '- '-))

(check-expect (slide-row-left '(2 2 2 2))(list 4 4 '- '-))
(check-expect (slide-row-left '(4 2 2 2))(list 4 4 2 '-))
(check-expect (slide-row-left '(2 4 2 2))(list 2 4 4 '-))
(check-expect (slide-row-left '(2 2 4 2))(list 4 4 2 '-))
(check-expect (slide-row-left '(2 2 4 4))(list 4 8 '- '-))
(define (drop ls n)
  (cond [(empty? ls)
         ls]
        [(>= 0 n)
         ls]
        [else
         (drop (rest ls) (- n 1))]))