Swaping elements in list

This is a discussion on Swaping elements in list within the logo forums in Programming Languages category; Hi all! I've just started to play with UCBLogo 5.5. Is there any nice way to swap (exchange) two elements in list? I need something like this: show swap [1 2 3] 2 3 [1 3 2] Thanks in advance! Best regards, Pawel...

Go Back   Application Development Forum > Programming Languages > logo

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #1  
Old 08-26-2008, 06:48 PM
nowosielski@gmail.com
Guest
 
Default Swaping elements in list

Hi all!
I've just started to play with UCBLogo 5.5.
Is there any nice way to swap (exchange) two elements in list?

I need something like this:
show swap [1 2 3] 2 3
[1 3 2]

Thanks in advance!
Best regards, Pawel
Reply With Quote
  #2  
Old 08-26-2008, 10:05 PM
Brett Frankenberger
Guest
 
Default Re: Swaping elements in list

In article <4e587d73-dc3b-4501-bd8c-0bbda0b43eb9@34g2000hsh.googlegroups.com>,
<nowosielski@gmail.com> wrote:
>Hi all!
>I've just started to play with UCBLogo 5.5.
>Is there any nice way to swap (exchange) two elements in list?
>
>I need something like this:
>show swap [1 2 3] 2 3
>[1 3 2]
>
>Thanks in advance!
>Best regards, Pawel


It's not clear if the second and third arguments to swap are intended
to represent positions in the list or values in the list. (You should
have provided an example where the values were different from the
positions.)

The following assumes that
swap [ ... ] 2 3
means swap the second and third items in the list. For example:
swap [ 5 6 7 1 2 3 ] 2 3
would output [ 5 7 6 1 2 3 ] (as opposed to [ 5 6 7 1 3 2 ]).

to swap :l :a :b
if :a = :b [ op :l ]
if :b > count :l [ op :l ]
if :a < 1 [ op :l ]
if :b < :a [ op swap :l :b :a ]
if :a > 1 [ op fput first :l swap bf :l :a - 1 :b - 1 ]
if :b < count :l [ op lput last :l swap bl :l :a :b ]
op ( fput last :l lput first :l bf bl :l )
end

There are better ways, but doing it recursively was more fun.

This doesn't work in UCBLogo if the first input is a word.

To get that functionality, replace "fput" with "combine" and replace
"lput" with "lcombine" defined as follows:

to lcombine :a :b
if wordp :b [ op word :b :a ]
op lput :a :b
end

-- Brett
Reply With Quote
  #3  
Old 08-27-2008, 12:20 AM
Brian Harvey
Guest
 
Default Re: Swaping elements in list

Brett Frankenberger <rbf+logoforum@panix.com> writes:
>to swap :l :a :b
> if :a = :b [ op :l ]
> if :b > count :l [ op :l ]
> if :a < 1 [ op :l ]
> if :b < :a [ op swap :l :b :a ]
> if :a > 1 [ op fput first :l swap bf :l :a - 1 :b - 1 ]
> if :b < count :l [ op lput last :l swap bl :l :a :b ]
> op ( fput last :l lput first :l bf bl :l )
>end


I like your solution, with two caveats:

1. All those error checks, while important in industrial-strength software,
make it harder to read the code. I had to think pretty hard about whether
any of the first three IF lines actually contributed anything to the flow of
control when the inputs are well-formed. I suspect the OP would find it
just as intimidating as I did. :-)

2. Because of the way lists are stored in Logo, BUTLAST and LPUT take
time proportional to the length of the list, so your solution takes
quadratic time. This doesn't really matter for kid-sized problems, but
I'd be inclined to try to scan the list left to right, just once, even in
a recursive solution:

to swap :l :a :b
if :a=1 [output ...]
if :b=1 [output ...]
output fput (first :l) (swap (butfirst :l) :a-1 :b-1)
end

I think probably to make the "..." parts work I'd need local variables
holding the values at positions :a and :b, or something.

And that's why I'd really probably write it with MAP:

