But I Get Up Again

The RailsConf speakers have been notified and …. I’m not one of them. Sadly, neither of my proposals were accepted this year. I’m taking it as a small consolation that each made it through several rounds of reviews. A very small consolation.

I also was not selected as a CodeNewbie apprentice. That program was absolutely perfect, but the woman who was selected is absolutely amazing and will do great things for the community.

So, I get knocked down but I get up again. I just wrapped up the prep work for Launch School as part of an application for a scholarship. It’s online and part-time and would be a great way to get some focus to my learning. While I wait for news, I thought I’d dip a toe into django (wow — talk about a quick and dirty way to build a site!)

Advertisement

January Retrospective

Trying a little something new here. Here’s my January Retrospective

The Good:

  • New blog, new domain name and (counting this post) five blog posts in January.
  • Completed full-month streaks on GitHub and StackOverflow (my Seinfeld productivity tracker tools).
  • Submitted proposals to RailsConf on time! (woot!!).
  • Completed a big project for a client that snagged the CIOs attention.
  • Applied for the Launch School scholarship and to be a volunteer at WWC Connect 2016

The Bad:

  • Not accepted as a PT apprentice at CodeNewbies.
  • Rolling off my current client, which means I will stop working with a team I really like.
  • Still haven’t completed PokerHands.

What I Can Do Better

  • Have my resume ready at all times, no matter how secure I feel on a particular team.
  • FINISH POKER HANDS ALREADY (oh, look, a squirrel with a scholarship opportunity…) No, really — I will push the code in February.
  • When faced with an opportunity, I will jump in with both feet. For a lot of ventures (even the successful ones), I’ve hemmed and hawed, feeling uncertain if I was even good enough to consider it. I need to accept that no, I won’t get everything I go after. But I won’t get anything that I don’t actually try for.

 

Slight Detour May Lead to a Steadier Path

 

Last week, I learned about a special scholarship being jointly offered by Women Who Code and Launch School. I first uncovered Launch School a few years ago (when they were called Tea Leaf Academy) and thought their intention to teach code the right way and the slow way was just what I needed. They’re remote, part time and focus on the fundamentals. But they co$t, and while I never lack for ambition and drive, I do lack money to funnel into my studies. I jumped at the chance to apply.

I’m working through the Launch School preliminary work. One of the assignments is “What is Code” by Paul Ford. I’m developing a long list of future reading.

  • The Rosetta Code
  • Hitchhiker’s Guide to Python (which, to be fair, I first heard mentioned on a CodeNewbies podcast)
  • Re-read JavaScript the Good Parts (and actually write all of the code described within)

Wow – in the “languages” section, only really mentions JavaScript to say you don’t have to be particularly smart or good at math to be a JS programmer; mentions Ruby only to point out CoC violations and the Pr0n slidedeck. The author clearly adores Python.

Poker Hands

It’s the classic: Poker Hands. Write a program to evaluate and compare two hands of cards. It’s a fun way to stretch some algorithm-building muscles and practice a little OOP while you’re at at.

The Rules

I started this challenge with very little card game knowledge. Aside from Go Fish, War and Spit, I don’t really play cards. My first step was to track down the rules. In order:

public enum HandStrength
{    
    RoyalFlush, // same suit, consecutively ranked, 10-Ace
    StraightFlush, // same suit, consecutively ranked cards
    FourOfAKind, // four cards same rank, break a tie with the high card
    FullHouse, // a set of three and a pair
    Flush, // same suit, ranks not consecutive
    Straight, // different suits, consecutively ranked cards
    ThreeOfAKind, // three cards same rank, same tie break as four of a kind
    TwoPair, // two pairs same rank, same tie break as four of a kind
    OnePair, // a single pair a same rank cards, same tie break as above
    HighCard // highest ranking card in the hand
}

The job is to compare several pairs of poker hands and to indicate which, if either, has a higher rank. My eureka moment (yes, new to the game, remember?) was when I realized that this can be solved with three basic tests (ok, 4 if you count the HighCard):

// Straight: Returns true if all cards are consecutive values. public static bool Straight(PlayerHand playerHand)
{
    SortByRank(playerHand);
    for (int i = 0; i < playerHand.Cards.Count-1; i++)
    {
        if ((playerHand.Cards[i].Rank + 1) != playerHand.Cards[i + 1].Rank)
        { return false; }
    }
    return true;
}
 
//  Flush: All cards of the same suit.
public static bool Flush(PlayerHand playerHand)
{
    if (playerHand.Cards[0].Suit == playerHand.Cards[1].Suit)
    {
        Suit handSuit = playerHand.Cards[0].Suit;
        foreach (Card c in playerHand.Cards)
        {
            if (c.Suit != handSuit)
            { return false; }
            else { continue; }
        }
     return true;
     }
     else { return false; }
     return false;
}
//  One Pair: Two cards of the same value.
public static bool OnePair(PlayerHand playerHand)
{ 
    SortByRank(playerHand);
    if (rankCount.ContainsValue(2)) { return true; }
    else { return false; }
}

Most of these methods rely on a sorted hand of cards. One of the first things I discovered, though, was I needed to find a way to compare the ranks of two cards. To implement a Comparable for rank as one part of a Card, I used this:

// take two cards, compare Rank - return 1 if x > y, 0 if x == y, -1 if x < y
public static int CompareCards(Card x, Card y)
{
    if ((x == null && y == null) || (x.Rank == y.Rank))
    { return 0; }             // either they're both null or both equal
    else if (x.Rank > y.Rank)
    { return 1; }
    else // y.Rank > x.Rank is the only other option
    { return -1; }
}

Then I used that Comparable in the Sort() function:

sorted.Cards.Sort(CompareCards);

