Author Topic: -={ Challenge }=- Group By Assoc  (Read 8858 times)

0 Members and 1 Guest are viewing this topic.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
-={ Challenge }=- Group By Assoc
« on: April 03, 2010, 08:38:46 AM »
The Challenge:

To emulate the behaviour of the Express Tools' acet-list-group-by-assoc function, (however the list should be in the correct order, unlike that function...). The function needn't accomodate for dotted pairs.

Example:

Code: [Select]
(setq lst '((1 123 234) (2 234 345) (3 345 456) (2 456 567) (3 567 678)))

==> ((1 123 234) (2 234 345) (3 345 456) (2 456 567) (3 567 678))

Code: [Select]
(reverse (acet-list-group-by-assoc lst))

==> ((1 123 234) (2 234 345 456 567) (3 345 456 567 678))

I'll kick us off, as an example:

Code: [Select]
(defun _GroupByAssoc ( lst / rtn a )
  (setq rtn (list (car lst)))

  (while (setq lst (cdr lst))
    (setq rtn
      (if (setq a (assoc (caar lst) rtn))
        (subst (cons (car a) (append (cdr a) (cdar lst))) a rtn)
        (cons (car lst) rtn))))
 
  (reverse rtn))

Enjoy,

Lee

JohnK

  • Administrator
  • Seagull
  • Posts: 10640
Re: -={ Challenge }=- Group By Assoc
« Reply #1 on: April 03, 2010, 05:30:10 PM »
Here is my c++ entry.
Code: [Select]
int main ( )
/*
   sort a three dimensional array by first colum using the bubble sort.

   the array:
   (
    (1 123 234)
    (2 234 345)
    (3 345 456)
    (2 456 567)
    (3 567 678)
   )
*/
{
        int rows = 5,
            cols = 3;
        int r,
            c = 0;
        int tmp[1][3];
            // temp array to hold value while switch is made.
        int nums[5][3] = {
                {1, 123, 234},
                {2, 234, 345},
                {3, 345, 456},
                {2, 456, 567},
                {3, 567, 678}};
               
        cout << "\nOrig array is:\n";
        for(r=0; r<rows; r++)
                // print the array
        {
                for(c=0; c<cols; ++c) cout << '\t' << nums[r][c];
                // print each entry
               
                cout << endl;
                // add a line break
        }

        cout << endl;

        for(r=1; r<rows; r++)
        {
                // if array entry is bigger then the previous
                // entry, swap them
                if(nums[r][0] < nums[r-1][0])
                {
                        for(c=0; c<cols; c++)
                        {
                           tmp[0][c] = nums[r-1][c];
                           nums[r-1][c] = nums[r][c];
                           nums[r][c] = tmp[0][c];
                        }
                }
        }

        cout << "\nSorted array is:\n";
        for(r=0; r<rows; r++)
                // print the array
        {
                for(c=0; c<cols; ++c) cout << '\t' << nums[r][c];
                // print each entry

                cout << endl;
                // add a line break
        }

        return 0;
}

Quote
Orig array is:
        1       123     234
        2       234     345
        3       345     456
        2       456     567
        3       567     678


Sorted array is:
        1       123     234
        2       234     345
        2       456     567
        3       345     456
        3       567     678
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #2 on: April 04, 2010, 07:05:35 AM »
Thanks John  :-)

It seems the challenge isn't as interesting as the other one, but I'm having fun anyway  :-)

Here's an attempt at 'Bicursion'  :-)

Code: [Select]
(defun _GroupByAssoc2 ( lst / g f )

  (defun g ( l )
    (if l
      (f (caar l) l)))

  (defun f ( x l )
    (cons
      (cons x (apply (function append)
                     (mapcar (function cdr)
                             (vl-remove-if-not
                               (function
                                 (lambda (pair) (= x (car pair)))) l))))
      (g (vl-remove-if (function (lambda (pair) (= x (car pair)))) l))))

  (g lst))

qjchen

  • Bull Frog
  • Posts: 285
  • Best wishes to all
Re: -={ Challenge }=- Group By Assoc
« Reply #3 on: April 04, 2010, 08:21:13 AM »
Hi, Lee mac:)

When I finish the code, I feel it is similar to your first code.

Code: [Select]
(defun c:test ()
  (setq lst '((9 1111)
         (1 123 234) (2 234 345)
(3 345 456)
(2 456 567)
(4 678 789 90)
(3 567 678)
(1 111)
)
  )
  (chenGroupassoc lst)
)

