Complex Loop Optimization - lisp

I have a function that takes a state and an action, and returns a new state that results from applying the received action in the original state.
My problem is I did code a complex loop that I would like to optimize it so that it will bring me a more clear function to read and more optimized.
I have this complex "pseudocode" loop part of that function source:
(loop for l from 0 upto (1- (array-dimension variable1 0)) do
(if (not (aref variable1 l 0))
(1+ max-height)
(return)))
What chance do I have to make this loop more simple and optimized?
The Loop Documentation and the DoTimes Documentation don't seems to me enough clear to make the changes on my code and I say sorry for that. Any explanation will be valuable to me.

Your original code probably had some errors, since there were syntax problems, array-dimension wasn't being called with the right number of arguments, etc., but your loop can easily be turned into a dotimes. It would be something like this (but note that you'll need to check whether you want to refer to array or object):
(dotimes (i (array-dimension array 0)) ; array here
(unless (aref object i 0) ; but object here?
(decf max-height)))
Based on the updates to the question, I think we can refine this a bit. From the code, we can tell that you expect to have a two dimension array of (generalized) booleans, and you're trying to count the true elements in the first column. Here's what such a board might look like:
(defparameter *board* #2A((nil t nil)
(t t t)
(t t t)))
Notice that there is one true value in its first row, and two true values in the first column. Now, you could write a dotimes loop to count the number of true values in the first column with something like this:
(let ((max-height 0))
(dotimes (i (array-dimension *board* 0) max-height)
(when (aref *board* i 0)
(incf max-height))))
;=> 2
However, I think that loop is actually cleaner here, if you take advantage of some of its features. You can use below instead of upto, and from defaults to 0, so you can omit it. You can use count to count true values, and then the value of the count is returned by default:
(loop for i below (array-dimension *board* 0)
count (aref *board* i 0))
;=> 2

Related

how to return the value of a prime number while trying to print the sum of prime numbers in a range of numbers from check-prime to prime-sum

