Sunday, December 2, 2012

Do your ancestors suffer from unplanned mutations?

This was a discussion item I posted to the CS101 forum. If you want to see the original posting see: http://forums.udacity.com/questions/2017355/do-your-ancestors-suffer-from-unplanned-mutations#cs101

If you want to see the referenced homework problem, see: http://www.udacity.com/view#Course/cs101/CourseRev/apr2012/Unit/709001/Nugget/710001

I learned more than I intended from Homework6-1starred. I wrote up a note about it to my once-upon-a-time (well, 1973) college roommate and cc'ed it to Professor Evans. Professor Evans suggested that I'm probably not the only person to run into this snag, and suggested that I make a forum post out of my note. So, here it is.

Unit 6 in udacity's CS101 is basically about recursion. One of the homework problems gives a "dictionary" that is keyed by names and for each name gives a list of that person's parents. It asks me to write a procedure "ancestors", that given a name, returns a list of all the known ancestors of that person or an empty list if the genealogy dictionary gives no ancestors for that name. Sounds straight forward. Strangely, it said, the robo-grader wouldn't mind duplicates in the output and was indifferent to the order of the output list. The "indifferent to the order" part made sense. I could put 1 parent on the list and then the ancestors of that parent, followed by the other parent and then the ancestors of that other parent, or I could put both parents on the list and then the 2 sets of ancestors. So, various output orderings are possible, but duplicates? Unless there is something funky in the genealogy, how could there be duplicates?

So I tossed together a straightforward recursive procedure to return an empty list if the given person is not in the dictionary, and otherwise, put that person's parents onto a list I called thegang, and then for each parent call ancestors to get grandparents, etc. If a non-null list comes back, then thegang gets those additional ancestors tagged onto the list. Much to my surprise, my output differed from the expected results in that I had duplicates. Just to make it easier to check results I added a line of code to the part that adds the additional ancestors to thegang to skip ones that are already in thegang. My output now matched the expected results, but I wanted to know where those duplicates came from. The genealogy was the family of Lady Ada Lovelace, Lord Byron, et al.

Here's the version of the program that the robo-grader declared as "correct", when I submitted it, but that I now know is flawed.

def ancestors(genealogy, person):
    if person in genealogy:
        parents=genealogy[person]
    else:
        return []
    thegang=parents
    for p in parents:
        q=ancestors(genealogy,p)
        for name in q:
            if name not in thegang:
                thegang.append(name)
    return thegang

The "if name not in thegang" test explicitly rules out adding duplicates to the output.

Here's a listing of the program that produces duplicates in the output.

def ancestors(genealogy, person):
    if person in genealogy:
        parents=genealogy[person]
    else:
        return []
    thegang=parents
    for p in parents:
        q=ancestors(genealogy,p)
        for name in q:
            thegang.append(name)
    return thegang

Took a lot of experimenting to find the source of the duplicates, but in the end I was able to fix the program to get rid of the duplicates without the brute force approach (albeit "brute force" being one line of code thanks to Python) of checking for duplicates and not putting 2nd copies into the list. You'd have laughed if you'd watched me at the library here. More than once I stood up at my cubbie desk and silently declared to myself "This can't be!', walked around a little bit and then settled back down to experiment some more. In the end, the problem turned out to be aliased lists, like I was fretting about in recent e-mail.

Here's a listing of the debugged program,

def ancestors(genealogy, person):
    if person in genealogy:
        parents=genealogy[person]
    else:
        return []
    thegang=list(parents)
    for p in parents:
        q=ancestors(genealogy,p)
        for name in q:
            thegang.append(name)
    return thegang

The significant change is "thegang=parents" became "thegang=list(parents)".

The problem was that I set parents by looking the person's name up in the genealogy dictionary. So, parents is an alias for the list of the person's parents. And then I initialize thegang by assigning parents to thegang, so now thegang is an alias too for the list of the person's parents as given in the genealogy dictionary. And then I do my recursions and add more names to thegang. But, when I do so, I'm packing those additional names into the original list of parents in the genealogy dictionary. So, when I am working on the next person, if there is any common ancestory, I don't get 2 parents, but a much longer list of parents. Fix is that when I initialize thegang, instead of saying thegang=parents, I instead say thegang=list(parents). That way, thegang isn't an alias of parents, but a copy of the parent's list, a fresh list of its own. Cheaper copy than you might think as the underlying strings are immutable and so get re-used without having to be copied themselves. That is, all that is copied are the 2 string references into a new list of those 2 string references.

