Thursday, August 11, 2011

Hett's Problem

Sorry for not writing for a while, I've been busy looking for a new job. If you've got one, you can contact me here or at slabounty at large search company that starts with "g".

Anyway ... over at Programming Praxis there's a problem via PrologSite concerning lists. Here's the problem statement ...
1.28 (**) Sorting a list of lists according to length of sublists
a) We suppose that a list (InList) contains elements that are lists themselves. The objective is to sort the elements of InList according to their length. E.g. short lists first, longer lists later, or vice versa.

Example:
?- lsort([[a,b,c],[d,e],[f,g,h],[d,e],[i,j,k,l],[m,n],[o]],L).
L = [[o], [d, e], [d, e], [m, n], [a, b, c], [f, g, h], [i, j, k, l]]

b) Again, we suppose that a list (InList) contains elements that are lists themselves. But this time the objective is to sort the elements of InList according to their length frequency; i.e. in the default, where sorting is done ascendingly, lists with rare lengths are placed first, others with a more frequent length come later.

Example:
?- lfsort([[a,b,c],[d,e],[f,g,h],[d,e],[i,j,k,l],[m,n],[o]],L).
L = [[i, j, k, l], [o], [a, b, c], [f, g, h], [d, e], [d, e], [m, n]]

Note that in the above example, the first two lists in the result L have length 4 and 1, both lengths appear just once. The third and forth list have length 3; there are two list of this length. And finally, the last three lists have length 2. This is the most frequent length.


So how can we solve these two problems in Ruby? The first one is pretty much trivial. Here's the code ...


list = [%w[a, b, c], %w[d], %w[e, f], %w[g, h, i, j, k], %w[l], %w[m, n, o]]
list_sort_length = list.sort {|a, b| a.length <=> b.length}
p list_sort_length


All we're going to do is use the option to sort that takes a block. The block will get two values and instead of the default, we're going to use the values length. Run this and you should see ...
[["l"], ["d"], ["e,", "f"], ["a,", "b,", "c"], ["m,", "n,", "o"], ["g,", "h,", "i,", "j,", "k"]].

The next piece is a bit trickier. Here, we can't do just a one-liner (that I could see anyway). Here's the code ...


hist = Hash.new{|h, k| h[k] = []}
list.each { |l| hist[l.length] << l }
list_sort_hist = []
hist.sort {|a,b| a.length <=> b.length}.each { |key, value| value.each {|e| list_sort_hist << e } }
p list_sort_hist


We start out creating the histogram hash and passing a block so that each element is initialized with an empty array. Then, we work through the list and add each element to an array at the appropriate histogram hash location. Next, create the empty sorted histogram array. Finally, we're going to sort the histogram the same way that we did in the earlier problem (we can do this because they both are Enumerable. We take the result of that and do and each for every item in the histogram. For each of the values (which remember are arrays), we add them to the list_sort_hist array. Finally, we print that out. If it makes it easier to see, split that long line in two. First create a sorted histogram array and then for each value loop through the value and add it to the list_sort_hist array.

Let me know if you have any comments, questions, or jobs.

Saturday, May 28, 2011

Array.zip() and Upside Up Numbers

I've known about the zip method for arrays but have never really found much of a use for it. I was working a problem on Programming Praxis the other day and saw some Python solutions that used it, so I decided to give it a try in my solution. Let's start out with how it works.

In the simplest case, we have an array and we zip it with an array of the same size. Here's what it looks like ...


a = [1, 2, 3]
b = [4, 5, 6]
a.zip(b) => [[1,4], [2,5], [3,6]]


We can see that we end up with an array that's the same size as the original arrays made up of elements of each of the arrays. We can also zip multiple arrays ...


a = [1, 2, 3]
b = [4, 5, 6]
c = [7, 8, 9]
d = %w[a, b, c]
a.zip(b, c, d) => [[1, 4, 7, "a,"], [2, 5, 8, "b,"], [3, 6, 9, "c"]]


With that here's the documented code for the upside_up program including, at the beginning, the original requirements from Programming Praxis ...


# An “upside up” number is a number that reads the same when it is rotated
# 180°. For instance, 689 and 1961 are upside up numbers.

# Your task is to find the next upside up number greater than 1961, and to
# count the number of upside up numbers less than ten thousand. When you are
# finished, you are welcome to read or run a suggested solution, or to post
# your own solution or discuss the exercise in the comments below.
#
# Create an array of pairs that can match. We should end up with
# UPSIDE_DICT = [[0, 0], [1, 1], [6, 9], [8, 8], [9, 6]]
UPSIDE_DICT = %w[0 1 6 8 9].zip(%w[0 1 9 8 6])

# Open the Integer class and add the upside_up? method that returns true/false
# based on whether the integer is an upside number or not.
# Let's take this a piece at a time:
# 1) self.to_s.split(//) will give us an array of characters for the given number
# such as [1, 9, 6, 1]
# 2) zip this array with
# 3) self.to_s.split(//).reverse will give us the array above reversed ...
# [1, 6, 9, 1]
# 4) and zipping the two together should give us something like ...
# [[1, 1], [9, 6], [6, 9], [1, 1]]
# 5) Now, we'll loop through the above zipped array using inject and make sure that every pair
# in it is also in the UPSIDE_DICT array. If all of them are, then we'll return
# true otherwise the inject() will return false.
class Integer
def upside_up?
self.to_s.split(//).zip(self.to_s.split(//).reverse).inject(true) { |r,v| r && UPSIDE_DICT.include?(v) }
end
end

# Find all the upside values up to 10000 and print them.
(1..10000).each do |v|
puts "#{v} is an upside number" if v.upside_up?
end


Be sure to let me know if you have questions or comments.

Wednesday, May 18, 2011

Interviewing

I had a young person come in for an internship interview a couple of days ago and it made me realize that I've never posted anything outside the programming world. I'm going to try to do a few different posts on the subject of interviews and resumes to hopefully help give some perspective to the hiring process from someone who actually hires rather than someone who tries to get you hired (head hunter). Is my perspective better than theirs? No probably not, but it may be a bit different.

With any interview there are going to be both soft questions and hard questions. By this I don't mean easy and hard but personality questions and technical questions. Let's start by looking at some of the soft questions you might get and why they're asked in the first place. The first thing to remember here is that you're going to be part of a group (as an aside, I hate the term "team" unless you're all dressed the same). Because of this, the hiring manager is going to want to know how you're going to fit in with the rest of the group and the soft questions will be used to try to ascertain that.

One question that seems to get asked is "Tell me about yourself". This is where you should discuss your interests related to the job. Since the interviewer is most likely going to ask about job related items later, now is a good time to bring up any outside projects that might relate. Open source projects that you've done or contributed to or a blog that you write (programming/technical related) are things that will get the interviewer's attention. Just about anything technically related is a good thing to bring up.

You're also almost certain to get a question on a group project that you worked on. Here, it won't matter if you're a developer with 20 years experience or a new grad, you'll probably have to talk about working with other people. The question may be as straight forward as "Tell me about a project that you worked on with other people." or it may be more subtle "Tell me about your last project" with the expectation that this involved other people. As you talk about this project, you may get follow on questions such as "Were there any personal issues between people in the group?" or "Was there anyone in the group who didn't pull their weight?". Then these will be followed up with "How did these issues get resolved?". All of these questions are geared towards finding out how well you will fit in in a group situation. And, as a subtext, the interviewer will be looking for your "leadership" capabilities. All of these questions are a chance for you to show that you will work well in a group and not just work well but make the whole group work better. In the example of someone not pulling their weight, stating that you noticed that Fred wasn't doing what was expected, you could tell how you talked with Fred and let him know that you'd noticed his work wasn't as good as it had been and then worked with him to get him back up to speed. In the case of personality issues, discuss how in a meeting where things were getting tense, you played the peacemaker by making sure that both sides got heard and then working through the issues.

There's probably more, but these are the types of questions that I'll usually pursue, these (or similar ones) and then follow ons based on the responses I receive. The thing to remember though is that all of these soft questions are designed for better or worse to figure out if you will fit in the group structure. Try to approach them in this way and you should do fine.

As always, let me know if you have questions or comments.

Wednesday, April 20, 2011

All True

I was working a problem on Programming Praxis yesterday and ended up writing a little piece of code that returned true if every element in a hash was true. It used inject and I thought it would be worth posting a generalized version here.


module Enumerable
def all_true
self.inject(true) { |r, v| r && (yield v) }
end
end


We start by monkey patching the Enumerable module which will make it available for Arrays, Hashes, etc., basically anything that includes Enumerable. Next, we define the method all_true. The only line in the method is an inject which we initialize with true and then give it a block with two parameters, the r(esult) and the v(alue). We then and/&& the r(esult) with whatever the yield of the v(alue) returns.

You can test it with the following code ...


puts "#{[2, 4, 6, 8].all_true { |n| n%2 == 0 }}"
puts "#{[2, 4, 7, 8].all_true { |n| n%2 == 0 }}"

puts "#{{ 2=>2, 4=>4, 6=>6, 8=>8}.all_true { |n| n[0]%2 == 0 && n[1]%2 == 0 }}"
puts "#{{ 2=>2, 4=>4, 7=>7, 8=>8}.all_true { |n| n[0]%2 == 0 && n[1]%2 == 0 }}"


The first two of each set will return true, the second false.

As I've been doing the Programming Praxis problems, I've found myself using inject and its close relative map/collect more and more. I think this is partly because of the types of problems posted there and the influence of the solutions that are generated which tend to be functional programming based. At any rate, having a good understanding of both inject and map/collect will serve you well and simplify many of your day to day programming tasks.

Let me know if you have questions or comments.

Tuesday, March 29, 2011

Nanoc and No Compiling or Routing

Here's a short post on using nanoc with files that you just want copied from the content directory to the output directory unchanged. For these types of files, it's best if you have them in their own subdirectory (say images or css). Let's say we have some images (.jpg, .png, etc.). First just put them in an images directory under content. Then we need to add a couple of rules to our Rules files ...


compile '/images/*/' do
# Leave everything in the images directory as is.
end


and then a bit later on in the routing section ...


route '/images/*/' do
# Make sure that /images/some_image/ is routed to
# /images/some_image.jpg or /images/some_image.png or so
item.identifier.chop + '.' + item[:extension]
end


I didn't do an actual project and put it up on GitHub for this one, but if this isn't clear, then let me know and I can do that too.

Friday, March 25, 2011

Nanoc and Multiple Layout Templates

A while back we took a quick look at nanoc for generating static web sites. I've been using it a bit both experimenting and for a simple web site for an author friend of mine. I'm going to do a few short articles on using it, documenting what I've learned in much the same way I've tried to do with Ramaze.

Let's start with some simple code that uses multiple layout templates. You have this often with web sites where there's a home page that uses a different layout than the rest of the pages of the site. Let's start with creating a new site. We do that the same way we did last time with ...

nanoc create_site multiple_templates

and let's add a couple of pages to go along with them ...

nanoc create_item page1
nanoc create_item page2

We didn't really talk about the Rules in the last post and I'm only going to touch on them now. You should take a few minutes and read a bit about them here. We'll discuss them a bit more as we go through future posts.

Now, we need to modify the Rules file to tell it to use an alternate layout for the content/page[12].html files. I'm not going to show the entire file, just the compile rule for these ...


compile '/page*/' do
filter :erb
layout 'page'
end


What this rule says is that when we "compile" files in our content/ directory, we should first run them through the erb (embedded ruby) and then use the page template in the layouts directory.

Here's the default which will get use by everything else (essentially our main page at content/index.html).


compile '*' do
filter :erb
layout 'default'
end


This along with the code for all of this up on github should be enough to get you started. As always though, let me know if you have questions or comments.

Tuesday, March 1, 2011

Inkscape

This one is going to be short since I'm not a designer. I've been reading "Web Design for Developers" by Brian P. Hogan and he recommends using Illustrator for parts of his book. Since the cost was a bit umm... prohibitive for learning purposes, I started looking around for a suitable alternative. What I found was Inkscape. This is a nice little program for generating SVG (Scalable Vector Graphics) files. You can use it for generating files for say logos or banners on websites. While I won't say it's simple to use (and this probably says more about me than the program), with the tutorials available, you shouldn't have too much problem getting it to work. Additionally, there's a book on it that's reviewed on Slashdot. I haven't read the book yet but do have it on order and if it seems worthwhile, I'll post here about it.

To install ...

sudo apt-get install inkscape

and you should have an inkscape selection Applications/Graphics or at least on Ubuntu.

Once again, I'm not sure how much I'll be able to help, but if you have questions, be sure and let me know.