(defun chenGroupassoc (lst / res a b item)
  (setq res (list (car lst)))
  (while (setq lst (cdr lst))
    (setq a (car lst) b (car a))
    (if (not (setq item (assoc b res)))
      (setq res (append res (list a)))
        (setq res (subst (append item (cdr a)) item res))))
)
« Last Edit: April 04, 2010, 09:04:26 AM by yuanqiu »
http://qjchen.mjtd.com
My blog http://chenqj.blogspot.com (Chinese, can be translate into English)

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: -={ Challenge }=- Group By Assoc
« Reply #4 on: April 04, 2010, 09:40:48 AM »
Hi

A cross recursive example

Code: [Select]
(defun GroupByAssoc (lst / f1 f2)
  (defun f1 (a l / b)
    (if (setq b (assoc (car a) l))
      (f1 (append a (cdr b)) (vl-remove b l))
      (cons a (f2 l))
    )
  )
  (defun f2 (l)
    (if (cdr l)
      (f1 (car l) (cdr l))
      l
    )
  )
  (f1 (car lst) (cdr lst))
)
Speaking English as a French Frog

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #5 on: April 04, 2010, 09:53:25 AM »
Very nice Gile!  I like it  :-)

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #6 on: April 04, 2010, 10:34:23 AM »
Another to mess with the mind  :lol:

Code: [Select]
(defun _GroupByAssoc3 ( lst / g f )

  (defun g ( a b )
    (if a
      (if (assoc (caar a) b)
        (g (cdr a) b)
        (g (cdr a)
           (cons
             (cons (caar a)
                (f (caar a) a)) b))) b))

  (defun f ( x l )
    (if l
      (if (= x (caar l))
        (append (cdar l) (f x (cdr l)))
        (f x (cdr l)))))

  (reverse (g lst nil)))

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: -={ Challenge }=- Group By Assoc
« Reply #7 on: April 04, 2010, 10:41:12 AM »
my version:
Code: [Select]
(defun gba-ee (l / a)
 (setq l (vl-sort l (function (lambda (a b) (>= (car a) (car b)))))
       a nil
 )
 (while l
  (setq a (cons (car l) a)
        l (cdr l)
  )
  (while (and l (= (caar l) (caar a)))
   (setq a (cons (cons (caar l) (append (cdar l) (cdar a))) (cdr a))
         l (cdr l)
   )
  )
 )
 a
)

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #8 on: April 04, 2010, 11:06:09 AM »
Nice idea Evgeniy  :-)

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: -={ Challenge }=- Group By Assoc
« Reply #9 on: April 04, 2010, 11:09:17 AM »
Nice idea Evgeniy  :-)

I hope this idea will give odds to speed ... :)

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #10 on: April 04, 2010, 11:11:02 AM »
Nice idea Evgeniy  :-)

I hope this idea will give odds to speed ... :)

But would Sorting reduce speed for longer lists...  :angel:

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: -={ Challenge }=- Group By Assoc
« Reply #11 on: April 04, 2010, 11:12:51 AM »
But would Sorting reduce speed for longer lists...  :angel:

Yes, sorting is very fast!
Particularly noticeable is in large lists...

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8702
  • AKA Daniel
Re: -={ Challenge }=- Group By Assoc
« Reply #12 on: April 04, 2010, 11:20:56 AM »
What's the difference between 'cross recursive' and 'Bicursion'... just so I know I'm properly dressed   :laugh:

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #13 on: April 04, 2010, 11:23:10 AM »
What's the difference between 'cross recursive' and 'Bicursion'...  :laugh:

Bicursion is a term I picked up from this thread  :-)

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #14 on: April 04, 2010, 01:08:28 PM »
Quick speed test:

Code: [Select]
Intel Core2Duo @ 2.1GHz
3GB RAM

Elapsed milliseconds / relative speed for 16384 iteration(s):

    (MAC_GROUPBYASSOC LST)......1201 / 5.61 <fastest>
    (GILE_GROUPBYASSOC LST).....1264 / 5.33
    (GBA-EE LST)................1872 / 3.60
    (MAC_GROUPBYASSOC3 LST).....1903 / 3.54
    (MAC_GROUPBYASSOC2 LST).....6740 / 1.00 <slowest>

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: -={ Challenge }=- Group By Assoc
« Reply #15 on: April 04, 2010, 01:11:42 PM »
« Last Edit: April 04, 2010, 11:05:12 PM by Trauma »
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #16 on: April 04, 2010, 01:19:17 PM »
A test with a longer list reveals more...  :evil:

Code: [Select]
List Length: 80

Elapsed milliseconds / relative speed for 16384 iteration(s):

    (GILE_GROUPBYASSOC LST)......1310 / 8.00 <fastest>
    (GBA-EE LST).................4056 / 2.58
    (MAC_GROUPBYASSOC LST)......10484 / 1.00 <slowest>

My laptop's not fast enough to process lists much longer than that  :|

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #17 on: April 04, 2010, 01:33:39 PM »
Another  :-)

