(Scheme) Find distance between two words in a list? - scheme

Ok, so I'm trying to write a function that finds the distance between two elements in a list, s and t.
For example, if s = bob and t = pizza:
(d 'bob 'pizza '(bob blah blah pizza))
it would return: 3
This is what I have so far.
(define dist
(lambda (s t line)
(cond
[(equal? s (car line))
[(equal? t (car (cdr line)))
1]]
[else (add1 (dist s t (cdr line)))])))
For some reason, it's not working. Help?
Thanks!

The proposed code in the question is not going to work, it's just checking if the two elements are contiguous in the list. Let's try a different approach altogether - split the problem in smaller subproblems, begin by defining a procedure that returns the index of an element in a list, counting indexes from zero:
(define (index-of elt lst)
<???>) ; ToDo
With the above procedure in place, and assuming that both s and t are present in the list and t appears after s, it's easy to find the solution to the question:
(define dist
(lambda (s t line)
(- (index-of t line)
(index-of s line))))
For example:
(dist 'bob 'pizza '(bob blah blah pizza))
=> 3
For extra credit, consider the cases where one or both of the elements are not present in the list (so index-of should return a value indicating this, say, #f), or when s appears after t in the list.

When you are taking (cdr line) in the last step you are throwing away bob even if bob is the first element.
You need to take care of 3 and maybe 4 cases.
Where s and t match the first two elements you do fine.
Where s matches and t doesn't you need to add 1 to a recursive call using line with the 2nd element removed. Something like (cons (car line) (cdr (cdr line))).
Where s doesn't match you need to remove the car of line and try again.
Unless you are sure s and t will both occur and in order you need a terminating condition(s) to take care of running out of line.

Here is a solution that iterates down the list looking for 's' and 't' each time. When both have been seen, the result is returned; otherwise, continue looking:
(define (dist s t line)
(let looking ((l line) (n 0) (i #f))
(and (not (null? l))
(let ((item (car l)))
(if (or (equal? item s)
(equal? item t))
(if (not i)
(looking (cdr l) (+ n 1) n) ; found first, continue
(- n i)) ; found second, done
(looking (cdr l) (+ n 1) i)))))); continue looking

Related

How to multiply a list in scheme?

New to scheme but trying to learn the basics.
Let's say I passed a list in as a parameter and I wanted to multiply each element by -1. Right now I have this:
(define (negative b)
(* (car b) -1 )))
Which returns the first element as -1 * that element
So in this case giving it (negative '(5 1 2 3)) returns -5.
But lets say I want it to return
-5 -1 -2 -3
How would I go about making the rest of the list negative? Using cdr recursively?
Do it recursively.
(define (negative l)
(if (null? l)
'()
(cons (* (car l) -1)
(negative (cdr l)))))
If the list is empty, this just returns an empty list, as the base case.
Otherwise, it calculates -1 * the first element, the negative of the rest of the list, and combines them to produce the result.
The purpose of your exercise may be for you to code up your own map procedure, in which case that's fine. But if not, use scheme's built in 'map' procedure which is intended for just this kind of purpose.
'map' has been available at least since R4RS (that is, a long time ago) and possibly earlier.
by using map. If you want it returned as list.
It would be like this
(define negative
(lambda (b)
(map - b)))
Map is going through list b, and apply procedure "-" to each number in list
If you want to return as single numbers not in list you apply values on the list.
(define negative1
(lambda (b)
(apply values (map - b))))
Edit: I saw that you are asking for recursive solution, which would go like this
(define negative1
(lambda (b)
(if (null? b)
'()
(cons (- (car b)) (negative1 (cdr b))))))

In beginner scheme how do I represent a variable as a string?

My question is how do i code for
(triangle 5) produces (list "*****" "****" "***" "**" "*")
Note: (5 astericks 4, then 3 then 2 then 1). So far I have:
(define (triangle n)
(cond
[(zero? n) empty]
[else (cons n (triangle (sub1 n)))]))
But that only gives me (list 5 4 3 2 1). Please keep note that this uses only the basic of scheme beginner lists and abbreviations. Thanks!
It's always a good idea to split a complex problem in simpler, shorter subparts. In this case, we can simplify the general solution by first writing solutions to subproblems, like this:
First, build a procedure that creates a list of strings, where a string is "*****" or "****" or ... or "*"
Second, write a repeat helper procedure that given a string and a number, repeats the string that many times - for example: (repeat "*" 3) will return "***"
It's easy to see how the first subproblem can be expressed in terms of the second one. Because this looks like a homework, you shouldn't be asking for complete solutions here. It'll be more useful for you to reach the answer by yourself, here's the general idea, fill-in the blanks:
(define (triangle n)
(cond [<???> <???>] ; if n is zero return the empty list: '()
[else ; otherwise
(cons <???> ; cons n repetitions of * (using `repeat`)
(triangle <???>))])) ; and advance the recursion
(define (repeat str n)
(cond [<???> <???>] ; if n is zero return the empty string: ""
[else ; otherwise
(string-append <???> ; append the given string
(repeat <???> <???>))])) ; and advance the recursion
If you look at it carefully, both procedures share exactly the same structure. What changes is the value returned in the base case (an empty list and an empty string) and the procedure used for sticking together the partial answers (cons and string-append).
If you're just looking for how to convert numbers to string, you can use the (number->string x).
However, since you're looking to have the numbers represented as asterisks, it may be better for you to keep them as numbers until you've constructed a string of asterisks. In that case, you probably want a method like:
(define (num-to-asterisks x)
(make-string x #\*))
Try this:
(define (triangle n)
(let building ((i 0) (r '()))
(if (= i n)
r
(building (+ i 1)
(cons (string-append "*" (if (null? r) "" (car r)))
r)))))
this is nicely tail-recursive; builds up the result list by adding "*" to the first element of the result list.

Remove element off list

Someone tell me what is wrong with this code. I thought I mastered a few scheme skills to solve a friend's problem but it ended up messing my head. I am trying to remove all similar elements off the list. Earlier it was removing only the first element I want to remove, but now its removing the car and the first element f what I want to remove. I am looking for an output like: (delete 3 (list 2 3 4 3 5 3)), returns (2 4 5).
(define (delete n lst)
(cond
((null? lst) null)
((equal? n (car lst)) (cdr lst))
(else
(remove n (cdr lst)))))
It's because of this conditional:
((equal? n (car lst)) (cdr lst))
What this line does is it checks that n is the same as the first element in the list. If it is, it returns the rest of the list. Since your target element is the second element of the list, it returns the rest of the list, from the third element onward. Your first element in the list is completely dropped. You're not keeping track of the OK elements you've checked so far.
From your code, it looks like you want to loop through the elements of the list and, if you find your target value, call remove. If you want to implement it in this fashion, you need to also track the values that you've checked and verified that are not your target value. So your function needs to take three parameters: n, your target; lst the remaining numbers to check; and clean (or whatever you want to call it) that holds the already checked numbers.
This is a working version of your algorithm:
(define (delete n lst clean)
(cond
((empty? lst) clean)
((equal? n (car lst)) (delete n (cdr lst) clean))
(else
(delete n (cdr lst) (append clean (list (car lst)))))))
You'd call it like so: (delete 3 (list 2 3 4 3 5 3) '())
First it checks if you have numbers left to check. If you don't, it returns your clean list.
Then it checks to see if the first element matches your target element. If it does, then it calls delete again, effectively dropping the first element in the lst (notice it does not append it to the list of clean numbers).
The else, which is reached if the first element is not the target number, appends the first value of lst to the end of clean and calls delete again.
(Note that this code uses tail recursion, which is a way of writing recursive methods that track the intermediate values with each recursive call, as opposed to "regular" recursion that does the calculation at the end. Samrat's answer, below, is a regular recursive solution. A discussion of the tail recursion can be found here.)
From your post, it sounds like you want to remove all instances of the target number. Instead of using the remove function -- which only removes the first instance of the target number -- you should look at using the remove* function, which removes all instances. This would greatly simplify your function. So to remove all instances of 3 from your list, this would suffice:
(remove* '(3) (list 2 3 4 3 5 3))
If you wanted to wrap it in a function:
(define (delete n lst)
(remove* (list n) lst))
You should read up on map functions in general, since they pretty much do what you're looking for. (They apply a procedure against all elements in a list; The above could also be implemented with a filter-map if you had a more complicated procedure.)
Here's what I came up with:
(define (delete n lst)
(cond ((empty? lst) lst)
((= (car lst) n) (delete n (cdr lst)))
(else (append (list (car lst)) (delete n (cdr lst))))))

List length in scheme

Hi I am trying to write a program where given a list of lists check to see if they are equal in size and return #t if they are.
So for example if i were to write (list-counter? '((1 2 3) (4 5 6) (7 8 9))) the program would return #t, and (list-counter? '((1 2 3) (4 5 6) (7 8))) would return #f.
SO far this is what I have done:
(define list-counter?
(lambda (x)
(if (list? x)
(if (list?(car x))
(let (l (length (car x))))
(if (equal? l (length(car x))))
(list-counter?(cdr x))
) ) ) ) )
I think where I am going wrong is after I set the length of l to the length of the first list. Any help would be appreciated.
There are several ways to solve this problem. For instance, by hand and going step-by-step:
(define (all-lengths lists)
(if (null? lists)
'()
(cons (length (car lists))
(all-lengths (cdr lists)))))
(define (all-equal? head lengths)
(if (null? lengths)
true
(and (= head (car lengths))
(all-equal? head (cdr lengths)))))
(define (list-counter? lists)
(let ((lengths (all-lengths lists)))
(all-equal? (car lengths) (cdr lengths))))
Let me explain the above procedures. I'm dividing the problem in two steps, first create a new list with the lengths of each sublist - that's what all-lengths does. Then, compare the first element in a list with the rest of the elements, and see if they're all equal - that's what all-equal? does. Finally, list-counter? wraps it all together, calling both of the previous procedures with the right parameters.
Or even simpler (and shorter), by using list procedures (higher-order procedures):
(define (list-counter? lists)
(apply = (map length lists)))
For understanding the second solution, observe that all-lengths and all-equal? represent special cases of more general procedures. When we need to create a new list with the result of applying a procedure to each of the elements of another list, we use map. And when we need to apply a procedure (= in this case) to all of the elements of a list at the same time, we use apply. And that's exactly what the second version of list-counter? is doing.
You could write an all-equal? function like so:
(define (all-equal? list)
;; (all-equal? '()) -> #t
;; (all-equal? '(35)) -> #t
;; (all-equal? '(2 3 2)) -> #f
(if (or (null? list) (null? (cdr list)))
#t
(reduce equal? list)
))
then do:
(all-equal? (map length listOfLists))
Alternatively you can do:
(define (lists-same-size? list-of-lists)
(if (== (length listOfLists) 0)
#t
(let*
(( firstLength
(length (car listOfLists)) )
( length-equal-to-first?
(lambda (x) (== (length x) firstLength)) )
)
(reduce and #t (map length-equal-to-first? listOfLists))
)
)))
What this says is: if the list length is 0, our statement is vacuously true, otherwise we capture the first element of the list's length (in the 'else' part of the if-clause), put it in the closure defined by let's syntactic sugar (actually a lambda), and use that to define an length-equal-to-first? function.
Unfortunately reduce is not lazy. What we'd really like is to avoid calculating lengths of lists if we find that just one is not equal. Thus to be more efficient we could do:
...
(let*
...
( all-match? ;; lazy
(lambda (pred list)
(if (null? list)
#t
(and (pred (first list)) (all-match? (cdr list)))
;;^^^^^^^^^^^^^^^^^^^ stops recursion if this is false
)) )
)
(all-match? length-equal-to-first? listOfLists)
)
)))
Note that all-match? is already effectively defined for you with MIT scheme's (list-search-positive list pred) or (for-all? list pred), or in Racket as andmap.
Why does it take so long to write?
You are forced to write a base-case because your reduction has no canonical element since it relies on the first element, and list manipulation in most languages is not very powerful. You'd even have the same issue in other languages like Python. In case this helps:
second method:
if len(listOfLists)==0:
return True
else:
firstLength = len(listOfLists[0])
return all(len(x)==firstLength for x in listOfLists)
However the first method is much simpler to write in any language, because it skirts this issue by ignoring the base-cases.
first method:
if len(listOfLists)<2:
return True
else:
return reduce(lambda a,b: a==b, listOfLists)
This might sound a bit weird, but I think it is easy.
Run down the list, building a new list containing the length of each (contained) list, i.e. map length.
Run down the constructed list of lengths, comparing the head to the rest, return #t if they are all the same as the head. Return false as soon as it fails to match the head.

How can I get all possible permutations of a list with Common Lisp?

I'm trying to write a Common Lisp function that will give me all possible permutations of a list, using each element only once. For example, the list '(1 2 3) will give the output ((1 2 3) (1 3 2) (2 1 3) (2 3 1) (3 1 2) (3 2 1)).
I already wrote something that kind of works, but it's clunky, it doesn't always work and I don't even really understand it. I'm not asking for code, just maybe for some guidance on how to think about it. I don't know much about writing algorithms.
Thanks,
Jason
As a basic approach, "all permutations" follow this recursive pattern:
all permutations of a list L is:
for each element E in L:
that element prepended to all permutations of [ L with E removed ]
If we take as given that you have no duplicate elements in your list, the following should do:
(defun all-permutations (list)
(cond ((null list) nil)
((null (cdr list)) (list list))
(t (loop for element in list
append (mapcar (lambda (l) (cons element l))
(all-permutations (remove element list)))))))
Here is the answer which allows repeated elements. The code is even more "lispish" as it doesn't use loop, with the disadvantage of being less comprehensible than Rainer Joswig's solution:
(defun all-permutations (lst &optional (remain lst))
(cond ((null remain) nil)
((null (rest lst)) (list lst))
(t (append
(mapcar (lambda (l) (cons (first lst) l))
(all-permutations (rest lst)))
(all-permutations (append (rest lst) (list (first lst))) (rest remain))))))
The optional remain argument is used for cdring down the list, rotating the list elements before entering the recursion.
Walk through your list, selecting each element in turn. That element will be the first element of your current permutation.
Cons that element to all permutations of the remaining elements.

Resources