From: ···········@gmail.com
Subject: newbie looping question
Date: 
Message-ID: <1174421847.792183.240790@y66g2000hsf.googlegroups.com>
I'm a lisp newbie....using clisp.
Can someone suggest an easier way
of setting some commonly used variables
my program will need...

I started using dolist:

(dolist (file '(h g f e d c b a))
  (dolist (row '(1 2 3 4 5 6 7 8))
	       (print (concatenate file row))))

but that didn't quite work....
Here's what I need....

(setf h1 (ash 1 0))
(setf g1 (ash 1 1))
(setf f1 (ash 1 2))
(setf e1 (ash 1 3))
(setf d1 (ash 1 4))
(setf c1 (ash 1 5))
(setf b1 (ash 1 6))
(setf a1 (ash 1 7))

(setf h2 (ash 1 8))
(setf g2 (ash 1 9))
(setf f2 (ash 1 10))
(setf e2 (ash 1 11))
(setf d2 (ash 1 12))
(setf c2 (ash 1 13))
(setf b2 (ash 1 14))
(setf a2 (ash 1 15))
...
(setf a8 (ash 1 63))

you get the idea...
These bignum variables will never change.

Thanks,

From: Thomas A. Russ
Subject: Re: newbie looping question
Date: 
Message-ID: <ymiaby74ffq.fsf@sevak.isi.edu>
···········@gmail.com writes:

> I'm a lisp newbie....using clisp.
> Can someone suggest an easier way
> of setting some commonly used variables
> my program will need...

Well, my first reaction is to wonder why you need to have all of these
global variables in the first place.  Perhaps there is another line of
implementation that would be a better choice than specifically named
variables, particularly if those names end up being generated.  How are
the references to those names constructed?

If you are generating keys to associate with values, then using some
sort of association list, property list or hash table may be a better
solution to what you want to do.


> I started using dolist:
> 
> (dolist (file '(h g f e d c b a))
>   (dolist (row '(1 2 3 4 5 6 7 8))
> 	       (print (concatenate file row))))
> 
> but that didn't quite work....



> Here's what I need....

Well, no quite.  You shouldn't be setting undeclared variables at the
top level.  You probably want to have something like DEFPARAMETER or
maybe DEFCONSTANT instead?

In any case, to do this you want to write a macro that generates this
code (inside a PROGN form, since macros can only return a single form),
using the loops to generate the values you want.  Perhaps something like

(defmacro make-constants ()
  (let ((forms nil)
        (count 0))
   (dolist number from 1 to 8
      (dolist letter '(h g f e d c b a)
        (push `(defconstant (intern (format nil "~A~D" letter number))
                            (ash 1 ,count))
              forms)
        (incf count)))
   `(progn ,@forms)))


> (setf h1 (ash 1 0))
> (setf g1 (ash 1 1))
> (setf f1 (ash 1 2))
> (setf e1 (ash 1 3))
> (setf d1 (ash 1 4))
> (setf c1 (ash 1 5))
> (setf b1 (ash 1 6))
> (setf a1 (ash 1 7))
> 
> (setf h2 (ash 1 8))
> (setf g2 (ash 1 9))
> (setf f2 (ash 1 10))
> (setf e2 (ash 1 11))
> (setf d2 (ash 1 12))
> (setf c2 (ash 1 13))
> (setf b2 (ash 1 14))
> (setf a2 (ash 1 15))
> ...
> (setf a8 (ash 1 63))
> 
> you get the idea...
> These bignum variables will never change.

Are you just trying to generate bit masks?  Perhaps what you want to do
with these values can be more easily done another way?

What is the purpose of defining all of these constants?

> 
> Thanks,
> 

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: ···········@gmail.com
Subject: Re: newbie looping question
Date: 
Message-ID: <1174443229.298799.64700@o5g2000hsb.googlegroups.com>
On Mar 20, 8:18 pm, ····@sevak.isi.edu (Thomas A. Russ) wrote:

> Are you just trying to generate bit masks?  Perhaps what you want to do
> with these values can be more easily done another way?
>
> What is the purpose of defining all of these constants?
>

It's for a chess program.  (In my scheme a1=128, h1=1.)
This makes referring to the squares on the board much easier
both for interactive use and for the rest of the code
(let ((initial-black-knights (logior b8 g8)...
From: Pascal Bourguignon
Subject: Re: newbie looping question
Date: 
Message-ID: <878xdrypgm.fsf@voyager.informatimago.com>
···········@gmail.com writes:

> On Mar 20, 8:18 pm, ····@sevak.isi.edu (Thomas A. Russ) wrote:
>
>> Are you just trying to generate bit masks?  Perhaps what you want to do
>> with these values can be more easily done another way?
>>
>> What is the purpose of defining all of these constants?
>>
>
> It's for a chess program.  (In my scheme a1=128, h1=1.)
> This makes referring to the squares on the board much easier
> both for interactive use and for the rest of the code
> (let ((initial-black-knights (logior b8 g8)...

This sounds like premature optimization.  
You won't make a better chess player with bit tiddling...

-- 
__Pascal Bourguignon__
http://www.informatimago.com
http://pjb.ogamita.org
From: Paul Wallich
Subject: Re: newbie looping question
Date: 
Message-ID: <etrc5t$h3q$1@reader2.panix.com>
Pascal Bourguignon wrote:
> ···········@gmail.com writes:
> 
>> On Mar 20, 8:18 pm, ····@sevak.isi.edu (Thomas A. Russ) wrote:
>>
>>> Are you just trying to generate bit masks?  Perhaps what you want to do
>>> with these values can be more easily done another way?
>>>
>>> What is the purpose of defining all of these constants?
>>>
>> It's for a chess program.  (In my scheme a1=128, h1=1.)
>> This makes referring to the squares on the board much easier
>> both for interactive use and for the rest of the code
>> (let ((initial-black-knights (logior b8 g8)...
> 
> This sounds like premature optimization.  
> You won't make a better chess player with bit tiddling...

And probably not a good premature optimization (if there is such a 
thing) since it means that all of your code will have to do a bunch of 
opaque twiddling to determine the relative positions of pieces. You 
should be writing accessors for all of this stuff rather than exposing 
your representation anywhere near the top level.

paul
From: Timofei Shatrov
Subject: Re: newbie looping question
Date: 
Message-ID: <4600f7d9.5000039@news.readfreenews.net>
On 20 Mar 2007 19:13:49 -0700, ···········@gmail.com tried to confuse everyone
with this message:

>On Mar 20, 8:18 pm, ····@sevak.isi.edu (Thomas A. Russ) wrote:
>
>> Are you just trying to generate bit masks?  Perhaps what you want to do
>> with these values can be more easily done another way?
>>
>> What is the purpose of defining all of these constants?
>>
>
>It's for a chess program.  (In my scheme a1=128, h1=1.)
>This makes referring to the squares on the board much easier
>both for interactive use and for the rest of the code
>(let ((initial-black-knights (logior b8 g8)...

I don't think you should use numbers here. 2^63 is quite big, and operations
with such big numbers may be slower than you expect. I think using bit arrays
may be the better idea.

(defun bit-map (f b1 b2)
   (map '(vector bit) f b1 b2))

(defun coord (i j)
   (let ((array (make-array 64 :element-type 'bit :initial-element 0)))
       (setf (bit array (+ (* 8 (1- i)) (1- j))) 1)))

(let ((initial-black-knights (bit-map #'logior (coord 2 8) (coord 7 8))))
  .... 
           
-- 
|Don't believe this - you're not worthless              ,gr---------.ru
|It's us against millions and we can't take them all... |  ue     il   |
|But we can take them on!                               |     @ma      |
|                       (A Wilhelm Scream - The Rip)    |______________|
From: ···········@gmail.com
Subject: Re: newbie looping question
Date: 
Message-ID: <1174482322.101270.134680@e1g2000hsg.googlegroups.com>
> I don't think you should use numbers here. 2^63 is quite big, and operations
> with such big numbers may be slower than you expect. I think using bit arrays
> may be the better idea.
>
> (defun bit-map (f b1 b2)
>    (map '(vector bit) f b1 b2))
>
> (defun coord (i j)
>    (let ((array (make-array 64 :element-type 'bit :initial-element 0)))
>        (setf (bit array (+ (* 8 (1- i)) (1- j))) 1)))
>
> (let ((initial-black-knights (bit-map #'logior (coord 2 8) (coord 7 8))))
>   ....

Chess programmers are very fond of 64 bit numbers (bitboards).
When viewed in binary, a 1 can represent the existence of
a piece (or some other information) at a particular square...

They're used to answer questions in a "parallel" method
(e.g. can any of my white pawns capture a black piece...
if white-pawns is a bignum with 1s where the white pawns
are located and all_black_pieces is a bignum with 1s where
any black piece is located, then

    white_pawn_captures = ((white-pawns<<7) & all_black_pieces) |
                                        (white-pawns<<9) &
all_black_pieces)

Then you have a number you can pick off the capture bits with
a simple operation (lsb = b & -b,  clear_lsb = b & (b-1))

Using bitboards turns your chess questions into binary operations
on bignums....and there appear to be lots of these questions in
chess programs (of a certain ilk).

But if you can do this more quickly with bit arrays, I'd love to
hear about it.  It would seem to me that doing a bitwise & would take
longer with an array of 64 numbers (even including the slowdown
in using bignums....and even finding the "least significant" bit
would take O(n) rather then O(1) that a single & on two bignums, no?

Regards,
From: Alan Crowe
Subject: Re: newbie looping question
Date: 
Message-ID: <86ps73a6fz.fsf@cawtech.freeserve.co.uk>
···········@gmail.com writes:

> I'm a lisp newbie....using clisp.
> Can someone suggest an easier way
> of setting some commonly used variables
> my program will need...
> 
> I started using dolist:
> 
> (dolist (file '(h g f e d c b a))
>   (dolist (row '(1 2 3 4 5 6 7 8))
> 	       (print (concatenate file row))))
> 
> but that didn't quite work....
> Here's what I need....
> 
> (setf h1 (ash 1 0))
> (setf g1 (ash 1 1))
> (setf f1 (ash 1 2))
> (setf e1 (ash 1 3))
> (setf d1 (ash 1 4))
> (setf c1 (ash 1 5))
> (setf b1 (ash 1 6))
> (setf a1 (ash 1 7))
> 
> (setf h2 (ash 1 8))
> (setf g2 (ash 1 9))
> (setf f2 (ash 1 10))
> (setf e2 (ash 1 11))
> (setf d2 (ash 1 12))
> (setf c2 (ash 1 13))
> (setf b2 (ash 1 14))
> (setf a2 (ash 1 15))
> ...
> (setf a8 (ash 1 63))
> 
> you get the idea...
> These bignum variables will never change.
> 
> Thanks,

I think that the usual idea for this kind of code is to use
strings not symbols, and an 8x8 array not lots of different
variables. So one might write routines to map between lists
of indices and strings:

CL-USER> (defun say (list)
           (let ((s (make-string 2)))
             (setf (char s 0) (aref "ABCDEFGH" (first list))
                   (char s 1) (digit-char (+ (second list) 1)))
             s))
SAY

CL-USER> (defun hear (char-numb)
           (list (position (char char-numb 0) "ABCDEFGH")
                 (- (digit-char-p (char char-numb 1)) 1)))
HEAR

CL-USER> (say '(0 0))
"A1"

CL-USER> (say '(7 7))
"H8"

CL-USER> (hear "A8")
(0 7)

and so on.

Then you can make an array

CL-USER> (defparameter *a* (make-array '(8 8) :initial-element 0))
*A*
CL-USER> *a*
#2A((0 0 0 0 0 0 0 0)
    (0 0 0 0 0 0 0 0)
    (0 0 0 0 0 0 0 0)
    (0 0 0 0 0 0 0 0)
    (0 0 0 0 0 0 0 0)
    (0 0 0 0 0 0 0 0)
    (0 0 0 0 0 0 0 0)
    (0 0 0 0 0 0 0 0))

and access elements by applying aref to the list of indices

CL-USER> (setf (apply #'aref *a* (hear "b3")) 'x)
X

CL-USER> *a*
#2A((0 0 0 0 0 0 0 0)
    (0 0 X 0 0 0 0 0)
    (0 0 0 0 0 0 0 0)
    (0 0 0 0 0 0 0 0)
    (0 0 0 0 0 0 0 0)
    (0 0 0 0 0 0 0 0)
    (0 0 0 0 0 0 0 0)
    (0 0 0 0 0 0 0 0))

What you ask for can be done

CL-USER> (dotimes (file 8)
           (dotimes (row 8)
             (eval `(defconstant ,(intern (say (list file row)))
                     (ash 1 (+ (* 8 ,file) ,row))))))
NIL

CL-USER> d4
134217728

but it seems to me that it leaves you stranded with your
magic numbers in 64 separate variables that are hard to
access systematically from code. Numbers in arrays are easy
to access, eg print them out with

(dotimes (file 8)
  (dotimes (row 8)
    (print (aref *a* file row))))

Alan Crowe
Edinburgh
Scotland
From: ···········@gmail.com
Subject: Re: newbie looping question
Date: 
Message-ID: <1174440724.713942.100840@l77g2000hsb.googlegroups.com>
On Mar 20, 6:36 pm, Alan Crowe <····@cawtech.freeserve.co.uk> wrote:
> ···········@gmail.com writes:
> I think that the usual idea for this kind of code is to use
> strings not symbols, and an 8x8 array not lots of different
> variables. So one might write routines to map between lists
>

no.  I need 64 variables.  I don't want an 8x8 array.
humor me.

> What you ask for can be done
>

(not trying to start a flame war or anything....)
I can do this in about 6 lines in another language ;-)...

count = 0
for i in range(1,9):
    for j in "hgfedcba":
        var = "%s%s" % (j,i)
        exec(name + "=" + str(1<<count) )
        count += 1

surely there's an easier way to do this in lisp without
creating an 8x8 array.

Thanks,
From: John Thingstad
Subject: Re: newbie looping question
Date: 
Message-ID: <op.tpizbaampqzri1@pandora.upc.no>
On Wed, 21 Mar 2007 02:32:04 +0100, <···········@gmail.com> wrote:

> On Mar 20, 6:36 pm, Alan Crowe <····@cawtech.freeserve.co.uk> wrote:
>> ···········@gmail.com writes:
>> I think that the usual idea for this kind of code is to use
>> strings not symbols, and an 8x8 array not lots of different
>> variables. So one might write routines to map between lists
>>
>
> no.  I need 64 variables.  I don't want an 8x8 array.
> humor me.
>
>> What you ask for can be done
>>
>
> (not trying to start a flame war or anything....)
> I can do this in about 6 lines in another language ;-)...
>
> count = 0
> for i in range(1,9):
>     for j in "hgfedcba":
>         var = "%s%s" % (j,i)
>         exec(name + "=" + str(1<<count) )
>         count += 1
>
> surely there's an easier way to do this in lisp without
> creating an 8x8 array.
>
> Thanks,
>
>
>

1. What on earth makes you think cluttering the namespace with 64 names is  
a easy way?
2. Look over his reply aagain. He show you how to clutter the namespace  
with
    all 64 variables.


CL-USER> (defun say (list)
            (let ((s (make-string 2)))
              (setf (char s 0) (aref "HGFEDCBA" (first list))
                    (char s 1) (digit-char (+ (second list) 1)))
              s))
CL-USER> (dotimes (file 8)
            (dotimes (row 8)
              (eval `(defconstant ,(intern (say (list file row)))
                      (ash 1 (+ (* 8 ,file) ,row))))))

or you could use

(let ((count 0))
   (loop for i from 1 to 8 do
         (loop for j across "HGFEDVBA" do
               (eval `(defconstant
                          ,(intern (format nil "~C~C" j (digit-char i)))
                        (ash 1 ,count)))
               (incf count))))

Which looks kinda simular to your Python code.

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: Pascal Bourguignon
Subject: Re: newbie looping question
Date: 
Message-ID: <87d533ypl7.fsf@voyager.informatimago.com>
···········@gmail.com writes:

> On Mar 20, 6:36 pm, Alan Crowe <····@cawtech.freeserve.co.uk> wrote:
>> ···········@gmail.com writes:
>> I think that the usual idea for this kind of code is to use
>> strings not symbols, and an 8x8 array not lots of different
>> variables. So one might write routines to map between lists
>>
>
> no.  I need 64 variables.  I don't want an 8x8 array.
> humor me.

Even if you need 64 names, you should still put them in a 8x8 array.

(defun generate-names-for-array (array-name w h)
   (loop :for i :from 0 :below w
         :nconc (loop :for j :from 0 :below h
                      :collect `(define-symbol-macro
                                   ,(intern (format nil "~36R~A" (+ 10 i) j))
                                   (aref ,array-name ,i ,j)))))

Try it as: (generate-names-for-array 'table 8 8)

Then you can use it like this:

(defmacro define-array-with-named-slots (name width height)
   (assert (and (symbolp name) (integerp width) (integerp height)))
     `(progn
         (defparameter ,name (make-array '(,width ,height)))
         ,@(generate-names-for-array name width height)))

(define-array-with-named-slots *tic-tac-toe* 3 3)

Use: 
   (macroexpand-1 '(define-array-with-named-slots *tic-tac-toe* 3 3))
to see what it expands to.


Of course, the big problem of this approach is what happens when you
invent a new game, like chess, but when a piece tries to take another,
the players must do a tic-tac-toe game to which piece dies.

(define-array-with-named-slots *chess*       8 8)
(define-array-with-named-slots *tic-tac-toe* 3 3)


Really, you're making an extraordinary claim that you need these
names, you should provide us some extraordinary justification...

Use an array and AREF !




Note that you can define some constants if you like:

(defconstant +a+ 0)
(defconstant +b+ 1)
....
(defconstant +h+ 7)
 
and use (aref table +a+ 2)  for � table.A2 �.



-- 
__Pascal Bourguignon__
http://www.informatimago.com
http://pjb.ogamita.org
From: John Thingstad
Subject: Re: newbie looping question
Date: 
Message-ID: <op.tpihp7vrpqzri1@pandora.upc.no>
On Tue, 20 Mar 2007 23:36:16 +0100, Alan Crowe  
<····@cawtech.freeserve.co.uk> wrote:

>
> but it seems to me that it leaves you stranded with your
> magic numbers in 64 separate variables that are hard to
> access systematically from code. Numbers in arrays are easy
> to access, eg print them out with
>
> (dotimes (file 8)
>   (dotimes (row 8)
>     (print (aref *a* file row))))
>

or (dotimes (i 64) (print (row-major-aref *a* i))

or perhaps
(defparamater *b* (make-array 64 :displaced-to *a*)
(dotimes (i 64) (print (aref *b* i))

(got a headache yet :) )
-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: Wade Humeniuk
Subject: Re: newbie looping question
Date: 
Message-ID: <lw%Lh.131229$cE3.128859@edtnps89>
Try this,

(defun populate-vars (&aux (shift -1))
   (dolist (file '(h g f e d c b a))
     (dolist (row '(1 2 3 4 5 6 7 8))
       (eval `(setf ,(intern (format nil "~A~A" file row))
                    ,(ash 1 (incf shift)))))))

CL-USER 5 > (populate-vars)
NIL

CL-USER 6 > h3
4

CL-USER 7 > h1
1

CL-USER 8 > e1
16777216

CL-USER 9 >

Wade
From: ···········@gmail.com
Subject: Re: newbie looping question
Date: 
Message-ID: <1174442441.852067.308210@p15g2000hsd.googlegroups.com>
On Mar 20, 9:04 pm, Wade Humeniuk <··················@telus.net>
wrote:
> Try this,
>
> (defun populate-vars (&aux (shift -1))
>    (dolist (file '(h g f e d c b a))
>      (dolist (row '(1 2 3 4 5 6 7 8))
>        (eval `(setf ,(intern (format nil "~A~A" file row))
>                     ,(ash 1 (incf shift)))))))
>

yep...that's what I needed.

Thanks!
From: Winston Smith
Subject: Re: newbie looping question
Date: 
Message-ID: <slrnf019k8.e6d.ga41h@localhost.localdomain>
On 2007-03-21, Wade Humeniuk <··················@telus.net> wrote:
> Try this,
>
> (defun populate-vars (&aux (shift -1))
>    (dolist (file '(h g f e d c b a))
>      (dolist (row '(1 2 3 4 5 6 7 8))
>        (eval `(setf ,(intern (format nil "~A~A" file row))
>                     ,(ash 1 (incf shift)))))))


Far be it from me to be an anti-eval dogmatist, but if you wanted to
avoid the eval you could use 

(defun populate-vars (&aux (shift -1))
  (dolist (file '(h g f e d c b a))
    (dolist (row '(1 2 3 4 5 6 7 8))
      (setf (symbol-value (intern (format nil "~A~A" file row)))
            (ash 1 (incf shift))))))
From: Winston Smith
Subject: Re: newbie looping question
Date: 
Message-ID: <slrnf053js.p7d.ga41h@localhost.localdomain>
On 2007-03-21, Winston Smith <·····@yahoo.com> wrote:
> (defun populate-vars (&aux (shift -1))
>   (dolist (file '(h g f e d c b a))
>     (dolist (row '(1 2 3 4 5 6 7 8))
>       (setf (symbol-value (intern (format nil "~A~A" file row)))
>             (ash 1 (incf shift))))))

Or just:

(defun populate-vars (&aux (shift -1))
  (dolist (file '(h g f e d c b a))
    (dolist (row '(1 2 3 4 5 6 7 8))
      (set (intern (format nil "~A~A" file row))
       (ash 1 (incf shift))))))