Connection between pairs and list in scheme - list

I am trying to understand the connection between pairs and lists in scheme. Let's take a look at the following scheme expression:
(((a) (b)) ((c) (d)))
I wish to count the number of pairs in the above expression, so I constructed it in the following manner:
(list (list (list 'a) (list 'b)) (list (list 'c) (list 'd)))
=> (((a) (b)) ((c) (d)))
(list 'a),(list 'b),(list 'c),(list 'd) - 4 pairs
(list (list 'a) (list 'b)) and (list (list 'c) (list 'd)) - 2 pairs
(list (list (list 'a) (list 'b)) (list (list 'c) (list 'd))) - 1 pair
So far, 7 pairs. Supposed to be 10.
What am I missing here?

Simple fact: a proper list with n elements has n pairs:
So, which is the total number of elements in your list?
Lists like (a) have one element, so they have one pair. You have four of them, so you have 4 pairs.
Lists like (thing1 thing2) have two elements, so they have two pairs. You have three of them (the two internals containing the lists like (a), and one external), so you have 3 x 2 = 6 other pairs.
In total, you have 6 + 4 = 10 pairs.

Related

How is this the correct representation of the given nested structure [SICP]? What am I missing?

Second sentence of Section 2.2.2 (Hierarchical Structures) of SICP: the authors say that ((1 2) 3 4) (a list of three elements) can be constructed by (cons (list 1 2) (list 3 4)).
I think (wrongly so, of course) that it will construct ((1 2) (3 4)) (two elements) instead because:
3 and 4 will be enclosed in a nested list not in the top-level cons, and
cons constructs a pair of items, and pair means 2 elements not 3.
What am I failing to understand here?
A list is a chain of pairs, ending with a pair whose cdr is the empty list.
(list 3 4) is two pairs, equivalent to
(cons 3 (cons 4 '()))
So (cons (list 1 2) (list 3 4)) is 3 pairs, equivalent to
(cons (list 1 2) (cons 3 (cons 4 '())))
In general, if you have a list old-list, you can create a new list with a new element on the front with:
(cons new-element old-list)
You would get what you expected if you wrote
(list (list 1 2) (list 3 4))

Scheme / Racket : transposing lists with map and lambda

I'm currently trying to code a procedure which gets a list of lists and returns a list of lists, which contains each first item of the input lists. For example I'll provide you with a Input and Output.
Input:
(list (list 1 5) (list 2 6) (list 3 7) (list 4 8)))
Output:
(list (list 1 2 3 4) (list 5 6 7 8))
My idea was to build a somewhat map procedure using lambda for function. I'm currently struggling on mapping any function on combined list elements, since map only processes a single item on the list (to my understanding).
Could anyone provide me with helpful insights?
Thank you so much in advance.
This can be done in Scheme / Racket with
(apply map list (list (list 1 5) (list 2 6) (list 3 7) (list 4 8)))
which in DrRacket returns
'((1 2 3 4) (5 6 7 8))
Basically, calling (apply map list [a b c ... n]) (in pseudocode), is the same as calling
(map list a b c ... n)
The argument list is "opened up", so to speak.
cf. Matrix multiplication in scheme, List of lists
(lambda x x) could be used instead of list, too:
(apply map (lambda x x) (list ....... ))
This is because map can be used with several lists as its inputs, not just one. In such a case the number of arguments to the lambda function must match the number of input lists.
A special case is (lambda x ...) where x is not enclosed in parentheses. This means such a lambda function can be applied to any number of arguments, which will all be collected and passed in as a list. So (lambda x x) will act just the same as the built-in list does, and can be seen as its implementation.
And by the way, this isn't "merging", it is "transposition".

Dr. Racket: Removing elements from a list using abstract list functions

So when given two lists, how do I remove elements in one list from another using only map, filter or foldr? I can't use explicit recursion or lambda either.
The lists consist of only numbers that are sorted in ascending order.
For example, if given (list 1 2 3) and (list 1 3 5), I want to remove all of the second list's elements from the first list. The output I want is (list 2).
If given (list 4 5 6) and (list 2 3 5), I would get (list 4 6).
I'm guessing the final code would be something like:
(define (fn-name list-one list-two)
(filter ... list-one))
Thanks!
Given that you're using Racket, we can write a simple solution in terms of some of the built-in abstract list functions and without using explicit lambdas, we only need a little help from SRFI-26. Try this:
(require srfi/26)
(define (difference lst1 lst2)
(filter-not (cut member <> lst2) lst1))
It works as expected:
(difference (list 1 2 3) (list 1 3 5))
=> '(2)
(difference (list 4 5 6) (list 2 3 5))
=> '(4 6)
You use filter, but you have to curry and invert member so you cannot do it without lambda.
(define (remove-elements needles haystack)
(filter (lambda (x) (not (member ...)))
haystack))
(define (remove-elements needles haystack)
(define (not-in-needles x)
(not (member ...)))
(filter not-in-needles haystack))
Both of these use lambda twice! Once for the define of remove-elements and once explicit / in not-in-needles. In your own example you use lambda once too since (define (name . args) . body) is the same as (define name (lambda args . body))

Transpose a matrix in racket (list of lists

I got a list of lists in racket and have to transpose them.
(: transpose ((list-of(list-of %a)) -> (list-of (list-of %a))))
(check-expect (transpose (list (list 1 2 3)
(list 4 5 6)))
(list (list 1 4)
(list 2 5)
(list 3 6)))
(define transpose
(lambda (xs)
(cond
((empty? xs)empty)
((pair? xs)(make-pair (make-pair (first(first xs)) (make-pair (first(first(rest xs)))empty)) (transpose (rest(rest xs))))))))
That's my code at the moment.
I think the problem is in the recursive call (correct me if I'm wrong please).
The actual outcome is (list (list 1 4)). The rest seems kinda ignored.
It would really help me, if somebody knows the problem, or has a tip.
The simplest definition of transpose is:
(define (transpose xss)
(apply map list xss))
Why does it work?
(apply map list '((a b) (d e))
= (apply map List '((a b) (d e)) ; use List rather than list
= (map List '(a b) '(d e))
= (list (List 'a 'd) (List 'b e))
= '((a d) (b e))
Here List is spelled with capital letters only to show which list was given by the user and which was produced by map.
Here is a less "clever" solution. It uses that the first column of
a matrix becomes the first row in the transposed matrix.
(define transpose
(lambda (xss)
(cond
[(empty? xss) empty]
[(empty? (first xss)) empty]
[else (define first-column (map first xss))
(define other-columns (map rest xss))
(cons first-column
(transpose other-columns))])))
(define (transpose xss)
(apply map list xss))
If you are, like me, new to Scheme, you'll wonder how the apply map list trick works.
It all boils down to understanding apply and map.
First, apply does its job. It takes a function, some fixed arguments and a list of arguments.
It calls the function with the fixed arguments followed by the flattenned list arguments.
So:
(apply map list '((1 2) (3 4)))
^^^^^^^^^^^^^^-- list of arguments
^^^^ ---------------- a fixed argument
^^^ --------------------- function
evaluates to:
(map list '(1 2) '(3 4))
Note how the list of lists is turned into two lists.
Now map accepts an N-argument function and N lists of equal length. Then it returns a list, where each element is an application of the function.
For example
(map + '(1 2) '(3 4))
evaluates to:
(list (+ 1 3) (+ 2 4))
In the transpose trick the function is simply list, so:
(map list '(1 2) '(3 4))
evaluates to:
(list (list 1 3) (list 2 4))
where the first list constructs a list because map always returns a list and the other two are invocations of the passed list function.
for/list can be used sequentially to create a list of lists with transposed items:
(define (transpose_ lol) ; lol is list of lists
(for/list ((i (length (list-ref lol 0)))) ; loop for length of first inner list
(for/list ((il lol)) ; for each inner list (il)
(list-ref il i)))) ; get its item
Testing:
(transpose_ (list (list 1 2 3)
(list 4 5 6)))
Output:
'((1 4) (2 5) (3 6))
(define (tr ls)
(if (empty? (car ls)) empty
(if (null? ls) empty
(cons (map car ls) (tr (map cdr ls))))))

Racket: filtering with two conditions (turning columns into lists)

I'm trying to create a list containing all the values of a column from lists of lists resembling a matrix.
The list should contain only numbers and guess-number of a
(define-struct guess (symbol number))
puzzle1:
(list
(list 'a 'b 'b 'c)
(list 'a 2 1 4)
(list 'f 3 'g 'g)
(list 'f 'h 'i 'i))
The parameters are the matrix and a position, so:
(check-expect (used-in-column puzzle1 (make-posn 0 1)) (list 2 3))
(define-struct puzzle (size board constraints))
where the board part is the puzzle1 example needed above
I can create a list with only the numbers, but seem unable to alter the code so it adds any guess-number to the list
so here's an example with a guess inside of it, where the output given by my code is empty
(check-expect (used-in-column puzzle1partial2 (make-posn 0 1)) (list 2))
Where the puzzle-board is
(list
(list (make-guess 'a 2) 'b 'b 'c)
(list 'a 2 1 4)
(list 'f 3 'g 'g)
(list 'f 'h 'i 'i))
So far my code looks like this:
(define (used-in-column puz pos)
(local [(define (columns board pos)
(cond
[(empty? board) empty]
[else (cons (list-ref (first board) (posn-x pos))
(columns (rest board) pos))]))]
(cond
[(empty? puz) empty?]
[else (quicksort (filter number? (columns (puzzle-board puz) pos)) <)])))
I tried using if statements and other variants, but it ends up making my code a mess and not getting me any results.
Can anybody give me any advice on this?
As for you subject you can transpose with the standard unzip:
(define (unzip lsts)
(apply map list lsts))
(unzip '((1 2) (a b))) ; ==> ((1 a) (2 b))
If you just want one row you use list-ref:
(map (lambda (x) (list-ref x 1)) '((1 2) (a b))) ; ==> (2 b)
I really don't understand what your code is supposed to do and I can't run it either (lacks a stuct I think) so I leave it at this.