Last active
January 4, 2016 05:49
-
-
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"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
######### 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
###### 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