From: An[z]elmus
Subject: [Newbie] removing an element from a sequence
Date: 
Message-ID: <9girs31rvf6iht5lokfh0usfq9pe842p1r@4ax.com>
Function remove (or delete) eliminate all the occurences of an item in
a sequence.
for example:

(remove #\a "adagio") ----> "dgio"

Let say that I need to remove only one occurence at a time, for 
exmple I may need to remove the #\a at index 2 in "adagio" and obtain
as a result "adgio".
In other words, it would be handy to have a function that remove an
element based on its position/index.
I have not yet figured out how to do it properly.

From: Marco Antoniotti
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <19eca052-4f81-4b7f-ae33-b72c7b360bc2@59g2000hsb.googlegroups.com>
On Mar 4, 11:39 pm, "An[z]elmus" <·······@somewhere.org> wrote:
> Function remove (or delete) eliminate all the occurences of an item in
> a sequence.
> for example:
>
> (remove #\a "adagio") ----> "dgio"
>
> Let say that I need to remove only one occurence at a time, for
> exmple I may need to remove the #\a at index 2 in "adagio" and obtain
> as a result "adgio".
> In other words, it would be handy to have a function that remove an
> element based on its position/index.
> I have not yet figured out how to do it properly.

(remove #\a "adagio" :start 1)

Most sequence functions take :start, :end and :count keywords.

CL-USER 11 > (remove #\e "removing an element")
"rmoving an lmnt"

CL-USER 12 > (remove #\e "removing an element" :start 2)
"removing an lmnt"

CL-USER 13 > (remove #\e "removing an element" :start 2 :end 15)
"removing an lment"

CL-USER 14 > (remove #\e "removing an element" :start 2 :end 15 :count
1)
"removing an lement"

The CLHS is your friend.

Cheers
--
Marco
From: An[z]elmus
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <oimrs3dh8dmrphmprgqa21s57rkpb38s43@4ax.com>
On Tue, 4 Mar 2008 14:49:28 -0800 (PST), Marco Antoniotti
<·······@gmail.com> wrote:
>> In other words, it would be handy to have a function that remove an
>> element based on its position/index.
>> I have not yet figured out how to do it properly.
>
>(remove #\a "adagio" :start 1)

(remove #\a "adagiare" :start 0 :count 1) ------------> "dagiare"
(remove #\a "adagiare" :start 2 :count 1) ------------> "adgiare"
(remove #\a "adagiare" :start 5 :count 1) ------------> "adagire"

This works fine.The position/index inside the sequence is  the right
value for the :start keyword parameter and all it remains to do is to
limit :count to 1.
Thank you both.
From: Thomas A. Russ
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <ymi1w6p7w3a.fsf@blackcat.isi.edu>
"An[z]elmus" <·······@somewhere.org> writes:

> (remove #\a "adagiare" :start 0 :count 1) ------------> "dagiare"
> (remove #\a "adagiare" :start 2 :count 1) ------------> "adgiare"
> (remove #\a "adagiare" :start 5 :count 1) ------------> "adagire"
> 
> This works fine.The position/index inside the sequence is  the right
> value for the :start keyword parameter and all it remains to do is to
> limit :count to 1.

Of course, depending on what you are doing with this, there may be more
efficient alternatives, since each edit does require creating a new
sequence (in general -- DELETE may not for some sequences, but for
strings I'm sure DELETE must also create a new one).

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: An[z]elmus
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <i4lss3p13gafj0a9j8ukc66f5buv7cs4ce@4ax.com>
On 04 Mar 2008 18:17:45 -0800, ···@sevak.isi.edu (Thomas A. Russ)
wrote:
>> (remove #\a "adagiare" :start 5 :count 1) ------------> "adagire"
>> [...]
>
>Of course, depending on what you are doing with this, there may be more
>efficient alternatives [...]

I am practicing, but this is the "domain" I'd like to focus on:
string/sequence manipulation in various way, to create sort of games,
but also to investigate the "patterns" of a particular language.
I am writing a function called "scramble", that take a word and mix up
every characters randomly. This is the algorithm (I am more interested
on clarity then efficiency for now):

- create a new vector of the same size of the original
- choose a position at random in the original vector
- copy the element from  the chosen position  to the first position in
vector02
- delete the element from vector01
- again choose a position at random in the original vector (that
actually "is" the original vector "minus" the item(s) eliminated
- copy this item to the second position of the new vector
- remove it from vector01
- chose at random .... and so on.

An here is the implementation:

(defun scramble01 (vec01) 
  (let*
      ((len (length vec01))
       (vec02 (make-string len)))
    (do ((n 0 (1+ n)))
        ((>= n len))
      (setf rnd (random (length vec01)))
      (setf elem (aref vec01 rnd))
      (setf (aref vec02 n) elem)
      (delete elem vec01 :start rnd :count 1))
    (format t "~A~%" vec02)))
From: Thomas A. Russ
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <ymiod9t582j.fsf@blackcat.isi.edu>
"An[z]elmus" <·······@somewhere.org> writes:

> On 04 Mar 2008 18:17:45 -0800, ···@sevak.isi.edu (Thomas A. Russ)
> wrote:
> >> (remove #\a "adagiare" :start 5 :count 1) ------------> "adagire"
> >> [...]
> >
> >Of course, depending on what you are doing with this, there may be more
> >efficient alternatives [...]
> 
> I am practicing, but this is the "domain" I'd like to focus on:
> string/sequence manipulation in various way, to create sort of games,
> but also to investigate the "patterns" of a particular language.
> I am writing a function called "scramble", that take a word and mix up
> every characters randomly. This is the algorithm (I am more interested
> on clarity then efficiency for now):

Essentially, what you are doing is creating a permutation of the
original vector.  So you should search for some of the algorithms for
generating permutations.  They appear from time to time in this
newsgroup.

The only question then, is whether you want all permutations, or just
some subset of them.  If you want to do this repeatedly, you could
perhaps generate all permutations, shuffle them, and then process the
shuffled set serially.


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: An[z]elmus
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <vjuts3dd3vugtvhjpmdtohbamtd40enl1q@4ax.com>
On 05 Mar 2008 10:39:32 -0800, ···@sevak.isi.edu (Thomas A. Russ)
wrote:
>Essentially, what you are doing is creating a permutation of the
>original vector.  

Well, thank you for introducing me the word "permutation".

>So you should search for some of the algorithms for
>generating permutations.  They appear from time to time in this
>newsgroup.

Indeed in a few seconds I found some of the algorithms you mention. I
just tried one that appear in a thread in 1998 and the author claims
he wrote it about 8 or 9 years before.
From times to times I have something like that in mind when I think
about how "sounds" combine to make sillables and sillables to make
words. Some combinations are allowed, some are not, some possible
combinations are exploited, some other are not.

>The only question then, is whether you want all permutations, or just
>some subset of them.

Ditto (like I said).

>If you want to do this repeatedly, you could
>perhaps generate all permutations, shuffle them, and then process the
>shuffled set serially.

There is always something to shuffle.
From: Pascal Costanza
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <6381qgF26fsskU1@mid.individual.net>
An[z]elmus wrote:
> On 04 Mar 2008 18:17:45 -0800, ···@sevak.isi.edu (Thomas A. Russ)
> wrote:
>>> (remove #\a "adagiare" :start 5 :count 1) ------------> "adagire"
>>> [...]
>> Of course, depending on what you are doing with this, there may be more
>> efficient alternatives [...]
> 
> I am practicing, but this is the "domain" I'd like to focus on:
> string/sequence manipulation in various way, to create sort of games,
> but also to investigate the "patterns" of a particular language.
> I am writing a function called "scramble", that take a word and mix up
> every characters randomly. This is the algorithm (I am more interested
> on clarity then efficiency for now):
> 
> - create a new vector of the same size of the original
> - choose a position at random in the original vector
> - copy the element from  the chosen position  to the first position in
> vector02
> - delete the element from vector01
> - again choose a position at random in the original vector (that
> actually "is" the original vector "minus" the item(s) eliminated
> - copy this item to the second position of the new vector
> - remove it from vector01
> - chose at random .... and so on.
> 
> An here is the implementation:
> 
> (defun scramble01 (vec01) 
>   (let*
>       ((len (length vec01))
>        (vec02 (make-string len)))
>     (do ((n 0 (1+ n)))
>         ((>= n len))
>       (setf rnd (random (length vec01)))
>       (setf elem (aref vec01 rnd))
>       (setf (aref vec02 n) elem)
>       (delete elem vec01 :start rnd :count 1))
>     (format t "~A~%" vec02)))

This may not do what you expect it to do: Delete _may_ modify a vector, 
but it doesn't have to. The only thing you can rely on is that delete 
returns a modified vector. Whether the original vector is changed by 
delete or not is implementation-dependent (and implementations are not 
required to be consistent in their behavior either).

It's better to use functions here that are guaranteed to perform side 
effects on vectors, like (setf aref).


Pascal

-- 
1st European Lisp Symposium (ELS'08)
http://prog.vub.ac.be/~pcostanza/els08/

My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: An[z]elmus
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <rgqts39ud27tgmeosej0hrmrebkk6b60ge@4ax.com>
On Wed, 05 Mar 2008 17:58:55 +0100, Pascal Costanza <··@p-cos.net>
wrote:
>> (defun scramble01 (vec01) 
>> [...]
>>       (delete elem vec01 :start rnd :count 1))
>>     (format t "~A~%" vec02)))
>
>This may not do what you expect it to do: Delete _may_ modify a vector, 
>but it doesn't have to. The only thing you can rely on is that delete 
>returns a modified vector. Whether the original vector is changed by 
>delete or not is implementation-dependent (and implementations are not 
>required to be consistent in their behavior either).
>
>It's better to use functions here that are guaranteed to perform side 
>effects on vectors, like (setf aref).

Yes, right, in a previous post in this same thread I have been already
warned about this problem. I'll try to figure out how to fix it.

The only think that come to my my mind is to write a function that
return a "shrinked" string without the character to be removed. May be
this can be done using adjustable array and fill pointer.
From: An[z]elmus
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <1540t3ljqvfo91jke5g3tc831u01auvo1o@4ax.com>
On Wed, 05 Mar 2008 19:51:20 +0100, "An[z]elmus"
<·······@somewhere.org> wrote:

>>> (defun scramble01 (vec01) 
>>> [...]
>>>       (delete elem vec01 :start rnd :count 1))
>>> [...]

Using the function delete in that way it is is not safe beacuse it may
not modify it's second argument and it may instead create a copy.

But is it too bad to re-bind the variable/argument with setf as shown
below?

(setf vec01 (delete elem vec01 :start rnd :count 1))
or
(setf vec01 (remove elem vec01 :start rnd :count 1))
From: Pascal Costanza
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <63aiuhF25mjqfU1@mid.individual.net>
An[z]elmus wrote:
> On Wed, 05 Mar 2008 19:51:20 +0100, "An[z]elmus"
> <·······@somewhere.org> wrote:
> 
>>>> (defun scramble01 (vec01) 
>>>> [...]
>>>>       (delete elem vec01 :start rnd :count 1))
>>>> [...]
> 
> Using the function delete in that way it is is not safe beacuse it may
> not modify it's second argument and it may instead create a copy.
> 
> But is it too bad to re-bind the variable/argument with setf as shown
> below?
> 
> (setf vec01 (delete elem vec01 :start rnd :count 1))
> or
> (setf vec01 (remove elem vec01 :start rnd :count 1))

No. That's actually what you should do in conjunction with delete.


Pascal

-- 
1st European Lisp Symposium (ELS'08)
http://prog.vub.ac.be/~pcostanza/els08/

My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: An[z]elmus
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <11e0t3htbskfbtloo0gtat3qhfs77mdecd@4ax.com>
On Thu, 06 Mar 2008 16:51:20 +0100, "An[z]elmus"
<·······@somewhere.org> wrote:
>>>> (defun scramble01 (vec01) 
I took the idea from an old post in this newsgroup and re-wrote the
function.

(defun my-random (from to)
  (+ from (random (- to from))))

;;" ... randomly permute a vector of length n by swapping the first
;;element of the vector with a random (possibly also the first)
;;element.  After this swap, the first element in the permutation is
;;fixed.  We next swap the second element of the vector with a random
;;element other than the first element.  And so on. ..."
;;
;;uses my-random

(defun scramble04 (seq)
  (let ((lim (length seq)))
    (do ((n 0 (1+ n)))
        ((>= n lim))
      (setf rnd (my-random n lim))
      (rotatef (elt seq n) (elt seq rnd)))
    seq)) 
From: Thomas A. Russ
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <ymiejan65fy.fsf@blackcat.isi.edu>
"An[z]elmus" <·······@somewhere.org> writes:

> I took the idea from an old post in this newsgroup and re-wrote the
> function.
> 
> (defun my-random (from to)
>   (+ from (random (- to from))))
> 
> ;;" ... randomly permute a vector of length n by swapping the first
> ;;element of the vector with a random (possibly also the first)
> ;;element.  After this swap, the first element in the permutation is
> ;;fixed.  We next swap the second element of the vector with a random
> ;;element other than the first element.  And so on. ..."
> ;;
> ;;uses my-random
> 
> (defun scramble04 (seq)
>   (let ((lim (length seq)))
>     (do ((n 0 (1+ n)))
>         ((>= n lim))
>       (setf rnd (my-random n lim))
>       (rotatef (elt seq n) (elt seq rnd)))
>     seq)) 

Well, the only problem that I see with tthis code is that it globally
sets the value of RND.  You don't want to do that.  There are three ways
you can avoid that.  I'll give them in increasing order of code
modification, although I'll say I prefer the last one best.

;; 1.  Establish local binding for the variable RND in the LET

(defun scramble04 (seq)
   (let ((lim (length seq))
         rnd)
     (do ((n 0 (1+ n)))
         ((>= n lim))
       (setf rnd (my-random n lim))
       (rotatef (elt seq n) (elt seq rnd)))
     seq))

;; 2.  Let DO do the updating for you

(defun scramble04 (seq)
   (let ((lim (length seq)))
     (do ((n 0 (1+ n))
          (rnd (my-random n lim) (my-random n lim)))
         ((>= n lim))
       (rotatef (elt seq n) (elt seq rnd)))
     seq))

;; 3.  Don't bother with a variable at all,
;;     since it's only used once

(defun scramble04 (seq)
   (let ((lim (length seq)))
     (do ((n 0 (1+ n)))
         ((>= n lim))
       (rotatef (elt seq n) (elt seq (my-random n lim))))
     seq))

;; 4.  Use DOTIMES instead of DO,
;;      since you don't need all that power

(defun scramble04 (seq)
  (let ((lim (length seq)))
    (dotimes (n lim)
       (rotatef (elt seq n) (elt seq (my-random n lim))))
    seq))

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: An[z]elmus
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <m8o0t35le1ckdgjg2hligbp5kv1shqf4ra@4ax.com>
On 06 Mar 2008 11:03:13 -0800, ···@sevak.isi.edu (Thomas A. Russ)
wrote:
> [...]
>;; 3.  Don't bother with a variable at all,
>;;     since it's only used once
>
>(defun scramble04 (seq)
>   (let ((lim (length seq)))
>     (do ((n 0 (1+ n)))
>         ((>= n lim))
>       (rotatef (elt seq n) (elt seq (my-random n lim))))
>     seq))
>
>;; 4.  Use DOTIMES instead of DO,
>;;      since you don't need all that power
>
>(defun scramble04 (seq)
>  (let ((lim (length seq)))
>    (dotimes (n lim)
>       (rotatef (elt seq n) (elt seq (my-random n lim))))
>    seq))

Thank you, that was really very clear. 
From: Marco Antoniotti
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <4bff64cb-f6ae-4acc-a566-5aa01b2caf78@e60g2000hsh.googlegroups.com>
On Mar 6, 8:03 pm, ····@sevak.isi.edu (Thomas A. Russ) wrote:
> "An[z]elmus" <·······@somewhere.org> writes:
> > I took the idea from an old post in this newsgroup and re-wrote the
> > function.
>
> > (defun my-random (from to)
> >   (+ from (random (- to from))))
>
> > ;;" ... randomly permute a vector of length n by swapping the first
> > ;;element of the vector with a random (possibly also the first)
> > ;;element.  After this swap, the first element in the permutation is
> > ;;fixed.  We next swap the second element of the vector with a random
> > ;;element other than the first element.  And so on. ..."
> > ;;
> > ;;uses my-random
>
> > (defun scramble04 (seq)
> >   (let ((lim (length seq)))
> >     (do ((n 0 (1+ n)))
> >         ((>= n lim))
> >       (setf rnd (my-random n lim))
> >       (rotatef (elt seq n) (elt seq rnd)))
> >     seq))
>
> Well, the only problem that I see with tthis code is that it globally
> sets the value of RND.  You don't want to do that.  There are three ways
> you can avoid that.  I'll give them in increasing order of code
> modification, although I'll say I prefer the last one best.
>
> ;; 1.  Establish local binding for the variable RND in the LET
>
> (defun scramble04 (seq)
>    (let ((lim (length seq))
>          rnd)
>      (do ((n 0 (1+ n)))
>          ((>= n lim))
>        (setf rnd (my-random n lim))
>        (rotatef (elt seq n) (elt seq rnd)))
>      seq))
>
> ;; 2.  Let DO do the updating for you
>
> (defun scramble04 (seq)
>    (let ((lim (length seq)))
>      (do ((n 0 (1+ n))
>           (rnd (my-random n lim) (my-random n lim)))
>          ((>= n lim))
>        (rotatef (elt seq n) (elt seq rnd)))
>      seq))
>
> ;; 3.  Don't bother with a variable at all,
> ;;     since it's only used once
>
> (defun scramble04 (seq)
>    (let ((lim (length seq)))
>      (do ((n 0 (1+ n)))
>          ((>= n lim))
>        (rotatef (elt seq n) (elt seq (my-random n lim))))
>      seq))
>
> ;; 4.  Use DOTIMES instead of DO,
> ;;      since you don't need all that power
>
> (defun scramble04 (seq)
>   (let ((lim (length seq)))
>     (dotimes (n lim)
>        (rotatef (elt seq n) (elt seq (my-random n lim))))
>     seq))

... and to be consistent with Common Lisp lore and revered traditions

(defun scramble (seq &aux
                     (lim (lenght seq))
                     (result (copy-seq seq)))
   (dotimes (n lim result)
      (rotatef (elt result n) (elt result (my-random n lim))))

(defun nscramble (seq &aux (lim (length seq)))
   (dotimes (n lim seq)
      (rotatef (elt seq n) (elt seq (my-random n lim))))

Cheers
--
Marco
From: William James
Subject: Re: removing an element from a sequence
Date: 
Message-ID: <495f07fd-4fb5-4fff-a101-ceb9407f6896@v3g2000hsc.googlegroups.com>
On Mar 4, 4:39 pm, "An[z]elmus" <·······@somewhere.org> wrote:
> Function remove (or delete) eliminate all the occurences of an item in
> a sequence.
> for example:
>
> (remove #\a "adagio") ----> "dgio"
>
> Let say that I need to remove only one occurence at a time, for
> exmple I may need to remove the #\a at index 2 in "adagio" and obtain
> as a result "adgio".
> In other words, it would be handy to have a function that remove an
> element based on its position/index.
> I have not yet figured out how to do it properly.

newLISP v.9.3.0 on Win32, execute 'newlisp -h' for more info.

> (set 's "adagio")
"adagio"
> (nth-set (s 2) "")
"a"
> s
"adgio"
From: Pascal Costanza
Subject: Re: [Newbie] removing an element from a sequence
Date: 
Message-ID: <6361qsF25psg5U1@mid.individual.net>
An[z]elmus wrote:
> Function remove (or delete) eliminate all the occurences of an item in
> a sequence.
> for example:
> 
> (remove #\a "adagio") ----> "dgio"
> 
> Let say that I need to remove only one occurence at a time, for 
> exmple I may need to remove the #\a at index 2 in "adagio" and obtain
> as a result "adgio".
> In other words, it would be handy to have a function that remove an
> element based on its position/index.
> I have not yet figured out how to do it properly.

Check out the functions 'position and 'replace.

If you basically want 'remove or 'delete, but want to limit the number 
of removals/deletions, check out the keyword arguments to 'remove and 
'delete, especially the 'count argument.


Pascal

-- 
1st European Lisp Symposium (ELS'08)
http://prog.vub.ac.be/~pcostanza/els08/

My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Thomas A. Russ
Subject: Re: [Newbie] removing an element from a sequence
Date: 
Message-ID: <ymi8x0x7w6s.fsf@blackcat.isi.edu>
An[z]elmus wrote:
> Function remove (or delete) eliminate all the occurences of an item in
> a sequence.
> for example:
> (remove #\a "adagio") ----> "dgio"
> Let say that I need to remove only one occurence at a time, for exmple
> I may need to remove the #\a at index 2 in "adagio" and obtain
> as a result "adgio".

You mean like:

  (remove #\a "adagio" :start 2 :count 1)


> I have not yet figured out how to do it properly.

Look at <http://www.lisp.org/HyperSpec/FrontMatter/index.html> to find
teh full documentation of the Lisp functions.

-- 
Thomas A. Russ,  USC/Information Sciences Institute