view 2-Io/day2-self-study.io @ 47:409249712590

Add final experimentation and note about DSL
author IBBoard <dev@ibboard.co.uk>
date Fri, 22 Sep 2017 19:48:13 +0100
parents f4ea1f637f22
children
line wrap: on
line source

# 1) Fibanacci by recursion (fibr) and loop (fibl)
fibr := method(num,
    if (num < 1,
        return 0,
        if (num == 1,
            return 1,
            prev := fibr(num - 1) ;
                prev_prev := fibr(num - 2) ;
                return prev + prev_prev
        )
    )
)

"fibr(9) = " print
fibr(9) println
"fibr(4) = " print
fibr(4) println
"fibr(1) = " print
fibr(1) println


fibl := method(num,
    if (num < 1, return 0)
    if (num == 1, return 1)
    prev := 1
    prev_prev := 0
    val := 0    
    for(i, 2, num,
        val = prev + prev_prev
        prev_prev = prev
        prev = val
    )
    return val
)

"fibl(9) = " print
fibl(9) println
"fibl(4) = " print
fibl(4) println
"fibl(1) = " print
fibl(1) println


# 2) Changing "/" operator to return 0 for a zero denominator
# Operators are just messages on objects, so "/" is the message to override
# and it must be on the object type Number
Number defaultDivide := Number getSlot("/")
Number / := method(denom,
    if (denom == 0,
        return 0,
        return self defaultDivide(denom))
)
(4 / 2) println
(4 / 0) println


# 3) Add up numbers in a 2D array
arr := list(
    list(1, 2, 3),
    list(4, 5, 6),
    list(7, 8, 9)
)

add2D := method(arr,
    sum := 0
    # A "reduce()" method would be nice, but KISS for now and foreach all the things
    arr foreach(dimension, dimension foreach(val, sum = sum + val))
    return sum
)

add2D(arr) println


# 4) Add myAverage to average numbers in a list
List myAverage := method(
    sum := 0
    self foreach(val, if (val proto == Number,
                          sum = sum + val,
                          Exception raise("Non-object found in list"))
                )
    return sum / self size
)

list(1, 2, 3) myAverage println
# This will exception - run at the end!
# list(1, 2, 3, "foo") myAverage
# With default behaviour then this could divide by zero (unless we'd been defensive coding)
# But we're in the same file as our custom "/", so we should get zero
list() myAverage println


#5) 2D list
TwoDList := Object clone
# It'd be nice to do something to set defaults when first cloning
# but I can't find how to do that, so force the developer to
# always dim() after clone
TwoDList dim := method(x, y,
    self arr := list()
    for (i, 1, x,
        sub_list := list()
        for (j, 1, y, 
            sub_list append(nil)
        )
        arr append(sub_list)
    )
)
TwoDList set := method(x, y, value,
    self arr at(x) atPut(y, value)
)

TwoDList get := method(x, y,
    outer := self arr at(x)
    if (outer != nil,
        return outer at(y),
        return nil
    )
)

my_arr := TwoDList clone
my_arr dim(2, 3)
my_arr println
my_arr set(0, 1, "0,1")
my_arr set(1, 2, "Bottom-right")
my_arr get(1, 2) println
my_arr get(0, 1) println
my_arr get(0, 0) println
my_arr get(5, 5) println


#6) Bonus "transpose" method (ugly and inefficient method)
TwoDList transpose := method(
    new_list := TwoDList clone
    x := self arr size
    y := self arr at(0) size
    new_list dim(y, x)
    for (i, 0, x - 1,
        for (j, 0, y - 1,
            new_list set(j, i, self get(i, j))
        )
    )
    return new_list
)

transposed := my_arr transpose
transposed get(1, 2) println
transposed get(0, 1) println
transposed get(2, 1) println
transposed get(1, 0) println

#7) Write a matrix to a file and read it back
# Might as well use the TwoDList as a matrix
# Note: This isn't white-space safe, but nvm
TwoDList as_string := method(
    x := self arr size
    y := self arr at(0) size
    #str := "#{self arr size}×#{self arr at(0) size}\n" interpolate
    str := ""
    for (i, 0, x - 1,
        for (j, 0, y - 1,
            str = "#{str}#{self get(i, j)} " interpolate
        )
        str = "#{str asMutable strip}\n" interpolate
    )
)

TwoDList load := method(matrix_string,
    # strip to make sure that we don't get trailing new lines
    rows := matrix_string strip split("\n")
    row_count := rows size
    # Ugly way to get column count
    col_count := rows at(0) split(" ") size
    self dim(row_count, col_count)    
    for (i, 0, row_count - 1,
        row := rows at(i) split(" ")
        for (j, 0, col_count - 1,
            self set(i, j, row at(j))
        )
    )
)
matrix_file := "matrix.txt"
f := File with(matrix_file)
f remove
f openForUpdating
f write(my_arr as_string)
f flush
f close

f2 := File with(matrix_file)
f2 openForReading
new_list := TwoDList clone
new_list load(f2 contents)
f2 close
new_list get(1, 2) println
new_list get(0, 1) println


# 4) final piece
list(1, 2, 3, "foo") myAverage