Content from 2008-05

Downtime Considered Harmful
posted on 2008-05-28 01:25:32

At long last, the site is live again. Clearly the downtime ended up being a little longer than expected. This was caused by a few things.


One thing was that there were not 3 prong outlets where the server needed to go. This hosting facility (house) is a little old and the only places the DSL line runs have 2 prong outlets. So that slowed me down a bit.


Secondly, there are 2 network cards on the server (one integrated in the mobo, the other's PCI). Linux was confusing the two. I could've fixed that Saturday evening, I grant you. I had previous engagements and better things to do the last few days though.


Finally, Bellsouth seems to be suffering more DNS outages over the last few days which caused a bit of chaos here. Anyone who has experienced this or has any questions about it feel free to ask me. If you are having DNS issues, I advise setting your secondary DNS to one of the OpenDNS servers or getting one of your friends to do so.


EDIT: This was originally written on Tuesday the 27th. Further delays were experienced due to internal political issues in the house but all is now resolved and the site has been up since last night. A blog entry with photos of the house is planned for later today.

Site Downtime
posted on 2008-05-24 20:17:38
Ladies and Gents,

Redlinernotes.com will be down from 4:15pm EST - ~5:30pm to move the server to a new hosting facility (i.e. house).

Thanks for your understanding. I look forward to filling your RSS feed again soon.

-Admin
Towards a new HR
posted on 2008-05-21 17:33:06
It's time to post on something other than code for a change. The last time I posted something non-technical was a music-related post in mid-April. I've had a strong urge lately to say something about this blog's title, "Improved Means for Achieving Deteriorated Ends". I've never really explained what that means to me before. It relates somewhat to a a fairly recent post about my "emerging philosophy" and I definitely have more to say but am still searching for the words to get it out. While searching for those words I've stumbled on an idea that I think is worth discussing and that perhaps serves as a more concrete example of the sorts of issues I'm thinking about.

So, what's the grand exciting topic in store for today? Hiring practices. I'm sure your first thought is that hiring issues are inherently boring. I'd agree if we're talking about staffing a company of 75,000 people. For example, I talked to a Chik-fil-a manager today and asked him for a ball park estimate of how many people worked nationwide at Chik-fil-a. He said that he had a small store with about 25 employees but stores vary between 10 and 100 employees and average about 50. There are 1,300 stores nationwide and then you've still got whoever works at corporate facilities and not in retail.

The truth is, in this setting the product (and your company's success) are not a function of the quality of your individual employees. In fact, if you could sell people Chik-fil-a sandwiches without stores it'd be a huge cost savings provided you could figure out the distribution. You really just need people to fill a non-contributory role. If there were robots that could do the job and customers didn't mind the difference that would be just as good. The point being that the person working the register's chief contribution to the product is handing it over once you ask for it. I'm not generalizing to all retail here but you get the idea.

Now, the difference in the hiring problem occurs when you are looking for contributory employees. Employees whose contributions fundamentally shape the final product that the success of your company rides upon. Careers like architects, programmers, teachers, or journalists. Since these people make or break the success of your firm you can't hire based around basic arithmetic and serviceable grammar. Architects, for example, need to have a sense of design, an understanding of how buildings work, and working knowledge of the tools used to make designs become paper and then reality.

To be as successful as possible you don't just want to hire decent people. You want to hire talented people. To whatever extent possible, you want to hire the best people and this is precisely where we start running into problems. Spotting the best people is very hard and in some ways analogous to The Blub Paradox. That is, I wouldn't trust a person who'd never programmed to hire programmers. Moreover, if an incompetent or only decent programmer is hiring other programmers it's not evident that he'd be able to spot the programmers better than himself. He might not know how to recognize them.

Most companies have two chief hiring practices that I'm aware of, the resume and the interview. The resume process is a screening process. It really exists so that you can weed out candidates based on a standard set of assumptions about the things they need to be successful and whether their qualifications seem to match up with those assumptions. It's pattern matching. This is why it's more difficult to get jobs sans sheepskin. People who pass the initial screen are interviewed by a member of the department with some experience (generally a manager) and evaluated for competency based on the interviewer's (hopefully reasoned and up-to-date) understanding of the job requirements.

One problem with this strategy is that you wind up with false positives in both directions. Any hiring manager has a story about a sure thing hire that turned out to be a nightmare working with the team or the long shot employee that wound up turning around two lagging departments. The real problem, I'll argue, is that current hiring practice is not evolving. You don't learn from your false positives. How would you do that you might ask? I'll tell you how. Treat employee hiring like investing. Companies, especially companies that sell products derived from their employees' creativity, like to talk about how their product is their people or the people are the difference. I say put your money where your mouth is.

If you turn an employee down for a job, I want someone to be able to tell me in two years whether he's gone on to have a very successful career at another company or has wound up working in a different industry. If I hire somebody and they turn out to be a disaster I want to dig up anything I've got on their initial interviews, write the eventual problems on the transcripts in red and put it in a separate filing cabinet for future reference. Do you see anybody going that far to hire good people? No. I won't argue that there's no reason for this. One reason is: it would be a full time job.

Let's take this idea a little further though. Let's say we don't just track our false positives. Lets keep in mind that there are different classes of applicants to begin with and, just to stick with our investment theme, let's call them low-risk, medium-risk and high-risk. Why not? After all, that kid without the diploma is high-risk. At least, that's the reason you gave for not hiring him wasn't it? Oh, that's right. You didn't have to give a reason for not hiring him. Nobody checks up on hiring decisions. There's something else worth thinking about. If you miss a candidate that could've netted your firm an extra 10% last quarter should your ass be on the line or not?

Anyway, what was I saying? Oh, right. A standard reason that most hiring managers avoid candidates without diplomas is the amount of risk. It ties back to a famous IT saying, "Nobody ever got fired for buying IBM." If it seems like a sensible decision to hire a diploma holding guy, hire him. At least if he turns out to be a disaster a bunch of people can say he doesn't look like an obviously bad candidate and they might've done the same thing. If a high school dropout turns out to be a bad employee people will say you should've known from the get-go. So, let's just call the kid high-risk. But keep in mind that high-risk goes in both directions because even though he never got his GED he's been programming x86 Assembly since he was 7.

Now, obviously this isn't practical all the time. It wouldn't work for Chik-fil-a and I'm sure there's some point where it wouldn't work even for a company whose product depends on their creative, contributory employees. You could only scale a process like this so much and whether that's a function of the number of employees or something else I couldn't say. In fact, doing this internally in a firm might be suicide. It might have to start as an HR firm exclusively though what we're describing probably sounds more like a scouting agency. You'd also almost certainly have to stick to a certain industry since, as I mentioned above, you have to be a good programmer to recognize a good programmer. Additionally, you definitely would want to spread your portfolio of hires across risk segments but let's move on before we get bogged down.

About now you might be wondering how this all ties back to my "emerging philosophy". It ties back because of the chain of impact from the corporate world to the academic one and beyond. I think a lot of problems exist in the educational system because we think absolutely everyone has to go through it. Parents are convinced that without college diplomas their children will not find gainful employment or have successful lives. I don't claim that hiring practices alone account for this but they do play a part. More importantly, the overall impact of this is one of waste in society. It's waste of compulsory schooling on those that may not need or desire it and it's a waste of those who excel through nontraditional means. It's time to find as many of these little bits of waste and inefficiency as we can and fix them. I think if we'll do that we'll find that the problem isn't that we need to produce more to satisfy demand but that we need to figure out a more equitable and beneficial distribution of the copious resources we already have.
HTDP Section 04
posted on 2008-05-19 14:13:12
Well, here's Section 04.

Resources:
Read: Section 04
Watch: Nothing. To my knowledge there are no online lectures based around HTDP. Correct me if I’m wrong.
Checked against: Nothing.

Exercises

4.1.1:
1. (and true true) -> true
2. (or true false) -> true
3. (not false) -> true

4.1.2:
1. (a) true, (b) false, (c) true
2. (a) false, (b) false, (c) true
3. (a) false, (b) false, (c) false

4.2.1:

;;1.
(define (is-between-3-and-7? n)
(and (> n 3) (<= n 10)))

;;2.
(define (is-between-3-7? n)
(and (> n 3) (< n 10)))

;;3.
(define (is-between-3-9? n)
(and (>= n 3) (< n 9)))

;;4.
(define (is-1-3-or-9-11? n)
(or (is-1-3? n) (is-9-11? n)))

(define (is-1-3? n)
(and (> n 1) (< n 3)))

(define (is-9-11? n)
(and (> n 9) (< n 11)))

;;alternate implementation in case the first smacks of premature optimization:
;;(both suffer from an ominous arbitrary function naming schema!)
(define (is-1-3-or-9-11? n)
(or (and (> n 1) (< n 3))
(and (> n 9) (< n 11))))

;;5.
(define (is-outside-1-3? n)
(not (and (>= n 1) (<= n 3))))

4.2.2:

;; 1. | | | | | | | | | | |
;; -5 0 5
;; (-----)
;; Contract: in-interval-1? : number -> boolean
;; Purpose: To test if a number is between -3 and 0.
(in-interval-1? -2)
(and (< -3 -2) (< -2 0))
(and true true)
true

;;2. | | | | | | | | | | |
;; 0 5 10
;; --) (----------------
;; Contract: in-interval-2? : number -> boolean
;; Purpose: To test if a number is less than 1 or greater than 2.
(in-interval-2? -2)
(or (< -2 1) (> -2 2))
(or true false)
true

;;3. | | | | | | | | | | |
;; 0 5 10
;; --) (----------
;; Contract: in-interval-3? : number -> boolean
;; Purpose: To test if a number is less than 1 or greater than 5.
(in-interval-3? -2)
(not (and (<= 1 -2) (<= -2 5)))
(not (and false true))
(not false)
true

4.2.3:

;;1.
(define (is-solution-1? x)
(= (+ (* 4 x) 2) 62))

;;2.
(define (is-solution-2? x)
(= (* (sqr x) 2) 102))

;;3.
(define (is-solution-3? x)
(= (+ 2 (* 4 (sqr x)) (* 6 x)) 462))

10 is a solution to 3. 12 and 14 are not solutions.

4.2.4:

;; I don't know what specific test cases the authors are referring to for problems 2.2.1 - 2.2.4 so I'll just make up a few.
(= (Fahrenheit->Celsius 32) 0)
(= (dollar->euro 20) 12.8399) ;; as of 05/18/08
(= (triangle 5 2) 5)
(= (convert3 9 2 7) 729)

4.3.1:
The left cond is legal. The right cond is illegal because it's second clause has no answer to evaluate. The last cond is illegal because it has no second clause to evaluate.

4.3.2:
(a) .040
(b) .045
(c) .060

4.3.3:
(a) 40
(b) 121
(c) 595

4.4.1:

(define (interest x)
(cond ((<= x 1000) (* .04 x))
((<= x 5000) (* .045 x))
(else (* .05 x))))

4.4.2:

(define (tax x)
(cond ((<= x 240) 0)
((<= x 480) (* .15 x))
(else (* .28 x))))

(define (netpay hrs)
(- (grosspay hrs) (tax (grosspay hrs))))

(define (grosspay hrs)
(* 12 hrs))

4.4.3:

(define (pay-back charges)
(cond ((<= charges 500) (* .025 charges))
((<= charges 1500) (* .05 charges))
((<= charges 2500) (* .075 charges))
(else (* .01 charges))))

4.4.4:

(define (how-many a b c)
(cond ((> (sqr b) (* 4 a c)) 2)
((= (sqr b) (* 4 a c)) 1)
((< (sqr b) (* 4 a c)) 0))) ;; or else 0))
;; (how-many 1 0 1) = 0