But in thinking about it, it seems to me that the robo-grader should enforce a rule that thou shalt not screw up the genealogy data structure. Easy enough for it to have a private deep-copy of the original data structure and then compare the data structure in the end to the way it is supposed to be and see if anything changed. A similar watch for corruption of the index structure of the web search engine that is the recurring theme of the course would also be sensible.

Anyhow, it was a worthwhile mistake as it further educated me on the sort of bugs that can come from having aliased lists. Will I dodge the next such bug? Or at least be quicker to discover what is wrong? Well, time will tell....

Did you run into any such bug in working hw6star-1? Repeating a line I used on another question about lists, mutation of lists is a very powerful feature of Python, but with great power comes great responsibility.

Drew

Friday, November 30, 2012

Keeping Busy

My blogging activity here has been even spottier than usual, but I have actually been keeping myself productively busy, even writing stuff, just not on this blog. Back in June 2012, I enrolled in udacity.com's cs101 course. It's an introduction to Python, programming and Computer Science. I already have a Master's degree (more or less in Computer Science), but have been teaching myself Python, hanging around the Python language Facebook page answering newbie questions, and I've been writing code in Python to solve Project Euler problems. I figured that taking the course would help me with my Python knowledge and let me see if udacity cs101 is something I should be recommending to newbies to the language.

By mid-July 2012, I'd completed the course, scoring 100% on the final exam, so I earned their "Certificate of accomplishment with highest distinction". Yay!

The course is mostly taught by Professor David Evans from U. of Virginia. He's also authored an introductory computer science textbook which isn't used in udacity cs101, though in one lesson, he pulls out a copy of the book to show an example of an index, the index pages at the back of the textbook. I have since learned that the entire textbook is available in e-book form as a free download. I installed the full PDF file onto my iPod to read in my spare time. I do think the larger screen of an iPad would make a better e-reader, but so it goes. I have an iPod. I don't have (and can't afford) an iPad. If the fine print on the tiny screen wears me down, perhaps I'll shift to reading the PDF file on my laptop PC.

Since completing the cs101 course, I continued to hang around the cs101 forum to see what help I could be by answering questions posted there by other students. Part of my motive for sticking around was that I've proposed to mentor a udacity cs101 class at the local North Hempstead, NY "Yes We Can" Community Center. The community center has a classroom full of PC's with Internet access, and I'd very much like to increase interest in software development around here, and this looks like a feasible start on that. Professor Evans has given his blessing to the offering.

Alas, the center's director still hasn't approved a start date for the course, so I'm thinking it'll begin after New Years. My intent is to recruit students in December before Christmas break is here.

Meanwhile, I'll republish here on this blog in the next several days some of the Forum material that I think is of interest outside the confines of the cs101 course itself.

If you have any interest in learning to program, the CS101 course from udacity.com is a good place to start. It's free of charge, self-paced, assumes no prior knowledge, and is well constructed. Python is a wonderful language for computer programming because in relatively few lines of code you can write some seriously useful software.

If you are in North Hempstead, NY, come and join the "Yes We Can" community center in New Cassel, on Garden St. If you are age 60+, ask about the free membership deal. Membership gets you use of the indoor basketball courts and of the computers too. I'd be happy to have you participate in the CS-101 class.

We're also starting a "Computers-100" class for people who are completely new to computers and aren't looking to program them, but want to learn how to use them. Here's links to the course description and to the slides for the first session.

Drew

Saturday, November 3, 2012

Recovering from the storm and MRE's

The electricity was off here (Westbury, NY on Long Island) for a while courtesy of Hurricane Sandy. The gas and water stayed on though. My house lucked out in getting electricity back sooner than neighboring blocks, but cable (TV, telephone, Internet) was a while longer to come back. Happily my dumb cell phone kept working and has a nice long battery life. My wife's 3G Smartphone has the internet (slowly), but it runs the battery down awfully fast.

