Using SERIES library from CLTL2 appendix A, I want a flat series from nested series. For example:
(map-fn t (lambda (x)
(map-fn t (lambda (y)
(cons x y))
(scan '(1 2 3))))
(scan '(4 5 6)))
=> #Z( #Z( (4 . 1) (4 . 2) (4 . 3) )
#Z( (5 . 1) (5 . 2) (5 . 3) )
#Z( (6 . 1) (6 . 2) (6 . 3) ) )
I want to make this series of series to one series as below:
=> #Z( (4 . 1) (4 . 2) (4 . 3)
(5 . 1) (5 . 2) (5 . 3)
(6 . 1) (6 . 2) (6 . 3) )
If I would have an appropriate series concatenation function, it would be good. Although the series library has CATENATE function, it takes just some series in its &rest parameter. I could
(apply #'catenate list-of-series)
but it accepts a list of series, not series of series. Unfortunately, there are not any functions for folding series, while there are for mapping and filtering. The PRODUCING macro shown on A.4. Primitives section in CLTL2 does not work for me because it also seems not to flatten a nested loop. I cannot use NEXT-OUT macro in nested situation.
(apply #'catenate
(collect (map-fn t (lambda (x)
(map-fn t (lambda (y)
(cons x y))
(scan '(1 2 3))))
(scan '(4 5 6)))))
But that is bit of a cheat. To do it properly in series:
(producing (prod) ((zz (generator (map-fn t (lambda (x)
(map-fn t (lambda (y)
(cons x y))
(scan '(1 2 3))))
(scan '(4 5 6)))))
cur)
(loop
(tagbody
redo
(if (null cur)
(setq cur (generator (next-in zz (terminate-producing)))))
(next-out prod (next-in cur (progn
(setq cur nil)
(go redo)))))))
=> #Z((4 . 1) (4 . 2) (4 . 3)
(5 . 1) (5 . 2) (5 . 3)
(6 . 1) (6 . 2) (6 . 3))
Related
I'm trying to make a function that, given a list, will return a list of pairs of elements where the two elements are not equal. For example, given the list (1 2 3) it would return ((1 2) (1 3) (2 1) (2 3) (3 1) (3 2)). The code I have now works, but it adds nil to each spot where it would have matching numbers; (1 1) for example.
(defun make-permutations-without-identical(list)
(loop for x in list
append (loop for y in list
collect (append (if (not (equal x y)) (list x y))))))
This code, given (1 2 3) returns (NIL (1 2) (1 3) (2 1) NIL (2 3) (3 1) (3 2) NIL). How do I get rid of the NIL's?
Since the lists generated by the inner loop are fresh, you can nconc them. The loop macro has unless part so that you can conditionally collect parts. Thus you can just collect except when (equal x y):
CL-USER> (loop for x in '(1 2 3)
nconcing (loop for y in '(1 2 3)
unless (equal x y)
collect (list x y)))
((1 2) (1 3) (2 1) (2 3) (3 1) (3 2))
If you don't want to see NIL in the result list, just don't collect NILs. Collect only the items you want to be in the result list.
In racket a higher order function like map used on two lists does this:
(map list '(1 2 3) '(1 2 3))
> '( (1 1) (2 2) (3 3) )
But I would like a cartesian-product thing like this:
'( (1 1) (1 2) (1 3) (2 1) (2 2) (2 3) (3 1) (3 2) (3 3) )
How can I achieve this? Preferably with higher order functions?
Here's a method that totally uses higher-order functions (foldr, append-map, and map; now also with compose1, curry, and curryr):
(define (cartesian-product . lists)
(foldr (lambda (a b)
(append-map (compose1 (curryr map b) (curry cons))
a))
'(())
lists))
Pardon the terrible parameter names. One day I'll come up with something good. :-)
> (require unstable/list)
> (cartesian-product '(1 2 3) '(a b c))
'((1 a) (1 b) (1 c) (2 a) (2 b) (2 c) (3 a) (3 b) (3 c))
See http://docs.racket-lang.org/unstable/list.html#%28def._%28%28lib._unstable%2Flist..rkt%29._cartesian-product%29%29
In SCIP chapter 2.2.3 "Sequences as Conventional Interfaces, authors show us a general way to approach such problem. There is actually a similar example. The book uses flatmap as a common abstraction. The combination of mapping and accumulating with append is so common in this sort of program that we will isolate it as a separate procedure: flatmap. Here is a solution using flatmap:
>(define (flatmap proc seq)
(foldr append '() (map proc seq)))
>(flatmap
(lambda (x)
(map
(lambda (y) (list y x))
'(1 2 3)))
'(a b c))
'((1 a) (2 a) (3 a) (1 b) (2 b) (3 b) (1 c) (2 c) (3 c))
I need to create a pair that contains two pairs inside using Common Lisp.
The output needs to be:
((1 . 2) . (3 . 4))
Literature states (cons (cons 1 2) (cons 3 4)) should output what I need but when I run that I obtain:
((1 . 2) 3 . 4)
Any help is appreciated.
In Lisp
((1 . 2) . (3 . 4))
and
((1 . 2) 3 . 4)
are exactly the same thing. You can check by evaluating '((1 . 2) . (3 . 4)).
If you think about it the 3 is the car of the cdr, so it's the second element of the improper list, so the pair (1 . 2) is the first element, 3 as second element and that has 4 instead of NIL to terminate it.
They're just two ways to see the very same cons cells configuration:
CL-USER 4 > (equal '((1 . 2) . (3 . 4))
'((1 . 2) 3 . 4 ))
T
#xA is the exact same as 10, but when it's printed it's system settings that dictates how a number is to be printed. The reason is that the fixnum doesn't have a base, but the visual representation does. Just as #xA is the same as 10, ((1 . 2) . (3 . 4)) is the same as ((1 . 2) 3 . 4).
The illusion is that we have lists. In order to do that we display pairs with either nil or a pair as tails differently than pairs that has other values as their tail.. A list (1 2) is modeled as (1 . (2 . ())). The rules are something like this: Whenever the tail is nil or a pair you can omit this pair dot and the first parenthesis of the tail. Apply it recursively and (1 . (2 . ())) displays as (1 2) and ((1 . 2) . (3 . 4)) displays as `((1 . 2) 3 . 4).
To make the illusion complete the reader does the reverse so when it reads (1 2) it creates (1 . (2 . ())) in memory.
To really be a good Lisp programmer (in any dialect) you need to be able to see the omitted dot and parentheses in (1 2). When you do it becomes obvious what you need to do with (a (b c) d) in order to retrieve c (It's obviously (cadadr '(a (b c) d))). When you do master this you'll "see" ((1 . 2) . (3 . 4)).
This will do it: (cons (cons 1 2) (cons (cons 3 4) empty))
Good luck!
I have a small exercise in Lisp:
Write a function test-delta with parameters delta and lst, which will
check if the difference between successive elements in lst is smaller than
delta. Write the function in two ways:
recursively
using a mapping function
I have no problem writing that function recursively, but I don't know which mapping function I should use. All the standard mapping functions work with only one element of the list at a time. reduce cannot be used either, because I do not have some operation to use between successive elements. What function could I use here?
All standard functions are working only with one element at time.
Reduce function cannot be use either
because i do not have some operation to use between to elements.
There's already an answer by uselpa showing that you can do this with reduce, but it feels a bit awkward to me to bend reduce to this case.
It's much more natural, in my opinion, to recognize that the standard mapping functions actually let you work with multiple lists. I'll show mapcar and loop first, and then every, which I think is the real winner here. Finally, just for completeness, I've also included maplist.
mapcar
The standard mapcar can take more than one list, which means that you can take elements from two different lists at once. Of particular note, it could take a list and (rest list). E.g.,
(let ((list '(1 2 3 4 5 6)))
(mapcar 'cons
list
(rest list)))
;=> ((1 . 2) (2 . 3) (3 . 4) (4 . 5) (5 . 6))
loop
You can use loop to do the same sort of thing:
(loop
with l = '(1 2 3 4 5 6)
for a in l
for b in (rest l)
collect (cons a b))
;=> ((1 . 2) (2 . 3) (3 . 4) (4 . 5) (5 . 6))
There are some other variations on loop that you can use, but some of them have less conventient results. E.g., you could loop for (a b) on list, but then you get a (perhaps) unexpected final binding of your variables:
(loop for (a b) on '(1 2 3 4 5 6)
collect (list a b))
;=> ((1 2) (2 3) (3 4) (4 5) (5 6) (6 NIL))
This is similar to what maplist will give you.
every
I think the real winners here, though, are going to the be every, some, notevery, and notany functions. These, like mapcar can take more than one list as an argument. This means that your problem can simply be:
(let ((delta 4)
(lst '(1 2 4 7 9)))
(every (lambda (x y)
(< (abs (- x y)) delta))
lst
(rest lst)))
;=> T
(let ((delta 2)
(lst '(1 2 4 7 9)))
(every (lambda (x y)
(< (abs (- x y)) delta))
lst
(rest lst)))
;=> NIL
maplist
You could also do this with maplist, which works on successive tails of the list, which means you'd have access to each element and the one following. This has the same 6 NIL at the end that the second loop solution did, though. E.g.:
(maplist (lambda (tail)
(list (first tail)
(second tail)))
'(1 2 3 4 5 6))
;=> ((1 2) (2 3) (3 4) (4 5) (5 6) (6 NIL))
reduce can be used:
(defun testdelta (delta lst)
(reduce
(lambda (r e)
(if (< (abs (- r e)) delta)
e
(return-from testdelta nil)))
lst)
t)
or, without return-from (but possibly slower):
(defun testdelta (delta lst)
(and
(reduce
(lambda (r e)
(and r (if (< (abs (- r e)) delta) e nil)))
lst)
t))
I have a union method setup to combine 2 sets of ordered intervals:
(define (union set1 set2)
(cond [(empty? set1) set2]
[(empty? set2) set1]
[(< (caar set1) (caar set2)) (cons (car set1) (union (cdr set1)
set2))]
[else (cons (car set2) (union set1
(cdr set2)))]))
Given 2 lists '((1 3) (5 10) (19 29)) and '((2 4) (17 25) (30 49)) they produce
'((1 3) (2 4) (5 10) (17 25) (19 29) (30 49)) with the code above.
But with the above implementation the overlapping intervals aren't being handled correctly. I am needing to merge the overlapping intervals to produce '((1 3) (2 4) (5 10) (17 29) (30 49)). How could I go about handling these interval merges so that there are no overlaps?
Assuming you're working with half-open intervals [from upto), Racket provides an interval-map module:
An interval-map is a mutable data structure that maps half-open intervals of exact integers to values. An interval-map is queried at a discrete point, and the result of the query is the value mapped to the interval containing the point.
The provided examples:
> (define r (make-interval-map))
> (interval-map-set! r 1 5 'apple)
> (interval-map-set! r 6 10 'pear)
> (interval-map-set! r 3 7 'banana)
> (dict-map r list)
'(((1 . 3) apple) ((3 . 7) banana) ((7 . 10) pear))
Using your example inputs '((1 3) (5 10) (19 29)) and '((2 4) (17 25) (30 49)):
#lang racket/base
(require data/interval-map
racket/list
racket/match
racket/dict)
(define im (make-interval-map))
;; Add your first set
(for ([x '((1 3) (5 10) (19 29))])
(interval-map-set! im (first x) (second x) #f))
;; Add your second set
(for ([x '((2 4) (17 25) (30 49))])
(interval-map-set! im (first x) (second x) #f))
;; The result
(map car (dict-map im list))
;; => '((1 . 2) (2 . 4) (5 . 10) (17 . 25) (25 . 29) (30 . 49))