-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmath.rb
59 lines (56 loc) · 1.38 KB
/
math.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# takes a list [[a, [b, c], 0, [3, 4], d]]
# Be aware of the double wrapping list brackets
# and returns all possible combinations
# - [a, b, 0, 3, d]
# - [a, b, 0, 4, d]
# - [a, c, 0, 3, d]
# - [a, c, 0, 4, d]
#
# Inner lists can be empty
def combinations(l)
# If the cartesian product contains one empty list, the
# complete result is empty
l.each do |e|
if e.class == Array
if e.include?([])
return []
end
end
end
# This helper function takes a list
# [a, [c, d], e, [7, 8]] and expands
# the first bracket within the list to
# [[a, c, e, [7, 8]], [a, d, e, [7,8]]]
expand = ->(list) {
res = []
list.each_index do |i|
if list[i].class == Array
list[i].each do |e|
copy = Array.new(list)
copy[i, 1] = e
res.push(copy)
end
return res
end
end
}
# Helper function which returns true if there is
# still sth to expand
# [bin, c, b, 3] -> false
# [bin, [a,c], b, 3] -> true
containsArray = ->(list) { list.class == Array ? list.any? { |el| el.class == Array } : false }
# Check first if there is work left
if l.any? { |list| containsArray.call(list) }
# If Yes: expand something
l.map! { |list| expand.call(list) }
# Is there still something to expand?
# then call recursively
if l.any? { |list| containsArray.call(list) }
return combinations(l.flatten(1))
else
return l.flatten(1)
end
else
return l
end
end