Your solution is close but not really random (depending on what's
in the list).
Your solution assumes each element in the list is unique.
Your solution picks a random element but then removes the
first occurance from the left. You can see that trend in the
first run below. Notice that it removed the first 4 "3"'s first
which is not very probably. Pick itself is random but you
don't know what occurance it was.
Note in the second run below it removed some before the
"1" and some after. Because it is now data independent
and strictly position dependent.
The code for both methods is below.
And tweaked for MSWLogo (changed ? to p and replace let with make).
testrem
[3 3 3 3 1 3 3 3 3 3 3 3 3 3 3 3]
[3 3 3 1 3 3 3 3 3 3 3 3 3 3 3]
[3 3 1 3 3 3 3 3 3 3 3 3 3 3]
[3 1 3 3 3 3 3 3 3 3 3 3 3]
[1 3 3 3 3 3 3 3 3 3 3 3]
[1 3 3 3 3 3 3 3 3 3 3]
[1 3 3 3 3 3 3 3 3 3]
[1 3 3 3 3 3 3 3 3]
[1 3 3 3 3 3 3 3]
[1 3 3 3 3 3 3]
[1 3 3 3 3 3]
[1 3 3 3 3]
[1 3 3 3]
[1 3 3]
[1 3]
[3]
[]
[3 3 3 3 3 1 3 3 3 3 3 3 3 3 3 3]
[3 3 3 3 3 1 3 3 3 3 3 3 3 3 3]
[3 3 3 3 1 3 3 3 3 3 3 3 3 3]
[3 3 3 3 1 3 3 3 3 3 3 3 3]
[3 3 3 1 3 3 3 3 3 3 3 3]
[3 3 3 3 3 3 3 3 3 3 3]
[3 3 3 3 3 3 3 3 3 3]
[3 3 3 3 3 3 3 3 3]
[3 3 3 3 3 3 3 3]
[3 3 3 3 3 3 3]
[3 3 3 3 3 3]
[3 3 3 3 3]
[3 3 3 3]
[3 3 3]
[3 3]
[3]
[]
to remItemFrom :anItem :aList
;; empty listp output nil
if emptyp :aList [op [] ]
;; if anItem isn't in aList output aList
if not memberp :anItem :aList [op :aList]
;; if anItem is the first element in aList output the butfirst
of aList
if equalp :anItem first :aList [op bf :aList]
;; other wise create a list (with se) with the first element in
aList
;; and call us again with the rest of the list.
op (se first :aList remItemFrom :anItem bf :aList)
end
to remRandomFrom :aList
;; first pick the element to remove
make "anItem pick :aList
;; now remove it
op remItemFrom :anItem :aList
end
to testrem
;; Test old method
make "foo [3 3 3 3 3 1 3 3 3 3 3 3 3 3 3 3 3]
repeat count :foo [make "foo remRandomFrom :foo show :foo]
;; Test new method
make "foo [3 3 3 3 3 1 3 3 3 3 3 3 3 3 3 3 3]
repeat count :foo [make "foo TrueRemRandomFrom :foo show :foo]
end
to TrueRemItemFrom :anItem :aList
;; If we have shifted the list down such that the first element
;; is the one to be removed then do it
if :anItem = 1 [op butfirst :aList]
;; Shift the element we want to keep over and continue looking
op (se first :aList TrueRemItemFrom :anItem - 1 butfirst :aList)
end
to TrueRemRandomFrom :aList
;; Pick a random POSITION within the list
make "item (random (count :aList) - 1) + 1
;; Remove the element at that position
op TrueRemItemFrom :item :aList
end
Frank Caggiano wrote:
>
> Wendy Petti wrote:
> > I have a list with 11 words in it; each is the name of a procedure. I am
> > trying to pick one of these words at random and then eliminate it from the
> > list. (At a certain button click, all of the words can be restored to the
> > list.) But all I can manage to do is either run through the list in the
> > same order as originally entered, eliminating the first (or last) each time
> > (using butfirst or butlast), or select randomly without eliminating any
> > words and sometimes have the same word get chosen repeatedly. How can I
> > select a word randomly and then place that word at the beginning or end of
> > the list so it can be eliminated? Or if this is not possible, is there
> > some handy way of entering the list in a newly scrambled order each time a
> > button is clicked? Does it help to put the list into a text box?
>
> This will remove a random element from a list
> ;;
> ;; Remove a random element from a List
> ;; Report the updated list
> ;;
> to remRandomFrom :aList
> ;; first pick the element to remove
>
> let [anItem pick :aList]
>
> ;; now remove it
>
> op remItemFrom :anItem :aList
> end
>
> to remItemFrom :anItem :aList
> ;; empty list? output nil
> if empty? :aList [op [] ]
>
> ;; if anItem isn't in aList output aList
> if not member? :anItem :aList [op :aList]
>
> ;; if anItem is the first element in aList output the butfirst of aList
> if equal? :anItem first :aList [op bf :aList]
>
> ;; other wise create a list (with se) with the first element in aList
> ;; and call us again with the rest of the list.
> op (se first :aList remItemFrom :anItem bf :aList)
> end
>
> You would use it like:
> make "foo [1 2 3 4 5 6]
> show :foo
> -> 1 2 3 4 5 6
> make "foo remRandomFrom :foo
> show :foo
> -> 1 2 4 5 6
>
> Or
>
> make "foo [1 2 3 4 5 6 7 8 9]
> repeat count :foo [make "foo remRandomFrom :foo show :foo]
> 1 3 4 5 6 7 8 9
> 1 3 4 5 7 8 9
> 3 4 5 7 8 9
> 3 4 5 7 8
> 4 5 7 8
> 4 7 8
> 4 8
> 4
>
> Hope this helps.
> Be sure to check out my web site for more logo stuff.
>
> regards
> --
> Frank Caggiano
> caggiano@atlantic.net
> http://www.atlantic.net/~caggiano
> ---------------------------------------------------------------
> Please post messages to the Logo forum to logo-l@gsn.org. Mail
> questions about the list administration to logofdn@gsn.org. To
> unsubscribe send unsubscribe logo-l to majordomo@gsn.org.
--
===============================================================
George Mills
email: mills@softronix.com
http://www.softronix.com
The www page contains some very powerful educational software.
Our single most important investment is our kids.
---------------------------------------------------------------
Please post messages to the Logo forum to logo-l@gsn.org. Mail
questions about the list administration to logofdn@gsn.org. To
unsubscribe send unsubscribe logo-l to majordomo@gsn.org.
Global SchoolNet Foundation -
Linking Kids Around the World!
Copyright GSN - All Rights Reserved
- Comments
& Questions
Visit GSN's
Global
Schoolhouse for more exciting learning resources!
Search our Site
-
Home