to swap :l :a :b
output (map [cond [[[:a = #] [item :b :l]]
[[:b = #] [item :a :l]]
[else ?]]]
:l)
end
Reply With Quote
  #4  
Old 08-27-2008, 03:20 AM
nowosielski@gmail.com
Guest
 
Default Re: Swaping elements in list

>
> And that's why I'd really probably write it with MAP:
>
> to swap :l :a :b
> output (map [cond [[[:a = #] [item :b :l]]
> [[:b = #] [item :a :l]]
> [else ?]]]
> :l)
> end


Brett, Brian - thank you very much!

Brian, your solution looks perfect to me, unfortunately it seems
doesn't work. Logo doesn't evaluate the second members in both lists.
(Well, I'm not quite sure how should tell it). Please consider example
before:

? show swap [x y z] 2 3
[x [item :b :l] [item :a :l]]

How can I fix it?

Once again thanks for reply,
Pawel
Reply With Quote
  #5  
Old 08-27-2008, 10:26 AM
Brian Harvey
Guest
 
Default Re: Swaping elements in list

nowosielski@gmail.com writes:
>Brian, your solution looks perfect to me, unfortunately it seems
>doesn't work. Logo doesn't evaluate the second members in both lists.


Oops I should have double-checked the syntax before I tried using COND,
which I don't use that often in Logo... just leave out the brackets
around those expressions. (The way I did it matches Scheme's COND syntax,
not Logo's!)

to swap :l :a :b
output (map [cond [[[:a = #] item :b :l]
[[:b = #] item :a :l]
[else ?]]]
:l)
end
Reply With Quote
  #6  
Old 08-27-2008, 11:09 AM
Michael Malien
Guest
 
Default Re: Swaping elements in list

On Aug 27, 4:26*pm, b...@cs.berkeley.edu (Brian Harvey) wrote:
> nowosiel...@gmail.com writes:
> >Brian, your solution looks perfect to me, unfortunately it seems
> >doesn't work. Logo doesn't evaluate the second members in both lists.

>
> Oops I should have double-checked the syntax before I tried using COND,
> which I don't use that often in Logo... *just leave out the brackets
> around those expressions. *(The way I did it matches Scheme's COND syntax,
> not Logo's!)
>
> to swap :l :a :b
> output (map [cond [[[:a = #] item :b :l]
> * * * * * * * * * *[[:b = #] item :a :l]
> * * * * * * * * * *[else ?]]]
> * * * * * * :l)
> end


Hello,

by using two helper procedures
now :l can be either a word or a list
and more than one swap is allowed, as follows:

to ashow :i
if wordp :l [localmake "s " repeat :i [make "s word :s thing word "v
repcount]]
if listp :l [localmake "s [] repeat :i [make "s se :s thing word "v
repcount]]
op :s
end

to aswap :a :b :i [:m 0]
repeat count :a [
make "m thing word "v item repcount :a
make word "v item repcount :a thing word "v item repcount :b
make word "v item repcount :b :m]
end

to myswap :l :a :b :i
if emptyp :l [aswap :a :b :i op ashow :i]
make "i :i+1
localmake word "v :i first :l
op myswap bf :l :a :b :i
end


To avoid the 4th argument '0'
in
myswap "567123 [1 3] [2 4] 0

myswap becomes:

to myswap :l :a :b
if not namep "flag [localmake "i 0 localmake "flag "x]
if emptyp :l [aswap :a :b :i op ashow :i]
make "i :i+1
localmake word "v :i first :l
pr thing word "v :i
op myswap bf :l :a :b
end


Examples:

For
pr myswap "567123 [1 3] [2 4]
and
pr myswap [e f g 1 2 3] [1 3] [2 4]

and I obtain this:

-1-
651723
-2-
f e 1 g 2 3

I wonder whether there is an alternative to 'avoiding the 0' with a
flag. In other words: How can I write this more elegantly?

Michael
Reply With Quote
  #7  
Old 08-27-2008, 01:21 PM
Michael Malien
Guest
 
Default Re: Swaping elements in list

> I wonder whether there is an alternative to 'avoiding the 0' with a
> flag. In other words: How can I write this more elegantly?



flag is just a name here and bears no boolean value, opposed to the
usual use of this term.
Reply With Quote
  #8  
Old 08-27-2008, 03:35 PM
Brian Harvey
Guest
 
Default Re: Swaping elements in list

Michael Malien <michaelm@quantentunnel.de> writes:
> In other words: How can I write this more elegantly?


Well, first of all, I don't see how this:

>if not namep "flag [localmake "i 0 localmake "flag "x]


can work more than once. After the first time, FLAG will be defined,
and so the initialization of I won't happen. You'd need an ERN "FLAG
in there somewhere.

But, again, I'd use higher order functions. I think what you're really
trying to do in MYSWAP is this:

FOREACH :L [MAKE WORD "V # ?]

and in ASHOW what you're doing is basically just

OUTPUT APPLY (IFELSE WORDP :L ["WORD] ["LIST]) ~
MAP "THING MAP.SE [WORD "V #] :L

It's a little tricky (MAP and MAP.SE) if you want to be able to handle
lists of lists correctly. The MAP.SE gives you a list [V1 V2 V3 ...]
and then the MAP gives you the values of those variables.

Of course there are lots of other ways to do it! I'm just a big fan of
higher order functions.
Reply With Quote
  #9  
Old 08-27-2008, 04:45 PM
Michael Malien
Guest
 
Default Re: Swaping elements in list

On Aug 27, 9:35*pm, b...@cs.berkeley.edu (Brian Harvey) wrote:
> Michael Malien <micha...@quantentunnel.de> writes:
> > In other words: How can I write this more elegantly?

>
> Well, first of all, I don't see how this:
>
> >if not namep "flag [localmake "i 0 localmake "flag "x]

>
> can work more than once. *After the first time, FLAG will be defined,
> and so the initialization of I won't happen. *You'd need an ERN "FLAG
> in there somewhere.


the line was meant to make I local and set it to 0 once.


> But, again, I'd use higher order functions. *I think what you're really
> trying to do in MYSWAP is this:
>
> * * * * FOREACH :L [MAKE WORD "V # ?]
>
> and in ASHOW what you're doing is basically just
>
> * * * * OUTPUT APPLY (IFELSE WORDP :L ["WORD] ["LIST]) ~
> * * * * * * * * * * *MAP "THING MAP.SE [WORD "V #] :L
>
> It's a little tricky (MAP and MAP.SE) if you want to be able to handle
> lists of lists correctly. *The MAP.SE gives you a list [V1 V2 V3 ...]
> and then the MAP gives you the values of those variables.


Thanks Brian, the program works fine now and looks more compact.


> Of course there are lots of other ways to do it! *I'm just a big fan of
> higher order functions.


I would be interested to see a few other ways ...

Reply With Quote
  #10  
Old 08-28-2008, 11:03 PM
Andru Luvisi
Guest
 
Default Re: Swaping elements in list

>>>>> "nowosielski" == nowosielski <nowosielski@gmail.com> writes:
nowosielski> Hi all! I've just started to play with UCBLogo 5.5.
nowosielski> Is there any nice way to swap (exchange) two elements
nowosielski> in list?
nowosielski> I need something like this: show swap [1 2 3] 2 3 [1
nowosielski> 3 2]

Here is my attempt. It contains no error checking and assumes that
pos2 is greater than pos1.

to swap :l os1 os2
if os1 = 1 [
local "seconditem
local "sublist
make "sublist swaphelper (bf :l) os2-1 (first :l)
op fput :seconditem :sublist
]
op fput (first :l) (swap (butfirst :l) os1-1 os2-1)
end

to swaphelper :l os :replacement
if os = 1 [
make "seconditem first :l
op fput :replacement (butfirst :l)
]
op fput (first :l) (swaphelper (butfirst :l) os-1 :replacement)
end

Andru
--
Andru Luvisi

Quote Of The Moment:
One of the most straightforward measures [of programmer productivity],
of course, is the number of lines a programmer produces per day. By that
measure *my* most productive days are when I have a negative count.
-- Niklaus Wirth
Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 01:57 AM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.