abedzantout
abedzantout

Reputation: 832

I am trying to sum each parameter with a value, what is wrong with my code?

I am basically new to Scheme, and this is my second attempt to solve a certain problem.

So what I am trying to do basically is sum each parameter we pass into the function, with an appropriate value for example:

 (sum 3 1 2 0 2) ;would return 228

Here is my code:

(define  (sum one five ten twenty fifty hundred)
    (+ (* 1 one)(* 5 five) (* 10 ten) (* twenty 20) (* 50 fifty) (* 100 hundred)) 

I think a possible solution is using the lambda function, but I could't know how to implement it.

Upvotes: 0

Views: 143

Answers (3)

Tot Zam
Tot Zam

Reputation: 8746

Here is one way you can calculate the numbers by sending in only 5 arguments instead of 6:

(define sum
    (lambda (L skip) ;stores yourList and the number you want to skip
       (define loop
          (lambda (L L2 total) ;yourList, (1,5,10...) list, running total
             (cond
               ((null? L) (list total)) ;print the total when finish yourList

               ;if the next number is the skip number, just move on to next value
               ((= (car L2) skip) (loop L (cdr L2) total)) 

               ;otherwise, increase total and send in both lists, minus the head, to the loop
               (else (loop (cdr L) (cdr L2) (+ total (* (car L) (car L2)) ))) 
              )
           )
        )(loop L (list 1 5 10 20 50 100) 0) ;initial values of loop
    )
)

;send in your list of numbers, plus the value place you want to skip
(sum (list 3 1 2 0 2) 20) ; ==> 228

I would be much easier, though, to just fill in all the places that you don't want with a 0. Once you have 6 arguments, the following code will work.

(define sum
    (lambda (one five ten twenty fifty hundred)
        (+ (* 1 one) (* 5 five) (* 10 ten) (* 20 twenty) (* 50 fifty) (* 100 hundred) )
    )
)

(sum 3 1 2 0 0 2)

Upvotes: 1

Sylwester
Sylwester

Reputation: 48765

If you want to use standard scheme with a similar scheme as Chris' answer in plain old Scheme you need to plan how to identify which currency your number is in. Perhaps by sending them in pairs would be both simpler to implement and simpler to use:

#!r6rs
(import (rnrs))

(define (total-bills . args)
  (fold-left (lambda (acc x)
               (+ acc (apply * x)))
             0
             args))

(total-bills '(5 1) '(2 10) '(3 100)) ; ==> 325
(apply total-bills '((1 3) (5 1) (10 1) (20 2))) ; ==> 58

You can make a procedure that makes a specialized procedure based on currencies you pass to it:

#!r6rs
(import (rnrs))

(define (make-currency-procedure . currencies)
  (lambda amounts
    (fold-left (lambda (acc currency amount)
                 (+ acc (* currency amount)))
               0
               currencies
               amounts)))

(define small-bills (make-currency-procedure 1 5 10 20))
(define large-bills (make-currency-procedure 10 100 1000 10000))

(small-bills 3 1 1 2) ; ==> 58
(small-bills 0 1 0 1) ; ==> 25
(large-bills 3 1 1 2) ; ==> 21130
(large-bills 0 1 0 1) ; ==> 10100

Upvotes: 0

C. K. Young
C. K. Young

Reputation: 223133

The OP wants to be able to pass fewer arguments than there are parameters. In this specific case, it's best to use keyword (named) arguments. Here's how you might do this (in Racket syntax):

(define (total-bills #:ones (ones 0)
                     #:fives (fives 0)
                     #:tens (tens 0)
                     #:twenties (twenties 0)
                     #:fifties (fifties 0)
                     #:hundreds (hundreds 0))
  (+ ones (* fives 5) (* tens 10) (* twenties 20) (* fifties 50) (* hundreds 100)))

(The 0 after each of the variable names are the default values, that is, what the value would be if you don't specify it.)

Example usage:

> (total-bills #:ones 3 #:fives 1 #:tens 2 #:hundreds 2)
228

Upvotes: 1

Related Questions