The National Guard showed up in our neighborhood yesterday, handing out food (MRE's - Meal-Ready-to-Eat) and bottled water. My wife's son picked up a case of each for the house. I felt a little bad about accepting emergency supplies we didn't have an emergency need for, but rationalized that we could always use the bottled water and that there was no need to turn down an offer of free food. So, Thanks Uncle Sam!

The carton of MRE's is labeled "A-pack emergency meals". The carton of MRE's has 12 meals in it, in 6 varieties. Today my wife and I tried a "Spaghetti with meat sauce" meal. She sneered at the small size of the meal-pack, but the label says it's more than 1800 calories, so clearly if an adult eats one meal-pack, they aren't starving that day.

Other info on the nutrition label is a bit more worrisome. The pack delivers nearly 2 grams of sodium, more than 50% of a days allowance. I could believe it was formulated to compensate for troops in hot climates losing a lot of salt to their sweat, but I suspect it was just a low-cost seasoning to give some flavor to the entree.

The meal pack had quite a bit of stuff in it:

  1. A plastic-wrapped spoon to use to consume the entree.
  2. A cardboard sleeve to hold the entree packet so you don't burn your fingers.
  3. A chemical heating packet to heat up the entree.
  4. A packet of salt water to activate the chemical heating packet.
  5. A package of crackers.
  6. A packet of peanut butter.
  7. A package containing a big chocolate chip cookie.
  8. A plastic-wrapped hard candy mint.
  9. A moist towelette packet.
  10. An unlabeled packet that we deduced was the spaghetti in tomato/meat sauce.
  11. A cinnamon/brown-sugar toaster pastry.
  12. A packet of artificially sweetened lemon-flavored drink-mix (Like unbranded "Crystal-lite", I think).

The instructions on the chemical heating packet spoke as if the meal-pack was packed in a cardboard box, but the meal-pack arrived in a plastic over-wrap. The cardboard sleeve in the meal-pack had newer instructions explaining that you now use the sleeve instead of a box.

We formed up the sleeve, folding in the tabs that give it a bottom and inserted the entree packet into the sleeve. My reading of the instructions was that I was to tear off the top of the outer package of the chemical heating packet and dump the salt-water into that bag. I was unprepared for how quickly the chemical heating packet gets steaming hot after you add the salt water and had a heck of a hard time inserting the steaming-hot heating packet into the cardboard sleeve next to the entree packet. In retrospect, I think I should insert the chemical heating packet into the cardboard sleeve next to the entree packet before adding the salt water to the heating packet. The instructions were strangely silent on how long to leave the assembly alone to give it time to heat through. We gave it a few minutes until the chemical heating packet started to lose its oomph and the steaming pretty much slowed to a halt.

We dumped the heated entree out onto a plate to eat it using a fork. It might have been smarter to eat the entree out of its packet with the plastic spoon, using the cardboard sleeve as a holder. The entree packet is opaque and keeping the entree out-of-sight probably improves the dining experience. Dumped onto a plate, it really isn't pretty, though it tasted OK.

The carton of MRE's doesn't include a pair of scissors. The inner packets stubbornly resist opening and we used a serrated kitchen knife to open each as we got to it. Next time, I plan to bring a pair of scissors to the party.

Stored in a cool dry place the MRE shelf life is said to be 5 years, but stored at 120-degrees F, the shelf life is reduced to just one month. Far as I can see, the packaging includes nothing to clue you in to what sort of temps the meals endured while traveling to you. Something like these Temperature Sensing Stickers is what I have in mind.

There was apparently little attention paid to modern nutrition guidance in formulating the meal. It was very low in fiber and lacked whole-grain content. Seems to me it could have used whole grain crackers without hurting the shelf-life.

The instructions on the drink mix said to add the powder to a bottle of water, but were strangely silent on saying what size bottle of water it expected you to use. We had some cooled 1/2-liter bottles in the fridge, so we used one of those. That worked out fine, though there really wasn't enough air space in the bottle to accommodate all the powder from the packet. I had to recap the bottle and shake to dissolve the powder to make room for the rest of it. Next time, I think I'll start by drinking a mouthful of the water to leave enough room in the bottle for the drink mix all in one go. It'll give me a little more room for shaking it up too.

The makers of the MRE apparently don't believe in "season to your taste". It would definitely have been an improved dining experience for me if they'd included a packet of (imitation?) grated parmesan cheese to sprinkle on the entree. Some like it spicy, so a packet of red pepper flakes would be a nice additional touch to broaden the meal's appeal.

The toaster pastry was difficult to get out of its package. The pastry's frosting stubbornly adhered to the bag. Not clear to me where they expect you to toast the pastry. I ate it untoasted. (I did have access here to a genuine 4-slot toaster, but to toast up the broken bits of pastry after extricating them from the package, I'd have needed a toaster oven with a tray to hold the little pieces). I wonder if I should should have crammed the toaster pastry packet into the cardboard sleeve next to the entree so the chemical heating packet would at least warm the pastry through, though I expect that might make even more of a mess of the frosting. Scissors may make things better next time.

