Forming Lisp code to task -- related to flatten list method -
i'm having issues trying form code problem want resolve. goes this:
~ goal: flatten nested list 1 number
- if object list, replace list sum of atoms.
- with nested lists, flatten innermost lists first , work there.
example:
(condense '(2 3 4 (3 1 1 1) (2 3 (1 2)) 5)) (2 3 4 (6) (2 3 (3)) 5) (2 3 4 (6) (8) 5) (28) => 28 i've tried implement flatten list function problem , ended this:
(defun condense (lst) (cond ((null lst) nil) ((atom lst) (list lst))) (t (append (flatten (apply #'+ (cdr lst)))))) but gives me errors :(
could explain me wrong processing/code? how can improve it?
update: june 5 2012
(defun condense(lxt) (typecase lxt (number (abs lxt)) (list (if (all-atoms lxt) (calculate lxt) (condense (mapcar #'condense lxt)))))) so here, in code, true intent shown. have function calculate performs calculation based off values in list. not same operation each time. also, aware returning absolute value of number; did because couldn't find way return number itself. need find way return number if lxt number. , had recurse 2 times @ bottom, because 1 way loops on infinitely until computes single number. note: function doesn't implement flatten function anymore nor use it.
imagine have function already. get? must produce?
given atom, return? given simple list of atoms, should return?
(defun condense (x) (typecase x (number ; what? (condense-number x)) (list ; what? (if (all-atoms x) (condense-list-of-atoms x) ; how that? (process-further-somehow (condense-lists-inside x)))) ; other clauses, if any, must here? )) what must condense-lists-inside do? according description, condense nested lists inside - each a number, , leave atoms intact. leave list of numbers. process further somehow, "have" function, condense-list-of-atoms, right?
now, how implement condense-lists-inside? that's easy,
(defun condense-lists-inside (xs) (mapcar #'dowhat xs)) do what? why, condense, of course! remember, imagine have already. long gets it's meant get, shall produce designed produce. namely, given atom or list (with possibly nested lists inside), produce a number.
so now, fill in blanks, , simplify. in particular, see whether need all-atoms check.
edit: actually, using typecase unfortunate choice, treats nil list. need treat nil differently, return "zero value" instead. it's better use usual (cond ((null x) ...) ((numberp x) ...) ((listp x) ...) ... ) construct.
about new code: you've erred: process list of atoms returned after (mapcar #'condense x), have function calculate that, no need go far condense itself. when substitute calculate there, become evident check all-atoms not needed @ all; pedagogical device, ease development of code. :) ok make superfluous choices when develop, if simplify them away, after we've achieved goal of correctness!
but, removing all-atoms check break requirement #2. calculation proceed follows
(condense '(2 3 4 (3 1 1 1) (2 3 (1 2)) 5)) == (calculate (mapcar #'condense '(2 3 4 (3 1 1 1) (2 3 (1 2)) 5))) == (calculate (list 2 3 4 (condense '(3 1 1 1)) (condense '(2 3 (1 2))) 5)) == (calculate (list 2 3 4 (calculate '(3 1 1 1)) (calculate (list 2 3 (calculate '(1 2)))) 5)) == (calculate (list 2 3 4 6 (calculate '(2 3 3)) 5)) == (calculate (list 2 3 4 6 8 5)) == 28 i.e. it'll proceed in left-to-right fashion instead of deepest-nested level out. imagining nested list tree (which is), "munch" on tree deepest left corner , right; code all-atoms check proceed strictly levels up.
so final simplified code is:
(defun condense (x) (if (listp x) (reduce #'+ (mapcar #'condense x)) (abs x))) a remark: looking @ last illustration of reduction sequence, clear picture emerges - of replacing each node in argument tree calculate application. clear case of folding, such done on tree instead of plain list, reduce is.
this can directly coded what's known "car-cdr recursion", replacing each cons cell application of combining function f on 2 results of recursive calls car , cdr components of cell:
(defun condense (x) (reduce-tree x #'+ 0)) (defun reduce-tree (x f z) (labels ((g (x) (cond ((consp x) (funcall f (g (car x)) (g (cdr x)))) ((numberp x) x) ((null x) z) (t (error "not number"))))) (g x))) as can see version highly recursive, not good.
Comments
Post a Comment