If we didn't assume the equation was proper we'd need to check (with
a cond) to see if a equaled 0 and return an error if it did.

That does it for Section 04. Hopefully, I'll get my act together and wrap up SICP Section 2.1 in the next week or so. :-) You've gotta work on some hard stuff too, right? Besides it's more interesting anyway.
HTDP Section 03
posted on 2008-05-19 13:43:29
As promised, here’s Section 03 with 04 soon to follow. Sections 03 and 04 are pretty unremarkable and the questions and answers are pretty self-explanatory. Again, you can check all the latest code in my repo by going to manifest, then books, htdp, and navigating to the various source files.

Resources:
Read: Section 03
Watch: Nothing. To my knowledge there are no online lectures based around HTDP. Correct me if I’m wrong.
Checked against: Nothing. Again, to my knowledge there are no available sources to check your answers beyond the locked solutions on the official site and message boards. That’s one reason I’m excited about doing HTDP this way along with SICP. The plethora of SICP resources stand in contrast to an absolute dearth of resources for HTDP.

Exercises

3.1.1:

(define (attendees ticket-price)
(- 870 (* 150 ticket-price)))


This function will give incorrect answers for negative values of ticket-price.

3.1.2:

(define (revenue ticket-price)
(* (attendees ticket-price) ticket-price))

