Last active
January 28, 2017 23:51
-
-
Save wobh/06fd32bf46ae876bc656d0a1a165b025 to your computer and use it in GitHub Desktop.
Exercise implementing multidimensional arrays in Ruby
This file contains hidden or 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
# Exercise for implementing multi-dimesional arrays in Ruby | |
# TODO: | |
# Level 0: Implement `row_major_index` and `to_a`. | |
# Level 1: How could tests be improved? | |
# Level 2: How could the interface of ArrayN be extended? Made more idiomatic? | |
# Multi-dimensional array | |
class ArrayN | |
def initialize (dimension, *dimensions) | |
@dimensions = dimension, *dimensions | |
@dimensions.freeze | |
@contents = Array.new total_size | |
end | |
attr_reader :dimensions | |
def total_size | |
@total_size ||= @dimensions.reduce(:*) | |
end | |
def rank | |
@rank ||= dimensions.size | |
end | |
def in_bounds? (subscript, *subscripts) | |
all = subscript, *subscripts | |
return false unless all.size == rank | |
rank.times do |idx| | |
one = all.fetch(idx) | |
return false if one < 0 | |
return false unless one < dimensions.fetch(idx) | |
end | |
true | |
end | |
def fetch (subscript, *subscripts) | |
@contents.fetch row_major_index(subscript, *subscripts) | |
end | |
def store (item, subscript, *subscripts) | |
@contents[row_major_index(subscript, *subscripts)] = item | |
end | |
def row_major_index (subscript, *subscripts) | |
raise NotImplementedError, "Left as exercise to student." | |
end | |
def to_a | |
raise NotImplementedError, "Left as exercise to student." | |
end | |
end | |
require 'minitest/autorun' | |
class ArrayNTest < Minitest::Test | |
def setup | |
@subject = ArrayN.new 2, 3, 5 | |
end | |
def test_total_size | |
assert_equal 30, @subject.total_size | |
end | |
def test_rank | |
assert_equal 3, @subject.rank | |
end | |
def test_in_bounds? | |
assert @subject.in_bounds?(1, 2, 4) | |
refute @subject.in_bounds?(2, 2, 4) | |
end | |
def test_store_fetch | |
@subject.store 0, 0, 0, 0 | |
assert_equal 0, @subject.fetch(0, 0, 0) | |
end | |
def test_row_major_index | |
assert_equal 1, @subject.row_major_index(0, 0, 1) | |
assert_equal 5, @subject.row_major_index(0, 1, 0) | |
assert_equal 15, @subject.row_major_index(1, 0, 0) | |
end | |
def test_to_a | |
assert_equal [[[nil, nil, nil, nil, nil], | |
[nil, nil, nil, nil, nil], | |
[nil, nil, nil, nil, nil]], | |
[[nil, nil, nil, nil, nil], | |
[nil, nil, nil, nil, nil], | |
[nil, nil, nil, nil, nil]]], @subject.to_a | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment