From: Zachary Turner
Subject: matrix operations
Date: 
Message-ID: <880568CADBCAD7BA.553D9AD154730FA7.D53F6AC6426EB71F@lp.airnews.net>
I've got a 3x3 matrix, stored as ((r1c1 r1c2 r1c3) (r2c1 r2c2 r2c3) (r3c1
r3c2 r3c3)).  I want to check if any of the columns have the same three
elements.  It's easy for rows, I can just use
(or
   (every #'equal (car matrix))
   (every #'equal (cadr matrix))
   (every #'equal (caddr matrix)))

My questions are:
a) Can I do this more elegantly using a mapxxx function?
b) How can I check columns using one of the map functions?  It seems like
there should be a way using mapcar since it pulls elements from each list
and applies a function to each of them, but I don't know how to or the
results together.  Or maybe there's even a better way that I'm not aware of.

Thanks,

Zachary J. Turner
Software Development Engineer
BindView Development Corp.

713-561-4309
·······@bindview.com

From: Robert Monfera
Subject: Re: matrix operations
Date: 
Message-ID: <38B72D1D.C3D1364F@fisec.com>
Zachary Turner wrote:

> It's easy for rows, I can just use
> (or
>    (every #'equal (car matrix))
>    (every #'equal (cadr matrix))
>    (every #'equal (caddr matrix)))

Besides what Barry said, it's preferable to use FIRST, SECOND and THIRD
in lieu of CAR, CADR and CADDR in cases like this, because they name
what you want more specifically.

Robert
From: Lieven Marchand
Subject: Re: matrix operations
Date: 
Message-ID: <8991pk$ojc$1@newnews1.news.nl.uu.net>
"Zachary Turner" <·······@bindview.com> writes:

> I've got a 3x3 matrix, stored as ((r1c1 r1c2 r1c3) (r2c1 r2c2 r2c3) (r3c1
> r3c2 r3c3)).  

This seems to come right out of Gabriel's Worse is better paper. Any
reason why you don't want to use the built in array functionality of
CL?

-- 
Lieven Marchand <···@bewoner.dma.be>
If there are aliens, they play Go. -- Lasker
From: Barry Margolin
Subject: Re: matrix operations
Date: 
Message-ID: <4nFt4.86$I31.1906@burlma1-snr2>
In article <··················································@lp.airnews.net>,
Zachary Turner <·······@bindview.com> wrote:
>I've got a 3x3 matrix, stored as ((r1c1 r1c2 r1c3) (r2c1 r2c2 r2c3) (r3c1
>r3c2 r3c3)).  I want to check if any of the columns have the same three
>elements.  It's easy for rows, I can just use
>(or
>   (every #'equal (car matrix))
>   (every #'equal (cadr matrix))
>   (every #'equal (caddr matrix)))

Actually, that doesn't work.  EVERY passes a single element to the test
function, but EQUAL requires two arguments.  What you need is:

(or (every #'(lambda (x) (equal x (caar matrix)))
           (cdar matrix))
    (every #'(lambda (x) (equal x (caadr matrix)))
           (cdadr matrix))
    (every #'(lambda (x) (equal x (caaddr matrix)))
           (cdaddr matrix)))

>My questions are:
>a) Can I do this more elegantly using a mapxxx function?

(defun (all-elements-equal (list)
  (destructuring-bind (head . tail) list
    (every #'(lambda (x) (equal x head))
           tail))))

(defun any-rows-equal (matrix)
  (any #'all-elements-equal matrix))

>b) How can I check columns using one of the map functions?  It seems like
>there should be a way using mapcar since it pulls elements from each list
>and applies a function to each of them, but I don't know how to or the
>results together.  Or maybe there's even a better way that I'm not aware of.

Well, here's a solution similar to my first rewrite:

(or (every #'(lambda (x) (equal x (caar matrix)))
           (mapcar #'car (cdr matrix)))
    (every #'(lambda (x) (equal x (cadar matrix)))
           (mapcar #'cadr (cdr matrix)))
    (every #'(lambda (x) (equal x (caddar matrix)))
           (mapcar #'caddr (cdr matrix))))

Here's a simpler one, but it's probably more expensive, because it has to
map over the matrix once to transpose it, then it has to scan it again in
the earlier functions.  But if you don't need to squeeze every bit of
performance out of your algorithm, the modularity is nice.

(defun any-columns-equal (matrix)
  (any-rows-equal (transpose matrix)))

Writing transpose is left as an exercise for the reader (I think there was
a thread on it a few months ago if you're willing to search deja.com).

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Gareth McCaughan
Subject: Re: matrix operations
Date: 
Message-ID: <86snygzqxg.fsf@g.local>
Zachary Turner wrote:

> I've got a 3x3 matrix, stored as ((r1c1 r1c2 r1c3) (r2c1 r2c2 r2c3) (r3c1
> r3c2 r3c3)).  I want to check if any of the columns have the same three
> elements.  It's easy for rows, I can just use
> (or
>    (every #'equal (car matrix))
>    (every #'equal (cadr matrix))
>    (every #'equal (caddr matrix)))

I don't understand. Surely
  (every #'equal (car matrix))
is equivalent to
  (and (equal r1c1) (equal r1c2) (equal r1c3))
which isn't at all what you want?

> 
> My questions are:
> a) Can I do this more elegantly using a mapxxx function?

(defun first-is-repeated (x)
  (some (lambda (y) (equal y (first x)))
        (rest x)))

(defun something-is-repeated (x)
  (some #'first-is-repeated (maplist #'identity x)))

Of course, you can make FIRST-IS-REPEATED into an
anonymous function for a slight decrease in size
and a considerable decrease in clarity:

(defun something-is-repeated (x)
  (some
    (lambda (x)
      (some (lambda (y) (equal y (first x)))
            (rest x)))
    (maplist #'identity x)))

> b) How can I check columns using one of the map functions?  It seems like
> there should be a way using mapcar since it pulls elements from each list
> and applies a function to each of them, but I don't know how to or the
> results together.  Or maybe there's even a better way that I'm not aware of.

Well, since you're asking about clever hacks with MAPxxx,
you could always transpose the matrix and then apply the
function above to it.

(defun hacky-transpose (matrix)
  (if matrix (apply #'mapcar #'list matrix)))

I realise that this isn't quite what you're after...

-- 
Gareth McCaughan  ················@pobox.com
sig under construction