help with multiplying polynomials in lisp - polynomial-math

for example: (3x2 - 5x + 2)(7x + 1) and you simplify it like this:
((3 2)(-5 1)(2 0))((7 1)(1 0))
((21 3)(3 2)(-35 2)(-5 1)(14 1)(2 0))
(21 3)(32 2)(9 1)(2 0)
and you get this answer: 21x3 + 32x2 + 9x + 2
i need this solution in lisp please help

For the first stage, you need to pair up every LHS component with every RHS component; a cartesian product of the two sets. This requires a two-level map followed by a concatenation of the second-level lists of pairs into a single top level list (think (apply #'append ...).
The second stage can be done with a reduce that builds up an association list, keyed on the exponent.
EDIT: Let me solve a different problem for you, and let you figure out how to translate it into the solution for your problem:
Compute (a + b + ... + k) * (l + m + ... + z) by first expanding into pairs and then summing the products:
(defun mul-sums (aa bb)
(reduce #'+
(apply #'append
(map 'list
#'(lambda (a)
(map 'list
#'(lambda (b)
(* a b))
bb))
aa))))
; Compute (1 + 2 + 3) * (3 + 4).
> (mul-sums '(1 2 3) '(3 4))
42

Related

SICP- the expression of tree data structure in LISP [duplicate]

