| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
| |||
| |||
| 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 |
|
#2
| |||
| |||
| 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 |
|
#3
| |||
| |||
| 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 |
|
#4
| |||
| |||
| > > 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 |
|
#5
| |||
| |||
| 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 |
|
#6
| |||
| |||
| 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 |
|
#7
| |||
| |||
| > 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. |
|
#8
| |||
| |||
| 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. |
|
#9
| |||
| |||
| 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 ... |
|
#10
| |||
| |||
| >>>>> "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 os2if 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 :replacementif 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 |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.