handmade Carcassonne

Carcassonne tiles

I wanted to play Carcassonne with my family today and had remembered to bring home the Followers, scoreboard, point tiles, rules, and the River expansion tiles, but not the big bag of tiles that are the whole point of the game. Derr. Well, one can find all sorts of images of tiles online, so I saved those files, scaled them a bit to be a decent size, and printed them out. I then felt like a second-grader again as I cut out all the tiles and glued them onto cardboard to make them sturdier. We played the game with both the River and Inns and Cathedrals expansions and it turned out just fine. I made a full set myself by pasting the tiles onto a Priority Mail box, and my dad made another full set by pasting the tiles onto cigarette tube boxes. His came out neater than mine because he used a utility knife and a ruler to cut the tiles while I used scissors alone. I don’t feel bad about reproducing the tiles since I own the game and the expansions we used, having bought them at a game store in Lexington.

Posted in Daily life | Tagged , | Leave a comment

heap sort in ML

This past semester for my programming languages class, we had to implement heap sort in Standard ML. This is my implementation, which I release under the GNU General Public License v3. I split the code into two separate files: shared.ml and heap_sort.ml, where shared.ml contains functions that might be of use with other sorting algorithms and heap_sort.ml contains functions and code specific to heap sort.

Note for students: my professor requested I state that, should you be taking his programming languages class CS 655 at the University of Kentucky and you try to use this code, (1) you'll get in trouble for using someone else's work and (2) you have to include the GPL and my copyright notice, which would be a real big hint that it's not entirely your work. ;)

shared.ml

OCaml

(* Copyright 2009 Sarah Vessels
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. *)

(* Define a comparison function for integers that will return -1 if the first
 * element is smaller than the second, 0 if they are equal, and 1 if the first
 * element is larger than the second. *)

fun int_compare (a:int, b) = if a < b then ~1 else if a = b then 0 else 1;

(* Comparison function for reals; see int_compare. *)
fun real_compare (a:real, b) = if a < b then ~1 else if a = b then 0 else 1;

(* Comparison function for chars; see int_compare. *)
fun char_compare (a:char, b) = if a < b then ~1 else if a = b then 0 else 1;

(* Comparison function for bools; see int_compare.  Arbitrarily choosing true to
 * be less than false. *)

fun bool_compare (a:bool, b) = if a=true andalso b=false then ~1 else if a = b then 0 else 1;

(* Comparison function for strings; see int_compare. *)
fun str_compare (a:string, b) = if a < b then ~1 else if a = b then 0 else 1;

(* Using the given comparison function, this returns true if a <= b, false
 * otherwise. *)

fun leq (<=>, a, b) = if (<=> (a, b)) < 1 then true else false;

(* Using the given comparison function, this returns true if a >= b, false
 * otherwise. *)

fun geq (<=>, a, b) = if (<=> (a, b)) > ~1 then true else false;

(* Using the given comparison function, this returns true if a < b, false
 * otherwise. *)

fun lt (<=>, a, b) = if (<=> (a, b)) = ~1 then true else false;

(* Using the given comparison function, this returns true if a > b, false
 * otherwise. *)

fun gt (<=>, a, b) = if (<=> (a, b)) = 1 then true else false;

(* Using the given comparison function, this returns true if a = b, false
 * otherwise. *)

fun eq (<=>, a, b) = if (<=> (a, b)) = 0 then true else false;