Code: [Select]
(defun Mac_GroupByAssoc4 ( lst / item rtn out)
  (setq item (caar lst) rtn (cdar lst))

  (while (setq lst (cdr lst))
   
    (while (and lst (setq a (assoc item lst)))
     
      (setq rtn (append rtn (cdr a)) lst (vl-remove a lst)))
   
    (setq out (cons (cons item rtn) out) item (caar lst) rtn (cdar lst)))
 
  (reverse out))

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #18 on: April 04, 2010, 01:34:55 PM »
Code: [Select]
List Length: 5

Elapsed milliseconds / relative speed for 32768 iteration(s):

    (MAC_GROUPBYASSOC4 LST).....1482 / 1.41 <fastest>
    (MAC_GROUPBYASSOC LST)......1528 / 1.37
    (GILE_GROUPBYASSOC LST).....1576 / 1.33
    (GBA-EE LST)................2090 / 1.00 <slowest>

Code: [Select]
List Length: 80

Elapsed milliseconds / relative speed for 16384 iteration(s):

    (MAC_GROUPBYASSOC4 LST).....1139 / 8.49 <fastest>
    (GILE_GROUPBYASSOC LST).....1170 / 8.27
    (GBA-EE LST)................3697 / 2.62
    (MAC_GROUPBYASSOC LST)......9672 / 1.00 <slowest>

 8-)

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: -={ Challenge }=- Group By Assoc
« Reply #19 on: April 04, 2010, 02:20:50 PM »
Hi Lee! :)

