So I have a problem I'm trying to solve.
Write a function called parity that takes four numbers, where each
number is either 0 or 1, and produces another number that is either 0 or 1. Your function should produce 1 if there are an odd number
of ones in the input numbers and 0 if there are an even number of ones.
I'm trying to do this in a roundabout way using the map function, currently sitting at
(define (parity a b c d)
(map (lambda (thing)
(positive? thing))
'(a b c d)))
Then I would like to somehow create a new list using only the positive numbers, then find the length, then equate that to a 0 or a 1. However, my code doesn't work after I define it due to the positive? searching for a number and finding an a.
First error is already mentioned in comments- instead of '(a b c d), use (list a b c d) to get values of symbols.
There are two ways to get desired output and you don't need map in any of them:
I can follow your process of thinking and use exactly these functions:
create a new list using only the positive numbers -> filter
then find the length -> length
then equate that to a 0 or a 1. -> odd?/even? length or modulo
(define (parity a b c d)
(let* ((only-positive (filter positive? (list a b c d)))
(len (length only-positive)))
(if (odd? len) 1 0)))
This can be shortened to
(define (parity a b c d)
(if (odd? (length (filter positive? (list a b c d)))) 1 0))
And note, that problem description almost exactly matches this solution: if (odd (number of (ones in the input numbers))) 1 0.
Shorter solution with apply:
(define (parity a b c d)
(modulo (apply + (list a b c d)) 2))
Related
How can I make the GCD of a list of numbers in LISP? I want to calculate the Greatest Common Divisor of a given input list.
Common Lisp has a gcd function which takes any number of arguments. So one way is to use that function and apply in an obvious way.
That's a fairly bad way though. A better way is to rely on the fact that GCD is an associative function. This means that gcd(a, gcd(b, c)) = gcd(gcd(a, b), c). That leads you to a very neat approach for computing the gcd of arbitrary length lists:
Given a list l, and a current gcd g, then
if l is empty the result is g;
if l is not empty then it is of the form (a . r), and the result is now the gcd of r using a current value of gcd(g, a).
As an additional trick: once you've got 1 as the current value, you can stop.
If you are required to write the two argument function, here are two implementations which work for non-zero natural numbers:
(defun gcd/euclidean (a b)
(declare (type (integer 0) a b))
(cond
((= a 0) b)
((= a b) a)
((> a b) (gcd/euclidean (mod a b) b))
(t (gcd/euclidean b a))))
(defun gcd/euclid (a b)
(declare (type (integer 1) a b))
(cond
((= a b) a)
((> a b) (gcd/euclid (- a b) b))
(t (gcd/euclid b a))))
One of these is much better than the other!
I want to count the elements in a list and return a list containing the elements paired with them respective quantity
Something like that:
Input:
(count-elements '(a b d d a b c c b d d))
Output:
((a 2) (b 3) (d 4) (c 2))
How can I do it? I'm not having any success trying to pair the element and its accounting
Your problem can be divided into three broad parts:
Duplicate recognition/ deletion : This can be done by either removing all the duplicates of every element, or by knowing that the current element is a duplicate(and thus not counting it as a new element.). This(the former strategy) can be done by using the function remove-duplicates
Counting: A way to actually count the elements. This can be done by the function count
Combination: A way to combine the results into a list. This can be done by the macro push.
The Code:
(defun count-elements (lst)
(loop for i in (remove-duplicates lst)
with ans = nil
do (push (list i (count i lst)) ans)
finally (return ans)))
CL-USER> (count-elements '(a a b c))
((C 1) (B 1) (A 2))
CL-USER> (count-elements '(a b c d d a b s a c d))
((D 3) (C 2) (A 3) (S 1) (B 2))
CL-USER>
NOTE: The result might not be arranged as you would expect, because of the value returned by remove-duplicates
EDIT: As pointed out by coredump, a better version of count-elements would be:
(defun count-elements (lst)
(map 'list
(lambda (e)
(list e (count e lst)))
(remove-duplicates lst)))
which, instead of using loop, uses map.
I was asked in an internship interview to do a R5RS program that creates a function, let's say two-subsets. This function has to return #t if the list L contains two subsets with equal sums of elements and with equal numbers of elements, otherwise it returns #f. It takes in entry the list L (only positive numbers) and some parameters (that I judge useful. There is no conditions on the number of parameters) all equal to 0 at the beginning.
The requirements as I still remember were as follow:
- Do not define other functions and call them inside the "two-subsets" function.
- It can only use the following constructs: null?, cond, car, cdr, else, + ,=, not, and, #t, #f, two-subsets (itself for recursive call), the names of the parameters, such as list, sum, ...etc, numeric constants and parentheses.
There were some given examples on the results that we are supposed to have, let's say:
(two-subsets '(7 7) 0 0 0) returns #t. The two subsets are {7} and {7}.
(two-subsets '(7 7 1) 0 0) returns #t. The two subsets are {7} and {7}.
(two-subsets '(5 3 2 4) 0 0) returns #t. The two subsets are {2, 5} and {3, 4}.
(two-subsets '(1 2 3 6 9) 0 0) returns #f.
I started by writing the signature that it looks to me it should be something like this:
(define two-subsets (lambda (L m n ... other parameters)
(cond
The problem is really complicated and it's complexity is obviously more than O(n), I read on it on https://en.wikipedia.org/wiki/Partition_problem .
I tried to start by defining the algorithm first before coding it. I thought about taking as parameters: sum of the list L so in my conditions I'll iterate only on the combinations which sum is <= sum(L)/2. By doing that I can reduce a little bit the complexity of the problem, but still I couldn't figure out how to do it.
It looks like an interesting problem and I really want to know more about it.
Here is a version which does not depend on the numbers being all positive. I am reasonably sure that, by knowing they are, you can do much better than this.
Note this assumes that:
the partition does not need to be exhaustive;
but the sets must not be empty.
I'd be very interested to see a version which relies on the elements of the list being +ve!
(define (two-subsets? l sl sld ssd)
;; l is the list we want to partition
;; sl is how many elements we have eaten from it so far
;; sld is the length difference in the partitions
;; ssd is the sum difference in the partitions
(cond [(and (not (= sl 0))
(= sld 0)
(= ssd 0))
;; we have eaten some elements, the differences are zero
;; we are done.
#t]
[(null? l)
;; out of l, failed
#f]
;; this is where I am sure we could be clever about the set containing
;; only positive numbers, but I am too lazy to think
[(two-subsets? (cdr l)
(+ sl 1)
(+ sld 1)
(+ ssd (car l)))
;; the left-hand set worked
#t]
[(two-subsets? (cdr l)
(+ sl 1)
(- sld 1)
(- ssd (car l)))
;; the right-hand set worked
#t]
[else
;; finally drop the first element of l and try the others
(two-subsets? (cdr l) sl sld ssd)]))
I want to give a number and return the element of this position.
List lab = (R K K K K) and I want to know if something like this (position 1 lab) exists on lisp. Like in C return lab[1].
In Common Lisp the operator that gets the n-th element of a list is called nth (see the manual):
(nth 2 '(a b c d)) ; returns C
A related operator is nthcdr that returns the rest of the list starting from the n-th element:
(nthcdr 2 '(a b c d)) ; returns (C D)
For an operator that works on vectors and proper lists, see elt.
(let ((list (list 'a 'b 'c 'd)))
(prog1 list
(setf (elt list 1) 1)))
=> (A 1 C D)
I have been slowly learning Lisp over the past 2 weeks. I have come across a situation where Lisp performs two Loops in parallel, and is not what I am aiming for. If I understand correctly, what I want to achieve would be categorized as sequentially. To give you an idea of what happens, we can take a look at the following:
(loop for x in '(a b c d e)
for y in '(1 2 3 4 5)
collect (list x y))
With this type of coding, one will get:
((A 1) (B 2) (C 3) (D 4) (E 5))
But what I am seeking is:
((A 1) (A 2) (A 3) (A 4) (A 5) (B 1) (B 2) (B 3) and so on
What would I need to change with the Loop to get this type of desired result?
If I am wrong in the usage of the term "sequentially", please correct me. I have been reading up on it, but I am having a bit of a hard time grasping this.
You need nested loops:
(loop for x in '(a b c d e)
nconc (loop for y in '(1 2 3 4 5)
collect (list x y)))