(define (costs ticket-price)
(+ 180 (* .04 (attendees ticket-price))))

(define (profit ticket-price)
(- (revenue ticket-price) (costs ticket-price)))


(profit 3) returns the best price which is 1063.2.

3.1.3:
Both program definitions return the same results for inputs of 3, 4
and 5.

3.1.4:

(define (profit ticket-price)
(- (revenue ticket-price)
(cost ticket-price)))

(define (revenue ticket-price)
(* (attendees ticket-price) ticket-price))

(define (cost ticket-price)
(* 1.5 (attendees ticket-price)))

(define (attendees ticket-price)
(+ 120
(* (/ 15 .10) (- 5.00 ticket-price))))

(define (profit price)
(- (* (+ 120
(* (/ 15 .10)
(- 5.00 price)))
price)
(* 1.5
(+ 120
(* (/ 15 .10)
(- 5.00 price))))))


Both programs return the same results but profit margins have changed based on the new costs. (max (profit 3) (profit 4) (profit 5) is now (profit 4).

3.2.1:

(define fixed-costs 180)
(define price-per-attendee .04)
(define start-attendees 120)
(define attendees-per-dime 15)
(define dime .10)
(define start-price 5.00)


3.3.1:

(define inches-in-cm 2.54)
(define inches-in-ft 12)
(define feet-in-yard 3)
(define yards-in-rod 5.5)
(define rods-in-furlong 40)
(define furlongs-in-mile 8)

(define (inches->cm inches)
(* inches-in-cm inches))

(define (feet->inches feet)
(* inches-in-ft feet))

(define (yards->feet yards)
(* feet-in-yard yards))

(define (rods->yards rods)
(* yards-in-rod rods))

(define (furlongs->rods furlongs)
(* rods-in-furlong furlongs))

(define (miles->furlongs miles)
(* furlongs-in-mile miles))

(define (feet->cm feet)
(inches->cm (feet->inches feet)))

(define (yards->cm yards)
(feet->cm (yards->feet yards)))

(define (rods->inches rods)
(feet->inches (yards->feet (rods->yards rods))))

(define (miles->feet miles)
(yards->feet (rods->yards (furlongs->yards
(miles-furlongs miles)))))


3.3.2:

(define pi 3.14159)

(define (volume-cylinder radius height)
(* pi (sqr radius) height))


3.3.3:

(define pi 3.14159)

(define (area-cylinder radius height)
(* 2 pi radius (+ radius height)))


3.3.4:

(define (area-pipe inner-radius length thickness)
(+ (* 2 pi length (+ inner-radius thickness))
(* 2 (- (* pi (+ inner-radius thickness))
(* pi inner-radius)))))

(define (area-pipe inner-radius length thickness)
(+ (area-pipe-side inner-radius length thickness)
(* 2 (area-pipe-ring inner-radius thickness))))

(define (area-pipe-side inner-radius length thickness)
(* 2 pi length (+ inner-radius thickness)))

(define (area-pipe-ring inner-radius thickness)
(* 2 (- (* pi (+ inner-radius thickness))
(* pi inner-radius))))


This problem reminds me of several in SICP in that the real difficulty with it is a misunderstanding of the question. Once you understand what is desired it’s pretty easy to bang the code out. This seems analogous to the idea that once you have a well-understood, well-specified set of requirements producing the code is trivial and that the requirements are the difficult part. Of course, this leads to blather about how good enough specifications (and UML Diagrams) are equivalent to code (which is bullshit). People forget that requirements change and that unambiguous well-specified requirements are often impossible.

3.3.5:

(define (height time)
(* .5 time (speed time)))

(define (speed time acceleration)
(* time acceleration))


3.3.6:

(define (Celsius->Fahrenheit cels)
(+ 32 (/ (* cels 9) 5)))

(I 32)
(Celsius->Fahrenheit (Fahrenheit->Celsius 32))
(Celsius->Fahrenheit (* (- 32 32) (/ 5 9)))
(Celsius->Fahrenheit (* 0 (/ 5 9)))
(Celsius->Fahrenheit 0)
(+ 32 (/ (* 0 9) 5))
(+ 32 (/ 0 5))
(+ 32 0)
32


Plainly, these functions are inverses of each other though that should be self evident. Since they are inverses their composition returns the original input. The stepper returns the same results.

Well, that’s it for Section 03. It seems that the first 8 Sections at least deal with language primitives and fairly basic material. It certainly is easier to progress through HTDP relative to SICP but I have had the sense that I was learning more in SICP. We’ll see if this changes at all once I progress beyond the early sections though I haven’t decided whether I’ll keep going through HTDP or forge ahead on SICP.
HTDP Section 02
posted on 2008-05-19 03:25:27

So, I've finally gotten around to cleaning up SICP Section 1.3. It's not quite done but it's damn close. For now, I want to start posting some of the HTDP code I've been writing to get back in the hacking habit over the past few days. I also have some of Concrete Abstractions done and in my source code repository but it's nothing substantial. Without further ado, here's HTDP Section 02 (of 43!). Sections 03 and 04 will go up tomorrow. Note: I skipped HTDP Section 01 because there are no exercises or problems whatsoever.



Resources:

Read: Sections 01 and 02

Watch: Nothing. To my knowledge there are no online lectures based around HTDP. Correct me if I'm wrong.

Checked against: Nothing. Again, to my knowledge there are no available sources to check your answers beyond the locked solutions on the official site and message boards. That's one reason I'm excited about doing HTDP this way along with SICP. The plethora of SICP resources stand in contrast to an absolute dearth of resources for HTDP.


Exercises


2.1.1:

Dr. Scheme does have operations for squaring (sqr x), computing sines (sin x), and finding maximums (max x). If you are not running in the HTDP Beginning Student Language though these functions may not be available.


2.1.2:



(sqrt 4)
2
(sqrt 2)
#i1.4142135623730951
(sqrt -1)
0+1i

;;(tan x) determines the tangent of a given angle.

2.2.1:



(define (Fahrenheit->Celsius fahr)
(* (- fahr 32) (/ 5 9)))

The teachpack worked as intended. Just go to Language -> Add Teachpack. Feel free to test the different convert-*s on your own.


2.2.2:



(define (dollar->euro dollars)
(* .642 dollars)) ;; as of 05/18/08

2.2.3:



(define (triangle side height)
(/ (* side height) 2))

2.2.4:



(define (convert3 first second third)
(+ (* 100 third) (* 10 second) (* 1 first)))

This was sort of counter-intuitive. The idea that this is related to something in an Algebra book is true but misleadingly so. You could try to do something fancy with max but that's not the idea.


2.2.5:



(define (f n)
(+ (/ n 3) 2))

;;The evaluations for 2, 5, and 9 are 2.6, 3.6 and 5, respectively.

(define (f n)
(+ 10 (sqr n)))

;;The evaluations for 2 and 9 are 14 and 91, respectively.

(define (f n)
(+ 20 (* (sqr n) .5)))

;;The evaluations for 2 and 9 are 22 and 60.5, respectively.

(define (f n)
(- 2 (/ 1 n)))

;;The evaluations for 2 and 9 are 1.5 and 1.8, respectively.

2.3.1:



(define (tax income)
(* .15 income))

(define (netpay hrs)
(- (wage hrs) (tax (wage hrs))))

;;supplementary functions:
(define (wage hrs)
(* 12 hrs))

2.3.2:



(define (sum-coins pennies nickels dimes quarters)
(+ (* .01 pennies) (* .05 nickels) (* .1 dimes) (* .25 quarters)))

2.3.3:



(define (total-function attendees)
(- (* 5 attendees) (+ 20 (* .5 attendees))))

2.4.1:

(10) causes the interpreter to expect a function, procedure or expression but it is in fact primitive data, i.e. a number.


(10 + 20) is incorrect because the expression uses infix rather than prefix notation but the error from the interpreter is the same. This is due to the fact that the interpreter has been given a number rather than an procedure as it's operator.


(+ +) fails because the operator + is only given one argument (it requires a minimum of two) and that argument is a function which is the wrong type of input.


2.4.2:



(define (f x)
(+ x 10))
;;The argument to f needed to be changed.

(define (g x)
(+ x 10))
;;There was a missing open-paren before the + operator.

(define (h x)
(+ x 10))
;;The open-paren was in front of x when it should have been in front of h.

2.4.3:



;;> (+ 5 (/ 1 0))
;;/: division by zero
;;> (sin 10 20)
;;sin: expects 1 argument, given 2: 10 20
;;> (somef 10)
;;reference to an identifier before its definition: somef

2.4.4:



(define (somef x)
(sin x x))

;;> (somef 10 20)
;;somef: this procedure expects 1 argument, here it is provided 2 arguments
;;> (somef 10)
;;sin: expects 1 argument, given 2: 10 10

The section ends with a bit on program design. It makes the important note of having human solved examples to test against. Sounds like an argument for unit tests to me.

Adulthood and Academics
posted on 2008-05-14 03:39:37
Admittedly, the title of this post is a misnomer. I'm no adult yet. I am trying my damnedest to keep this house running smoothly though. As of today I think we're up on all the utilities and I've got a Static IP here with AT&T so I can move my server at some point. Work's been going well and I'm taking MARTA in to simplify my life a bit. I'm cooking (if you can call it that) and keeping the dishes done and the house clean with regularity. I'd say I've almost settled into a groove. I say almost because the people actually staying in the house won't stabilize until after May 25th. Heck, even I'm gone from the 17th to the 24th to house sit for my parents. For the most part though I'm enjoying myself.

Additionally,  I'm way behind on programming. I know. I've had a lot going on but my progress the last month or two is still just shameful. I've started HTDP to get the juices flowing again and am already through Section 03. It's definitely more straightforward than SICP if less revelatory. I'm considering going ahead and trying to blow through HTDP completely over the next month or two. Then I could circle back to SICP and hopefully be better prepared. I haven't decided on anything yet other than tidying up the presently unadorned answers to SICP 1.3 and then posting what I've got from HTDP so far. I am more than half-way through SICP 2.1 but I'm wondering if it makes more sense to knock out HTDP considering the difference in pace between the books. I'll let you know as I move forward. I'm hoping to get a post up with some pictures of my new digs in the next week or so. Feel free to drop me a line if you'd like to swing by.
Official Fix for MIT-Scheme in Hardy
posted on 2008-05-05 15:34:39
Bug reports work! Finlay McWalter commented on the bug report saying that the package maintainer, Chris Hanson, found a fix for the issue. His fix is far better than my workaround. Apparently, AppArmor is preventing applications (such as MIT-Scheme) from accessing lower memory. The fix is to edit /etc/sysctl.conf and change the vm.mmap_min_addr value from 65536 to 0. Afterwards, MIT-Scheme works just fine.

In other news, this has been a really disastrous Monday.
Moved In
posted on 2008-05-04 22:10:57
Things might be a bit quiet from me for a few days. I've moved into my new house on Windsor Pkwy and am really enjoying it. We have warm water and electricity but no internet until May 13th. It's tough but free Wi-Fi from my Alma Mater isn't far away. I'll try to post some pictures up later this week and give you all "the tour". In the meantime I've got to cook dinner and work on a presentation about the AV Equipment at the Office. It's a glamorous IT life, I tell ya. Feel free to call me for directions and visit!

Update: So, apparently the landowner's DSL still hasn't been cut off. The internet is among the utilities that are up in the air at present. Everything should be straightened out soon.

This blog covers 2015, Books, Butler, C, Dad, Discrete Math, Displays, Education, Erlang, Essay, Gaming, Gapingvoid, HTDP, Hardware, IP Law, LISP, Lecture, Lessig, Linkpost, Linux, Lists, MPAA, Milosz, Music, Neruda, Open Source, Operating Systems, Personal, Pics, Poetry, Programming, Programming Languages, Project Euler, Quotes, Reddit, SICP, Self-Learning, Uncategorized, Webcomic, XKCD, Xmas, \"Real World\", adulthood, apple, careers, coleslaw, consumption, creation, fqa, games, goals, heroes, injustice, linux, lisp, math, melee, metapost, milosz, personal, poetry, programming, ragequit, recreation, rip, strangeloop, work

View content from 2015-05, 2015-03, 2015-02, 2015-01, 2014-11, 2014-09, 2014-07, 2014-05, 2014-01, 2013-10, 2013-09, 2013-07, 2013-06, 2013-05, 2013-04, 2013-03, 2013-01, 2012-12, 2012-10, 2012-09, 2012-08, 2012-06, 2012-05, 2012-04, 2012-03, 2012-01, 2011-10, 2011-09, 2011-08, 2011-07, 2011-06, 2011-05, 2011-04, 2011-02, 2011-01, 2010-11, 2010-10, 2010-09, 2010-08, 2010-07, 2010-05, 2010-04, 2010-03, 2010-02, 2010-01, 2009-12, 2009-11, 2009-10, 2009-09, 2009-08, 2009-07, 2009-06, 2009-05, 2009-04, 2009-03, 2009-02, 2009-01, 2008-12, 2008-11, 2008-10, 2008-09, 2008-08, 2008-07, 2008-06, 2008-05, 2008-04, 2008-03, 2008-02, 2008-01, 2007-12, 2007-11, 2007-10, 2007-09, 2007-08, 2007-07, 2007-06, 2007-05


Unless otherwise credited all material Creative Commons License by Brit Butler