From: Jochen Schmidt on
On 12 Mrz., 14:40, Jochen Schmidt <j...(a)crispylogics.com> wrote:
> (defun group (list n)
>   (loop for e in list
>         for i upfrom 1
>         collect e into group
>         if (zerop (mod i 5))
>           collect (copy-list group) and do (setf group nil)))
>

Actually I missed the trailing incomplete group:

(defun group (list n)
(loop for e in list
for i upfrom 1
collect e into group
if (zerop (mod i 5))
collect (copy-list group) and do (setf group nil)
finally when group collect group))

--
Jochen Schmidt
CRISPYLOGICS
Uhlandstr. 9, 90408 Nuremberg
Fon +49 (0)911 517 999 82
Fax +49 (0)911 517 999 83
mailto:(format nil "~(~36r@~36r.~36r~)" 870180 1680085828711918828
16438)
http://www.crispylogics.com

From: Jochen Schmidt on
On 12 Mrz., 14:48, Jochen Schmidt <j...(a)crispylogics.com> wrote:
> On 12 Mrz., 14:40, Jochen Schmidt <j...(a)crispylogics.com> wrote:
>
> > (defun group (list n)
> >   (loop for e in list
> >         for i upfrom 1
> >         collect e into group
> >         if (zerop (mod i 5))
> >           collect (copy-list group) and do (setf group nil)))
>
> Actually I missed the trailing incomplete group:
>
> (defun group (list n)
>   (loop for e in list
>         for i upfrom 1
>         collect e into group
>         if (zerop (mod i 5))
>           collect (copy-list group) and do (setf group nil)
>         finally when group collect group))


*sigh* I missed to replace the group-size n from my REPL example; AND
this use of finally is actually not ANSI conform. One could rewrite it
as:

(defun group (list n)
(check-type n (integer 1))
(loop for e in list
for i upfrom 1
collect e into group
if (zerop (mod i n))
collect (copy-list group) into result
and do (setf group nil)
finally return (if group (nconc result (list group)) result)))

This doesn't make it look nicer though ;-)

ciao,
Jochen

--
Jochen Schmidt
CRISPYLOGICS
Uhlandstr. 9, 90408 Nuremberg
Fon +49 (0)911 517 999 82
Fax +49 (0)911 517 999 83
mailto:(format nil "~(~36r@~36r.~36r~)" 870180 1680085828711918828
16438)
http://www.crispylogics.com
From: Rob Warnock on
Jochen Schmidt <js(a)crispylogics.com> wrote:
+---------------
| (defun group (list n)
| (loop for e in list
| for i upfrom 1
| collect e into group
| if (zerop (mod i 5))
| collect (copy-list group) and do (setf group nil)))
+---------------

Surely you meant (MOD I N), yes?

In any case, even with the correction, the above doesn't work
in CMUCL [might be a bug in CMUCL's "COLLECT...INTO..."]:

> (group (iota 12) 3)

((0 1 2) (0 1 2 3 4 5) (0 1 2 3 4 5 6 7 8) (0 1 2 3 4 5 6 7 8 9 10 11))
>

But this does:

> (defun group (list n)
(loop with group = nil
for e in list
and i upfrom 1
do (push e group)
if (zerop (mod i n))
collect (reverse group)
and
do (setf group nil)))

GROUP
> (group (iota 12) 3)

((0 1 2) (3 4 5) (6 7 8) (9 10 11))
> (group (iota 12) 4)

((0 1 2 3) (4 5 6 7) (8 9 10 11))
>


-Rob

-----
Rob Warnock <rpw3(a)rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

From: Jochen Schmidt on
On 12 Mrz., 10:31, Tamas K Papp <tkp...(a)gmail.com> wrote:
> Hi,
>
> I am trying to rewrite GROUP from On Lisp without recursion (just as an
> exercise).  My first attempt is below, I am wondering if there is a
> nicer (more idiomatic, etc) way to do it.
>
> (defun group (list n)
>   "Return elements of LIST as a list of lists in groups of N."
>   (check-type n (integer 1))
>   (let (sublist
>         result
>         (i 0))
>     (dolist (element list)
>       (push element sublist)
>       (incf i)
>       (when (= i n)
>         (push (nreverse sublist) result)
>         (setf i 0
>               sublist nil)))
>     (assert (zerop i) () "~A could not be broken up to sublists of ~A elements" list n)
>     (nreverse result)))
>

Here is an alternative to my other approach:

(defun take-n (list n)
(loop repeat n for e in list collect e))

(defun group (list n)
(check-type n (integer 1))
(loop for tail = list then (nthcdr n tail)
while tail
collect (take-n tail n)))


From: Pillsy on
On Mar 12, 4:31 am, Tamas K Papp <tkp...(a)gmail.com> wrote:

> I am trying to rewrite GROUP from On Lisp without recursion (just as an
> exercise).  My first attempt is below, I am wondering if there is a
> nicer (more idiomatic, etc) way to do it.

I think REDUCE is a great function for problems like this.

(defun group (list n)
(check-type n (integer 1))
(let* ((i -1)
(groups
(reduce (lambda (e acc)
(if (zerop (mod (incf i) n))
(cons (list e) acc)
;; You could also smash the car here to
;; reduce consing:
(cons (cons e (car acc)) (cdr acc))))
list :from-end t :initial-value '())))
(if (/= (mod (1+ i) n) 0)
(error "~A could not be broken up into sublists of ~A
elements"
list n)
groups)))

Cheers,
Pillsy