LISP : Counting Sub strings to check occurrences - lisp

(defun count-sub (str pat)
(loop with z = 0 with s = 0 while s do
(when (setf s (search pat str :start6 s))
(incf z) (incf s (length pat)))
finally (return z))))
Right so i have this code for counting sub strings but it will only take to sub string inputs at a time, how do i get it to take in more inputs ?
I.e. so the input would be like:
(count-sub "abcde" "a" "d" "e" "c")
instead of just:
(count-sub "abcd" "a")

I would have it so that the unary function has a different name:
(defun count-sub-1 (str pat)
(loop with z = 0 with s = 0 while s do
(when (setf s (search pat str :start2 s)) ;; :start6 typo fixed
(incf z) (incf s (length pat)))
finally (return z))))
Then the N-ary API function is just a reduce job over this:
(defun count-sub (str &rest patterns)
(reduce #'+ patterns :key (lambda (item) (count-sub-1 str item))))
Some tests:
(count-sub "aabc") -> 0
(count-sub "aabc" "a") -> 2
(count-sub "aabc" "a" "a") -> 4
(count-sub "aabc" "b") -> 1
(count-sub "aabc" "a" "b") -> 3
You have a bug in your logic, however. If a pattern is the empty string, you get an infinite loop, because (incf s (length pat)) doesn't change the value of s:
(count-sub "abc" "") -> #<non-termination!>
A possible fix is:
(incf s (min (length pat) 1))
to always advance by at least one character, in the event of a zero length match. In this case, the empty string will match numerous times in the target string; if that is undesirable (you want an empty pattern to result in zero) then a check has to be put against that:
(if (plusp (length pat))
(loop ...)
0)
Then the (min (length pat) 1) compensation is unnecessary.

Related

How to modify list inside a function

(defun list-parser (list count)
...);;this function reads items by count from list and do some process to them.
;;i.e.convert items read from code to char, or to other things and then return it.
;;Also, the items in list should be consumed, globally.
(defmethod foo ((obj objtype-2) data-list)
(setf (slot-1 obj) (read-list data-list 1))
obj)
(defmethod foo ((obj objtype-1) data-list)
(setf (slot-1 obj) (read-list data-list 1)
(print data-list)
(slot-2 obj) (read-list data-list 2)
(print data-list)
(slot-3 obj) (foo (make-instance 'objtype-2) data-list)
(print data-list)
(slot-4 obj) (read-list data-list 3))
obj)
How to let it work like this:(read-list just works like read-byte in some way:
1.return a value read(and parsed here)
2.change the stream position(here the list)).
(let ((obj)
(data))
(setf data '(1 2 3 4 5 6 7 8)
obj (foo (make-instance 'objtype-1) data))
(print data))
>>(2 3 4 5 6 7 8)
>>(4 5 6 7 8)
>>(5 6 7 8)
>>(8)
Or rather, how do you deal with this kind of task? Do you convert list to other type?
I am not quite sure what you are after, but here is a function which creates a 'list reader' object (just a function). A list reader will let you read chunks of a list, treating it a bit like a stream.
(defun make-list-reader (l)
;; Make a list reader which, when called, returns three values: a
;; chunk of list, the length of tha chunk (which may be less than
;; how much was asked for) and the remaining length. The chunk is
;; allowed to share with L
(let ((lt l)
(len (length l)))
(lambda (&optional (n 1))
(cond
((zerop len)
(values nil 0 0))
((< len n)
(values lt len 0))
(t
(let ((it (subseq lt 0 n)))
(setf lt (nthcdr n lt)
len (- len n))
(values it n len)))))))
(defun read-from-list-reader (r &optional (n 1))
;; Read from a list reader (see above for values)
(funcall r n))
And now:
(defvar *l* (make-list-reader '(1 2 3)))
*l*
> (read-from-list-reader *l* 1)
(1)
1
2
> (read-from-list-reader *l* 2)
(2 3)
2
0
> (read-from-list-reader *l* 10)
nil
0
0
What you can't really do is write a function (not actually a function of course since it modifies its argument) which works like this while modifying its argument list. So you can write a function which will do this:
> (let ((l (list 1 2)))
(values (read-from-list l)
l))
(1)
(2)
which works by modifying the car and cdr of the first cons of l as you'd expect. But this can't work when there is no more to read: l is a cons and nil isn't a cons, so you can't ever make l nil with a function.
But in any case such a function is just a mass of traps for the unwary and generally horrid: for instance your example would involve modifying a literal, which isn't legal.

How do I append a list recursively in common lisp?

(defun foo (in i out)
(if (>= i 0)
(progn
(append (list (intern (string (elt in i)))) out)
(print output)
(foo in (- i 1) out )
)
(out)
)
)
(print (foo "abcd" (- (length "abcd") 1) (list)))
I am trying to return this string as (a b c d). But it does return nil as output. What do I do wrong here? Thanks
I don’t know what this has to do with appending. I think your desired output is also weird and you shouldn’t do what you’re doing. The right object for a character is a character not a symbol. Nevertheless, a good way to get the list (a b c d) is as follows:
CL-USER> '(a b c d)
Interning symbols at runtime is weird so maybe you would like this:
(defconstant +alphabet+ #(a b c d e f g h i j k l m n o p q r s t u v w x y z))
(defun foo (seq)
(map 'list
(lambda (char)
(let ((index (- (char-code char) (char-code #\a))))
(if (< -1 index (length +alphabet+))
(svref +alphabet+ index)
(error "not in alphabet: ~c" char))))
seq))
You have just some minor mistakes. First, we need to get rid of output and (output); these bear no relation to the code. It seems you were working with a variable called output and then renamed it to out without fixing all the code. Moreover, (output) is a function call; it expects a function called output to exist.
Secondly, the result of append must be captured somehow; in the progn you're just discarding it. Here is a working version:
(defun foo (in i out)
(if (>= i 0)
(foo in (1- i) (cons (intern (string (elt in i))) out))
out))
Note also that instead of your (append (list X) Y), I'm using the more efficient and idiomatic (cons X Y). The result of this cons operation has to be passed to foo. The out argument is our accumulator that is threaded through the tail recursion; it holds how much of the list we have so far.
I.e. we can't have (progn <make-new-list> (foo ... <old-list>)); that just creates the new list and throws it away, and then just passes the old list to the recursive call. Since the old list initially comes as nil, we just keep passing along this nil and when the index hits zero, that's what pops out. We need (foo .... <make-new-list>), which is what I've done.
Tests:
[1]> (foo "" -1 nil)
NIL
[2]> (foo "a" 0 nil)
(|a|)
[3]> (foo "ab" 1 nil)
(|a| |b|)
[4]> (foo "abcd" 3 nil)
(|a| |b| |c| |d|)
[5]> (foo "abcd" 3 '(x y z))
(|a| |b| |c| |d| X Y Z)
Lastly, if you want the (|a| |b| |c| |d|) symbols to appear as (a b c d), you have to fiddle withreadtable-case.
Of course:
[6]> (foo "ABCD" 3 nil)
(A B C D)

error in dr Racket problem. unbound identifier in mymeber

trying to do a dr racket problem to tell if a number is apart of list. getting errors
#lang racket
(mymember (x, l))
if l=?null
then "false"
if x==car(l)
then "true"
mymember(x,l)
mymember 2' (1,3,4,5,6)
Racket uses prefix notation. This makes commas unnecessary. First, some syntax:
How to define a function?
( define ( name variable1 variable2 ) body )
Where name is the name of the function, and the variables are the parameters. Which are followed by the body expression.
Example:
; Number -> Number
; converts from fahrenheit to celsius.
(define (f2c f)
(* 5/9 (- f 32)))
How to call a function?
( name expression1 expression2 )
name is the name of the function and expression1 and expression2 are its arguments.
Example:
(sqr 3)
;; == 9
Similarly, to check if two values are equal: (equal? x y)
How to use the if expressions?
( if question-expression then-answer-expression else-answer-expression )
If the value of the question-expression is not false, the if evaluates the then-answer-expression, otherwise it evaluates the else-answer-expression.
Example:
;; Number -> Number
;; reciprocate all non-zero x, otherwise return 0.
(define (inverse-of-x x)
(if (= x 0) 0 (/ 1 x)))
... and so on. Read the Racket Guide for the essentials on syntax, semantics and datatypes in the language.
Fixing all the syntax still leads to one error: an infinite loop. That is because the recursive call doesn't call cdr on the list. So the recursive call is made on the same list (not a shorter list) forever. Wrapping a cdr and fixing the syntax leads to a correct function.
#lang racket
; [X] [List-of X] -> "true" U "false"
; is x an element of l?
(define (mymember x l)
(if (equal? l null)
"false"
(if (equal? x (car l))
"true"
(mymember x (cdr l)))))
(mymember 2 '()) ; = false
(mymember 2 '(1 3 4 5 6)) ; = false
(mymember 2 '(1 3 2 5 6)) ; = true

Converting list of strings to list of ints in Common Lisp

I have a line like "fun,arg1,arg2" <- it is a string
I split this string into list of strings by "," separator. Then I compare "fun" with some string (e.g. "Fibonacci").
Function for splitting (works fine)
(defun split-str (string &optional (r nil))
(let ((n (position "," string
:from-end t
:test #'(lambda (x y)
(find y x :test #'string=)))))
(if n
(split-str (subseq string 0 n)
(cons (subseq string (1+ n)) r))
(cons string r))))
Test function
(defun tmp (a)
(if (string= (nth 0 a) "Fibonacci")
(progn
(setf tab '())
(dolist (n (cdr a))
(cons tab '(parse-integer n))) ; parsing works fine (checked with write)
(write tab)) ; always NIL
;(apply #'parse-integer (apply #'values a)) - doesn't work
(write "nok")))
Calling:
(tmp (split-str "Fibonacci,15,33"))
Why my tab hasn't 2 elements?
cons doesn't change anything; it returns a new list using tab.

How to create list of lists from one single list with odd and even pair in common lisp

I am new in Lisp programming and trying to create sublists from one single list in lisp with pair of odd and even from the list. for example:
I have a list
ListA ("a" "b" "c" "d" "e" "f" "g" "h")
now I want to convert into the following list:
enter code here
ListB ( ("a" "b") ("c" "d") ("e" "f") ("g" "h") )
so always sublist will be generated with the value of ( (first second) (third fourth) (fifth sixth) ............)
I have tried with mutiple ways for example first take out odd item and even item separate and used the function (list (oddlist evenlist)) but not getting above expected values in the above ListB.Could someone please help me in this regard. Your help would be highly appreciated.
This is actually very short with loop:
(loop for (x y) on '(a b c d e f) by #'cddr
collect (list x y))
;=> ((A B) (C D) (E F))
This does give you a NIL in the last pair if you have an odd number of elements, but you didn't mention what should happen in that case:
(loop for (x y) on '(a b c d e f g ) by #'cddr
collect (list x y))
;=> ((A B) (C D) (E F) (G NIL))
You need to make a procedure that does the following:
handle when argument is (). Usually the result is ()
default case you handle one chain of two. eg. (cons (list "a" "b") recursive-call-here)
So the result of '("g" "h") becomes (cons (list "g" "h") ()) and if you add that to recursive-call-here backwards you end up with:
(cons (list "a" "b")
(cons (list "c" "d")
(cons (list "e" "f")
(cons (list "g" "h") ()))))
; ==> (("a" "b") ("c" "d") ("e" "f") ("g" "h"))
If you already have the even elements separated from the odd ones as you seemed to suggest, the next step would be:
(mapcar #'list evenlist oddlist)
Which one comes first, evenlist or oddlist, depends on whether you started counting from 0 or 1.
Or, the whole problem can be tackled with a single loop expression:
(loop for head = '(a b c d e f g h i j k l m n o p) then (cddr head)
until (null head)
if (= (length head) 1) collect head
else collect (subseq head 0 2))