Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Ruby Implementation #44

Draft
wants to merge 43 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ad225f1
init commit
robertDurst Apr 9, 2023
a49178f
remove sorbet, create schema & row classes
robertDurst Apr 11, 2023
4e6bf9b
begin add column and codify ensures/requires
robertDurst Apr 11, 2023
45a1556
tests pass for data structs closer adhering to paper
robertDurst Apr 11, 2023
21cee35
especially hacky, but satisfying source code reflecting require/ensur…
robertDurst Apr 11, 2023
14e366f
work on build_column
robertDurst Apr 13, 2023
485afb8
un-negate assertions
robertDurst Apr 14, 2023
325c296
add progress to README, need to fill in what I have done thus far
robertDurst Apr 14, 2023
8a26b7d
begin working way down list of TODOs one at a time w/ tests
robertDurst Apr 15, 2023
0d33310
finish up basic functions
robertDurst Apr 15, 2023
4f79691
fix semantics of an empty table
robertDurst Apr 15, 2023
0abdf7f
fix basics to be importable module, implement table properties
robertDurst Apr 15, 2023
4e9a2f2
re-org'd to implement b2t2 closer, added rubocop for style
robertDurst Apr 15, 2023
4535b1e
Access Subcomponents
robertDurst Apr 16, 2023
a3b7db4
test type assertions, tests for empty_table, reimplement add_rows
robertDurst Apr 17, 2023
cbd603f
add column and build column constructors with tests
robertDurst Apr 17, 2023
b59c9fc
update readme with progress
robertDurst Apr 17, 2023
07f1568
remove relations from readme
robertDurst Apr 17, 2023
f78badf
add vcat and build_column
robertDurst Apr 22, 2023
a4619df
add values and cross join
robertDurst Apr 22, 2023
baf9f65
re-org before beginning example programs
robertDurst Apr 22, 2023
426e939
implement quizScoreFilter example program
robertDurst Apr 22, 2023
fe97e1a
implement brown jelly beans
robertDurst Apr 22, 2023
b1e98cd
fix test forbrown jelly beans
robertDurst Apr 22, 2023
05cb08d
make jelly bean test more functional like the example
robertDurst Apr 22, 2023
9090cf7
implement table encoder... good enough for now
robertDurst May 22, 2023
8449ef9
dot product example program
robertDurst May 25, 2023
7f94641
sample_rows example program
robertDurst May 25, 2023
3c6e1a6
select_rows, both overloads
robertDurst May 25, 2023
c5a8818
implement more errors
robertDurst May 25, 2023
e2e564c
fix brown get acne error test
robertDurst May 26, 2023
24c2435
add error for black and white
robertDurst May 26, 2023
c6e04c5
begin error helpers
robertDurst May 26, 2023
d2e7e86
implement mid final error
robertDurst May 26, 2023
d3639a6
update readme with progress
robertDurst May 26, 2023
988f42f
add final error programs
robertDurst May 26, 2023
944d9b7
complete the last error example program for use table
robertDurst May 26, 2023
e45fc83
update readme with progress
robertDurst May 26, 2023
60689d7
small simplification
robertDurst May 26, 2023
43f445b
implement head
robertDurst May 26, 2023
37b223d
implement drop_column(s), distinct
robertDurst May 26, 2023
8b9c9bc
move around some rubocop declarations and implement tsort
robertDurst May 26, 2023
64d7877
phacking example programs
robertDurst May 26, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Media/Ruby/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
source 'https://rubygems.org'

# gem 'sorbet-static-and-runtime'
gem 'ruby2ruby'

group :development, :test do
gem 'rspec'
# gem 'tapioca', require: false
end