As I wrote each evaluator, I wrote its matching tests (both for the practice with MS Unit Tests) and to check my logic.

[TestMethod]
public void CanDeterminIfHandIsNotAStraightFlush()
{
    Assert.IsFalse(HandEvaluator.StraightFlush(basicHand));
}

The next step was to stitch the evaluators together. My first thought was to populate an array with the evaluators and step through it. My initial attempts were, well, clunky.

Func<uint>[] evaluators = { isStraight, isFlush, twoPair, ...};
foreach (var e in evaluators)
{
     // decision here
}

During a code session, a colleague suggested I dig into lambdas as a solution. Pluralsight has been a terrific resource and my next post will take a deep dive into what I’m learning there.

That brings us to the next post: Learning Lambdas!

Mental Models of Recursion

tl;dr
Thinking of a recursive call as the creation of and delegation of control to a new instance of the recursive function is vital to complete understanding and correct use of recursion. Prerequisites for this are solid understanding of function calling, parameter passing and embedded function calling. Instructors need to adopt different ways of teaching to match the understanding of their students.

Oh, and recursion is really cool.

While researching common misunderstandings of recursion for a conference talk proposal, I came across some interesting research by Tina Götschi. (Mental Models of Recursion )

Tina Götschi sought to uncover what kinds of mental models were used by computer science students and to evaluate the viability or usefulness of those models. Her goal was to find ways to improve upon current teaching methods and computer science curricula. As a first step, she used a written test with three parts. The first part gathered background information on the students, seeking to capture their previous programming experience. The second part asked the students to define recursion in their own words. The third and final section required the students to trace through four different recursion problems, writing and drawing out their process.

Mental Models Used

Prior to her work, previous research had uncovered five primary  categories of “mental models” used by students, children and programmers to conceptualize and understand recursion. These models are copiesloop, magic, odd, and null.

The copies model (which is credited as a signal of “expert” understanding of recursion), reflects that each recursive call is in essence a copy of the method instance. When the method is called recursively, a new copy is instantiated and the active control of the program is passed to this new instance. Once the final instance reaches the base case, then control is passively returned through the instances up to the originating recursive instance. Based upon Götschi’s research, this model is the only model which is viable for all types of recursive programs.

The remaining models can be somewhat viable for certain circumstances. The loop model reflects a student’s attempt to break down a recursive program as a series of iterations. The magic model refers to student who deduced their understanding of a program by treating the recursive call as a form of “syntactic magic.” This shallow understanding of the recursive program was only viable when used in the context of a familiar, actual problem (such as calculating a Fibonacci series) and not with “nonsense” programs that only manipulated the parameter with no real purpose.

The so-called odd model captured mental models that did not fit into any of the above categories. Null indicated that the students either did not form a mental model at all or at least were unable to articulate and demonstrate it in the testing.

Götschi’s research revealed additional models, as well: the algebraic (interpreting the recursive call as an algebraic formula), step (similar to the loop model), return value (based on a misunderstanding of parameter passing) and active models (which leaves out the passive control needed for the copies model.)

Götschi’s Conclusions

The primary goal of Götschi’s research was to identify ways in which instructors could improve upon how they teach the concept of recursion. As a first step, students need a solid understanding of function calling and parameter passing. Deficits here lead to faulty mental models that can work for some recursive problems but not all. This partial understanding then cements the wrong mental model, which can be difficult to overcome. Götschi recommends then explicit instruction in embedded function calls before attempting the topic of recursion. She also recommends frequent assessments to ensure correct understanding.

Finally, Götschi’s research emphasizes the importance of covering a full range of recursive program types. The non-viable models mentioned above work for some problems. Waiting until students have locked onto non-viable models delays the moment when they must adopt new ways of approaching the problem.

Other Thoughts

Given the large numbers of computer science students who develop faulty mental models of recursion, it’s unsurprising how difficult it can be to teach recursion. In Götschi’s research, only between a quarter and half of the subjects developed viable mental models of recursion. Given more experience, it is possible that some will develop a deeper understanding. Given the persistence of mental models Götschi observed, however, it is likely that many will not. Given that the next cohort of teachers will come from the current generation of students, there is risk that this misunderstanding will be carried forward.

What to do? New methods of instruction could help. Götschi calls for instructors to use student assessments as a pivot points: if students don’t understand the topic, a different point of view is required. “[Teaching] unvaryingly to each and every student will not mediate learning as well as one who is continually gauging his or her learners’ understanding.” Götschi and others point to visualization and dramatization of recursive methods (instead of the staid “Russian dolls” metaphor) as useful tools for developing student understanding.

What do you think?

Do you use a mental model unlike any of those listed above? Do you have confidence in your understanding of recursion? How would you explain it to a novice? Do you think it’s even possible?

 

 

 

 

 

First, Commit

It’s January, that time of year when we all embark on wondrous plans for self-improvement. We join gyms, quit smoking and … start blogging again. And this year it’s going to stick, dang it!

But first, commit. I commit to writing something useful or interesting here at least once a week. I commit to coming here first with my ideas and musing, my code snags and bugs, my reviews and recommendations. I commit to blogging here (and then I can always tweet about it later!)

My next post will be on this intriguing research paper by Tina Gotschi on Mental Models of Recursion. I uncovered Gotschi’s paper while researching recursion in preparation for a proposal for RailsConf. Recursion is such a perfect concept, but one which I don’t feel I completely understand. I’ve had a few Eureka moments when using it in a program (like for the Zombie vaccine problem), but my grasp in imperfect. A dive deep enough to explain it to others should take care of that!

What’s your favorite computer science concept that you want to understand better? Or do you have a topic that took something out of the ordinary studying to understand? How did you tackle it?