Author Topic: LISP Challenge: Grouping items.  (Read 4892 times)

0 Members and 1 Guest are viewing this topic.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
LISP Challenge: Grouping items.
« on: May 10, 2005, 11:39:40 AM »
Write a function that given a list, will group the items in sub lists of n items.

For example, if we defined a function GroupItems, that takes two arguments, a list 'lst' and a grouping number 'n', this snippette:

Code: [Select]
(   (lambda ( / lst )

        (setq lst '(1 2 3 4 5 6 7 8 9 10))

        (foreach n lst
       
            (princ
                (strcat
                    "\nGrouped "
                    (itoa n)
                    " at a time: "
                )
            )    

            (princ (GroupItems lst n))

        )

        (princ)

    )

)

Might produce this:

Code: [Select]
Grouped 1 at a time: ((1) (2) (3) (4) (5) (6) (7) (8) (9) (10))
Grouped 2 at a time: ((1 2) (3 4) (5 6) (7 8) (9 10))
Grouped 3 at a time: ((1 2 3) (4 5 6) (7 8 9) (10))
Grouped 4 at a time: ((1 2 3 4) (5 6 7 8) (9 10))
Grouped 5 at a time: ((1 2 3 4 5) (6 7 8 9 10))
Grouped 6 at a time: ((1 2 3 4 5 6) (7 8 9 10))
Grouped 7 at a time: ((1 2 3 4 5 6 7) (8 9 10))
Grouped 8 at a time: ((1 2 3 4 5 6 7 8) (9 10))
Grouped 9 at a time: ((1 2 3 4 5 6 7 8 9) (10))
Grouped 10 at a time: ((1 2 3 4 5 6 7 8 9 10))

Note how it might deal with lists that do not divide evenly by the grouping number 'n'.

Enjoy.

:)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

whdjr

  • Guest
LISP Challenge: Grouping items.
« Reply #1 on: May 10, 2005, 03:14:53 PM »
Well...it's pretty ugly but it works:
Code: [Select]
(defun GroupItems (lst n / idx nlst lst2)
  (while lst
    (setq idx 0)
    (while (and (< idx n) (> (length lst) idx))
      (setq nlst (cons (nth idx lst) nlst)
   idx (1+ idx)
      )
    )
    (setq lst2 (cons (reverse nlst) lst2)
 nlst nil
 lst  (member (nth n lst) lst)
    )
  )
  (reverse lst2)
)
Output:
Code: [Select]
Grouped 1 at a time: ((1) (2) (3) (4) (5) (6) (7) (8) (9) (10))
Grouped 2 at a time: ((1 2) (3 4) (5 6) (7 8) (9 10))
Grouped 3 at a time: ((1 2 3) (4 5 6) (7 8 9) (10))
Grouped 4 at a time: ((1 2 3 4) (5 6 7 8) (9 10))
Grouped 5 at a time: ((1 2 3 4 5) (6 7 8 9 10))
Grouped 6 at a time: ((1 2 3 4 5 6) (7 8 9 10))
Grouped 7 at a time: ((1 2 3 4 5 6 7) (8 9 10))
Grouped 8 at a time: ((1 2 3 4 5 6 7 8) (9 10))
Grouped 9 at a time: ((1 2 3 4 5 6 7 8 9) (10))
Grouped 10 at a time: ((1 2 3 4 5 6 7 8 9 10))

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
LISP Challenge: Grouping items.
« Reply #2 on: May 10, 2005, 03:22:59 PM »
Looks good to me Will, thanks for stepping up. I tried it and it works, good job. :)

I've written two: One for actual use (I've actually posted it before) and one for fun; the latter I wrote today. The 'fun' one is purposely obfuscated, ala Rube Goldberg, yet it demonstrates a use of mapcar folks might not have considered before. :lol:
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

whdjr

  • Guest
LISP Challenge: Grouping items.
« Reply #3 on: May 10, 2005, 03:28:46 PM »
My first thought was to use mapcar:
Code: [Select]
(mapcar 'list lst) but I couldn't get it to work for the different lengths so I did it the long way.  I still may go back and try it another way.

M-dub

  • Guest
LISP Challenge: Grouping items.
« Reply #4 on: May 10, 2005, 03:30:13 PM »
Quote from: MP
The 'fun' one is purposely obfuscated...


Obfuscated?!?

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
LISP Challenge: Grouping items.
« Reply #5 on: May 10, 2005, 07:14:16 PM »
Her's my submissions --

Code: [Select]
(defun GroupItems ( lst len / group result )

    (foreach item lst
        (if
            (eq len
                (length
                    (setq group
                        (cons item group)
                    )
                )
            )
            (setq
                result (cons group result)
                group  nil
            )
        )
    )

    (reverse
        (mapcar 'reverse
            (if group
                (cons group result)
                result
            )
        )
    )

)

This is merely for fun (read "not meant to be efficient", though it demonstrates a weird way to exploit mapcar) --

Code: [Select]
(defun RubeGoldbergGrouping ( lst n / len result )

    (setq len
        (   (lambda ( num div1 div2 / result )
                (if
                    (apply 'eq                        
                        (setq result
                            (mapcar
                               '(lambda (div) (/ num div))
                                (list div1 div2)
                            )    
                        )    
                    )
                    (car result)
                    (1+ (car result))
                )    
            )
            (length lst)
            (fix n)
            (float n)
        )
    )    
   
    (while
        (/= len
            (length
                (setq result
                    (cons nil result)
                )
            )
        )
    )
   
    (mapcar
       '(lambda ( group / result )
            (while (and lst (< (length result) n))
                (setq
                    result (cons (car lst) result)
                    lst    (cdr lst)
                )
            )
            (reverse result)
        )    
        result
    )

)

See if you can figure out / explain how the obfuscated (link for M-Dub) Rube Goldberg variant works. Hint: the last mapcar call.

:cheesy:
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
LISP Challenge: Grouping items.
« Reply #6 on: May 10, 2005, 07:43:16 PM »
My attempt.
Code: [Select]
(defun GroupItems (lst gp / newlst a sublst)
  (while lst
    (setq a      (car lst)
          lst    (cdr lst)
          sublst (cons a sublst)
    )
    (if (or (= (length sublst) gp) (null lst))
      (setq newlst (cons (reverse sublst) newlst)
            sublst '()
      )
    )
  )
  (reverse newlst)
)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
LISP Challenge: Grouping items.
« Reply #7 on: May 10, 2005, 09:20:09 PM »
Good one Alan. She works too. :)

I'm curious, why do you set sublst to '() when setting to nil achieves same? Is it to make the intent of your code clearer (i.e. empty list)?
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
LISP Challenge: Grouping items.
« Reply #8 on: May 10, 2005, 09:33:41 PM »
'() ? Well mentally I was thinking empty list and that is what came out.
I know that nil can be a list and it's the same as '().
Not always sure why I do some things? :)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
LISP Challenge: Grouping items.
« Reply #9 on: May 10, 2005, 09:35:21 PM »
Works for me. Thanks.

:)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst