lisp-interpreter 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +75 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +173 -0
- data/Rakefile +6 -0
- data/bin/console.bat +2 -0
- data/bin/setup +8 -0
- data/bin/start.rb +2 -0
- data/lib/lisp/interpreter.rb +9 -0
- data/lib/lisp/interpreter/boolean.rb +42 -0
- data/lib/lisp/interpreter/checker.rb +45 -0
- data/lib/lisp/interpreter/errors.rb +13 -0
- data/lib/lisp/interpreter/functional.rb +272 -0
- data/lib/lisp/interpreter/list.rb +162 -0
- data/lib/lisp/interpreter/numbers.rb +161 -0
- data/lib/lisp/interpreter/object.rb +51 -0
- data/lib/lisp/interpreter/parser.rb +72 -0
- data/lib/lisp/interpreter/run.rb +4 -0
- data/lib/lisp/interpreter/strings.rb +131 -0
- data/lib/lisp/interpreter/tokenizer.rb +185 -0
- data/lib/lisp/interpreter/validator.rb +53 -0
- data/lib/lisp/interpreter/value_finder.rb +60 -0
- data/lib/lisp/interpreter/version.rb +5 -0
- data/lisp-interpreter.gemspec +35 -0
- data/spec/lisp/interpreter_spec.rb +987 -0
- data/spec/spec_helper.rb +14 -0
- metadata +116 -0
@@ -0,0 +1,272 @@
|
|
1
|
+
# Optimization module
|
2
|
+
module Optimize
|
3
|
+
def fold_values_helper(other)
|
4
|
+
other = other.map { |t| find_list_function_value [t] }
|
5
|
+
(equalize_lists other).transpose
|
6
|
+
end
|
7
|
+
|
8
|
+
def get_fold_values(other)
|
9
|
+
values = find_all_values other
|
10
|
+
raise 'Incorrect number of arguments' if values.empty?
|
11
|
+
x = values[0]
|
12
|
+
y = fold_values_helper values[1..-1]
|
13
|
+
[x, y]
|
14
|
+
end
|
15
|
+
|
16
|
+
def rm_from_in_scope(scope, idx, def_vars)
|
17
|
+
i = find_bracket_idx scope, idx
|
18
|
+
def_vars[scope[idx + 2].to_s] = scope[idx + 3..i - 1]
|
19
|
+
scope.slice!(idx..i)
|
20
|
+
[i + 1, scope, def_vars]
|
21
|
+
end
|
22
|
+
|
23
|
+
def inner_scope_replace(scope, vars)
|
24
|
+
scope.each_with_index do |t, i|
|
25
|
+
scope[i] = vars[t.to_s] if vars.key? t.to_s
|
26
|
+
end
|
27
|
+
scope.flatten
|
28
|
+
end
|
29
|
+
|
30
|
+
def fetch_inner_scope(scope, idx = 0, def_vars = {})
|
31
|
+
until idx >= scope.size
|
32
|
+
if scope[idx] == 'define'
|
33
|
+
idx, scope, def_vars = rm_from_in_scope scope, idx - 1, def_vars
|
34
|
+
else
|
35
|
+
idx += 1
|
36
|
+
end
|
37
|
+
end
|
38
|
+
inner_scope_replace scope, def_vars
|
39
|
+
end
|
40
|
+
|
41
|
+
def filter_helper(func, values)
|
42
|
+
result =
|
43
|
+
if func.is_a? Proc
|
44
|
+
values.select { |t| func.call(*t) == '#t' }
|
45
|
+
else
|
46
|
+
values.select { |t| (send func, [t]) == '#t' }
|
47
|
+
end
|
48
|
+
build_list result
|
49
|
+
end
|
50
|
+
|
51
|
+
def apply_helper(func, values)
|
52
|
+
return func.call(*values) if func.is_a? Proc
|
53
|
+
send func, values
|
54
|
+
end
|
55
|
+
|
56
|
+
def call_compose(other)
|
57
|
+
tmp = ['(', *other[1..-1]]
|
58
|
+
idx = find_bracket_idx tmp, 0
|
59
|
+
funcs = find_all_values tmp[1..idx - 1]
|
60
|
+
value, = find_next_value tmp[idx + 1..-1]
|
61
|
+
funcs.reverse.each do |t|
|
62
|
+
value = calc_input_val ['(', t, value.to_s, ')']
|
63
|
+
end
|
64
|
+
value
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_compose_expr(funcs)
|
68
|
+
expr = ['(', 'x', ')']
|
69
|
+
funcs.each do |f|
|
70
|
+
expr << '('
|
71
|
+
expr << f
|
72
|
+
end
|
73
|
+
expr << 'x'
|
74
|
+
funcs.size.times { expr << ')' }
|
75
|
+
expr
|
76
|
+
end
|
77
|
+
|
78
|
+
def do_not_call_compose(other)
|
79
|
+
funcs = find_all_values other
|
80
|
+
raise 'Incorrect data type' if funcs.any? { |t| t.to_s.number? }
|
81
|
+
expr = build_compose_expr funcs
|
82
|
+
proc_lambda expr
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# FunctionalScheme helper
|
87
|
+
module FunctionalSchemeHelper
|
88
|
+
include Optimize
|
89
|
+
def foldl_helper(func, accum, lst)
|
90
|
+
return accum if lst.empty?
|
91
|
+
value = func.call(*lst[0], accum.to_s) if func.is_a? Proc
|
92
|
+
value = send func, [*lst[0], accum] if value.nil?
|
93
|
+
foldl_helper func, value.to_s, lst[1..-1]
|
94
|
+
end
|
95
|
+
|
96
|
+
def foldr_helper(func, accum, lst)
|
97
|
+
return accum if lst.empty?
|
98
|
+
value = foldr_helper func, accum, lst[1..-1]
|
99
|
+
return func.call(*lst[0], value.to_s) if func.is_a? Proc
|
100
|
+
send func, [*lst[0], value.to_s]
|
101
|
+
end
|
102
|
+
|
103
|
+
def equalize_lists(other)
|
104
|
+
min = other.map(&:size).min
|
105
|
+
other.map { |t| t[0..min - 1] }
|
106
|
+
end
|
107
|
+
|
108
|
+
def member_helper(to_check, values)
|
109
|
+
return '#f' unless values.include? to_check
|
110
|
+
idx = values.index(to_check)
|
111
|
+
build_list values[idx..-1]
|
112
|
+
end
|
113
|
+
|
114
|
+
def find_params_lambda(other)
|
115
|
+
raise 'Unbound symbol ' + other.to_s if other[0] != '('
|
116
|
+
idx = find_bracket_idx other, 0
|
117
|
+
[other[1..idx - 1], other[idx + 1..-1]]
|
118
|
+
end
|
119
|
+
|
120
|
+
def eval_lambda(other)
|
121
|
+
idx = find_bracket_idx other.unshift('('), 0
|
122
|
+
to_eval = other[1..idx - 1]
|
123
|
+
(proc_lambda to_eval).call(*other[idx + 1..-1])
|
124
|
+
end
|
125
|
+
|
126
|
+
def proc_lambda_helper(other, params, args)
|
127
|
+
args = arg_finder args
|
128
|
+
raise 'Incorrect number of arguments' unless params.size == args.size
|
129
|
+
define_func_helper other.dup, params.dup, args
|
130
|
+
end
|
131
|
+
|
132
|
+
def proc_lambda(other)
|
133
|
+
params, other = find_params_lambda other
|
134
|
+
other = fetch_inner_scope other
|
135
|
+
to_return = other[0..1].join == '(compose' && params.empty?
|
136
|
+
return calc_input_val other if to_return
|
137
|
+
proc = proc do |*args|
|
138
|
+
proc_lambda_helper other, params, args
|
139
|
+
end
|
140
|
+
proc
|
141
|
+
end
|
142
|
+
|
143
|
+
def fetch_define(other)
|
144
|
+
if other[0] == '('
|
145
|
+
define_function other
|
146
|
+
else
|
147
|
+
define_var other[0].to_s, (find_all_values other[1..-1])
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def define_var(var, values)
|
152
|
+
raise 'Incorrect number of arguments' if values.size != 1
|
153
|
+
raise 'Invalid variable name' unless valid_var_name var
|
154
|
+
set_var_helper var, values[0]
|
155
|
+
end
|
156
|
+
|
157
|
+
def set_values_define(other, params, args)
|
158
|
+
args = [args] unless args.is_a? Array
|
159
|
+
other.each_with_index do |t, idx|
|
160
|
+
if params.include? t
|
161
|
+
i = params.index t
|
162
|
+
other[idx] = args[i]
|
163
|
+
end
|
164
|
+
end
|
165
|
+
other
|
166
|
+
end
|
167
|
+
|
168
|
+
def define_func_helper(other, params, args)
|
169
|
+
temp = set_values_define other, params, args
|
170
|
+
calc_input_val temp
|
171
|
+
end
|
172
|
+
|
173
|
+
def arg_finder_helper(name, args)
|
174
|
+
if !name.nil?
|
175
|
+
args = args[1..-1]
|
176
|
+
[name, args]
|
177
|
+
else
|
178
|
+
find_next_value args
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def arg_finder(args)
|
183
|
+
result = []
|
184
|
+
until args.empty?
|
185
|
+
name = predefined_method_caller [args[0]]
|
186
|
+
temp, args = arg_finder_helper name, args
|
187
|
+
result << temp
|
188
|
+
end
|
189
|
+
result
|
190
|
+
end
|
191
|
+
|
192
|
+
def define_function(other)
|
193
|
+
idx = find_bracket_idx other, 0
|
194
|
+
name, *params = other[1..idx - 1]
|
195
|
+
build_fn = ['(', 'lambda', '(', *params, ')', *other[idx + 1..-1], ')']
|
196
|
+
define_var name, (find_all_values build_fn)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# Functional programming main functions
|
201
|
+
module FunctionalScheme
|
202
|
+
include FunctionalSchemeHelper
|
203
|
+
def foldl(other)
|
204
|
+
raise 'Incorrect number of parameters' if other.size < 2
|
205
|
+
func, other = valid_function other
|
206
|
+
val_one, val_two = get_fold_values other
|
207
|
+
foldl_helper func, val_one, val_two
|
208
|
+
end
|
209
|
+
|
210
|
+
def foldr(other)
|
211
|
+
raise 'Incorrect number of parameters' if other.size < 2
|
212
|
+
func, other = valid_function other
|
213
|
+
val_one, val_two = get_fold_values other
|
214
|
+
foldr_helper func, val_one, val_two
|
215
|
+
end
|
216
|
+
|
217
|
+
def filter(other)
|
218
|
+
raise 'Incorrect number of parameters' if other.size < 2
|
219
|
+
func, other = valid_function other
|
220
|
+
raise 'Incorrect number of parameters' if other.empty?
|
221
|
+
values = find_all_values other
|
222
|
+
values = find_list_function_value [values[0]]
|
223
|
+
filter_helper func, values
|
224
|
+
end
|
225
|
+
|
226
|
+
def member(other)
|
227
|
+
raise 'Incorrect number of arguments' unless other.size == 2
|
228
|
+
to_check = other[0]
|
229
|
+
split_val = split_list_string other[1]
|
230
|
+
raise 'Invalid argument' unless split_val.pair? || split_val.list?
|
231
|
+
values = find_all_values split_val[2..-2]
|
232
|
+
member_helper to_check, values
|
233
|
+
end
|
234
|
+
|
235
|
+
def remove(other)
|
236
|
+
raise 'Incorrect number of arguments' unless other.size == 2
|
237
|
+
to_remove = other[0]
|
238
|
+
values = find_list_function_value [other[1]]
|
239
|
+
values.delete_at(values.index(to_remove) || values.length)
|
240
|
+
build_list values
|
241
|
+
end
|
242
|
+
|
243
|
+
def apply(other)
|
244
|
+
raise 'Incorrect number of arguments' if other.nil? || other.empty?
|
245
|
+
func, other = valid_function other
|
246
|
+
values = find_all_values other
|
247
|
+
*vs, lst = values
|
248
|
+
raise 'Incorrect data type' unless lst.list?
|
249
|
+
(find_list_function_value [lst]).each { |t| vs << t }
|
250
|
+
apply_helper func, vs
|
251
|
+
end
|
252
|
+
|
253
|
+
def compose(other)
|
254
|
+
if other[0] != 'compose'
|
255
|
+
do_not_call_compose other
|
256
|
+
else
|
257
|
+
call_compose other
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def lambda(other)
|
262
|
+
if other[0] == 'lambda'
|
263
|
+
eval_lambda other[1..-1]
|
264
|
+
else
|
265
|
+
proc_lambda other
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def define(other)
|
270
|
+
fetch_define other
|
271
|
+
end
|
272
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# Helper functions for SchemeLists
|
2
|
+
module SchemeListsHelper
|
3
|
+
def evaluate_list(tokens, no_quotes)
|
4
|
+
find_all_values_list_evaluate tokens, no_quotes
|
5
|
+
end
|
6
|
+
|
7
|
+
def no_eval_list(tokens, no_quotes = false)
|
8
|
+
result = []
|
9
|
+
until tokens.empty?
|
10
|
+
value, tokens = build_next_value_as_string tokens
|
11
|
+
value = value[1..-2] if no_quotes && (check_for_string value.to_s)
|
12
|
+
result << value
|
13
|
+
end
|
14
|
+
result
|
15
|
+
end
|
16
|
+
|
17
|
+
def find_to_evaluate_or_not(tokens, no_quotes = false)
|
18
|
+
if tokens[0..1].join == '(list'
|
19
|
+
evaluate_list tokens[2..-2], no_quotes
|
20
|
+
elsif tokens[0..1].join == '(cons'
|
21
|
+
result = cons tokens[2..-2]
|
22
|
+
result[2..-2].split(' ')
|
23
|
+
else
|
24
|
+
no_eval_list tokens[2..-2], no_quotes
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_idx_for_list(tokens)
|
29
|
+
if tokens[0] == '('
|
30
|
+
find_bracket_idx tokens, 0
|
31
|
+
elsif tokens[1] == '('
|
32
|
+
find_bracket_idx tokens, 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def find_all_values_list_evaluate(tokens, no_quotes = false)
|
37
|
+
result = []
|
38
|
+
until tokens.empty?
|
39
|
+
x, tokens = find_next_value tokens
|
40
|
+
x = x[1..-2] if no_quotes && (check_for_string x.to_s)
|
41
|
+
result << x
|
42
|
+
end
|
43
|
+
result
|
44
|
+
end
|
45
|
+
|
46
|
+
def build_list(values)
|
47
|
+
'\'(' + values.join(' ') + ')'
|
48
|
+
end
|
49
|
+
|
50
|
+
def build_cons_from_list(values)
|
51
|
+
spacer = values[1].size == 3 ? '' : ' '
|
52
|
+
values[0].to_s + spacer + values[1][2..-2].to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
def cons_helper(values)
|
56
|
+
result =
|
57
|
+
if values[1].to_s[0..1] == '\'('
|
58
|
+
build_cons_from_list values
|
59
|
+
else
|
60
|
+
values[0].to_s + ' . ' + values[1].to_s
|
61
|
+
end
|
62
|
+
'\'(' + result + ')'
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_cons_values(tokens)
|
66
|
+
result = get_k_arguments tokens, false, 2
|
67
|
+
raise 'Too little arguments' if result.size != 2
|
68
|
+
result
|
69
|
+
end
|
70
|
+
|
71
|
+
def split_list_string(list)
|
72
|
+
result = list.split(/(\(|\)|\.)|\ /)
|
73
|
+
result.delete('')
|
74
|
+
result
|
75
|
+
end
|
76
|
+
|
77
|
+
def find_list_function_value(other)
|
78
|
+
raise 'Incorrect number of arguments' if other.size != 1
|
79
|
+
raise 'Invalid data type' unless other[0].list?
|
80
|
+
split_list_as_string other[0].to_s
|
81
|
+
end
|
82
|
+
|
83
|
+
def split_list_as_string(list_as_string)
|
84
|
+
split_value = split_list_string list_as_string.to_s
|
85
|
+
no_eval_list split_value[2..-2]
|
86
|
+
end
|
87
|
+
|
88
|
+
def car_cdr_values(other)
|
89
|
+
raise 'Incorrect number of arguments' if other.size != 1
|
90
|
+
return find_list_function_value other if other[0].list?
|
91
|
+
(split_list_string other[0].to_s)[2..-2] if other[0].pair?
|
92
|
+
end
|
93
|
+
|
94
|
+
def map_helper(lst, func)
|
95
|
+
return lst.map { |t| func.call(*t) } if func.is_a? Proc
|
96
|
+
lst.map { |t| send func, t }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Scheme lists module
|
101
|
+
module SchemeLists
|
102
|
+
include SchemeListsHelper
|
103
|
+
def cons(other)
|
104
|
+
raise 'Incorrect number of arguments' if other.size != 2
|
105
|
+
cons_helper other
|
106
|
+
end
|
107
|
+
|
108
|
+
def list(other)
|
109
|
+
build_list other
|
110
|
+
end
|
111
|
+
|
112
|
+
def car(other)
|
113
|
+
value = car_cdr_values other
|
114
|
+
raise 'Cannot apply car on ' + other[0].to_s if value.nil? || value.empty?
|
115
|
+
value.shift
|
116
|
+
end
|
117
|
+
|
118
|
+
def cdr(other)
|
119
|
+
value = car_cdr_values other
|
120
|
+
raise 'Cannot apply cdr on ' + other[0].to_s if value.nil? || value.empty?
|
121
|
+
idx = value[1] == '.' ? 2 : 1
|
122
|
+
build_list value[idx..-1]
|
123
|
+
end
|
124
|
+
|
125
|
+
def list?(other)
|
126
|
+
raise 'Incorrect number of arguments' if other.size != 1
|
127
|
+
other[0].to_s.list? ? '#t' : '#f'
|
128
|
+
end
|
129
|
+
|
130
|
+
def pair?(other)
|
131
|
+
raise 'Incorrect number of arguments' if other.size != 1
|
132
|
+
other[0].to_s.pair? ? '#t' : '#f'
|
133
|
+
end
|
134
|
+
|
135
|
+
def null?(other)
|
136
|
+
raise 'Incorrect number of arguments' if other.size != 1
|
137
|
+
return '#f' unless other[0].to_s.list?
|
138
|
+
other[0].to_s.size == 3 ? '#t' : '#f'
|
139
|
+
end
|
140
|
+
|
141
|
+
def length(other)
|
142
|
+
(find_list_function_value other).size
|
143
|
+
end
|
144
|
+
|
145
|
+
def reverse(other)
|
146
|
+
value = find_list_function_value other
|
147
|
+
build_list value.reverse
|
148
|
+
end
|
149
|
+
|
150
|
+
def map(other)
|
151
|
+
func, other = valid_function other
|
152
|
+
lst = find_all_values other
|
153
|
+
lst = lst.map { |t| find_list_function_value [t] }
|
154
|
+
lst = (equalize_lists lst).transpose
|
155
|
+
build_list map_helper lst, func
|
156
|
+
end
|
157
|
+
|
158
|
+
def shuffle(other)
|
159
|
+
values = find_list_function_value other
|
160
|
+
build_list values.shuffle
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
# Helper functions for SchemeNumbers
|
2
|
+
module SchemeNumbersHelper
|
3
|
+
def get_one_arg_function(other)
|
4
|
+
raise 'Incorrect number of arguments' if other.size != 1
|
5
|
+
raise 'Invalid data type' unless check_for_number other[0]
|
6
|
+
other[0].to_num
|
7
|
+
end
|
8
|
+
|
9
|
+
def find_idx_numerators(other)
|
10
|
+
other[0] == '(' ? (find_bracket_idx other, 0) + 1 : 1
|
11
|
+
end
|
12
|
+
|
13
|
+
def num_denom_helper(other)
|
14
|
+
raise 'Incorrect number of arguments' if other.empty?
|
15
|
+
if other.size == 1
|
16
|
+
other = other[0].split('/')
|
17
|
+
else
|
18
|
+
_, temp = find_next_value other
|
19
|
+
raise 'Incorrect number of arguments' unless temp[0] == '/' || temp.empty?
|
20
|
+
i = find_idx_numerators other
|
21
|
+
other.delete_at(i)
|
22
|
+
end
|
23
|
+
other
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_num_denom(other)
|
27
|
+
num, other = find_next_value other
|
28
|
+
raise 'Invalid data type' unless check_for_number num
|
29
|
+
return [num, 1] if other.empty?
|
30
|
+
denom, other = find_next_value other
|
31
|
+
raise 'Incorrect number of arguments' unless other.empty?
|
32
|
+
[num, denom]
|
33
|
+
end
|
34
|
+
|
35
|
+
def compare_value_arithmetic(other, oper)
|
36
|
+
raise 'Incorrect number of arguments' if other.size < 2
|
37
|
+
other = convert_to_num other
|
38
|
+
result = other.each_cons(2).all? { |x, y| x.public_send oper, y }
|
39
|
+
result ? '#t' : '#f'
|
40
|
+
end
|
41
|
+
|
42
|
+
def convert_to_num(other)
|
43
|
+
other.each do |t|
|
44
|
+
raise 'Invalid data type' unless check_for_number t
|
45
|
+
end
|
46
|
+
other.map(&:to_num)
|
47
|
+
end
|
48
|
+
|
49
|
+
def divide_special_convert(other)
|
50
|
+
other = convert_to_num other
|
51
|
+
return [0] if other.size == 1 && other[0] == 0.0
|
52
|
+
other
|
53
|
+
end
|
54
|
+
|
55
|
+
def divide_number(a, b)
|
56
|
+
return a / b if (a / b).to_i.to_f == a / b.to_f
|
57
|
+
a / b.to_f
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Scheme numbers module
|
62
|
+
module SchemeNumbers
|
63
|
+
include SchemeNumbersHelper
|
64
|
+
|
65
|
+
def <(other)
|
66
|
+
compare_value_arithmetic other, '<'
|
67
|
+
end
|
68
|
+
|
69
|
+
def >(other)
|
70
|
+
compare_value_arithmetic other, '>'
|
71
|
+
end
|
72
|
+
|
73
|
+
def <=(other)
|
74
|
+
compare_value_arithmetic other, '<='
|
75
|
+
end
|
76
|
+
|
77
|
+
def >=(other)
|
78
|
+
compare_value_arithmetic other, '>='
|
79
|
+
end
|
80
|
+
|
81
|
+
def +(other)
|
82
|
+
other = convert_to_num other
|
83
|
+
other.reduce(0, :+)
|
84
|
+
end
|
85
|
+
|
86
|
+
def -(other)
|
87
|
+
return 0 if other.empty?
|
88
|
+
other = convert_to_num other
|
89
|
+
return -other[0] if other.size == 1
|
90
|
+
other[0] + other[1..-1].reduce(0, :-)
|
91
|
+
end
|
92
|
+
|
93
|
+
def *(other)
|
94
|
+
other = convert_to_num other
|
95
|
+
other.reduce(1, :*)
|
96
|
+
end
|
97
|
+
|
98
|
+
def /(other)
|
99
|
+
raise 'Incorrect number of arguments' if other.empty?
|
100
|
+
other = divide_special_convert other
|
101
|
+
return (divide_number 1, other[0].to_num) if other.size == 1
|
102
|
+
other[1..-1].inject(other[0]) { |res, t| divide_number res, t }
|
103
|
+
end
|
104
|
+
|
105
|
+
def quotient(other)
|
106
|
+
raise 'Incorrect number of arguments' if other.size != 2
|
107
|
+
x, y = convert_to_num other
|
108
|
+
result = divide_number x, y
|
109
|
+
result < 0 ? result.ceil : result.floor
|
110
|
+
end
|
111
|
+
|
112
|
+
def remainder(other)
|
113
|
+
raise 'Incorrect number of arguments' if other.size != 2
|
114
|
+
x, y = convert_to_num other
|
115
|
+
(x.abs % y.abs) * (x / x.abs)
|
116
|
+
end
|
117
|
+
|
118
|
+
def modulo(other)
|
119
|
+
raise 'Incorrect number of arguments' if other.size != 2
|
120
|
+
x, y = convert_to_num other
|
121
|
+
x.modulo y
|
122
|
+
end
|
123
|
+
|
124
|
+
def numerator(other)
|
125
|
+
other = num_denom_helper other
|
126
|
+
result = (get_num_denom other)[0]
|
127
|
+
raise 'Invalid data type' unless check_for_number result
|
128
|
+
result.to_num
|
129
|
+
end
|
130
|
+
|
131
|
+
def denominator(other)
|
132
|
+
other = num_denom_helper other
|
133
|
+
result = (get_num_denom other)[1]
|
134
|
+
raise 'Invalid data type' unless check_for_number result
|
135
|
+
result.to_num
|
136
|
+
end
|
137
|
+
|
138
|
+
def abs(other)
|
139
|
+
(get_one_arg_function other).abs
|
140
|
+
end
|
141
|
+
|
142
|
+
def add1(other)
|
143
|
+
(get_one_arg_function other) + 1
|
144
|
+
end
|
145
|
+
|
146
|
+
def sub1(other)
|
147
|
+
(get_one_arg_function other) - 1
|
148
|
+
end
|
149
|
+
|
150
|
+
def min(other)
|
151
|
+
raise 'Incorrect number of arguments' if other.empty?
|
152
|
+
other = convert_to_num other
|
153
|
+
other.min
|
154
|
+
end
|
155
|
+
|
156
|
+
def max(other)
|
157
|
+
raise 'Incorrect number of arguments' if other.empty?
|
158
|
+
other = convert_to_num other
|
159
|
+
other.max
|
160
|
+
end
|
161
|
+
end
|