lisp - function (OccurencesOfPrimes < list >) which counts the number of primes in a (possibly nested) list -
i working on problem occurence
of prime in list in lisp. input: write function (occurencesofprimes < list >
) counts number of primes in (possibly nested) list.
output: example: (occurencesofprimes (((1)(2))(5)(3)((8)3)) returns 4
.
i using below code getting error like:
( defun occurencesofprimes (list) (loop 2 100 ( setq isprime t) (loop j 2 never (zerop (mod j)) (setq isprime f) (break) ) ) (if (setq isprime t) (append list i) ) ) ) loop: illegal syntax near (setq isprime f) in (loop j 2 never (zerop (mod j)) (setq isprime f) (break)
)
any help.
it important keep format consistent expected conventions of language. helps when reading code (in particular other programmers), , can see errors.
also, should use editor which, @ minimum, keep tracks of parentheses. in emacs, when put cursor in first opening parenthesis, matching parenthesis highlighted. can spot have 1 additional parenthesis serves no purpose.
( defun occurencesofprimes (list) (loop 2 100 ( setq isprime t) (loop j 2 never (zerop (mod j)) (setq isprime f) (break) ) ) (if (setq isprime t) (append list i) ) ) ;; <- end of defun ) ;; <- closes nothing
in lisp, parentheses computer, whereas indentation humans. tools can automatically indent code according structure (the parenthesis), , discrepancy between indentation expect , 1 being computed hint code badly formed. if @ indentation of expressions, can see how deep in form, , alone helps understand code.
symbol names dash-separated
, not camlcased
.
your code, remarks:
(defun occurences-of-primes (list) ;; argument list, given name , way ;; call append below. never iterate on list. ;; suspicious. (loop 2 100 (setq is-prime t) ;; setting undeclared variable (loop j 2 never (zerop (mod j)) ;; following 2 forms not expected here according ;; loop's grammar; setting is-prime f, f not ;; existing variable. if want set false, use ;; nil instead. (setq is-prime f) ;; break enters debugger, maybe wanted use ;; loop-finish instead, never clause above should ;; enough exit loop ;; sub-expression evaluates nil. (break))) ;; return value of (setq x v) v, here test ;; succeed. (if (setq is-prime t) ;; append returns new list, without modifying ;; arguments. in particular, list not modified. note "i" ;; unknown @ point, because bindings effective ;; inside loop not visible in scope. besides, "i" ;; number, not list. (append list i)))
original question
write 1 function counts occurrences of prime number in (possibly nested) list.
even though homework questions says "write 1 function", not should write 1 big function compute @ once. could write 1 such big function, if split problem sub-problems, end different auxiliary functions, which:
- are simpler understand (they 1 thing)
- can reused build other functions
the sub-problems are, example: how determine if number prime? how iterate on tree (a.k.a. possibly nested list)? how count occurrences?
the basic idea write "is-prime" function, iterate on tree , call "is-prime" on each element; if element prime , never seen before, add 1 counter, local function.
you can flatten input tree, obtain list, sort resulting list; iterate on list while keeping track of last value seen: if value same previous one, know if number prime; if previous number differs, have test if number prime first.
you abstract things little more, , define higher-order tree-walker function, calls function on each leaf of tree. , write higher-order function "memoizes" calls: wraps around function f if call f same arguments before, returns result stored instead of recomputing it.
example
i'll combine above ideas because if give answer teacher have explain each part (and if can, great you); not "best" answer, covers lot of things.
(defun tree-walk-leaves (tree function) (typecase tree (null nil) (cons (tree-walk-leaves (car tree) function) (tree-walk-leaves (cdr tree) function)) (t (funcall function tree)))) (defun flatten (tree &optional keep-order-p) (let ((flat nil)) (tree-walk-leaves tree (lambda (leaf) (push leaf flat))) (if keep-order-p (nreverse flat) flat))) (defun prime-p (n) (or (= n 2) (and (> n 2) (oddp n) (loop d 3 upto (isqrt n) 2 never (zerop (mod n d)))))) (defun count-occurences-of-prime (tree) (count-if #'prime-p (remove-duplicates (flatten tree)))) (count-occurences-of-prime '(((1)(2))(5)(3)((8)3))) => 4
if, instead, don't want remove duplicates count multiple times prime number occurs, can do:
(count-if (memoize #'prime-p) (flatten tree))
... memoize
is:
(defun memoize (function &key (test #'equalp) (key #'identity)) (let ((hash (make-hash-table :test test))) (lambda (&rest args) (let ((args (funcall key args))) (multiple-value-bind (result exists-p) (gethash args hash) (values-list (if exists-p result (setf (gethash args hash) (multiple-value-list (apply function args))))))))))
(memoize useless if there no duplicates)
Comments
Post a Comment