(* Returns a sub-list of the given list from indices i to j, inclusive. *)
fun sub_list (arr, i, j) =
  let
    (* The last valid index in the given list *)
    val last_index = (length arr) - 1
  in
    (* Ensure the given indices are valid in the given list. *)
    if i >= 0 andalso j >= 0 andalso i <= last_index andalso j <= last_index then
      let
        (* The first j+1 elements of the list *)
        val first_els = List.take (arr, j+1)
      in
        if i < j then
          (* Remove the first i elements of the first j+1 elements and return
           * what's left *)

          List.drop (first_els, i)
        else if i = j then
          (* Single-element list *)
          [List.nth (arr, i)]
        else
          (* i > j, so call this method again with the smaller element passed as
           * the first index. *)

          sub_list (arr, j, i)
      end
    else
      (* Invalid indices given, return an empty list/nil. *)
      []
  end;
     
(* Given a list arr and indices i and j, this will swap the values in arr found
 * at the indices i and j *)

fun swap (arr, i, j) =
  let
    (* Get a list of the first elements in the original list, up to the ith
     * element *)

    val first_els = List.take (arr, i)

    (* Get the ith element *)
    val i_el = List.nth (arr, i)

    (* Get the jth element *)
    val j_el = List.nth (arr, j)

    (* Get a list of the last elements in the original list, starting at the
     * (j+1)th element *)

    val last_els = List.drop (arr, j+1)

    (* Get the last valid index in the given list *)
    val last_index = (length arr) - 1
  in
    if i > last_index orelse i < 0 orelse j > last_index orelse j < 0 then
      (* Error, so just return the original array *)
      arr
    else if i = j-1 then
      (* No elements between i and j, so the swap is easy *)
      (first_els) @ [j_el] @ [i_el] @ (last_els)
    else if i < j then
      let
        (* Get a list of the elements strictly between indices i and j in
         * the original array *)

        val between_els = sub_list (arr, i+1, j-1)
      in
        (first_els) @ [j_el] @ between_els @ [i_el] @ (last_els)
      end
    else if i = j then
      (* Same indices given, no swap necessary *)
      arr
    else
      (* i > j, so call this method with the lower index first *)
      swap (arr, j, i)
  end;

(* Given a list, an index, and a value, this will return the same list with the
 * value at the given index set to be the given value. *)

fun set_value (arr, index, value) =
  let
    val size = length arr
  in
    (* If the given index is invalid, just return the original list,
     * unmodified. *)

    if index < 0 orelse index >= size then
      arr
    else
      (* Append the value to the end of the original list, then use swap to put
       * it at the desired index, then return only as many elements from the
       * new list as there were in the original list. *)

      List.take (swap (arr @ [value], index, size), size)
  end;

heap_sort.ml

OCaml

(* Copyright 2009 Sarah Vessels
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. *)
use "shared.ml";

(* Given i, this will return the index of i's left child. *)
val left_index = fn i => 2*i;

(* Given i, this will return the value at i's left child. *)
fun left_child (arr, i) = List.nth (arr, left_index i);

(* Given i, this will return the index of i's right child. *)
val right_index = fn i => (2*i) + 1;

(* Given i, this will return the value at i's right child. *)
fun right_child (arr, i) = List.nth (arr, right_index i);

(* Given a list arr, an index i, and the size of the heap contained in the
 * given list, this will returns the entire list, modified s.t. the heap rooted
 * at i is a max heap.  This also requires a comparison function that works with
 * the type of elements found in the given list. *)

fun max_heapify_w_size (compare, arr, i, heap_size) =
  let
    val l = left_index i  (* Index of i's left child *)
    val r = right_index i (* Index of i's right child *)

    (* Value at root i *)
    val value = List.nth (arr, i)
  in
    if (
      l <= heap_size andalso
      gt (compare, left_child (arr, i), value) andalso
      (
        r > heap_size orelse
        leq (compare, right_child (arr, i), left_child (arr, i))
      )
    ) then
      (* Largest is left child, so swap left child and root i, then max heapify
       * at the left child index. *)

      max_heapify_w_size (compare, swap (arr, i, l), l, heap_size)
    else if (
      r <= heap_size andalso
      gt (compare, right_child (arr, i), value)
    ) then
      (* Largest is right child, so swap right child and root i, then max
       * heapify at the right child index. *)

      max_heapify_w_size (compare, swap (arr, i, r), r, heap_size)
    else
      (* Largest is root i, no change necessary, just return the list
       * unchanged. *)

      arr
  end;

(* Convenience function for max heapifying a heap in the given list rooted at
 * the given i with a fixed heap size (namely, one less than the length of the
 * given list).  Requires a comparison function for comparing elements in the
 * given list. *)

fun max_heapify (compare, arr, i) =
  max_heapify_w_size (compare, arr, i, (length arr) - 1);

(* Recursive method for turning an entire given list into a max heap.  Requires
 * the initial root for max_heapify be given as a parameter.  Requires a
 * comparison function for comparing elements in the given list. *)

fun build_max_heap_rec (compare, arr, 0) = max_heapify (compare, arr, 0)
  | build_max_heap_rec (compare, arr, i) =
      build_max_heap_rec (compare, max_heapify (compare, arr, i), i-1);

(* Convenience function for turning an entire given list into a max heap.  Makes
 * use of the build_max_heap_rec function by passing in an initial root to
 * max_heapify.  Requires a comparison function to compare elements in the given
 * list. *)

fun build_max_heap (compare, arr) =
  let
    val heap_size = (length arr) - 1
    val initial_i = heap_size div 2
  in
    build_max_heap_rec (compare, arr, initial_i)
  end;

(* A recursive heap_sort implementation taking a list, an initial index, and a
 * heap size for the given list.  Requires a comparison function to compare
 * elements in the given list. *)

fun heap_sort_rec (compare, arr, 1, heap_size) =
    (* Max heapify the list at root 0 after swapping the values at indices 0 and
     * 1 in the given list. *)

    max_heapify_w_size (compare, swap (arr, 0, 1), 0, heap_size-1)
  | heap_sort_rec (compare, arr, i, heap_size) =
    let
      (* Decrement the heap size we're looking at by 1 each time *)
      val dec_heap_size = heap_size-1
    in
      (* Swap the values at indices 0 and i, then recursively heap_sort the
       * modified list by looking at the next value for i and looking at a
       * smaller heap *)

      heap_sort_rec (compare, max_heapify_w_size (compare, swap (arr, 0, i),
        0, dec_heap_size), i-1, dec_heap_size)
    end;

(* Convenience function for sorting a given list with heap_sort.  Makes use of
 * heap_sort_rec by passing in an initial index and initial heap size.
 * Initially converts the given list into a max heap, which is necessary for
 * heap_sort.  Requires a comparison function for comparing the elements in the
 * given list.
 *)

fun heap_sort (compare, arr) =
  let
    val heap_size = (length arr) - 1
    val max_heap = build_max_heap (compare, arr)
  in
    heap_sort_rec (compare, max_heap, heap_size, heap_size)
  end;

(* Example unsorted lists and the results of heap-sorting them.  I don't print
 * these out because mosml shows the results when you run this file. *)

print "Sorting integers:\n";
val unsorted_list = [16, 4, 10, 14, 7, 9, 3, 2, 8, 1];
val sorted = heap_sort (int_compare, unsorted_list);

val unsorted_list = [5, 4, 3, 2, 1, 0, ~1, ~2, ~3, ~4, ~5];
val sorted = heap_sort (int_compare, unsorted_list);

print "Sorting strings:\n";
val unsorted_list = ["my", "mother", "told", "me", "to", "pick", "the", "very"]
val sorted = heap_sort (str_compare, unsorted_list);

val unsorted_list = ["best", "one", "and", "you", "are", "not", "not", "it"]
val sorted = heap_sort (str_compare, unsorted_list);

print "Sorting Booleans:\n";
val unsorted_list = [false, true];
val sorted = heap_sort (bool_compare, unsorted_list);

print "Sorting characters:\n";
val unsorted_list = [#"z", #"k", #"b", #"c", #"f"];
val sorted = heap_sort (char_compare, unsorted_list);

print "Sorting reals:\n";
val unsorted_list = [1.3, ~0.225, 3.1415, 87.5];
val sorted = heap_sort (real_compare, unsorted_list);

Posted in Programming | Tagged , | 1 Comment

lack of parenting

I just found, courtesy of Fark, this article: Boston mom calls 911 over son’s video game habit. I’m just flabbergasted. Really? You feel the need to call emergency services because you suck as a mom? I have a few suggestions for getting your son off the game console:

  1. Tell him to stop.
  2. Threaten him with loss of privileges, and actually follow through with the threats. Though really, I don’t have much hope of this working if the mom can’t make her child obey and resorts to calling 911.
  3. Slap him and force him to stop. This might be especially effective if the mother has never physically disciplined her child which, if she resorted to calling 911 because he wouldn’t stop playing Grand Theft Auto, I think we can assume she’s never done more than mumble “Stop. Behave. Don’t do that.” If she went from that kind of attitude to a sharp slap on the face with firm instructions to get his ass in bed before she breaks his game, he might be shocked into behaving.
  4. Unplug the game, preferably in the middle of his unsaved progress.
  5. Go get a hammer, frying pan, heavy book, paperweight, something. Don’t even say anything to the child, just drop/slam/otherwise bust the game console. He wants another one? He can buy it himself… After he has gone to bed. An even better alternative was suggested by a commenter on Fark: take his console away and donate it to charity. That way, some other child, one hopefully more obedient, can still enjoy the console, but your punk-ass kid cannot.

I have worries about being a mother myself because I’ve never had a strong, commanding voice. I have trouble getting dogs to obey me, let alone some more intelligent creature that might outsmart me. It’s my hope that, should I have children, I have quiet, shy children that are content to read or play with blocks and just be quiet and obedient. I was a pretty shy, quiet child myself, so this might be reasonable.

Posted in Opinions | Tagged | 1 Comment

why I’m not a dog lover

I was just reading Rose’s post about her mom’s dog being mean toward male guests and it reminded me that I had aimed to write a post about why it is that I don’t really like dogs. I stayed at Jon’s aunt’s house a few days ago and they had two indoor dogs. One of them, Slick, was just fine. She followed me around and would plop down on the floor nearby when I stationed myself at a computer or on the couch. She slept and offered herself up to be petted but without pestering me or slobbering or jumping up or snapping or any of the other annoying things dogs do. I liked her.

Clancy, on the other hand, was not so nice. From the moment I entered the house, he acted wary of me. He whined and whimpered around me, despite Jon and his aunt scolding the dog. When I turned my back on him, he nipped at my calves. Jon’s uncle told me I could whack the dog in the head if he pestered me or tried to bite me, but it never came to that. He seemed to be obedient in that he would go away when told, but any time I sat next to Jon on the couch or waved my arms or made any sudden movements, here came Clancy. He’d jump off of his couch and come over to ours, anxiously trying to get to me. To do what, I don’t know, but Jon held him at bay until Clancy was convinced to go lie down again.

And therein lies half the trouble with dogs for me: you can’t sit down or hold a conversation around some of them because they just won’t let you alone. You have guests and the dog has to jump up on them, slobber on them, bark constantly, whine, and generally interrupt the conversation. Ugh, and the smell. I’ve met maybe two dogs in my life that didn’t smell terrible. My brother’s girlfriend has a Yorkshire terrier that was pleasant enough, and it smelled fine. It became a pest at night, though, when it wouldn’t lie still in bed and kept waking me up by jumping to the floor and clicking around, then wanting back up on the bed. However, when it was put in another room, it barked and whined constantly out of loneliness.

I think part of my problem with dogs stems from the fact that, growing up, our dogs stayed outside. If we wanted to interact with them, we’d go out and see them. Otherwise, they were out of the way and not bothering us. So many people have indoor dogs that get run of the house and are left free to hassle any humans that live there or their guests. It’s a different perspective, living with a dog versus having a dog that stays outside.

People are always so forgiving of their misbehaving dogs, too. I have very little patience with a dog that jumps up and gets mud on my clothes, arbitrarily barks, sheds on everything, or generally stinks. Jon’s dog Susie is pleasant enough because she doesn’t bark and she’s happy to lie around and sleep all the time. That’s really what I look for in an animal: something soft and cuddly that will leave me alone unless I choose to interact with it. I think that’s why I like cats pretty well, because they’re so independent and aren’t as loud as dogs. Cats don’t stink, either, but they certainly shed, which is annoying. Of course, you have the litter box to change if you have an indoor cat but if that’s kept in some less used room, the smell isn’t noticeable in the rest of the house.

My brother has recently had a stray dog come around his house, and it’s been sweet enough. It has a nasty habit of jumping up on you, so whenever I walk in the yard I hold out my hands at arm’s length and tell it to stay back. This time of year, everything’s a soggy, muddy mess and the dog gets wet red clay all over its paws, which I definitely do not want smeared on me. The dog followed me back to my parents’ house one day and took to chasing our cats and chickens, which got my dad riled up. He chased it back to my brother’s house because he won’t tolerate an animal that disturbs the peace around here. My parents have two dogs that appreciate our cats as extra blankets in the winter; it’s a pretty endearing sight to see a dog covered in fluffy cats on the porch when it’s cold out.

Most of my dislike of dogs comes from me not wanting to be grungy or stinky, and my dislike of sudden noises. I like peace and quiet, so no barking at random stuff or people that I like. I don’t want to be covered in spit or coarse hair or stinky-dog smell. Any time I pet a dog, I have to wash my hands and the smell still doesn’t go away. Blecch. Despite getting covered in hair, I’m still very fond of cuddling cats, especially fat, fluffy cats that just want to lie around and be cuddled. Jon’s aunt had two such cats, Ishmael and Sami (I don’t know if they spelled it that way, I just kept mentally picturing it like that), and they kept me company by sitting in my lap while I worked at the computer.

Posted in Opinions | Tagged , | 2 Comments

couldn’t watch Watchmen

We got a bit of snow, enough to cover my brother’s porch, the trampoline, and the cars, but only barely enough to dust the grass. That was last night, when it was still coming down. At one point when I went out, I couldn’t tell if it was rain or snow before it later became decidedly snow. This morning, though, it’s all melting and everything’s a soggy mess out there.

My dad and I watched Up yesterday which was a treat for me because I loved that movie when I first saw it in the theater with Jon. My dad enjoyed it, too, and pointed out something I hadn’t considered. Erm, spoiler alert! Right, so in the movie, the bad guy falls off a zeppelin while holding a few helium balloons. He plummets through the clouds and I had always assumed he died, which was surprising because Disney never lets the bad guys die. Even the bad dogs in the movie were shown floating safely down so you can guess they live. Well, my dad noted that the bad guy fell from a high altitude but would be falling into denser air, which could help slow his descent with those balloons. The way Pixar did it, you can choose to believe whichever ending you like: the bad guy died by going squish! against the earth, or he lived thanks to those few balloons he held.

We also tried to watch Watchmen, along with my mom, but couldn’t get past the first twenty minutes or so. We had first watched Tales of the Black Freighter, a twenty-minute animated short that comes with Watchmen, and it was terrible. It’s like some teenage boy with bad animation skills made a short movie to show off how gory he could be. My dad and I were cracking up, but not at points where we were supposed to laugh. For example, this shipwrecked guy is on an island and he builds a boat out of his shipmates’ corpses because they’re full of gas and thus buoyant. My dad pointed to all the palm trees shown in the background and said “See those palm trees? Coconuts float.” He also commented on how it was a really bad idea to build a ship for the ocean out of dead bodies because there are plenty of carrion eaters in the ocean. Sure enough, the guy got attacked by sharks that were coming after his dead-body boat. Ugh. The narration throughout was like really bad poetry written by some melodramatic emo kid who thought he was being deep.

So we finished Tales of the Black Freighter and moved on to Watchmen, which wasn’t much better. The movie starts out focusing on this smiley-face button that gets a splatter of blood on it, like that was sooo poignant. It moves on to following the character Rorschach around, and he keeps talking in the same overly dramatic style as the narrator from Tales of the Black Freighter. One of his lines was something about “screams like an abattoir filled with retarded children”, and that’s the line that got me. Really? A slaughterhouse full of retarded kids? My dad said he couldn’t take another hour and a half of that crap, and that was just the first disc.

Posted in Reviews | Tagged , | Leave a comment