I was working on this question to print the sum of prime numbers in a range of numbers. The range values will be be taken as an input from the user. I got the syntax errors all cleared out but could not figure out how to return the value of the prime no. to the sum if it is true.
(defun check-prime(num)
(if (= num 1) nil)
;(setq i 2)
(loop for i from 2 to ( isqrt num) do
(if (= (mod num i) 0) nil t)
(= i (+ i 1))
)
)
(defun prime-sum(*begin* *end*)
(defvar *s* 0)
(defvar *i* *end*)
(loop for *i* from *end* to *begin* do
;i= 13
(if (check-prime *i*)
(= *s* (+ *s* *i* ) )
)
(= *i* (- *i* 1))
)
(write *s*)
)
(defun vals()
(print "enter the range1: ")
(defvar *begin* (read))
(print "enter the range2: ")
(defvar *end* (read))
(prime-sum *begin* *end*)
)
(print(vals))
;b =4
;e 13
Here is your function, cleaned up a bit and formatted in a conventional way:
(defun check-prime(num)
(if (= num 1) nil)
(loop
for i from 2 to (isqrt num)
do
(if (= (mod num i) 0) nil t)
(= i (+ i 1))))
There are multiple things that are incorrect, and they boil down to how are Lisp forms evaluated.
There is a special form progn in Common Lisp that is used to evaluate a list of expressions, with the following pattern:
(progn E1 E2 ... EN)
A lot of other functions in Lisp are described has having "an implicit progn", that's the case for defun which allows for more than one expression in its body, but since the progn doesn't appear literally it is implicit. The behavior is however always the same: each expression E1 to EN is evaluated in sequence, and evaluation of the whole progn are the values returned by the last expression, EN (that's where the N comes from in the name). In other words, the intermediate values from E1 etc. are discarded, the expressions are only useful for their side-effects.
In your code, that's the case for (if (= num 1) nil), which is an expression in the body of defun which is not the last one, and which doesn't even have side-effects. It is thus completely useless.
Likewise, in the loop macro, all that follows the do keyword are expressions that are evaluated for their side effects and do not contribute to the resulting value of the whole loop form.
In fact, loop is a bit complicated but here your don't have any accumulating clause in your loop (something like collect, append, sum etc. that would compute a result). Instead, your loop will always return nil.
Note also that for i from 2 to (isqrt num) takes care of incrementing i, you don't have to do it yourself like you tried in the do. Moreover, = is a comparison operator, in order to mutate i you would need to use setf instead: (setf i (+ i 1)), or (incf i) (which I repeat is unnecessary here).
To combine the first two expressions, I would write:
(if (= num 1) nil ...)
Where ... is the loop: because if is a functional if, it evaluates to whichever branch is selected by the condition.
And inside the loop, I would use never:
(loop for i from 2 to (isqrt num) never (= 0 (mod num i)))
The never clause makes the loop compute a boolean and halt as soon as the result is false.

Questions about using recursive functions in lisp

I'm a beginner at lisp. I'm grateful that stackoverflow helped me a lot.
First, I want to express the recursive function using the lisp function.
There is no compilation error, but I want to check if the code I wrote is grammatically correct.
Below is the C code I wrote.
void queens(int i)
{
int j;
if (promising(i))
{
if (i == n)
{
//print all col list
return
}
else
{
for (j = 1; j <= n; j++)
{
col[i + 1] = j;
queens(i + 1);
}
}
}
}
Below is the lisp code.
(defvar n 4)
(defvar col (list 0 0 0 0 0 ))
(defun queens(i)
(let ((j 1))
(if (promising i)
(if (= i n) (print col)
(loop while (<= j n) do (setf (nth (+ 1 i ) col) j)
( queens (+ 1 i ) )
(incf j)))
)
))
First, you (still) need to fix the indentation, alignment, and general style. This is not merely to annoy you, but because it actually makes things clearer, and easier to debug. For example, if you do not indent properly, it becomes hard to see where each expression ends, and this is even worse when using complex macros such as loop. Your code, properly formatted but without any other modification, should be:
(defun queens (i)
(let ((j 1))
(if (promising i)
(if (= i n)
(print col)
(loop while (<= j n)
do (setf (nth (+ 1 i) col) j)
(queens (+ 1 i))
(incf j))))))
The closing parenthesis is placed right after the last form of the expression, without line break, without whitespace.
The opening parenthesis is also right before the first element of the form, without whitespace, but should be detached from what comes before, unless it is another parenthesis (so (defun queen (i) ...) is correct, while ( defun queens(i)) breaks two of the rules).
When using an if construct, either you write it all on a single line (the condition, the "then" form and the "else" form), or you have to insert line breaks after each of them. Otherwise, it is unclear when the "then" form ends and when the "else" starts.
When defining special variables with defvar, name them with '*' around their names, as in (defvar *n* 4) and (defvar *col* (list ...)).
Another style considerations, which helps with problems related to nesting: use when and unless instead of if if you are only interested in one of the two branches. This makes intent clear, and can also simplify the syntax in case of complex branches.
Now, for the code:
If you want to use loop, use the basic for constructs. Instead of writing
(loop while (< j n) do ... (incf j))
use
(loop for j from <start> to <end> do ...)
You can also use upto, below ... if you want subtly different termination conditions.
When you do this, you do not need to introduce a binding for j using let, it will be introduced by the loop.
If you want to modify a list, use a vector instead. Instead of defining col as (list ...), simply use (vector ...) or the make-array function. Afterwards, use elt or aref to access individual elements instead of nth which only works for lists. A version of the code which assumes that all the previous remarks have been taken into account:
(defun queens (i)
(when (promising i)
(if (= i n)
(print *col*)
(loop for j from 1 to *n*
do (setf (aref *col* (1+ i)) j)
(queens (1+ i))))))
Without knowing what promising does and what queens is supposed to do, it is hard to give more insight, but the algorithm is weird nonetheless. For example, in a given call to (queens i), the lexically apparent setf will only ever modify the i+1-th cell of col, setting it to a new j at each iteration. As far as I can tell, this simply results in (aref col (1+ i)) being set to n at the end of the loop. It also seems that you do not use the value recursively returned by queens (which is to be expected: your C function returns nothing !), and that you do not really do any check involving col, so a recursive solution seems weird, there is (seemingly) no relation between (queens i) and the (queens (1+ i)) that it calls n times in a loop !
If the above paragraph is irrelevant because promising also heavily modifies col: stop doing C-in-Lisp and stop modifying things all around the place. Don't rely on state, mutation, global variables & the like, when you can avoid it. It is easy to define recursive solution, to pass lists as arguments, to return several values ... and so it is generally unnecessary to use multiple functions, each of them calling the other ones, recursively modifying the shared global state. That's a mess and can't be debugged.

Common Lisp setf expansions for functions which access bits of integers

I am writing a program in Common Lisp which needs to store a bunch of status bits for a very large number of entries in an array (the whole program is pretty much fortran-in-lisp) and the status bits are encoded as bits in a fixnum sitting in this array. The accessors for these status bits are actually going to be defined by a macro so I don't have to care about allocating the bits, but a sample reader function might be
(defun deadp (e)
(logbitp 0 e))
(In real life this will be inlined and cluttered with declarations to try and make sure it's quick but those don't matter here I think.)
I need these things to be functions because I want to be able to map them, but also because the using-a-macro-to-inline-a-function thing makes me feel bad.
Then I'll be using this as something like this:
(defconstant status-index 3)
...
(dotimes (i nentries)
(unless (deadp (aref entries i status-index))
...))
(In real life (aref entries i status-index) will be (status entries i), which in turn is going to need a setf method but I think that's easy.)
or
(loop for i below nentries
counting (if (deadp entries i status-index) 1 0))
And of course there will be other similar single-bit flags which will have different bits associated with them.
So, now I want to be able to do this:
(dotimes (i nentries)
...
(when ...
(setf (deadp (aref entries i status-index) t)))
...)
which should turn into code equivalent to
(dotimes (i nentries)
...
(when ...
(progn
(setf (ldb (byte 1 0) (aref entries i status-index)) 1)
t))
...)
And also this:
(let ((status 0))
...
(when ...
(setf (deadp status) t))
...)
which should turn into code equivalent to this:
(let ((status 0))
...
(when ...
(progn
(setf (ldb (byte 1 0) status) 1)
t))
...)
In other words I want my deadp function to be an accessor and for setf on it to work in a general way for it: (setf (deadp (cdr x)) nil) should work, etc.
So this has dropped me into bits of CL that I've avoided for a long time: defining setf expanders. Pretty obviously just defining a (setf deadp) function won't work because numbers are immutable, and I'm fairly sure that defsetf is not powerful enough, so I need define-setf-expander, which I don't understand.
Can someone explain how I need to do this? I think the particular deadp function is not critical, although all the functions I care about will look like variants of it.
An alternative answer would be 'that's a braindead approach, instead do ...', and I'm open to those. I have considered writing code which abstracts the array away, so instead of (deadp (aref ...)) I'd write (deadp people ...) where people is the array of people. This would be fine, and it's easy to see how to make that setfable, except I also want to be able to say (deadp status) where status is just a fixnum. But perhaps there is some better approach.
According to the SBCL documentation for GET-SETF-EXPANSION, a setf expander must:
"Return five values needed by the SETF machinery: a list of temporary
variables, a list of values with which to fill them, a list of temporaries
for the new values, the setting function, and the accessing function."
The setting function and accessing function are actually just the forms that set and access the value at the place, not function objects.
Try this:
(define-setf-expander deadp (place)
(let ((new (gensym)))
(values nil nil (list new)
`(progn (setf (ldb (byte 1 0) ,place) (if ,new 1 0))
,new)
`(deadp ,place))))
Sample expansion:
(let ((status 1))
(setf (deadp status) t))
->
(let ((status 1))
(LET* ((#:G605 T))
(SETF (LDB (BYTE 1 0) STATUS)
(IF #:G605
1
0))
#:G605))

Number Partitioning in R5RS

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)]))

Define a syntax error in Lisp function

I am bad at Lisp. Help me please to find a syntax error. I need to write a function which swaps two elements in list. This function must consist loop-cycle. Here is what if have so far.
(defun swap-two-element(z x y)
(let ((newlist nil) (newlist2 nil) (copyz z) (copyz2 z) (newx nil))
(loop
(when (= (- (length z) (length copyz2)) y)
(return (set newx car z)))
(setq newlist2 (append newlist2(car copyz2))
copyz2 (cdr copyz2)))))
Call example: (swap-two-element '(a b c d) 2 3)
Replace the word set with the word values and you are good to go.
PS. You need to address the warnings though, and explain what the function is supposed to do so that we could help you with the algorithm.
You really need to tidy up your question. The title says nothing, the code is badly formatted and you really need to play around with loop to get started. I won't give you your solution since you need to learn this by trying. Here is an example you can make use of to do your assignment.
;; this orders a list by their odd index
;; NB: index starts at zero so first element is even
(defun order-odd-index (list)
(loop :for element :in list ; iterates your list
:for index :from 0 ; starts from 0 and goes on
:if (oddp index) ; if in a loop
:collect element :into odd-list ; variable is automatically created
:else ; else in a loop
:collect element :into even-list
:finally (return (append odd-list even-list)))) ; what to do in the end
(order-odd-index '(4 67 3 2 7 9)) ; ==> (67 2 9 4 3 7)
I use keywords (like :for instead of for) to indicate what symbols are loop keywords and what are not. It's optional but I think it looks a lot cleaner.
Now your problem can be solved with collecting element into 5 variables. Two of them is when index is equal to one of the places (given as arguments) to be switched the other 3 are before, in between and greater. In the finally you can just append those variables in the correct order and you're done.