Code: [Select]
(Mac_GroupByAssoc4 '((1 2) (1 2) (1 2))) ;=>> ((1 2 2))
(GroupByAssoc '((1 2) (1 2) (1 2)))      ;=>> ((1 2 2))
(gba-ee '((1 2) (1 2) (1 2)))           ;=>> ((1 2 2 2))
« Last Edit: April 04, 2010, 02:25:53 PM by ElpanovEvgeniy »

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #20 on: April 04, 2010, 02:34:24 PM »
I wondered who'd be the first to spot that...

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: -={ Challenge }=- Group By Assoc
« Reply #21 on: April 04, 2010, 02:40:34 PM »
I wondered who'd be the first to spot that...

Now I do not know, I must make a new version?  :kewl:

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #22 on: April 04, 2010, 02:50:42 PM »
I wondered who'd be the first to spot that...

Now I do not know, I must make a new version?  :kewl:

No, I think your version is the correct way to deal with that situation - I just wish there was a function like vl-remove that would only remove the first occurence of an item.  :-(

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #23 on: April 04, 2010, 03:12:48 PM »
I thought I'd try to write my own, but I cannot seem to get this to work  :-(

Code: [Select]
(defun vl-remove-1st (x l / foo)

    (defun foo (y)
      (if (equal x y)
        (defun foo (y) nil)))

    (vl-remove-if (function foo) l))

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: -={ Challenge }=- Group By Assoc
« Reply #24 on: April 04, 2010, 03:22:06 PM »
Don't have time to optimize but ...

Code: [Select]
(defun remove-first-if ( foo lst / bar )
   
    (defun bar (x) (if (foo x) (defun foo (x) nil)))   

    (vl-remove-if 'bar lst)

)

(remove-first-if

    (lambda (x) (eq 2 x))   
   
   '(0 1 2 2 3 4 5 6 7 8)   
   
)

=> (0 1 2 3 4 5 6 7 8)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #25 on: April 04, 2010, 03:37:32 PM »
Thanks Michael - appreciated.

I couldn't work out why my solution failed though  :-(

With my code

Code: [Select]
(defun vl-remove-1st (x l / foo)

    (defun foo (y)
      (if (equal x y)
        (defun foo (y) nil)))

    (vl-remove-if (function foo) l))

For say,

Code: [Select]
(vl-remove-1st 1 '(1 2 3 1 2 3))

I would have thought the first item is fed to foo, the IF statement evaluates and redefines foo (hence returning T, and so the first item is removed), and subsequent evaluation of foo would return nil (hence no more items are removed).

What is wrong in my reasoning?

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: -={ Challenge }=- Group By Assoc
« Reply #26 on: April 04, 2010, 03:54:09 PM »
my version remove first
Code: [Select]
(defun r1 (x l)
 (cond
  ((not l)nil)
  ((= x (car l))(cdr l))
  ((cons (car l)(r1 x(cdr l))))))

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #27 on: April 04, 2010, 03:57:33 PM »
As usual - nice idea Evgeniy!  :lol:

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
Re: -={ Challenge }=- Group By Assoc
« Reply #28 on: April 04, 2010, 04:16:30 PM »
Code: [Select]
(defun r2 (x l / ll)
 ;;iteration
 (while (and l (/= (car l) x))
  (setq ll (cons (car l) ll)
        l  (cdr l)
  ) ;_  setq
 ) ;_  while
 (if l
  (append (reverse ll) (cdr l))
  (reverse ll)
 ) ;_  if
)

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: -={ Challenge }=- Group By Assoc
« Reply #29 on: April 04, 2010, 04:43:28 PM »
A new version which doesn't remove duplicated items

Code: [Select]
(defun GroupByAssoc (lst / f1 f2)
  (defun f1 (a l / b)
    (if (setq b (assoc (car a) l))
      (f1 (append a (cdr b)) (removefirst b l))
      (cons a (f2 l))
    )
  )
  (defun f2 (l)
    (if (cdr l)
      (f1 (car l) (cdr l))
      l
    )
  )
  (f1 (car lst) (cdr lst))
)

(defun removefirst (item lst)
  (if (or (equal item (car lst)) (null lst))
    (cdr lst)
    (cons (car lst) (removefirst item (cdr lst)))
  )
)
« Last Edit: April 04, 2010, 04:56:37 PM by gile »
Speaking English as a French Frog

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: -={ Challenge }=- Group By Assoc
« Reply #30 on: April 04, 2010, 06:32:57 PM »
My clumsy attempt.
Code: [Select]
(defun remove1 (x lst / itm result)
  (while (setq itm (car lst))
    (setq lst (cdr lst))
    (if (= x itm)
      (setq x nil)
      (setq result (cons itm result))
    )
  )
  (reverse result)
)
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.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: -={ Challenge }=- Group By Assoc
« Reply #31 on: April 05, 2010, 06:23:44 AM »
Nice one Alan  :-)

Its a shame, all of these solutions will be slower than vl-remove - so its looking like Evgeniy may snatch it for longer lists....

Code: [Select]
List Length: 5

Benchmarking ..................Elapsed milliseconds / relative speed for 32768 iteration(s):

    (MAC_GROUPBYASSOC LST).......1217 / 1.28 <fastest>
    (MAC_GROUPBYASSOC5 LST)......1326 / 1.18
    (GILE_GROUPBYASSOC2 LST).....1389 / 1.12
    (GBA-EE LST).................1560 / 1.00 <slowest>

Code: [Select]
List Length: 80

Benchmarking ................Elapsed milliseconds / relative speed for 8192 iteration(s):

    (GBA-EE LST)..................1529 / 11.57 <fastest>
    (MAC_GROUPBYASSOC LST)........4446 / 3.98
    (GILE_GROUPBYASSOC2 LST).....16443 / 1.08
    (MAC_GROUPBYASSOC5 LST)......17690 / 1.00 <slowest>

Code: [Select]
(defun Mac_GroupByAssoc5 ( lst / item rtn out)
  (setq item (caar lst) rtn (cdar lst))

  (while (setq lst (cdr lst))
   
    (while (and lst (setq a (assoc item lst)))
     
      (setq rtn (append rtn (cdr a)) lst (r1 a lst)))
   
    (setq out (cons (cons item rtn) out) item (caar lst) rtn (cdar lst)))
 
  (reverse out))

(defun r1 (x l) ; ElpanovEvgeniy
    (cond (  (not l) nil)
          (  (equal x (car l)) (cdr l))
          (  (cons (car l) (r1 x (cdr l))))))

T.Willey

  • Needs a day job
  • Posts: 5251
Re: -={ Challenge }=- Group By Assoc
« Reply #32 on: April 05, 2010, 12:06:27 PM »
Late to the party, but didn't see one that did it the way I had in my head, so it is.

Code: [Select]
(defun gba-tmw ( lst / a b r )
   
    (while (setq a (car lst))
        (cond
            ((not r) (setq r (list a)))
            ((setq b (assoc (car a) r)) (setq r (subst (cons (car b) (append (cdr b) (cdr a))) b r)))
            (t (setq r (cons a r)))
        )
        (setq lst (cdr lst))
    )
    (vl-sort r (function (lambda ( a b ) (< (car a ) (car b)))))
)

Here is one that will sort the nested lists also, incase that also desired.
Code: [Select]
(defun gba-tmw2 ( lst / a b r )
    ; (setq lst '((1 123 234) (2 234 345) (3 345 456) (2 456 567 133) (3 567 678 125)))
    (while (setq a (car lst))
        (cond
            ((not r) (setq r (list a)))
            ((setq b (assoc (car a) r)) (setq r (subst (cons (car b) (append (cdr b) (cdr a))) b r)))
            (t (setq r (cons a r)))
        )
        (setq lst (cdr lst))
    )
    (vl-sort
        (mapcar (function (lambda (a) (cons (car a) (vl-sort (cdr a) (function (lambda (x y) (< x y))))))) r)
        (function (lambda ( a b ) (< (car a ) (car b))))
    )
)
« Last Edit: April 05, 2010, 12:11:24 PM by T.Willey »
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.