Quiz 5

February 22, 2007

I’ve got a fun one for you today. Suppose you have a list of numbers, let’s work with 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15. What I would like you to do is arrange these numbers so that the sum of every adjacent pair is a perfect square using every number exactly once.

For example:
8, 1, 3, 6, 4, …

8 + 1 = 9
1 + 3 = 4
3 + 6 = 9
6 + 4 = 10
and so on.

You should be able to prove that your solution will find a solution if a solution exists.


Quiz 2 :: Solutions

February 7, 2007

It’s been a while since I posted this one, but it took a long time to get any responses. So here they are:

Kevin:

# Initialization
alphasArr = ('a'..'z').to_a
alphasArr.sort!
alphas = Hash[*alphasArr.collect { |x| [x, 0] }.flatten]


def printCounts(alphas,text="Counts")
print "\n" + text.to_s + "\n"
alphas.keys.sort.each { |k| print k.to_s + ": " + alphas[k].to_s + " " }
print "\n\n"
end

printCounts(alphas, "Initial Character Counts")


print "Input Data: "
data = Array['all','your','base','are','belong','to','us']
data.each { |x|
print x + " "
x.scan(/./m) { |c| alphas[c] = alphas[c] + 1 }
}
print "\n"

printCounts(alphas, "Counts After Tally")

#notes: this is a bit of a long solution. Let’s talk about what’s going on. the first three lines builds a hash that has the letters a-z as the keys and always a value of 0. the next section defines a function for outputting the data. he then outputs the empty hash, sets the input data, and outputs it as he’s running the tally. finally, he outputs the calculated result.

Let’s spend some time studying this line: alphas = Hash[*alphasArr.collect { |x| [x, 0] }.flatten] as there is a lot going on here. The Hash class has a function [] that allows you to create a new hash by passing in an array in a variety of formats. The simplest of which is ['key', 'value', 'key', 'value'], which is exactly what he’s providing here. Note the * at the beginning of the statement which will expand the result array into a list of params for the [] method.

Also interesting is the use of the scan method to enumerate each character in a string. The built in each_byte method returns an integer, which is hardly what we want here.

there are some shortcuts that can be taken here: in the first section, the sort function can be tacked on to the end of the previous line or probably removed entirely because the range will return the letters in order. The function that increments can be shortened to alphas[c] += 1.

Tim: (I think)

var = {"a"=>0, "b"=>0, "c"=>0, "d"=>0, "e"=>0, "f"=>0, "g"=>0, "h"=>0, "i"=>0, "j"=>0, "k"=>0, "l"=>0, "m"=>0, "n"=
>0, "o"=>0, "p"=>0, "q"=>0, "r"=>0, "s"=>0, "t"=>0, "u"=>0, "v"=>0, "w"=>0, "x"=>0, "y"=>0, "z"=>0 }
open('250_words.txt'){|f| f.readlines}.each {|word| var[word[0,1]] +=1}
var.each {|key, value| print key, " is ", value, "\n" }

Pretty clean. There’s a lot of work being done at the beginning here to setup the hash. Whenever you feel you need to do something as repetitious as this, you’re probably missing something. The function employs a simple one line tally operation that’s based on the work we did for quiz 1. and lastly, some output.

Dave:

letter_counts = Hash.new(0)
open('250_words.txt'){|f| f.readlines}.each{|word| letter_counts[word[0,1]] += 1}
('a'..'z').each{|letter| puts "#{letter}: #{letter_counts[letter]}"}

My solution differs from the previous two in that I never create a full hash with all 26 letters. The constructor for Hash allows you to supply a default value for keys that do not yet exist. In this way, any entry that doesn’t exist will return 0 instead of the default nil. The only tricky part about going this way is the output. I can’t use a simple each because my hash only contains entries for letters that have been used. Instead, I use a range as the basis for my iterator.

All three solutions contain some interesting choices. Can’t wait to see what we come up with next.


