I'm working on a specific step in creating the 2048 game which you may have played. It's on a bunch of websites online.
Basically all this function does is: 1) All blank spaces move to the back and 2) if the first two numbers are equal then it doubles and checks every two numbers
These are the instructions for the step I'm stuck on:
Design a slide-left function so that it runs a single pass over the given row using an APS (accumulator passing style) helper. You will need to maintain two accumulators. The first accumulator remembers the last unmerged number. Initially, this value is false, meaning that we have not yet seen a number. The second accumulator is where we pile up the blanks as we come across them (a blank is '-) The easiest thing to do is to use a list for this purpose and, thus, its initial value is empty.
Do it in a single pass: You might think, at first, that it would be a good idea to use an accumulator for the solution. But then there is a problem with order. You could add new elements to the end of the current solution using something like (append solution (list number)), but that append operation is recursive and takes time proportional to the length of the solution list. We definitely want to avoid non-trivial operations during an APS recursion if we can. You could, instead, decide to add new numbers to the front of the current solution (using cons), with the intention of reversing the solution at the end. This is certainly better than the append approach. The drawback is that it requires a second pass over the data to do the reversal. We want to do this in one pass, and we can. So, the easiest and fastest thing to do is to just construct the solution, in the right order, as you back out of the recursion.
I added a bunch of check-expects here so you can see what it's doing:
(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 '- '-))
Alright, so here is what I have:
(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))]))
The first accumulator slide-row-left/help creates a list of the numbers that are not going to be merging. It checks that the first number and second are not equal and adds them to the list. If they are equal (which means they merge to double the original amount) then it just recurs. The second accumulator blank-help pushes all of the blank spaces '- to the end of the list, so all the numbers move left.
The problem is that I don't know how to make the pieces merge using these, especially in a single pass.
I'm about to head off for the night so hopefully you guys respond by tomorrow. Any help would be so great. Also this is for ISL+