I've started learning Scheme, for fun mostly, and because I've never used a functional language before. I chose Scheme because I wanted to read SICP for a long time.
Anyway, I'm currently learning about lists, and before that I learned about cons, car and cdr. And there's an example that creates a list of lists with cons, like this :
(cons (list 1 2) (list 3 4))
The resulting list is ((1 2) 3 4), which doesn't make sense to me, I would expect ((1 2)(3 4)) to be the result (a list made out of two lists). Why does it behave like that? I realize that if I were to use car, I would get (1 2), and cdr I'd get (3 4) becaue cdr always returns "the rest", but I don't understand why the list isn't made of two lists?
You get a list with (1 2) as the first element (the car) and (3 4) as the rest (the cdr) because the first argument to cons is the first element of the list and the second argument is a list containing the remaining items.
This closely resembles the structure of a list: each node of a (proper) list contains an element and a list containing all other element. cons creates one such node.
If the second argument to cons would become the second element of the list, how would you create a list with three arguments? You'd have to make cons variardic at which point, it'd just be another name for list.
If you want to create a list of lists use (list (list 1 2) (list 3 4)).
(list (list 1 2)
(list 3 4))
is the same as
(cons (list 1 2)
(cons (list 3 4)
'()))
Which results in
((1 2) (3 4))
which can also be written as
((1 . (2 . ()))
.
((3 . (4 . ()))
.
()))
list A: [ | ]
1 [ | ]
2 /
list B: [ | ]
3 [ | ]
4 /
======================
(cons A B)
[ | ]
[ | ] [ | ]
1 [ | ] 3 [ | ]
2 / 4 /
A graphic representation of the inner structures can help us to visualize the problem.
And this will help some more:
[ | ]
X [ | ]
3 [ | ]
4 /
Do you see the pattern? The above is the list (X 3 4). That's the reason (cons A B) draws only the car part as a separate list and not the cdr.
Because a cons-cell is not a list of two elements, the two are often confused. If (a . b) is a cons cell, then (a . (b . ())) is a list of two elements. Any list safe the empty list specifically is a cons cell whose car field contains the first element and whose cdr field contains the list which contains the remaining elements. A list is thus simply a binary tree whose right-most leaf is the special constant () or nil depending on your dialect.
Which is why (cons 0 '(1 2 3)) evaluates to (0 1 2 3) and not (0 (1 2 3)) we create a cons cell whose car is 0, and whose cdr is (1 2 3), so a list (0 1 2 3).
Here's a really simple explanation:
(define (x)
(cons (list 1 2) (list 3 4)))
we know that these two conditions must be true:
(car x) = (1 2) #car = first element
(cdr x) = (3 4) #cdr = rest of the elements
the only way to satisfy this is x = ((1 2) 3 4).
________________________________________________________________________________________________________
x = ((1 2)(3 4)) is incorrect because:
(car x) = (1 2)
(cdr x) = ((3 4))
See there is an extra bracket/list created for (cdr x).
x = ((1 2)(3 4)) is actually a list of lists:
list( list(1 2) list(3 4)) = ((1 2)(3 4))

Nested lists in Lisp comparison

I have a function that can produce a list of n-element sublists from a list of elements but I am stuck in filtering out elements that are just permutations of each other. For example, f(A,B) -> ((A, B) (B,A)) is what I get but I just want ((A,B)) since (B,A) is a permutation. Is there a lisp function for this? I don't need the whole answer but a clue would be appreciated, note that A,B need not be atoms but can be string literals and even lists themselves.
I am doing this
(let (newlist '())
(loop :for x in l1 :do
(loop :for y in l2 :do
(push (list x y) newlist)))
... and I have another function that filters out these duplicates but it is clunky and probs won't scale for large inputs.
One interesting function is the (destructive) pushnew which pushes an element to a list only if it is not already existent in the set (list).
(defun pair-comb (l1 l2 &key (test #'eql) (key #'identity))
(let ((result '()))
(loop for x in l1 do
(loop for y in l2 do
(pushnew (list x y) result :test test :key key))
finally (return result))))
When we make the comparison between the elements in a way that it is order-agnostic, we would have the perfect function for us to collect different lists while ruling out the permutations of any of the already collected lists.
This can be done by #'sort-ing each list and compare by #'equalp or whatever equality function.
(pair-comb '(1 2 3) '(1 2 3 4 5) :test #'equalp :key (lambda (x) (sort x #'<)))
;;=> ((3 5) (3 4) (3 3) (2 5) (2 4) (2 3) (2 2) (1 5) (1 4) (1 3) (1 2) (1 1))
;; well, actually in this case #'eql would do it.
;; when using non-numeric elements, the `#'<` in sort has to be changed!

Can any one convert this code to Pseudo Code

#lang racket
(define (cartesian-product . lists)
(foldr (lambda (xs ys)
(append-map (lambda (x)
(map (lambda (y)
(cons x y))
ys))
xs))
'(())
lists))
(cartesian-product '(1 2 3) '(5 6))
I have racket lang code, that calculate cartesian product of two sets or lists, I don't understand the code well, can any one convert code to pseudo code.
The function corresponds to this definition of cartesian products.
The dot . in the argument means that lists will collect all the arguments (in a list) no matter how many are passed in.
How to call such a function? Use apply. It applies a function using items from a list as the arguments: (apply f (list x-1 ... x-n)) = (f x-1 ... x-n)
foldr is just an abstraction over the natural recursion on lists
; my-foldr : [X Y] [X Y -> Y] Y [List-of X] -> Y
; applies fun from right to left to each item in lx and base
(define (my-foldr combine base lx)
(cond [(empty? lx) base]
[else (combine (first lx) (my-foldr func base (rest lx)))]))
Applying the simplifications from 1), 2) and 3) and turning the "combine" function in foldr to a separate helper:
(define (cartesian-product2 . lists)
(cond [(empty? lists) '(())]
[else (combine-cartesian (first lists)
(apply cartesian-product2 (rest lists)))]))
(define (combine-cartesian fst cart-rst)
(append-map (lambda (x)
(map (lambda (y)
(cons x y))
cart-rst))
fst))
(cartesian-product2 '(1 2 3) '(5 6))
Let's think about "what" combine-cartesian does: it simply converts a n-1-ary cartesian product to a n-ary cartesian product.
We want:
(cartesian-product '(1 2) '(3 4) '(5 6))
; =
; '((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
We have (first lists) = '(1 2) and the result of the recursive call (induction):
(cartesian-product '(3 4) '(5 6))
; =
; '((3 5) (3 6) (4 5) (4 6))
To go from what we have (result of the recursion) to what we want, we need to cons 1 onto every element, and cons 2 onto every element, and append those lists. Generalizing this, we get a simpler reformulation of the combine function using nested loops:
(define (combine-cartesian fst cart)
(apply append
(for/list ([elem-fst fst])
(for/list ([elem-cart cart])
(cons elem-fst elem-cart)))))
To add a dimension, we consed every element of (first lists) onto every element of the cartesian product of the rest.
Pseudocode:
cartesian product <- takes in 0 or more lists to compute the set of all
ordered pairs
- cartesian product of no list is a list containing an empty list.
- otherwise: take the cartesian product of all but one list
and add each element of that one list to every
element of the cartesian product and put all
those lists together.

Adding two lists

I want to add two lists : (1 2 3) and (5 3 4) should yield (6 5 7).
The function should add the elements on the corresponding position, so even if I would have (9 1 2) + ( 5 2 6) , it should yield (14 3 8).
My function
(defun add(l r)
(setf return-value '())
(loop for i from 0 to (- (length l) 1)
do (setf return-value (cons (+(nth i l)(nth i r)) return-value))
)
(reverse return-value)
)
How could I create a simmilar function which would subtract the lists ?
If you are allowed to use the standard functions, then mapcar is your friend:
(mapcar #'+ '(1 2 3) (9 7 5))
==> (10 9 8)
Similarly for -.
Your function suffers from quadratic performance - you should not be using nth.
You should also bind return-value with let.
You should also use nreverse instead of reverse since you are constructing a fresh list anyway.
The more idiomatic way to write your function is
(defun addl (l r)
(loop for x in l and y in r collect (+ x y)))
Polynomial arithmetic
This seems like a follow up to your previous question, Decompose a list of numbers into digits,. There, you had a list of digits numbers, and they were the ai of a polynomial of the form
∑i=0… 10iai
where the n numbers in your list are the values of a0 to an-1, and everything after that is presumed to be zero. You were asking for a way to normalize the values such that each ai was in the range [0,9]. My answer to that question showed a few ways to do that.
Now, once you view numbers as a polynomial of this form, it's easy to see that you can simply piecewise add and subtract coefficients to the get the right, if not yet normalized, coefficients of the sum or difference. E.g.,
378 = 8 + 7×10 + 3×100&rightarrow; (8 7 3)
519 = 9 + 1×10 + 5×100&rightarrow; (9 1 5)
The sum is simply
(8+9) + (7+1)×10 + (3+5)×100 &rightarrow;(mapcar '+ x y) (17 8 8) &rightarrow;(number->digits (digits->number …)) (7 9 8)
The difference is simply
(8-9) + (7-1)×10 + (3-5)×100 &rightarrow;(mapcar '- x y) (-1 6 -2) &rightarrow;??? ???
What we don't have here is an appropriate normalization procedure. The one provided in the previous question doesn't work here. However, the list of digits is still correct, insofar as coefficients go, and the digits->number procedure produces the correct value of -141.
So, while you'll need to rethink what it means to show a list of digits for a negative number, you can do the correct type of addition and subtraction on your lists with the following, as long as both lists have the same length. If they don't have the same length, you'll need to pad the shorter one with zeros. A reimplementation of mapcar that supports this sort of operation might be useful here.
(defun sum (x y)
(mapcar '+ x y))
(defun difference (x y)
(mapcar '- x y))

Why does using cons to create a pair of two lists produce a list and two elements?

I've started learning Scheme, for fun mostly, and because I've never used a functional language before. I chose Scheme because I wanted to read SICP for a long time.
Anyway, I'm currently learning about lists, and before that I learned about cons, car and cdr. And there's an example that creates a list of lists with cons, like this :
(cons (list 1 2) (list 3 4))
The resulting list is ((1 2) 3 4), which doesn't make sense to me, I would expect ((1 2)(3 4)) to be the result (a list made out of two lists). Why does it behave like that? I realize that if I were to use car, I would get (1 2), and cdr I'd get (3 4) becaue cdr always returns "the rest", but I don't understand why the list isn't made of two lists?
You get a list with (1 2) as the first element (the car) and (3 4) as the rest (the cdr) because the first argument to cons is the first element of the list and the second argument is a list containing the remaining items.
This closely resembles the structure of a list: each node of a (proper) list contains an element and a list containing all other element. cons creates one such node.
If the second argument to cons would become the second element of the list, how would you create a list with three arguments? You'd have to make cons variardic at which point, it'd just be another name for list.
If you want to create a list of lists use (list (list 1 2) (list 3 4)).
(list (list 1 2)
(list 3 4))
is the same as
(cons (list 1 2)
(cons (list 3 4)
'()))
Which results in
((1 2) (3 4))
which can also be written as
((1 . (2 . ()))
.
((3 . (4 . ()))
.
()))
list A: [ | ]
1 [ | ]
2 /
list B: [ | ]
3 [ | ]
4 /
======================
(cons A B)
[ | ]
[ | ] [ | ]
1 [ | ] 3 [ | ]
2 / 4 /
A graphic representation of the inner structures can help us to visualize the problem.
And this will help some more:
[ | ]
X [ | ]
3 [ | ]
4 /
Do you see the pattern? The above is the list (X 3 4). That's the reason (cons A B) draws only the car part as a separate list and not the cdr.
Because a cons-cell is not a list of two elements, the two are often confused. If (a . b) is a cons cell, then (a . (b . ())) is a list of two elements. Any list safe the empty list specifically is a cons cell whose car field contains the first element and whose cdr field contains the list which contains the remaining elements. A list is thus simply a binary tree whose right-most leaf is the special constant () or nil depending on your dialect.
Which is why (cons 0 '(1 2 3)) evaluates to (0 1 2 3) and not (0 (1 2 3)) we create a cons cell whose car is 0, and whose cdr is (1 2 3), so a list (0 1 2 3).
Here's a really simple explanation:
(define (x)
(cons (list 1 2) (list 3 4)))
we know that these two conditions must be true:
(car x) = (1 2) #car = first element
(cdr x) = (3 4) #cdr = rest of the elements
the only way to satisfy this is x = ((1 2) 3 4).
________________________________________________________________________________________________________
x = ((1 2)(3 4)) is incorrect because:
(car x) = (1 2)
(cdr x) = ((3 4))
See there is an extra bracket/list created for (cdr x).
x = ((1 2)(3 4)) is actually a list of lists:
list( list(1 2) list(3 4)) = ((1 2)(3 4))