Quiz 4

January 3, 2007

Up to this point, we’ve really only been using the features that Ruby offers right out of the box. There’s certainly a whole lot more that we can do if we’re ready to dig into some more features. We’ve already looked at how to use Ruby’s object oriented goodness to accomplish tasks. We haven’t however looked at creating our own classes or modifying existing ones.

Ruby’s object model allows for classes to be modified at any point. That even goes for built in classes. If you want to add a method to a class, all you have to do is open up that class definition and add it. That method will then be available to all objects of that type.

Your challenge for today is to make this code work:
puts [1, 4, 9, 17, 100, 576, 1000].map{|i| i.to_roman}
The output should look something like:

I
IIII
VIIII
XVII
C
DLXXVI
M

Hint: I =1 V =5 X = 10 L = 50 C = 100 D = 500 M = 1000


Quiz 3

December 18, 2006

Let’s do a little math today. Please write a script that outputs all of the prime numbers between 1 and 100, one entry per line.


Quiz 2

December 18, 2006

That turned out to be more interesting than I expected. Everyone’s solution was different. Today, let’s look at hashes a bit.

Using the same data set from yesterday, please submit a script that will report the number of times each letter is used to begin a word.

so, for a data set like this:

all
your
base
are
belong
to
us

the output from the script should be

a: 2
b: 2
t: 1
u: 1
y: 1

*extra points for outputting the complete alphabet whether every letter is used or not.

have fun


Quiz 1 :: Solutions

December 15, 2006

Here are the solutions people sent in with some notes:

Ben:

words = Array.new
File.open("250_words.txt").each { |line|
words.push(line)
}
words.sort.each { |word|
puts word
}

#notes: this looks a lot like a PHP solution transposed to ruby syntax. it’s actually pretty impressive considering Ben had 0 ruby experience at all. there are a few shortcuts to be had here:
-puts will output one item per line if you pass it an array, so the each block is not necessary.
-ruby provides [] as a synonym for Array.new

Kevin:
File.new("250_words.txt").readlines().sort().each { |x| print x, "\n" }

#notes: very clean. ruby does not require () for function calls, especially when there are no parameters. using puts could save you a bit of code, either within your block, or as the first function call of the line

Tim:

f = File.new("250_words.txt")
a = f.readlines[0..250]
a = a.sort
puts a

#notes: very nice. I like your use of a range here. It’s not necessary in this context because readlines returns an array and you’re doing a subselect of every item in that array, but if you wanted to limit the input to only 250 lines, that would be a perfect solution. ruby allows you to string multiple functions calls together on one line. for example, readlines returns an array, so we can sort it before we ever assign it to a variable ( f.readlines.sort).

Dave:
puts open('250_words.txt'){|f| f.read}.split("\n").sort

#notes: I’m pulling in the entire contents of the file as a string, then using split to separate it out to an array. readlines would be a better choice here. one thing i’d like to point out here. none of the other three solutions ever close the file. This is fine in this case because the file is closed when the script exists, but it’s a good practice to close a file as soon as you no longer need it. I’m taking advantage of the fact that the open function allows a block to be passed in. The documentation states that the file will automatically be closed when the block ends. The disadvantage is that I only have access to the file object (f) within the block, but that’s fine here, since we’re done with it once we read it’s contents into memory.

Taking from all the code we see here, we can probably make an even shorter version:
puts open('205_words.txt'){|f| f.readlines}.sort

I’ll be sending out today’s quiz in just a bit.


Quiz 1

December 14, 2006

Attached is a file containing 250 words in random order. What I would like you to do is write a ruby script that reads the list of words from the file, sorts them, and outputs them (one word per line).

250_words.txt

You will probably need these functions:
http://www.ruby-doc.org/core/classes/IO.html#M002320
http://www.ruby-doc.org/core/classes/Array.html#M002237


Follow

Get every new post delivered to your Inbox.