Two Element List Scheme - list

I need to write a function that determines if the given list is a pair of elements. The program will simply respond #t if the list contains exactly two elements or #f if it does not, such that:
(zipper? '((a 1)(b 2))) => #t
and
(zipper? '((foo 100)(bar 2 3))) => #f
I'm still fairly new to Scheme so any help would be much appreciated!
Thanks!

It isn't clear if the "correct" input for the procedure is an arbitrary list or a two-element list. If it's strictly a two-element list, this will work:
(define (is-two-element-list? lst)
(and (list? lst)
(= (length lst) 2)))
(define (zipper? lst)
(and (is-two-element-list? lst)
(is-two-element-list? (first lst))
(is-two-element-list? (second lst))))
… And if it's an arbitrary-length list whose elements we want to check, this will work in Racket, using andmap:
(define (zipper? lst)
(andmap is-two-element-list? lst))
If you are not using Racket, then this solution using every will work in any interpreter with SRFIs:
(require srfi/1)
(define (zipper? lst)
(every is-two-element-list? lst))
Either way, notice that the trick was defining the is-two-element-list? procedure, which verifies the two-element-list property, after that we can apply it as needed.

Think of it this way. If the zipper list is '() then the answer is #t. If the zipper list is not '() then if the first element is two elements and the rest is another zipper?, then return #t.
(define (zipper? list)
(or (null? list)
(and (= 2 (length (car list)))
(zipper? (cdr list)))))
or maybe you mean:
(define (zipper? list)
(or (not (pair? list))
(and (= 2 (length list))
(zipper? (list-ref list 0))
(zipper? (list-ref list 1)))))
every element, at any level, has two elements.
> (zipper? '((a 1 2) '(b)))
#f
> (zipper? '(a b))
#t
> (zipper? '(((a (b b)) c) (1 2)))
#t

Related

Finding the occurence element in the list in racket

Assume (list "apple" "orange" "apple" "grape" "orange")and produce (list (list 2 "apple") (list 2 "orange") (list 1 "grape")).
The most common fruit will occur first in the produced list.
In the case of ties, order the tied pairs with the fruit in increasing alphabetical order.
use abstract list function such as map,filter, foldr and quicksort in local. no recursion.
i'm not sure how to do it without recursion.
i wrote like this:
(define (function list)
(cond
[(empty? list) empty]
[else
(local
(define (helper1 a b)
(cond
[(equal? a b) a]
[else b]))
(define T (foldr helper1 (first list) (rest list)))
(define (count a)
(cond
[(equal? a T) true]
[else false]))
(define new-list (quicksort (length (filter count list)) >))]
The most efficient way is to use a (mutable) hash table:
(define (count-by-type lst)
; create hash
(define h (make-hash))
; update hash, creating entries if needed, otherwise adding 1 to existing entry
(map (lambda (e) (hash-update! h e add1 0)) lst)
; create list of (count key) elements from hash and sort accordingly
(sort (map (lambda (e) (list (cdr e) (car e))) (hash->list h))
(lambda (x y) (or (> (car x) (car y))
(and (= (car x) (car y)) (string<? (cadr x) (cadr y)))))))
testing:
> (count-by-type (list "apple" "orange" "apple" "grape" "orange"))
'((2 "apple") (2 "orange") (1 "grape"))
I just rehashed my own answer from a previous question. This seems to be a similar assignment, but without struct
Using a hash you could do it with only one pass through the unsorted list, then produced a list that then was sorted with a special <-function that sorts by count, then fruit.
These hints are for a functional solution. First sort the argument (sort list-of-fruits string>?). that the in descending order and oposite of your result. .
Given the list has at least one element:
(let rec ((cur (car sorted-fruits)) (cnt 1) (lst (cdr sorted-fruits)) (acc '()))
(cond ((equal? cur (car lst)) (rec cur (add1 cnt) (cdr lst) acc))
(else (rec (car lst) 1 (cdr lst) (cons (list cnt cur) acc)))))
This will produce a list in ascending order with counts.
If you sort again:
(sort list-of-counts-and-fruit (lambda (x y) (>= (car x) (car y)))
sort in Racket is stable. That means if you have two with equal counts in the list they will end up in their original order. The original order was the ascending animal order so the result is ordered by count descending, then name ascending.
I guess your procedure can be made by chaining these together, perhaps using let to store intermediates to make expressions shorter and more readable.

Search in a list with argument

I`m trying to implement a function that given an argument and a list, find that argument in the first element of the pair in a list
Like this:
#lang scheme
(define pairs
(list (cons 1 2) (cons 2 3) (cons 2 4) (cons 3 1) (cons 2 5) (cons 4 4)))
;This try only gets the first element, I need to runs o every pair on pairs
((lambda (lst arg)
(if (equal? (car (first lst)) arg) "DIFF" "EQ"))
pairs 2)
;This try below brings nok for every element, because Its not spliting the pairs
(define (arg) (lambda (x)2))
(map
(lambda (e)
(if (equal? arg (car e)) "ok" "nok"))
pairs)
The idea is simple, I have pair elements, and a given number. I need to see if the first element of the pairs (they are in a list) starts with that number
Thanks in advance
In Racket, this is easy to implement in terms of map. Simply do this:
(define (find-pair lst arg)
(map (lambda (e)
(if (equal? (car e) arg) "ok" "nok"))
lst))
Alternatively, you could do the same "by hand", basically reinventing map. Notice that in Scheme we use explicit recursion to implement looping:
(define (find-pair lst arg)
(cond ((null? lst) '())
((equal? (car (first lst)) arg)
(cons "ok" (find-pair (rest lst) arg)))
(else
(cons "nok" (find-pair (rest lst) arg)))))
Either way, it works as expected:
(find-pair pairs 2)
=> '("nok" "ok" "ok" "nok" "ok" "nok")
(find-pair pairs 7)
=> '("nok" "nok" "nok" "nok" "nok" "nok")
In Scheme, you should usually approach algorithms with a recursive mindset - especially when lists are involved. In your case, if you find the element in the car of the list then you are done; if not, then you've got the same problem on the cdr (rest) of the list. When the list is empty, you've not found the result.
Here is a solution:
(define (find pred list)
(and (not (null? list)) ; no list, #f result
(or (pred (car list)) ; pred on car, #t result
(find pred (cdr list))))) ; otherwise, recurse on cdr
With this your predicate function 'match if car of argument is n' is:
(define (predicate-if-car-is-n n)
(lambda (arg)
(eq? n (car arg))))
The above stretches your understanding; make sure you understand it - it returns a new function that uses n.
With everything together, some examples:
> (find (predicate-if-car-is-n 2) '((1 . 2) (2 . 3) (4 . 5)))
#t
> (find (predicate-if-car-is-n 5) '((1 . 2) (2 . 3) (4 . 5)))
#f

Return the second element for every element in a list

Let's say we have this list '( (4 (1 2)) (5 (5 5)) (7 (3 1)) (1 (2 3)))
I am trying to write smth in Scheme in order to get the second element for every element in the list.. So the result will look like '( (1 2) (5 5) (3 1) (2 3))
I have this code so far..
(define (second list1)
(if (null? (cdr list1))
(cdr (car list1))
((cdr (car list1))(second (cdr list1)))))
Here's a straightforward solution:
(define (seconds lst)
(map cadr lst))
In general, when you want to transform every element of a list, map is the way to go.
All you need to do is map the built-in function second onto the list lst:
(map second lst)
Your error is that you lack an operator, perhaps cons. If you look at the consequent:
((cdr (car list1))(second (cdr list1)))
So Scheme expects (cdr (car list)) to be a procedure since it's in operator position in the form, but since it isn't you get an error. In addition (cdr (car x)) == cdar wont take the second element in every element but the tail of each element. cadar is what you're lookig for.
(define (second list1)00+
(if (null? (cdr list1))
(cons (cadar list1) '())
(cons (cadar list1) (second (cdr list1)))))
It will fail for the empty list. To fix this you let the consequemt take care of every element and the base case only to stop:
(define (second list1)
(if (null? list1)
'()
(cons (cadar list1) (second (cdr list1)))))
The result for a list will be the same. There is a procedure called map. It supports several list arguments, but the implementation for one is:
(define (map fun lst)
(if (null? lst)
'()
(cons (fun (car lst)) (map fun (cdr lst)))))
Looks familiar? Both make a list based on each element, but map is generic. Thus we should try to make (fun (car lst)) do the same as (cadar lst).
(define (second lst)
(map cadr lst)) ; (cadr (car x)) == (cadar x)
There you have it. Chris beat me to it, but I'd like to comment one of the other answers that uses the abbreviation second. It's defined in racket/base and the library SRFI-1, but it's not mentioned in the last Scheme reports. I.e. some implementations might require an extra library to be imported for it to work.

(Scheme) Find out if some of the numbers in a list add up to a certain number?

I'm making a program that takes a list and a sum. If some of the numbers in the list add up to the sum, it returns true. Else, return false. It seems to be working for some cases but not for others. For example,
if I input this:
(numlist-sum '(5 9) 9)
It should return true because one of the numbers (9) equals the sum (9). But, for some reason, its returning false.
I can't figure out what the problem is. Help please?
(define (numlist-sum? ls sum)
(if (null? ls) #t
(if (and (null? (cdr ls)) (equal? (car ls) sum)) #t
(if (equal? (car ls) sum) #t
(if (equal? (cdr ls) sum) #t
(if (equal? (apply + (car ls) (cdr ls)) sum) #t
#f))))))
I'll give you some hints for solving this problem (looks like homework). First write a procedure that generates all the possible subsets of the list (e.g., the power set of the list). For example:
(powerset '(1 2 3))
=> '(() (1) (2) (3) (1 2) (1 3) (2 3) (1 2 3))
With the above procedure in hand (and it's easy to find the algorithm, Google is your best friend), simply iterate over each of the sublists and sum its values:
(apply + '(2 3))
=> 5
If one of the sublists' sum equals the expected value, return #t. If none of the sums satisfy the expected value, return #f.
EDIT:
I forgot to mention, this is a well-known problem - it's the subset sum problem, which can be efficiently solved (at least, more efficiently than generating the power set) using dynamic programming. But I don't think that's the goal of this homework in particular.
Here is a solution that checks each element one by one and then recurses down the list if the first element isn't the sum.
(define (numlist-sum list sum)
(and (not (null? list))
(let ((head (car list)))
(cond ((number? head)
(or (= sum head)
(numlist-sum (cdr list) sum)))
((list? head)
(or (= sum (apply + head))
(numlist-sum (cdr list) sum)))
(else 'ill-formed-list)))))
Also, note that your code can be rewritten as:
(define (numlist-sum? ls sum)
(or (null? ls)
(if (and (null? (cdr ls)) (equal? (car ls) sum))
(equal? (car ls) sum)
(equal? (cdr ls) sum)
(equal? (apply + (car ls) (cdr ls)) sum)))
I'd say the use of '(if pred #t else ...) is a bit awkward and hides the true logic of the code.

Scheme List Derangement (Rearrangement of sorts)

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)))))))))))