Reputation: 832
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
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
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
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