This sentence is false

functional programming, software, and emacs.

drawing names, take 2

It turns out, the consummate dunce who originally posted the Perl code mentioned in my previous post (and whose code I used as a model to write mine) was thoughtful enough to include the possibility of infinite recursion in some cases.

Suppose you have drawn n - 2 names, and Ann and Bill still need gift-recipients; Curtis The Dunce and Bill are the names in the hat. So, Ann reaches in and gets Curtis. (Of course, he is a bad little boy who won’t get any presents. But that’s another story.) Then Bill chooses… well, duh. Problem. This is the bug in Perl-boy’s code.

As a public service, I have updated my code to eliminate this possibility. Enjoy your bug-free gift-name-drawing.

(* Draw randomly-selected names for each person in `nameList'. *)structure DrawNames = structlocaltype match = {name: string, match: string}

(* Set of strings. *)structure S = BinarySetFn(type ord_key = string                          val compare = String.compare)

(* List of all names. *)val nameList = ["Denis", "Lisa", "Dave", "Beth", "Tim", "Emma"]val names = S.addList (S.empty, nameList)

(* For the random-number generator seed. This seed is only sufficient. *)fun getpid () =    SysWord.toInt (Posix.Process.pidToWord (Posix.ProcEnv.getpid ()))fun now () =    let val time = Time.toMilliseconds (Time.now ())        val time' = case Int.maxInt                     of NONE => time                      | SOME x => LargeInt.mod (time, Int.toLarge x)    in Int.fromLarge time'    end

in

(* Match up all the names. *)fun match () =    let val seed = Random.rand (now (), getpid ())        fun randomElt l =            List.nth (l, (Random.randRange (0, (length l) - 1) seed))        fun getName set =            randomElt (S.listItems set)        fun getNameExcluding (excl, set) =            randomElt (S.listItems (S.difference (set, S.singleton excl)))

        (* Find a match for the given `name'. *)        fun findMatch (mapFrom, mapTo, matches) =            if S.isEmpty mapFrom            then matches            else let val name = getName mapFrom                     val match = getNameExcluding (name, mapTo)                     val mapFrom' = S.delete (mapFrom, name)                     val mapTo' = S.delete (mapTo, match)                 (* If the only choice is to map to oneself, we made the                  * wrong choice: try again. *)                 in if S.numItems mapFrom' = 1                       andalso S.equal (mapFrom', mapTo')                    then findMatch (mapFrom, mapTo, matches)                    else findMatch (mapFrom', mapTo',                                    {from=name, to=match} :: matches)                 end        fun printMatch {from, to} = print (from ^ " -> " ^ to ^ "\n")

        val matches = findMatch (names, names, [])    in app printMatch matches    end

end (* local *)end (* struct *)

22 December 2005 - Posted by dbueno | Uncategorized | | 7 Comments

7 Comments »

  1. I see a lot of words … but does it mean anything?

    Oh, btw, go back to my Perl post … read the comments.

    Comment by curtis | 23 December 2005 | Reply

  2. Oh, fraptuous day! My gift-drawing script will work now!

    Comment by Nathanael | 23 December 2005 | Reply

  3. Callooh! Callay!

    And, though it’s nonsense-speak, and thus probably doesn’t matter: it’s “frabjous”.

    Comment by denis | 23 December 2005 | Reply

  4. Curtis,

    Pretty nifty about Randal Schwartz reading your code. I noticed that the version that you wrote looks *nothing like* what he came up with. I guess that tells you something.

    Comment by denis | 23 December 2005 | Reply

  5. Yeah … I even gave him credit though. splice() is pretty neat … with it’s 3-argument version. However, he didn’t solve the infinite recursion problem … which, of course, was about a 20 second ordeal. I could have made it look more like my first version with approximately the same number of lines of code, but, I did like his ideas better. Besides, he bloody wrote the Perl book. Who in his right mind would pass up advice on that level?

    Comment by curtis | 23 December 2005 | Reply

  6. Actually, fraptuous was the verification word that I had to enter to comment. Or not. I was subconsciously mixing rapturous and frabjous, I’m sure.

    Comment by Nathanael | 24 December 2005 | Reply

  7. That being the case, I just want to say, lmamenz!

    Comment by curtis | 26 December 2005 | Reply


Leave a comment