Skip to content

Instantly share code, notes, and snippets.

@junjiah
Last active January 4, 2016 05:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save junjiah/8577574 to your computer and use it in GitHub Desktop.
Save junjiah/8577574 to your computer and use it in GitHub Desktop.
Homework for "Seven Languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages"
######### day 1 homework #########
# Bonus problem: If you're feeling the need for a little more, write
# a program that picks a random number. Let a player guess the
# number, telling the player whether the guess is too low or too high.
while (true)
random_num = rand(10)
input = ""
puts "guess a number between 0 and 9"
input = gets
break if input =~ /^\s$/
input = input.chomp
if random_num == input.to_i
puts "you are right, the number is #{random_num}"
else
puts "sorry you are wrong, the number is #{random_num}"
end
end
######### day 2 homework #########
# Print the contents of an array of sixteen numbers, four numbers at a time
a = (1..16).to_a
a.each_slice(4) {|x| p x}
# The Tree class was interesting, but it did not allow you to specify
# a new tree with a clean user interface. Let the initializer accept a
# nested structure with hashes and arrays. You should be able to
# specify a tree like this: {'grandpa' => {' dad' => {'child 1' => {}, 'child
# 2' => {} }, 'uncle' => {'child 3' => {}, 'child 4' => {} } } }.
class Tree
attr_accessor :children, :node_name
def initialize(t)
first_items = t.first
@node_name = first_items[0]
@children = first_items[1].map do |h|
Tree.new([h])
end
end
def visit_all(&block)
visit &block
children.each {|c| c.visit_all &block}
end
def visit(&block)
block.call self
end
end
# Write a simple grep that will print the lines of a file having any
# occurrences of a phrase anywhere in that line. You will need to do
# a simple regular expression match and read lines from a file. (This
# is surprisingly simple in Ruby.) If you want, include line numbers.
def grep(filename, pattern)
file = File.open(filename)
file.each {|line| puts "#{file.lineno}: #{line.chomp}" if pattern =~ line}
end
######### day 3 homework #########
# Modify the CSV application to support an each method to return a
# CsvRow object. Use method_missing on that CsvRow to return the value
# for the column for a given heading.
# For example, for the file:
# one, two
# lions, tigers
# allow an API that works like this:
# csv = RubyCsv.new
# csv.each {|row| puts row.one}
# This should print "lions".
class CsvRow
attr_reader :row, :headers
def initialize row, headers
@row = row
@headers = headers
end
def method_missing name, *args
i = @headers.index(name.to_s)
if i
@row[i]
else
nil
end
end
end
class ActsAsCsv
def self.acts_as_csv
define_method 'read' do
file = File.new(self.class.to_s.downcase + '.txt')
@headers = file.gets.chomp.split(', ')
file.each do |row|
@result << CsvRow.new(row.chomp.split(', '), @headers)
end
end
define_method "headers" do
@headers
end
define_method "csv_contents" do
@result
end
define_method "initialize" do
@result = []
read
end
define_method "each" do |&block|
@result.each do |row|
block.call row
end
end
end
end
class RubyCsv < ActsAsCsv
acts_as_csv
end
###### day 1 homework ######
# Execute the code in a slot given its name.
getSlot("println") call "Hello, Io!" // target object is Lobby
###### day 2 homework ######
/*** reference: http://brikis98.blogspot.jp/2012/02/seven-languages-in-seven-weeks-io-day-2.html ***/
# Write a program to find the nth Fibonacci number
fibRec := method(n,
if(n <= 2, 1, fibRec(n-2) + fibRec(n-1))
)
fibIter := method(n,
if(n <= 2, 1,
prev1 := 1;
prev2 := 1;
i := 3;
while(i <= n,
res := prev1 + prev2;
prev1 = prev2;
prev2 = res;
i = i + 1;
);
prev2
)
)
# How would you change the "/" operator to return 0 if the denominator is zero?
Number div := Number getSlot("/") # tmp op for '/'
Number / := method(d, if(d == 0, 0, call target div(d)))
Number / := method(d, if(d == 0, 0, self div(d))) # alternatively
# Write a program to add up all the values in a 2-dimensional array.
x := list(list(1,2,3), list(4,5,6))
x reduce(res, cur, res + (cur sum), 0)
# alternatively
sum2dArray := method(arr,
arr flatten sum
)
# Add a slot called "myAverage" to a list that computes the average of all the numbers in a list. Bonus: raise an exception if any item in the list is not a number.
List myAverage := method(
if(
self select(v, v isKindOf(Number) == false) size == 0,
self average,
Exception raise("illegal operation on non-numbers")
)
)
# alternatively
List myAverage := method(
sum := 0
self foreach(i, v, if(v type == "Number", sum = sum + v, Exception raise("#{v} is not a Number" interpolate)))
sum / (self size)
)
# Write a prototype for a two-dimensional list. The dim(x, y) method should allocate a list of y lists that are x elements long. set(x, y, value) should set a value and get(x, y) should return that value. Write a transpose method so that new_matrix get(y, x) == original_matrix get(x, y). Write the matrix to a file and read the matrix from a file.
Matrix := List clone do (
dim := method(x, y,
self setSize(y);
self mapInPlace(v,
v = list();
v setSize(x)))
set := method(x, y, value,
self at(y) atPut(x, value))
get := method(x, y,
self at(y) at(x))
transpose := method(
x := self size;
y := self at(0) size;
res := Matrix clone dim(x, y);
for(i, 0, x-1,
for(j, 0, y-1,
res set(i, j, self get(j, i))
)
);
# or
self foreach(y, subList,
subList foreach(x, value,
res set(y, x, value)
)
)
res
)
)
// alternatively, from https://gist.github.com/tomtung/2922865
// Write a prototype for a two-dimensional list:
// - dim(x, y)
// - set(x,y,value), get(x, y)
// - transpose
Matrix := Object clone do(
indexOf := method(x, y,
if(rowMajor, x * dim2 + y, y * dim1 + x))
set := method(x, y, value, content atPut(indexOf(x, y), value))
get := method(x, y, content at(indexOf(x, y)))
transposed := method(
m := Matrix clone
m dim1 = dim2; m dim2 = dim1
m rowMajor = rowMajor not # negate!
m content = list() copy(content)
m
)
save := method(path,
File with(path) open write(self serialized) close
self
)
load := method(path, doFile(path))
rowMajor := true
dim1 := 1
dim2 := 1
content := list() setSize(1)
)
dim := method(x, y,
m := Matrix clone
m rowMajor = true
m dim1 = x
m dim2 = y
m content = list() setSize(x*y)
m
)
###### day 3 homework ######
/*** reference: http://brikis98.blogspot.jp/2012/02/seven-languages-in-seven-weeks-io-day-3.html ***/
/*** reference: https://gist.github.com/tomtung/2922865 ***/
// Create a list syntax that uses brackets.
squareBrackets := method(
l := List clone
call message arguments foreach(arg,
l push(doMessage(arg))
)
l
)
# alternatively
squareBrackets := method(call evalArgs)
// Enhance the XML program
// - to add spaces to show the indentation structure.
// - if the first argument is a map (use the curly brackets syntax),
// add attributes to the XML program.
OperatorTable addAssignOperator(":", "genAttr")
genAttr := method(
attrName := call evalArgAt(0) asMutable removePrefix("\"") removeSuffix("\"");
"#{attrName}=\"#{call evalArgAt(1)}\"" interpolate
)
Builder := Object clone do (
curlyBrackets := method(
call evalArgs join(" ")
)
forward := method(
args := call message arguments
if(args size > 0 and args at(0) name == "curlyBrackets",
attr := " " .. self doMessage(args removeFirst),
attr := ""
)
writeln(indent, "<#{call message name}#{attr}>" interpolate)
indentCount = indentCount + 1
args foreach(arg,
content := self doMessage(arg);
if(content type == "Sequence",
writeln(indent, content)
)
)
indentCount = indentCount - 1
writeln(indent, "</", call message name, ">")
)
indentCount := 0
indent := method(" " repeated(indentCount))
)
# test, should be put in another file
Builder html(
head(
title("Test webpage")
),
body(
h1("Welcome to my test webpage!"),
div({"class": "content", "id": "main"},
p("Lots of fun to be had!"),
p("Don't forget to sign the guest book")
)
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment