LISP. Create list of pairs - list

I have a code like below. It return list as (((1 . 2) (1 . 0)) ((1 . 2) (1 . 1)) ((1 . 2) (1 . 3)) ((1 . 2) (1 . 4)) ((1 . 2) (1 . 5)) ((1 . 2) (1 . 6)) ((1 . 2) (1 . 7)) ((1 . 2) (0 . 2)) ((1 . 2) (2 . 2)))
I wonder if I can rewrite generHod function in the way to make it return list like ((1.2 1.0) (3.4 4.2) (1.3 1.3)...)
(setf hod '())
(defun generHod (CurrX CurrY)
(dotimes (y 8)
(if (/= y CurrY)
(setf hod (append hod (list (append (list (cons CurrX CurrY))(list (cons CurrX y))))))
)
)
(dotimes (x 8)
(if (/= x CurrX)
(setf hod (append hod (list (append (list (cons CurrX CurrY))(list (cons x CurrY))))))
)
)
)

Firstly:
(setf hod '())
This is a bad way to define a global variable; try
(defparameter hod ())
But why use a global variable at all? The function can construct a new list and just return it. If the caller wants to stick it into a global variable, that's up to the caller; it's extraneous to the operation of the function.
(defun generHod ...)
The syntax generHod is not distinguished from GENERHOD or generhod in Common Lisp, under the default readtable. All those tokens produce the same symbol. It is best not to play mixed case games in Lisp identifiers; if you want multiple words, put in a dash like gen-hod. Usually generate is abbreviated all the way to gen by English speaking hackers, not gener. See the gensym funtion in Common Lisp, for instance.
In your function, there is a completely superfluous append:
(append
(list (cons CurrX CurrY))
(list (cons CurrX y))))
The pattern (append (list X0) (list X1) ... (list XN)) can be rewritten (list X0 X1 ... XN). You're making superfluous lists of things only to append them together to make one list, instead of just listing the things in the first place.
To get the values from integer to floating point, the float function can be used, and the loop macro provides an idiom for iterating and collecting items:
(defun gen-hod (curr-x curr-y)
(let ((cxy (list (float curr-x) (float curr-y)))) ;; allocate just once!
(nconc ;; destructive append: use with care
(loop for y from 1 to 8
when (/= y curr-y)
append (list cxy (list (float curr-x) (float y))))
(loop for x from 1 to 8
when (/= x curr-x)
append (list cxy (list (float x) (float curr-y)))))))

Related

LISP: take an arbitrary s-expression and reverse every cons node (car and cdr of a node) recursively

So in lisp a list is a collection of cons nodes, each node has two parts to it. The car of the node and the cdr of that node, how would I go about reversing each cons node?
Using reduce:
(defun reverse-conses (list)
(reduce (lambda (x acc) (cons acc x)) list :initial-value nil :from-end t))
Recursively:
(defun reverse-conses (list)
(if (null list) nil
(cons (reverse-conses (cdr list)) (car list))))
I'm starting with a single function that swaps a cons cell.
(defun swap-cons (cns)
(cons (cdr cns)
(car cns)))
Let's test it:
> (swap-cons (cons 1 2))
(2 . 1)
> (swap-cons (cons 1 (cons 2 3)))
((2 . 3) . 1)
So this works. Now we just need to map this function over the input list
(defun swap-conses (lst)
(mapcar #'swap-cons
lst))
> (swap-conses '((1 . 2)))
((2 . 1))
> (swap-conses '((1 . 2) (3 . 4)))
((2 . 1) (4 . 3))
> (swap-conses '((1 2)))
(((2) . 1))
> (swap-conses '((1 . 2) (3 4) (5 6 7)))
((2 . 1) ((4) . 3) ((6 7) . 5))
To recursively go through a whole tree and swap car and cdr you can do something like this:
(defun reverse-conses (tree)
(if (consp tree)
(cons (reverse-conses (cdr tree))
(reverse-conses (car tree)))
tree))
(reverse-conses (cons 1 2)) ; ==> (2 . 1)
(reverse-conses '(1 2 3)) ; ==> (((nil . 3) . 2) . 1)
(reverse-conses '(1 (2 3) 4)) ; ==> (((nil . 4) (nil . 3) . 2) . 1)
Considering the argument can consist of improper lists there isn't a simpler solution to this.

Combining list of list

Hello i have to programm this fucntion in lisp:
(defun combine-list-of-lsts (lst)...)
So when executing the function i should get
(combine-list-of-lsts '((a b c) (+-) (1 2 3 4)))
((A + 1) (A + 2) (A + 3) (A + 4) (A-1) (A-2) (A-3) (A-4) (B + 1) (B + 2) (B + 3) (B + 4) (B-1) (B-2) (B-3) (B-4)(C + 1) (C + 2) (C + 3) (C + 4) (C-1) (C-2) (C-3) (C-4))
What i have now is:
(defun combine-list-of-lsts (lst)
(if (null (cdr lst))
(car lst)
(if (null (cddr lst))
(combine-lst-lst (car lst) (cadr lst))
(combine-lst-lst (car lst) (combine-list-of-lsts (cdr lst))))))
Using this auxiliar functions:
(defun combine-lst-lst (lst1 lst2)
(mapcan #'(lambda (x) (combine-elt-lst x lst2)) lst1))
(defun combine-elt-lst (elt lst)
(mapcar #'(lambda (x) (list elt x)) lst))
But what i get with this:
((A (+ 1)) (A (+ 2)) (A (+ 3)) (A (+ 4)) (A(-1)) (A(-2)) (A(-3)) (A(-4))...)
I dont know how to make this but without the parenthesis
The first thing is to look at this case:
(combine-list-of-lsts '((a b c)))
What should that be? Maybe not what your function returns...
Then I would look at the function combine-list-of-lsts. Do you need two IF statements?
Then look at combine-elt-lst. Do you really want to use LIST? It creates a new list. Wouldn't it make more sense to just add the element to the front?
Usually, when you want to reduce mutliple arguments into single result, you need function #'reduce. Your combination of lists has name cartesian n-ary product.
Following function:
(defun cartesian (lst1 lst2)
(let (acc)
(dolist (v1 lst1 acc)
(dolist (v2 lst2)
(push (cons v1 v2) acc)))))
creates cartesian product of two supplied lists as list of conses, where #'car is an element of lst1, and #'cdr is an element of lst2.
(cartesian '(1 2 3) '(- +))
==> ((3 . -) (3 . +) (2 . -) (2 . +) (1 . -) (1 . +))
Note, however, that calling #'cartesian on such product will return malformed result - cons of cons and element:
(cartesian (cartesian '(1 2) '(+ -)) '(a))
==> (((1 . +) . A) ((1 . -) . A) ((2 . +) . A) ((2 . -) . A))
This happens, because members of the first set are conses, not atoms. On the other hand, lists are composed of conses, and if we reverse order of creating products, we could get closer to flat list, what is our goal:
(cartesian '(1 2)
(cartesian '(+ -) '(a)))
==> ((2 + . A) (2 - . A) (1 + . A) (1 - . A))
To create proper list, we only need to cons each product with nil - in other words to create another product.
(cartesian '(1 2)
(cartesian '(+ -)
(cartesian '(a) '(nil))))
==> ((2 + A) (2 - A) (1 + A) (1 - A))
Wrapping everything up: you need to create cartesian product of successive lists in reversed order, having last being '(nil), what can be achieved with reduce expression. Final code will look something like this:
(defun cartesian (lst1 lst2)
(let (acc)
(dolist (v1 lst1 acc)
(dolist (v2 lst2)
(push (cons v1 v2) acc)))))
(defun combine-lsts (lsts)
(reduce
#'cartesian
lsts
:from-end t
:initial-value '(nil)))
There is one more way you can try,
(defun mingle (x y)
(let ((temp nil))
(loop for item in x do
(loop for it in y do
(cond ((listp it) (setf temp (cons (append (cons item 'nil) it) temp)))
(t (setf temp (cons (append (cons item 'nil) (cons it 'nil)) temp))))))
temp))
Usage:(mingle '(c d f) (mingle '(1 2 3) '(+ -))) =>
((F 1 +) (F 1 -) (F 2 +) (F 2 -) (F 3 +) (F 3 -) (D 1 +) (D 1 -) (D 2 +)
(D 2 -) (D 3 +) (D 3 -) (C 1 +) (C 1 -) (C 2 +) (C 2 -) (C 3 +) (C 3 -))

Multiply 1st element of every sublist by -1?? Common Lisp

As part of a larger project I want to be able to multiple every first element of every sublistby -1. I am trying to do it using recursion at the moment like this:
(defun negative (secondpoly)
(let ((t1(car secondpoly))
(rem(cdr secondpoly)))
(let ((c1(car t1)))
(if (not (null (cdr secondpoly)))
(negative (append (* c1 -1) rem))
)
)
)
)
With this input:
(pminus '((5 x 2)(100 x 2)))
I want to receive this output:
(pminus '((-5 x 2)(-100 x 2)))
I was wondering if someone could show me a way to do this?
If your input really is something like: '(pminus ((5 x 2)(100 x 2)))
(defun negative-first (poly)
(cons (car poly)
(mapcar (lambda (el)
(cons (- (car el)) (cdr el)))
(cadr poly))))
CL-USER> (negative-first '(pminus ((5 x 2)(100 x 2))))
(PMINUS (-5 X 2) (-100 X 2))
But for me it looks like there is a mistake in explanation, and your input is '((5 x 2)(100 x 2)) and if so, your function is:
(defun negative-first (poly)
(mapcar (lambda (el)
(cons (- (car el)) (cdr el)))
poly))
CL-USER> (negative-first '((5 x 2)(100 x 2)))
((-5 X 2) (-100 X 2))
If you need to work with more nested and complex data, you probably should who some examples, this function will work only with one level ((5 x 2) (100 x 2) (40 x 3) .... ).

If you're mapping a function over a list in rackect how can you get a reference to the next element?

If I have a list and I map a lambda function over it how can I get a reference to the next or previous item while processing the current one?
(map (lambda (x) x) '(1 2 3))
How would I reference the previous or next element while processing x?
John McCarthy originally made maplist and it's defined in CL still and predates map(car). It's definition in Scheme would be something like:
(define (maplist fun lst)
(if (null? lst)
'()
(cons (fun lst) (maplist fun (cdr lst)))))
(maplist values '(1 2 3 4)) ; ==> ((1 2 3 4) (2 3 4) (3 4) (4))
It's slightly more difficult to get each element like map but if you need more than the first then it's perfect.
Start with your one list, construct two other lists, one 'shifted' right, and the other 'shifted' left. Like this:
(define (process func x)
(let ((to-front (cons 'front (reverse (cdr (reverse x)))))
(to-rear (append (cdr x) (list 'rear))))
(map func to-front x to-rear)))
Note that the stuff above with reverse is because map expects all lists to have the same length. So when adding to the front, you need to remove one from the tail.
Also, the provided func needs to accept three arguments.
> (process list '(a b c))
((front a b) (a b c) (b c rear))
You can always use map on two zipped lists, i.e.
(import (srfi srfi-1)) ; or use some zip implementation
(define a '(1 2 3 4 5))
(map (lambda (x) x)
(zip a
(append (cdr a) (list (car a)))))
which results in ((1 2) (2 3) (3 4) (4 5) (5 1)).
Of course, the above assumes "periodic" boundary conditions for the lists (you should modify the boundary conditions for your case).
And also you would need to modify the lambda to handle pairs of elements.
For simplicity let's take the case of two elements at a time -- the current and next one. So if you have (list 1 2 3), and a function that takes this and next args, you want it to be called with:
1 2
2 3
3 <some value, let's say 3>
You could write that concisely as:
(map f xs (append (drop xs 1) (list (last xs))))
However the drop and append-ing means that's not the fastest way to do it. Instead you could write a map-slide-pairs function to do it more directly:
#lang racket/base
(require racket/match)
;; map a list as "sliding pairs". For example:
;; (map-slide-pairs cons '(1 2 3)) ==> '((1 . 2)
;; (2 . 3)
;; (3 . 3))
(define (map-slide-pairs f xs #:last-val [last-val #f])
;; Concise implementation:
;; (map f xs (append (drop xs 1) (list (last xs)))))
;; Faster implementation:
(let loop ([xs xs])
(match xs
[(list) (list)]
[(list this) (list (f this (or last-val this)))]
[(list this next more ...) (cons (f this next)
(loop (cons next more)))])))
(module+ test
(require rackunit)
(check-equal? (map-slide-pairs cons '(1 2 3))
'([1 . 2][2 . 3][3 . 3]))
(check-equal? (map-slide-pairs cons '(1 2 3) #:last-val 100)
'([1 . 2][2 . 3][3 . 100])))
Hopefully you can see how to extend this and make a "map-slide-triples" function that would be called with the previous, current, and next elements of the list.

Building a 2D List

Looking for a function that would do something akin to the following:
(foo 3 2) => '( ( (1 1) (1 2) (1 3) )
( (2 1) (2 2) (2 3) ) )
Would there be any built-in function in DrRacket that accomplishes that?
The main tool that you want to use to get such things in Racket is the various for loops. Assuming that you want to create a list-based matrix structure, then this is one way to get it:
#lang racket
(define (foo x y)
(for/list ([i y])
(for/list ([j x])
(list (add1 i) (add1 j)))))
And since people raised the more general question of how to make foo create a matrix of any dimension, here's a generalized version that works with any number of arguments, and still returns the same result when called as (foo 3 2):
#lang racket
(define (foo . xs)
(let loop ([xs (reverse xs)] [r '()])
(if (null? xs)
(reverse r)
(for/list ([i (car xs)])
(loop (cdr xs) (cons (add1 i) r))))))
(Note BTW that in both cases I went with a simple 0-based iteration, and used add1 to get the numbers you want. An alternative way would be to replace
(for/list ([i x]) ... (add1 i) ...)
with
(for/list ([i (in-range 1 (add1 x)]) ... i ...)
)
Code:
(define (foo-makey const max data)
(let* ((i (length data))
(newy (- max i))
(newpair (cons const newy)))
(if (= max i)
data
(foo-makey const max
(cons newpair data)))))
(define (foo-makex xmax ymax data)
(let* ((i (length data))
(newx (- xmax i)))
(if (= xmax i)
data
(foo-makex xmax ymax
(cons (foo-makey newx ymax '()) data)))))
(define (foo x y)
(foo-makex y x '()))
Output:
> (foo 3 2)
'(((1 . 1) (1 . 2) (1 . 3)) ((2 . 1) (2 . 2) (2 . 3)))
I can't answer your question as-is because I don't understand how the nested lists should work for >2 arguments. AFAIK there is no built-in function to do what you want.
To start you off, here is some code that generates output without nested lists. As an exercise try adjusting the code to do the nested listing. And see if there's a way you can make the code more efficient.
;;can take in any number of arguments
(define (permutations . nums)
(foldl
(lambda (current-num acc)
(append-map
(lambda (list-in-acc)
(for/list ((i (build-list current-num (curry + 1))))
(append list-in-acc (list i))))
acc))
(list (list))
(reverse nums)))
Example 1:
> (permutations 3 2)
'((1 1) (1 2) (1 3) (2 1) (2 2) (2 3))
Example 2:
> (permutations 10)
'((1) (2) (3) (4) (5) (6) (7) (8) (9) (10))
Example 3:
> (permutations 2 3 4)
'((1 1 1)
(1 1 2)
(1 2 1)
(1 2 2)
(1 3 1)
(1 3 2)
(2 1 1)
(2 1 2)
(2 2 1)
(2 2 2)
(2 3 1)
(2 3 2)
(3 1 1)
(3 1 2)
(3 2 1)
(3 2 2)
(3 3 1)
(3 3 2)
(4 1 1)
(4 1 2)
(4 2 1)
(4 2 2)
(4 3 1)
(4 3 2))
(define (build-2d row col)
(build-list row (lambda(x) (build-list col (lambda(y) (list (+ x 1) (+ y 1))))))