2

My problem is to make a simple plus-minus program using Racket R5RS language. The basic idea of the problem is to put plus/minus signs in front of every element in list and check if the result is one of the elements in list. Below is what I have right now:

(define plus-minus (lambda (lst l sum)
                (cond
                  ((null? lst)
                   (cond
                     ((null? l) #f)
                     ((= sum (car l)) #t)
                     (else (plus-minus lst (cdr l) sum))))
                  ((plus-minus (cdr lst) l (+ sum (car lst))) #t)
                  ((plus-minus (cdr lst) l (- sum (car lst))) #t)
                  (else #f))))

This code is working, but it is required that there should be one and only one list in the parameters and all others are numbers. The first two parameters in my code are identical when the function is firstly called. The first one is the one to get the sum. The second one is to check if sum equals one of the elements in list. Both of the lists are required because as I get the sum, the elements in the first list are removed.
My question is, how to get rid of the second list in parameters? Is there anyway I can iterate through the list without removing elements (CDR commend)?

S.Y
  • 35
  • 5

1 Answers1

3

First of all, the part of your code

(cond
  ((null? l) #f)
  ((= sum (car l)) #t)
  (else (plus-minus lst (cdr l) sum))))

is to check if sum is in l or not. There is a function to do so already called member, so you can replace the entire chunk with (member sum l), which is cleaner.

I want to correct a misconception first too. cdr does not remove an element from a list. A list is defined as either an empty list, or a pair of an element and another list. For example

[1 [2 [3 empty]]]

is a list which has three elements: 1, 2, and 3. What car does is to fetch the first element of the pair. What cdr does is to fetch the second element of the pair. Nothing is removed.

To get rid of additional arguments, you might want to rename this function to another function, say plus-minus-helper, and create plus-minus which then calls plus-minus-helper. plus-minus then would be:

(define (plus-minus lst)
  (plus-minus-helper lst lst 0))

Alternatively, if you want to do everything in one function, you can also use letrec to bind plus-minus-helper inside plus-minus, or use the let form of letrec. With these ways, you can also refer to the original argument of the input, so you don't need another argument.

(define (plus-minus init-lst)
  (let plus-minus-helper ((lst init-lst)
                          (sum 0))
    (cond
      ((null? lst) (member sum init-lst))
      ((plus-minus-helper (cdr lst) (+ sum (car lst))) #t)
      ((plus-minus-helper (cdr lst) (- sum (car lst))) #t)
      (else #f))))
Sorawee Porncharoenwase
  • 6,305
  • 1
  • 14
  • 28