I am trying to define a procedure that takes an argument of 2 lists and a non-negative integer. Assume perfect input. I want it to construct a list of the elements in the first list UNTIL it reaches the given integer of elements at which point I want to finish it with the remainder of elements from the second list. Let me demonstrate.
~(combine '(a b c d e) '(w x y z) 2)
(a b y z)
Notice that the second list continued from the next index as if it were being made to cdr the whole time.
This is what I have. It doesn't work, of course and I think I may be using the wrong logic.
(define (combine seq1 seq2 point)
(if (null? (or seq1 seq2))
'()
(if (equal? point 0)
(cons seq2 '())
(cons (car seq1) (combine (cdr seq1) (cdr seq2) (- point 1) )))))
All help would be appreciated!
Thank you!
Well, this line doesn't do what you want:
(if (null? (or seq1 seq2))
In Scheme, the empty list is a true value; the only false value in Scheme is #f. That means that
(or '() '(a))
returns '() but
(or '(a) '())
returns '(a)
So your check for null will return #t only half of the time. (And if '() were a false value, as it is in regular Lisp, then it would never work, so I'm not sure what you are thinking).
If you want that line to return true if either of the lists is null, you will have to rethink it.
Then there's the line
(cons seq2 '())
Try testing that function on its own and see what happens - it's not what you need. If you think about it, that line should be rather simpler. What do you actually need to return at that point?
Related
I am trying to write my own 'list?' predicate in scheme. I know that definition of a list: 1. en empty list 2. pair, whose cdr is a pair
I know my code is wrong because it is returning true value on every pair, but every pair is not a list. I do not know how to implement the condition that cdr of the list must be also a pair.
(define (my-list? x)
(if (equal? x ()) #t
(pair? x)))
The list? procedure checks if a list is proper (nested cons-cells ending in a null value), hence we have to consider three cases:
(define (my-list? x)
(cond ((null? x) #t) ; empty list
((pair? x) (my-list? (cdr x))) ; pair, advance recursion
(else #f))) ; atom
A null value is considered an empty list. If we're in a pair, then we advance on its cdr by calling the procedure recursively. If it's not null nor a pair, it's an atom. This will cover edge cases, such as this:
(my-list? 42)
=> #f
(my-list? (cons 1 2))
=> #f
And will return true for proper lists:
(my-list? '())
=> #t
(my-list? (cons 1 (cons 2 '())))
=> #t
I am attempting to write a program that checks whether or not a list of lists has a certain property (unimportant to the question). Along the way I found it necessary to produce the list of "non-diagonal pairs" of a single given list, so I wrote a macro that takes a list and defines both the list of pairs (a list-version of the Cartesian product of sets) and what I'll call the "diagonal" of that list (pairs of the form '(x x)). The code I've written to accomplish this is below:
;;;These first two definitions are 'extended' car and cdr
;;;I only did this because the (prod a b) code below threw errors otherwise
(define (xcar a) (cond ((null? a) '()) ((car a))))
(define (xcdr a) (cond ((null? a) '()) ((cdr a))))
;;;This defines a pre-product, i.e. all pairs with the first element of the first list
(define (pre-prod a b)
(cond ((or (null? a) (null? b)) '())
((append (list (list (xcar a) (xcar b))) (pre-prod a (xcdr b))))))
;;;This defines the full product of the list
(define (prod a b)
(cond ((null? a) '())
((append (pre-prod a b) (prod (xcdr a) b)))))
;;;This defines the diagonal of the list
(define (diagonal a)
(cond ((null? a) '())
((append
(list (list (car a) (car a)))
(diagonal (cdr a))))))
Great, that code all seems to work just like I want it to. I next needed to take a list-version of the set-minus. I found the following code to do exactly this in an answer here:
;;;Returns #t if x is an element of lst and #f otherwise
(define (element? x lst)
(cond ((null? lst) #f)
((eq? x (car lst)) #t)
(#t (element? x (cdr lst)))))
;;;Takes list a and removes all elements of list b from it
(define (list-minus a b)
(cond ((null? a) '())
((element? (car a) b)
(list-minus (cdr a) b))
(#t (cons (car a) (list-minus (cdr a) b)))))
Cool, that seems to work just fine for what it needs to do. Now all I have to do is get DrRacket to return the list of proper pairs (removing the diagonal). I figure that the following code ought to do it:
(define (proper-pairs a) (list-minus (prod a a) (diagonal a)))
Now I test this new function on something easy, where it should return '():
> (proper-pairs '(1))
=> '((1 1))
WHAT? I've tried a lot of examples, reworked the code several times, tried it on various lists of lists. I always come up with the following problem: list-minus will not remove a list from a list of lists.
Question 1: Why does list-minus exhibit this anomalous behavior on lists of lists while working exactly as expected on things like the following example:
> (list-minus '(1 2 3 4 5) '(x 2 4 m))
=> '(1 3 5)
Question 2: How do I repair the list-minus code, or is it necessary to start from scratch?
Question 3: In the very first lines of code above I had to "extend" the car and cdr to ensure that the prod function would not throw an error. Is what I did a standard trick? I'm not sure I understand why it makes a difference (I just tried it in because I had a hunch it might work).
Disclaimer: I am not a programmer. I'm trying to learn functional programming as a means of testing various (mathematical) conjectures and compiling some examples. I have absolutely no experience writing code other than some very silly little bits that I've done in DrRacket and on an old TI-83 calculator. This being said, it will probably be necessary to "dumb-down" your answers for me.
Sorry for the long-windedness, and thank you for your time!
The problem is due to the fact that equality in Racket, like in other languages, is represented with different operators, that must be chosen according to:
the type of data that must be compared,
the semantics of the comparison.
The general hint is that you should use the operator which is logically more simple for the task and that can be used for a certain comparison.
For instance, you should use = to compare numbers; eq? to compare objects for identity i.e. two values are equal if the are the same object in memory; eqv? if you want to check that two values are the same object in memory or are equal numbers or equal characters; equal? if you want to check if two values are eqv? or if they are equal strings, or if they, being structured data like lists, are structurally equivalent (see the manual), i.e. recursively equivalent.
For instance:
(equal? '(a (b)) '(a (b))) ; => true, two different objects with the same structure
(eqv? '(a (b)) '(a (b))) ; => false, two different objects
(eq? '(a (b)) '(a (b))) ; => false, as for eqv?
(let ((x '(a (b))))
(eq? x x)) ; true, they are the same object
So I'm currently stuck on a "simple?" function in Racket. It's using the Intermediate Student with lambda language.
Some restrictions on this are that NO recursion is allowed, neither are local functions. It's plain and simple abstract list functions.
What this function is supposed to do is to take in a list of numbers, and output a list of pairs in which each pair has the first element as the number with the second element being the number it has occurred in the list.
Examples:
(1 1 2 3) => ((1 2) (2 1) (3 1))
(2 3 4 3) => ((2 1) (3 2) (4 1))
I have a function that produces the number of occurrences by inputting a list of numbers and a number which is:
(define (occurrences lon n)
(length (filter (lambda (x) (= x n)) lon)))
My approach, which was clearly wrong was:
(define (num-pairs-occurrences lon)
(list (lambda (x) (map (occurrences lon x) (remove x lon)) x))
I thought the above would work, but apparently my lambda isn't placed properly. Any ideas?
It's a bit trickier than you imagine. As you've probably noticed, we must remove duplicate elements in the output list. For this, is better that we define a remove-duplicates helper function (also using abstract list functions) - in fact, this is so common that is a built-in function in Racket, but not available in your current language settings:
(define (remove-duplicates lst)
(foldr (lambda (e acc)
(if (member e acc)
acc
(cons e acc)))
'()
lst))
Now it's easy to compose the solution using abstract list functions:
(define (num-pairs-occurrences lon)
(map (lambda (e) (list e (occurrences lon e)))
(remove-duplicates lon)))
The above might return and output list in a different order, but that's all right. And before you ask: yes, we do need that helper function. Please don't ask for a solution without it...
An easy, self-contained solution would be:
(define (num-pairs-occurences lst)
(foldl (lambda (e r)
(if (or (null? r) (not (= (caar r) e)))
(cons (list e 1) r)
(cons (list e (add1 (cadar r))) (cdr r))))
null
(sort lst >)))
Basically, you sort the list first, and then you fold over it. If the element (e) you get is the same as the first element of the result list (r), you increment the count, otherwise you add a new sublist to r.
If you sort by > (descending), you can actually use foldl which is more memory-efficient. If you sort by < (ascending), you need to use foldr which is less efficient.
I'm trying to write a function using Scheme that :
take a list of integers with more than two elements as a parameter
sum the n-th-element and (n+1)-th-element
return this list
Result should be as follows :
> (SumNeighbors (list 1 2 3 4))
(3 5 7)
I think I get the way to add elements but my recursion is totally wrong...
(define (SumNeighbors lst)
(if (not (null? (cdr lst)))
(append (list (+ (car lst) (car (cdr lst)))) (SumNeighbors (cdr lst)))))
Any help would be appreciated.
The solution to this problem follows a well-known pattern. I'll give you some hints, it'll be more fun if you find the answer by your own means:
(define (SumNeighbors lst)
(if <???> ; if there's only one element left
<???> ; we're done, return the empty list
(cons ; otherwise call `cons`
(+ <???> <???>) ; add first and second elements
(SumNeighbors <???>)))) ; and advance recursion
Notice the following:
Your solution is lacking the base case - what happens when the list we're traversing only has one element left? it's time to finish the recursion! and because we're building a list as the output, what should be the value returned?
We normally use cons to build an output list, not append. That's the natural way to build a list
The part of this procedure that falls outside the solution template is the fact that we stop when there's a single elment left in the list, not when the list is empty (as is the usual case)
You'll see that many procedures that iterate over an input list and return a list as output follow the same solution template, it's very important that you learn how and why this works, it's the foundation for writing solutions to other similar problems.
#!r6rs
(import (except (rnrs base) map)
(only (srfi :1) map))
(define (sum-neighbors lst)
(map + lst (cdr lst)))
The higher order function map as defined in SRFI-1 supports uneven lenght arguments. It will stop at the shortest list.
If you call (sum-neighbors '(1 2 3 4)) it will become (map + (1 2 3 4) (2 3 4)) which is the same as (cons (+ 1 2) (cons (+ 2 3) (cons (+ 3 4) '())))
I am writing a procedure which returns a list with all of the negative odd and positive
even integers removed (strings can stay), by using lambda in the primitive filter procedure. I also am avoiding using recursion, but that is what's stumping me.
What I have so far is:
(define (f2b lst)
(cond ((null? lst)'()) ; if the list is empty, return the empty list
((pair? (car lst)) ; if the current element isn't a list
(filter (lambda (x) (or (even? x) (positive? x))) (car lst))
(filter (lambda (x) (or (odd? x) (negative? x))) (car lst)))
(else (string? (car lst)) ;otherwise, if the current element is a string,
(car lst) ; then return that element
(f2b (cdr lst)))))
I'm also not sure how I can apply both of the filter procedures at the same time.
It's way simpler than that. All you have to do is filter the list. You just need the appropriate predicate.
When do you want to keep an element? You phrased it in terms of what you want to remove, so let's start with that. You want to remove if it's a negative odd or a positive even integer, and leave everything else in. It's easier to break it down into smaller functions.
(define (positive-even? x) (and (positive? x) (even? x)))
(define (negative-odd? x) (and (negative? x) (odd? x)))
(define (remove-num? x) (or (positive-even? x) (negative-odd? x)))
This defines whether to keep a number. But the list element might not be a number. So we
keep it if it's not a number, or if it doesn't match remove-num?:
(define (keep-element? x) (or (not (number? x)) (not (remove-num? x))
Then your function just has to call filter:
(define (f2b lst) (filter keep-element? lst))
Seems to work:
(f2b '(-4 -3 -2 -1 0 1 2 3 4 "a string" "another"))
=> (-4 -2 0 1 3 "a string" "another")
Here's how it would look as one big honkin' function:
(define (f2b lst)
(filter
(lambda (x)
(or (not (number? x))
(not (or (and (positive? x) (even? x))
(and (negative? x) (odd? x))))))
lst)
Personally, the nested or not or and gets a bit hard to read for my taste...
Ok, apparently you have nested lists. All you have to do here is map the result of the filter with a function which:
when given a list, returns (f2b lst)
otherwise, returns the element unchanged.
I will leave it as an exercise for you since, if you thought my function could possibly work on a nested list, clearly you have a lot of learning to do...