Linear Search in Lisp, array errors - lisp

Simple Linear Search for an Input Parameter, cannot use built in functions like find, etc.
Unfortunately, I can't find a lot of appropriate documentation as it's either outdated and most don't cover a problem this simple.
Tips on understanding lisp are much appreciated.
(defun search(numray x)
(defvar i 0)
(loop for i in numray
(cond
((= x (aref numray i) "Element is present in array")
((/= x (aref numray i) "Element is not present in array")
(t "iddunno")))))
)
(setf numray (make-array '(10)
:initial-contents '(0 11 2 33 44 55 66 7 88 99)))
(defvar x (read))
(search arr x)
Check defined array for an input variable. State whether it exists or not.

(defun search(numray x)
(defvar i 0)
(loop for i in numray
(cond
((= x (aref numray i) "Element is present in array")
((/= x (aref numray i) "Element is not present in array")
(t "iddunno")))))
)
(setf numray (make-array '(10)
:initial-contents '(0 11 2 33 44 55 66 7 88 99)))
(defvar x (read))
(search arr x)
The first thing you need to learn about Lisp is to indent your code according to the list structure:
(defun search (numray x)
(defvar i 0)
(loop for i in numray
(cond
((= x (aref numray i) "Element is present in array")
((/= x (aref numray i) "Element is not present in array")
(t "iddunno")))))
)
(setf numray (make-array '(10)
:initial-contents '(0 11 2 33 44 55 66 7 88 99)))
(defvar x (read))
(search arr x)
Next:
DEFVAR is for global variables, not local ones
you don't need to declare i, since LOOP declares it
you need to write a DO before the iteration forms in a LOOP
the parentheses around the call to = are wrong
the parentheses around the call to /= are wrong
a vector can easily be written as #(1 2 3 4 5)
put * around a global variable
don't name your function search, because that function is already built-in
IN works for lists, use ACROSS for vectors
Example:
CL-USER 3 > (defun note-num-in-array (vector number)
(loop for item across vector do
(print (if (= number item)
"Element is present in array"
"Element is not present in array"))))
NOTE-NUM-IN-ARRAY
CL-USER 4 > (note-num-in-array #(1 2 3 1 2 4 5 4 3 2) 2)
"Element is not present in array"
"Element is present in array"
"Element is not present in array"
"Element is not present in array"
"Element is present in array"
"Element is not present in array"
"Element is not present in array"
"Element is not present in array"
"Element is not present in array"
"Element is present in array"
NIL

Related

Racket, split a list in two different size lists. And randomly

I would like to code a program that given a list and a percentage, splits the list in two different size lists. It should have random pick of the elements, that way the created lists are always different.
These code is able to do that:
(define (clamp x a b)
(max (min x b) a))
(define (split pct xs)
(define pos (exact-round (* (clamp pct 0.0 1.0) (length xs))))
(split-at (shuffle xs) pos))
Here is an example:
(split 0.25 '(1 2 3 4 5 6 7 8 9))
'(6 2)
'(3 7 1 4 5 8 9)
But, instead of "shuffle" I would like to use this function to achieve the same:
(define (get-randomly-no-pair list)
(list-ref list (random (length list))))
so, get-randomly-no-pair takes one element randomly from the initial list. And all the elements are used to create both lists.
(define (shuffle-list lst)
(define indexes (shuffle (range (length lst))))
(lambda ()
(begin0
(list-ref lst (car indexes))
(set! indexes (cdr indexes)))))
(define gen (shuffle-list (list 10 12 14 16 18 20))
(gen) ; ==> 14 (e.g.)
Now I see you assume you need to pass the list then I would rather make a mapper:
(define (shuffle-accessor len)
(define indexes (list->vector (shuffle (range len))))
(lambda (lst index)
(list-ref lst (vector-ref indexes index))))
(define lst3-ref (shuffle-accessor 3))
(lst3-ref '(1 2 3) 0) ; ==> 3 (e.g.)
(lst3-ref '(6 7 8) 0) ; ==> 8

Test if all elements of a list are different from each other

I have a list of lists and want to test if all elements are different from each other, i.e. equal should return nil for all combinations of list elements.
E.g.
(defparameter feld '((1 0 0 5 5 0)
(0 0 0 0 0 0)
(1 1 5 5 0 0)
(0 1 0 1 5 5)
(5 5 1 0 1 0)
(1 0 1 0 5 5)))
I thought of using reduce but as far as I understand it only tests the equality of neighbors, as would do a loop construct like:
(loop for i below (length feld)
for j from 1
if (equal (nth i feld) (nth j feld)) return t)
Is there a simple way using a standard construct which I do not see at the moment or do I have to create a recursive function?
The whole data structure represents a "board game" where every list is a line on the board and each element in the inside-lists is a value of this very field. The three numerical values (0, 1 and 5) are something like empty, Symbol A and Symbol B. A valid board cannot have two identical lines. This is why I want to identify those.
Basically, it is like remove-duplicates without removing. In the meantime I was thinking about something like this:
(defun duplicates-p (lst)
(cond ((null lst) '())
((member (car lst) (cdr lst)) t)
(t (duplicates-p (rest lst)))))
Something like this:
(defun unique (lsts &aux (h (make-hash-table :test 'equal)))
(loop :for lst :in lsts
:never (gethash lst h)
:do (setf (gethash lst h) t)))

Element not being added to list

(defparameter *todo* '("Conquer the world" "Bake cake"))
(defun how-many-items (list)
if (list
(1+ (how-many-items (cdr list)))
0))
(defun add-item (item)
(cons item *todo*)) ; Attempt to add an item to the todo list
(princ (how-many-items *todo*))
(princ '#\newline)
(add-item "Write a book")
(princ (how-many-items *todo*))
(princ '#\newline)
(princ (cdr *todo*))
(princ '#\newline)
I'm still learning Lisp but I can't understand why the size of the list doesn't add when I supposedly add the item "Write a book" to it, the cdr call returns "Bake Cake" and the number of items is always two.
The output is:
2
2
(Bake cake)
Your problem is that cons is non-destructive. This means that even though you're adding an item to the item to the list that *todo* contains, you're not modifying *todo*
> (defparameter x '(1 2 3))
(1 2 3)
> (cons 1 x)
(1 1 2 3)
> x
(1 2 3)
See? No modification.
Instead use push. It does modify its parameters.
> (defparameter x '(1 2 3))
(1 2 3)
> (push 1 x)
(1 1 2 3)
> x
(1 1 2 3)
You can think of push like this
(push x 1) === (setf x (cons 1 x))
In fact, it's a macro that expands to just this in some implementations.
Your output can't be real, since your function has wrong syntax.
(defun how-many-items (list)
if (list
(1+ (how-many-items (cdr list)))
0))
CL-USER 20 > (how-many-items '(1 2))
Error: The variable IF is unbound.

In common lisp, how can I check the type of an object in a portable way

I want to define a method that will specialize on an object of array type with unsigned byte 8 elements. In sbcl, when you (make-array x :element-type '(unsigned-byte 8)) the object class is implemented by SB-KERNEL::SIMPLE-ARRAY-UNSIGNED-BYTE-8. Is there an implementation independent way of specializing on unsigned-byte array types?
Use a sharpsign-dot to insert the implementation dependent object class at read-time:
(defmethod foo ((v #.(class-of (make-array 0 :element-type '(unsigned-byte 8)))))
:unsigned-byte-8-array)
The sharpsign-dot reader macro evaluates the form at read-time, determining the class of the array. The method will be specialized on the class the particular Common Lisp implementation uses for the array.
Notice that the :ELEMENT-TYPE argument to MAKE-ARRAY does something special and its exact behavior might be a bit surprising.
By using it, you are telling Common Lisp that the ARRAY should be able to store items of that element type or some of its subtypes.
The Common Lisp system then will return an array that can store these elements. It may be a specialized array or an array that can also store more general elements.
Notice: it is not a type declaration and it will not necessarily be checked at compile or runtime.
The function UPGRADED-ARRAY-ELEMENT-TYPE tells you what element an array may actually be upgraded to.
LispWorks 64bit:
CL-USER 10 > (upgraded-array-element-type '(unsigned-byte 8))
(UNSIGNED-BYTE 8)
CL-USER 11 > (upgraded-array-element-type '(unsigned-byte 4))
(UNSIGNED-BYTE 4)
CL-USER 12 > (upgraded-array-element-type '(unsigned-byte 12))
(UNSIGNED-BYTE 16)
So, Lispworks 64bit has special arrays for 4 and 8 bit elements. For 12 bit elements it allocates an array which can store up to 16bit elements.
We generate an array which can store ten numbers of upto 12 bits:
CL-USER 13 > (make-array 10
:element-type '(unsigned-byte 12)
:initial-element 0)
#(0 0 0 0 0 0 0 0 0 0)
Let's check its type:
CL-USER 14 > (type-of *)
(SIMPLE-ARRAY (UNSIGNED-BYTE 16) (10))
It is a simple array (non-adjustable, no fill pointer).
It can store elements of type (UNSIGNED-BYTE 16) and its subtypes.
It is of length 10 and has one dimension.
In a normal function you could use etypecase to do the dispatch:
The following code isn't self-contained but should give an idea how to implement
a function that does point-wise operations when the even for 3D arrays:
(.* (make-array 3 :element-type 'single-float
:initial-contents '(1s0 2s0 3s0))
(make-array 3 :element-type 'single-float
:initial-contents '(2s0 2s0 3s0)))
Here is the code:
(def-generator (point-wise (op rank type) :override-name t)
(let ((name (format-symbol ".~a-~a-~a" op rank type)))
(store-new-function name)
`(defun ,name (a b &optional (b-start (make-vec-i)))
(declare ((simple-array ,long-type ,rank) a b)
(vec-i b-start)
(values (simple-array ,long-type ,rank) &optional))
(let ((result (make-array (array-dimensions b)
:element-type ',long-type)))
,(ecase rank
(1 `(destructuring-bind (x)
(array-dimensions b)
(let ((sx (vec-i-x b-start)))
(do-region ((i) (x))
(setf (aref result i)
(,op (aref a (+ i sx))
(aref b i)))))))
(2 `(destructuring-bind (y x)
(array-dimensions b)
(let ((sx (vec-i-x b-start))
(sy (vec-i-y b-start)))
(do-region ((j i) (y x))
(setf (aref result j i)
(,op (aref a (+ j sy) (+ i sx))
(aref b j i)))))))
(3 `(destructuring-bind (z y x)
(array-dimensions b)
(let ((sx (vec-i-x b-start))
(sy (vec-i-y b-start))
(sz (vec-i-z b-start)))
(do-region ((k j i) (z y x))
(setf (aref result k j i)
(,op (aref a (+ k sz) (+ j sy) (+ i sx))
(aref b k j i))))))))
result))))
#+nil
(def-point-wise-op-rank-type * 1 sf)
(defmacro def-point-wise-functions (ops ranks types)
(let ((specific-funcs nil)
(generic-funcs nil))
(loop for rank in ranks do
(loop for type in types do
(loop for op in ops do
(push `(def-point-wise-op-rank-type ,op ,rank ,type)
specific-funcs))))
(loop for op in ops do
(let ((cases nil))
(loop for rank in ranks do
(loop for type in types do
(push `((simple-array ,(get-long-type type) ,rank)
(,(format-symbol ".~a-~a-~a" op rank type)
a b b-start))
cases)))
(let ((name (format-symbol ".~a" op)))
(store-new-function name)
(push `(defun ,name (a b &optional (b-start (make-vec-i)))
(etypecase a
,#cases
(t (error "The given type can't be handled with a generic
point-wise function."))))
generic-funcs))))
`(progn ,#specific-funcs
,#generic-funcs)))
(def-point-wise-functions (+ - * /) (1 2 3) (ub8 sf df csf cdf))

Is there a common lisp macro for popping the nth element from a list?

I'm pretty fresh to the Common Lisp scene and I can't seem to find an quick way to get the nth element from a list and remove it from said list at the same time. I've done it, but it ain't pretty, what I'd really like is something like "pop" but took a second parameter:
(setf x '(a b c d))
(setf y (popnth 2 x))
; x is '(a b d)
; y is 'c
I'm pretty sure that "popnth" would have to be a macro, in case the parameter was 0 and it had to behave like "pop".
EDIT: Here's my crap first version:
(defmacro popnth (n lst)
(let ((tempvar (gensym)))
`(if (eql ,n 0)
(pop ,lst)
(let ((,tempvar (nth ,n ,lst)))
(setf (cdr (nthcdr ,(- n 1) ,lst)) (nthcdr ,(+ n 1) ,lst))
,tempvar))))
Something like this:
Removing the nth element of a list:
(defun remove-nth (list n)
(remove-if (constantly t) list :start n :end (1+ n)))
constantly returns a function, that always returns its argument.
As a macro that accepts a place, using define-modify-macro:
(define-modify-macro remove-nth-f (n) remove-nth "Remove the nth element")
POP-NTH
(defmacro pop-nth (list n)
(let ((n-var (gensym)))
`(let ((,n-var ,n))
(prog1 (nth ,n-var ,list)
(remove-nth-f ,list ,n-var)))))
Example:
CL-USER 26 > (defparameter *list* (list 1 2 3 4))
*LIST*
CL-USER 27 > (pop-nth *list* 0)
1
CL-USER 28 > *list*
(2 3 4)
CL-USER 29 > (pop-nth *list* 2)
4
CL-USER 30 > *list*
(2 3)
Yes, Lisp has a macro for popping the N-th element of a list: it is called pop.
$ clisp -q
[1]> (defvar list (list 0 1 2 3 4 5))
LIST
[2]> (pop (cdddr list))
3
[3]> list
(0 1 2 4 5)
[4]>
pop works with any form that denotes a place.
The problem is that, unlike cddr, nthcdr isn't an accessor; a form like (nthcdr 3 list) does not denote a place; it works only as a function call.
Writing a specialized form of pop is not the best answer; rather, we can achieve a more general fix by writing a clone of nthcdr which behaves like a place accessor. Then the pop macro will work, and so will every other macro that works with places like setf and rotatef.
;; our clone of nthcdr called cdnth
(defun cdnth (idx list)
(nthcdr idx list))
;; support for (cdnth <idx> <list>) as an assignable place
(define-setf-expander cdnth (idx list &environment env)
(multiple-value-bind (dummies vals newval setter getter)
(get-setf-expansion list env)
(let ((store (gensym))
(idx-temp (gensym)))
(values dummies
vals
`(,store)
`(let ((,idx-temp ,idx))
(progn
(if (zerop ,idx-temp)
(progn (setf ,getter ,store))
(progn (rplacd (nthcdr (1- ,idx-temp) ,getter) ,store)))
,store))
`(nthcdr ,idx ,getter)))))
Test:
$ clisp -q -i cdnth.lisp
;; Loading file cdnth.lisp ...
;; Loaded file cdnth.lisp
[1]> (defvar list (list 0 1 2 3 4 5))
LIST
[2]> (pop (cdnth 2 list))
2
[3]> list
(0 1 3 4 5)
[4]> (pop (cdnth 0 list))
0
[5]> list
(1 3 4 5)
[6]> (pop (cdnth 3 list))
5
[7]> list
(1 3 4)
[8]> (pop (cdnth 1 list))
3
[9]> list
(1 4)
[10]> (pop (cdnth 1 list))
4
[11]> list
(1)
[12]> (pop (cdnth 0 list))
1
[13]> list
NIL
[14]>
A possible improvement to the implementation is to analyze the idx form and optimize away the generated code that implements the run-time check on the value of idx. That is to say, if idx is a constant expression, there is no need to emit the code which tests whether idx is zero. The appropriate code variant can just be emitted. Not only that, but for small values of idx, the code can emit special variants based on the "cadavers": cddr, cdddr, rather than the general nthcdr. However, some of these optimizations might be done by the Lisp compiler and thus redundant.
I came up with a solution that is a little more efficient than my first attempt:
(defmacro popnth (n lst)
(let ((t1 (gensym))(t2 (gensym)))
`(if (eql ,n 0)
(pop ,lst)
(let* ((,t1 (nthcdr (- ,n 1) ,lst))
(,t2 (car (cdr ,t1))))
(setf (cdr ,t1) (cddr ,t1))
,t2))))
Here is it in action:
[2]> (defparameter *list* '(a b c d e f g))
*LIST*
[3]> (popnth 3 *list*)
D
[4]> *list*
(A B C E F G)
[5]> (popnth 0 *list*)
A
[6]> *list*
(B C E F G)
I have same suspicion as #6502...If I remember right...Neither push nor pop can be defined as modify-macros, the former because the place is not its first argument, and the latter because its return value is not the modified object.
Definition of define-modify-macro
An expression of the form (define-modify-macro m (p1 ... pn) f) defines a new macro m, such that a call of the form (m place a1 ... an) will cause place to be set to (f val a1 ... an), where val represents the value of place. The parameters may also include rest and optional parameters. The string, if present, becomes the documentation of the new macro.
I have this popnth works just fine:
(defun nthpop (index lst)
(pop (nthcdr (1- index) lst)))
> *list*
(1 2 3 4 5)
> (nthpop 2 *list*)
2
> *list*
(1 3 4 5)