34 changes: 34 additions & 0 deletions Media/Ruby/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.5.0)
rspec (3.12.0)
rspec-core (~> 3.12.0)
rspec-expectations (~> 3.12.0)
rspec-mocks (~> 3.12.0)
rspec-core (3.12.1)
rspec-support (~> 3.12.0)
rspec-expectations (3.12.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-mocks (3.12.5)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-support (3.12.0)
ruby2ruby (2.5.0)
ruby_parser (~> 3.1)
sexp_processor (~> 4.6)
ruby_parser (3.20.0)
sexp_processor (~> 4.16)
sexp_processor (4.16.1)

PLATFORMS
arm64-darwin-22
x86_64-linux

DEPENDENCIES
rspec
ruby2ruby

BUNDLED WITH
2.2.3
122 changes: 122 additions & 0 deletions Media/Ruby/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Ruby

**This code was written and tested with Ruby 3.2.0.**

## How to Execute Tests

If you haven't already, install gems.
```
bundle install
```

Execute tests.
```
bundle rspec .
```

***

## Table API Implementation Progress

#### Assumptions

**Functions:**

* [x] even
* [x] length
* [x] schema
* [x] range
* [x] concat
* [x] startsWith
* [x] average
* [x] filter
* [x] map
* [x] removeDuplicates
* [x] removeAll
* [x] colNameOfNumber


**Relations:**

* [ ] x has no duplicates
* [ ] x is equal to y
* [ ] x is (not) in y
* [ ] x is a subsequence of y
* [ ] x is of sort y
* [ ] x is y
* [ ] x is a categorical sort
* [ ] x is (non-)negative
* [ ] x is equal to the sort of y
* [ ] x is the sort of elements of y
* [ ] x is equal to y with all a_i replaced with b_i

#### Constructors
* [ ] emptyTable
* [ ] addRows
* [ ] addColumn
* [ ] buildColumn
* [ ] vcat
* [ ] hcat
* [ ] values
* [ ] crossJoin
* [ ] leftJoin

#### Properties

* [ ] nrows
* [ ] ncols
* [ ] header

#### Access Subcomponents

* [ ] getRow
* [ ] getValue
* [ ] getColumn (overloading 1 & 2)

#### Subtable

* [ ] selectRows (overloading 1 & 2)
* [ ] selectColumns (overloading 1 & 2 & 3)
* [ ] head
* [ ] distinct
* [ ] dropColumn
* [ ] dropColumns
* [ ] tfilter

#### Ordering

* [ ] tsort
* [ ] sortByColumns
* [ ] orderBy

#### Aggregate

* [ ] count
* [ ] bin
* [ ] piviotTable
* [ ] groupBy

#### Missing Values

* [ ] completeCases
* [ ] dropna
* [ ] fillna

#### Data Cleaning

* [ ] pivotLonger
* [ ] pivotWider

#### Utilities

* [ ] flatten
* [ ] transformColumn
* [ ] renameColumns
* [ ] find
* [ ] groupByRetentive
* [ ] grouoBySubtractive
* [ ] update
* [ ] select
* [ ] selectMany
* [ ] groupJoin
* [ ] join
141 changes: 141 additions & 0 deletions Media/Ruby/basics.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
module Basics
# consumes an integer and returns a boolean
def self.even(number)
assert_type_number(number)

number % 2 == 0
end

# consumes a sequence and measures its length
def self.length(sequence)
assert_type_sequence(sequence)

sequence.size
end

# extracts the schema of a table
def self.schema(table)
assert_type_table(table)

table.schema
end

# TODO: is this the desired definition of range?
# consumes a number and produces a sequence of valid indices
def self.range(number)
assert_type_number(number)

(0 ... number).to_a
end

# concatenates two sequences or two strings
def self.concat(value_a, value_b)
assert_types_match(value_a, value_b)
assert_type_sequence_or_string(value_a)

value_a.concat(value_b)
end

# checks whether a string starts with another string
def self.starts_with(string_value, start_value)
assert_type_string(string_value)
assert_type_string(start_value)

string_value.start_with?(start_value)
end

# computes the average of a sequence of numbers
def self.average(sequence_of_numbers)
assert_type_sequence(sequence_of_numbers)

return 0 unless sequence_of_numbers.size > 0

total = 0
sequence_of_numbers.each do |number|
assert_type_number(number)

total += number
end

total / sequence_of_numbers.size
end

# the conventional sequence (e.g. lists) filter
def self.filter(sequence, &block)
assert_type_sequence(sequence)

sequence.select { |x| block.call(x) }
end

# the conventional sequence (e.g. lists) map
def self.map(sequence, &block)
assert_type_sequence(sequence)

sequence.map { |x| block.call(x) }
end

# consumes a sequence and produces a subsequence with all duplicated elements removed
def self.remove_duplicates(sequence)
assert_type_sequence(sequence)

memoize = {}
sequence.select do |x|
next false if memoize.key?(x)

memoize[x] = true

true
end
end

# consumes two sequences and produces a subsequence of the first input, removing all elements that also appear in the second input
def self.remove_all(sequence_a, sequence_b)
assert_type_sequence(sequence_a)
assert_type_sequence(sequence_b)

values_in_b = sequence_b.reduce({}) { |memoize, x| memoize[x] = true; memoize }

sequence_a.select { |x| !values_in_b.key?(x) }
end

# TODO: figure out what the inputs should be
# converts a `Number` to a `ColName`
def self.col_name_of_number(schema, number)
assert_type_schema(schema)
assert_type_number(number)
raise ArgumentError.new("number is greater than number of columns") if schema.headers.size < number
raise ArgumentError.new("number is greater than number of columns") if number <= 0

index = number - 1
schema.headers[index][:column_name]
end

#### helpers specific to this class ####
def self.assert_type_number(number)
raise ArgumentError.new("expected an int or float") unless number.is_a?(Integer) || number.is_a?(Float)
end

def self.assert_type_sequence(sequence)
raise ArgumentError.new("expected a sequence") unless sequence.is_a?(Array)
end

def self.assert_type_string(string)
raise ArgumentError.new("expected a string") unless string.is_a?(String)
end

def self.assert_type_table(table)
raise ArgumentError.new("expected a table") unless table.is_a?(Table)
end

def self.assert_type_schema(schema)
raise ArgumentError.new("expected a schema") unless schema.is_a?(Schema)
end

def self.assert_type_sequence_or_string(value)
raise ArgumentError.new("expected a sequence or string") unless value.is_a?(Array) || value.is_a?(String)
end

def self.assert_types_match(value_a, value_b)
raise ArgumentError.new("expected types to match") unless value_a.class == value_b.class
end
end
Loading