The chocolate chip cookie was great. Large, thick and crunchy. I was pleasantly surprised to see it didn't crumble or even crack in its package. I do wonder if it would be smarter to pack several smaller cookies instead of one large one to encourage sharing.

I wonder if they make dietary-restriction-compliant MRE's? (Kosher, vegetarian, gluten-free, etc., etc.).

Well, that's my first MRE experience. Summary: Not gourmet by any means, but certainly edible. Bring a pair of scissors and your own condiments. If you have access to some fresh fruit (e.g. an apple or an orange) it'd surely make a good palate-cleanser after eating the MRE.

After eating one MRE, you are surely left with a large pile of scrap plastic wrappers and other bits of trash. Makes a McDonald's plastic polyfoam plastic clamshell feel positively ecological by comparison. Are soldiers in the field expected to feed all the garbage to a campfire?

I'll keep you posted as I try the other varieties. They all look like variations of pasta in a sauce. Beyond "Italian", it seemed like there was surprisingly little ethnic influence on the range of meals offered. None of the meals look to my white-bread American eye to be particularly suitable for breakfast. A single serve box of cereal and a packet of long-shelf-life ultra-pasteurized milk would be fine for me. I guess rolls, bagels or bread (toast) are out of the question. I hear rumors that the MRE scrambled eggs were so dreadful that they were discontinued. Hot oatmeal seems like it should be within reach of the technology.

I guess milk, juice, tea, & coffee are outside the realm of the MRE packages. We're happy to have the use of the refrigerator and microwave back, not to mention the furnace, clothes washer and dryer, and the Internet!

Wednesday, May 30, 2012

Browser Plugin Check

We can check your plugins and stuff

Monday, January 24, 2011

How to write good code

I found a tip on Youtube explaining how to enlarge the frame where blogger shows my blog entry after I create it on Google docs. The blog entry as displayed below looks OK to me. If that doesn't work out for you, please leave a comment for me so I'll know about the problem. Escape route: you can click here to see this posting over in Google docs: How to write good code

2012-04-09



Drew

Saturday, January 22, 2011

Dumb Moments in Automotive Engineering

Dumb Moments in Automotive Engineering

Hey! I used to prepare my blog postings in Google docs and use the Share button in Google docs to post the document to blogspot.com here. I no longer find that option in Google docs today. Simply copying and pasting the document from Google docs to Blogger's compose window seems to lose a lot of formatting, including links embedded in the document.


Seems like Google decided it was smarter to have people link back to the Google docs instance of the document. So, here's a link to the document I'd intended to be today's posting. My apologies for having you have to click through. If you run into access problems, please let me know about the trouble.

Dumb Moments in Automotive Engineering

Friday, May 14, 2010

Are the Folks at Google Having Fun Yet?

Are the Folks at Google Having Fun Yet?

Here's a couple of videos for you to view if you are wondering if the folks at Google are having fun yet.

The first is a series of speed tests of the Google Chrome Browser.


In case those demos leave you unsure of whether or not the folks from Google had fun making that video, then for sure you should look at this second video on "the Making of..." the first video.

http://www.youtube.com/watch?v=_oarMXGq3gI

Remember:
"It's not so much about lab coats as it is about having fun and blowing stuff up".
Drew