(define unary-add
(lambda (list1 list2)
(if (pair? list1)
(cons (car list1)
(unary-add (cdr list1) list2))
list2)))
I performed the addition of two unary representations of lists as above. Now I want to multiply them, considering multiplication as the repeated addition.
So, I made use of this function, and did the below:
(define unary-mul
(lambda (list1 list2)
(if (pair? list1)
(cons (car list1)
(unary-mul (unary-add (cdr list1) list2)))
list2)))
On running the code, it says arguments do not match. Where did I went wrong?
Your current approach doesn't seem right - the recursive call is misplaced, and the error reported indicates that you forgot to pass the second parameter to unary-mul. Try this instead:
(define unary-mul
(lambda (list1 list2)
(if (pair? list2)
(unary-add list1
(unary-mul list1 (cdr list2)))
'())))
Explanation: a multiplication is just a repeated addition, in the above code we keep adding list1 and decreasing the length of list2 until it's empty. It works as expected:
(unary-mul '(x x x) '(x x))
=> '(x x x x x x)
Related
i want to ask if someone wants to help me with a iterative scheme code that gives the sum of two lists. I already have the recursive version of the code.
(define (sum-lists l1 l2)(cond ((and (null? l1) (null? l2)) '())
((null? l1) l2)
((null? l2) l1)
(else (cons (+ (car l1) (car l2)) (sum-lists (cdr l1) (cdr l2))))))
The general "iterative procedure" recipe:
Write a helper function that takes an accumulator parameter.
Create each intermediate result in the accumulator.
When you terminate the recursion, return the accumulator.
Pass it a suitable initial accumulator.
It's common when transforming lists to accumulate the result in reverse and then reverse the result when you're done.
A trivial example, incrementing each list element by one:
(define (add-1 ls)
(if (null? ls)
'()
(cons (+ 1 (car ls)) (add-1 (cdr ls)))))
To make it iterative, create a helper function where you cons to the accumulator instead of the recursive result:
(define (add-one ls acc)
(if (null? ls)
(reverse acc)
(add-one (cdr ls) (cons (+ 1 (car ls)) acc))))
(Note that, except for the introduction of acc, the recursion contains the same parts as before but in a different order.)
Then you start it off with an empty accumulator:
(define (add-1 ls)
(add-one ls '()))
Your case has slightly more involved base cases since you need to accomodate inputs of different lengths.
Finishing it left as an exercise.
(Another exercise: figure out why your first condition, (and (null? l1) (null? l2)), is unnecessary.)
I have created the following expression which I would like to graph parabolas based on the last two elements in a list. It looks like this:
#lang racket
(require plot)
(define list-sqr-graph
(lambda (lst)
(cond
[(null? lst) (plot (function sqr 0 0))]
[(<= (car lst) 0) (list-sqr-graph (cdr lst))]
[(not (equal? (length lst) 2)) (list-sqr-graph (cdr lst))]
[else (plot (function sqr (car lst) (cdr lst)))])))
The first conditional statement checks if the list is null, and returns a blank graph if true. The second conditional statement skips past numbers from the list which are less than or equal to 0. The third conditional statement checks if the length of the list is equal to 2, and goes down the list until the length is equal to 2.
The else statement is where I get trouble when running an expression such as:
(list-sqr-graph '(1 2 3))
Which will result in an error reading:
function: contract violation
expected: (or/c rational? #f)
given: '(4)
From this error I am led to believe that the first element of the list is being read as a number, but that the second element is having trouble. Why is this?
Thank you in advance!
You are passing a list when ploting. Remember cdr returns a list and not an element (like car does).
You want to use cadr.
#lang racket
(require plot)
(define list-sqr-graph
(lambda (lst)
(cond
[(null? lst) (plot (function sqr 0 0))]
[(<= (car lst) 0) (list-sqr-graph (cdr lst))]
[(not (equal? (length lst) 2)) (list-sqr-graph (cdr lst))]
[else (plot (function sqr (car lst) (cadr lst)))]))) <- HERE
This is what I've written:
(: mmm : (Listof Any) (Listof Any) -> (Listof Any))
(define (mmm list1 list2)
(cond [(or (null? list1) (null? list2)) null]
(and (cons (first list1) (first list2)) (mmm (rest list1) (rest list2)))))
I'll give you an example:
list1: a b c
list2: 1 2 3
answer: ((a 1) (b 2) (c 3))
edited
they both same size
If you are allowed to use map, you can use:
(define (mmm lst1 lst2) (map (lambda (x y) (list x y)) lst1 lst2))
There are a couple of problems with your code:
The base case might or might not be right - if the input lists are guaranteed to be of the same size, then it's fine. If they can be of different size see #Sylwester's answer for advice
The second condition should start with an else (because it's the last one and the conditions are mutually exclusive), not with and
You are not building the output list correctly. The new element to be added is a list with the first element of both input lists, and that must be consed to the result of calling the recursion
To fix them, try this - assuming input lists of equal length:
(define (mmm list1 list2)
(cond [(or (null? list1) (null? list2)) null]
[else (cons (list (first list1) (first list2))
(mmm (rest list1) (rest list2)))]))
Now the procedure works as expected:
(mmm '(a b c ) '(1 2 3))
=> '((a 1) (b 2) (c 3))
If you know the lists are the same size, then it becomes simply:
(define (mmm list1 list2) (map list list1 list2))
Note: Replace map list with map cons if that is what you really want. Your code used cons but your result example suggests that list is what you want.
Is it possible to check two list against each other if anything is the same in them?
(check-list '(hey cookie monkey) '(apple pizza cookie) ==> #t
I tried something like
(define (check-list list element)
(let ((x list))
(cond ((null? x) #f)
((eq? (car x) (car element)) #t)
(else (check-list (cdr x) element))))
(check-list list (cdr element)))
I know this is not correctly written but don't know how to tackle this problem.
Anyone that can help me?
Sometimes it helps to formulate the process of the solution to a problem in your natural language. Let's simplify the problem a bit.
How do you check if one element is contained in a list? One way to do that would be to compare that one element with each element in the list until you found it - somewhere along the lines you have already done - but not quite. A quick draft would be:
(define (member? e lst)
(cond ((null? lst) #f) ; empty list doesn't contain e
(or (eq? e <??>) ; either the first element is e or
(member? e <??>))) ; the rest of the list contains e
We can use that previous knowledge to solve the real problem at hand. We know how to search for one element in a list, and now we need to search for each element in a list in another list.
(define (check-list lst1 lst2)
(if (or (null? lst1) (null? lst2)) #f ; empty list(s) share no elements
(or (member? <??> <??>) ; first element of lst1 in lst2?
(member? <??> <??>)))) ; rest of lst1 in lst2?
The <??> should be substituded with the appropriate expressions for selecting the parts of the lists.
Similar to a prior answer but exploiting logic primitives:
(define (intersect? list1 list2)
(and (not (null? list1))
(or (member (car list1) list2)
(intersect? (cdr list1) list2))))
If the lists are wicket long you might want to hash the first list and then just iterate through the second. This uses R5RS with srfi-69 and for small lists you'll get a little overhead but
(require srfi/69); alist->hash-table, hash-table-ref/default
(define (intersect? list1 list2)
(let ((hash (alist->hash-table (map (lambda (x) (cons x x)) list2) equal? )))
(let loop ((list list1))
(and (not (null? list))
(or (hash-table-ref/default hash (car list) #f)
(loop (cdr list)))))))
There seems to be a little confusion. The "big" problem here is how to determine if two lists share at least one element in common, let's write a procedure for that called element-in-common?. Before tackling this problem, we need to determine if a single element belongs in one list, that's what check-list should do (notice that in your code check-list receives as a second parameter an element, but you're treating it as if it were a list of elements).
You don't have to write the check-list procedure, it already exists and it's called member. With that knowledge in hand, we can solve the big problem - how to determine if at least one of the elements in one list (let's call it lst1) is in another list (called lst2)?
Simple: we iterate over each of the elements in lst1 using recursion, asking for each one if it belongs in lst2. If just one element of lst1 is a member of lst2, we return #t. If none of the elements in lst1 is in lst2, we return #f. Something like this:
(define (element-in-common? lst1 lst2)
(cond (<???> ; is the first list empty?
<???>) ; then there are no elements in common
((member <???> lst2) ; is the current element of `lst1` in `lst2`?
<???>) ; then there IS an element in common
(else ; otherwise
(element-in-common? <???> lst2)))) ; advance recursion
Don't forget to test your code:
(element-in-common? '(hey cookie monkey) '(apple pizza cookie))
=> #t
(element-in-common? '(hey cookie monkey) '(apple pizza pie))
=> #f
You can use memq to check if first element on the first list is on the second list, and if not then check recursively if something in the rest of the first list is in the second list:
(define (check-list list1 list2)
(cond ((null? list1) #f)
((memq (car list1) list2) #t)
(else (check-list (cdr list1) list2))))
Here's an answer using higher-order functions
in mit-schme
(define (check-list L1 L2)
(apply boolean/or (map (lambda (x) (member? x L2)) L1)))
(define remove-item
(lambda (lst ele)
(if (null? lst)
'()
(if (equal? (car lst) ele)
(remove-item (cdr lst) ele)
(cons (car lst)
(remove-item (cdr lst) ele))))))
im trying to write a function in Scheme where i accept a list and return all the different derangements (look below for definition) as a list of lists
derangement: A list where no item is in the same place as the original list
ex: '(a b c) -> '(cab)
any help is appreciated!
Compute all of the permutations of the input list and then filter out the ones that have an element in the same position as the input list. If you need more detail, leave a comment.
Edit 1:
Define (or maybe it's defined already? Good exercise, anyway) a procedure called filter that takes as its first argument a procedure p and a list l as its second argument. Return a list containing only the values for which (p l) returns a truthy value.
Define a procedure derangement? that tests if a list l1 is a derangement of l2. This will be handy when paired with filter.
The most obvious solution would be something like this:
(define filtered-permutations
(lambda (lst)
(filter
(lambda (permuted-list)
(deranged? permuted-list lst))
(permute lst))))
Since the number of derangements is considerably lower than then number of permutations, however, this is not very efficient. Here is a solution that mostly avoids generating permutations that are not derangements, but does use filter once, for the sake of simplicity:
(define deranged?
(lambda (lst1 lst2)
(if (null? lst1)
#t
(if (eq? (car lst1) (car lst2))
#f
(deranged? (cdr lst1) (cdr lst2))))))
(define derange
(lambda (lst)
(if (< (length lst) 2)
;; a list of zero or one elements can not be deranged
'()
(permute-helper lst lst))))
(define derange-helper
(lambda (lst template)
(if (= 2 (length lst))
(let ((one (car lst))
(two (cadr lst)))
(filter
(lambda (x)
(deranged? x template))
(list (list one two) (list two one))))
(let ((anchor (car template)))
(let loop ((todo lst)
(done '())
(result '()))
(if (null? todo)
result
(let ((item (car todo)))
(if (eq? item anchor)
;; this permutation would not be a derangement
(loop (cdr todo)
(cons item done)
result)
(let ((permutations
(map
(lambda (x)
(cons item x))
(derange-helper (append (cdr todo) done)
(cdr template)))))
(loop (cdr todo)
(cons item done)
(append result permutations)))))))))))