Reputation: 413
I need help with solving this ruby array question.
Get all the subsets of an array. Unique set only. No repeats of any number. num_subset([1,2,3])
==> result should be [[], ["1"], ["1", "2"], ["1", "2", "3"], ["1", "3"], ["2"], ["2", "3"], ["3"]]
def num_subset(arr)
holder =[]
order_subset = [[]]
(arr.length).times do |m|
arr.map do |n|
holder += [n]
order_subset << holder
end
holder =[] # resets holder
arr.shift # takes the first element out
end
order_subset
end
My result ==> [[], ["1"], ["1", "2"], ["1", "2", "3"], ["2"], ["2", "3"], ["3"]
. My problem is that I am missing one result ["1", "3"]
Need some help pointing me to the right direction. Spent hours on this already. Do not use #combination short cut. I need to work this out manually.
Upvotes: 4
Views: 6984
Reputation: 5340
Recursive solution
def subsets(arr)
(l = arr.pop) ? subsets(arr).map{|s| [s,s+[l]]}.flatten(1) : [[]]
end
or in a more descriptive way
def subsets(arr)
return [[]] if arr.empty?
last = arr.pop
subsets(arr).map{|set| [set, set + [last]]}.flatten(1)
end
Upvotes: 0
Reputation: 5340
I believe this is the most rubyish solution to find combinations
a = [1,2,3]
p (0..a.length).collect { |i|
a.combination(i).to_a
}.flatten(1)
# [[], [1], [2], [3], [4], [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4], [1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]]
Upvotes: 3
Reputation: 671
I have created a method to find all subsets of an array. I am using binary number to make iteration of array very less.
def find_subset(input_array)
no_of_subsets = 2**input_array.length - 1
all_subsets = []
expected_length_of_binary_no = input_array.length
for i in 1..(no_of_subsets) do
binary_string = i.to_s(2)
binary_string = binary_string.rjust(expected_length_of_binary_no, '0')
binary_array = binary_string.split('')
subset = []
binary_array.each_with_index do |bin, index|
if bin.to_i == 1
subset.push(input_array[index])
end
end
all_subsets.push(subset)
end
all_subsets
end
Output of [1,2,3] would be
[[3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]]
Upvotes: 1
Reputation: 1425
My solution.
The basic idea over here is that subsets of an array are
Subsets of the array with one less element - let's call these old subsets
array of elements containing that one less element added each of the old subsets
For Example -
Subsets([1, 2, 3]) are -
Subsets([1, 2]) - old_subsets
Tack on 3 to each of old_subsets
def subsets(arr)
return [[]] if arr.empty?
old_subsets = subsets(arr.drop(1))
new_subsets = []
old_subsets.each do |subset|
new_subsets << subset + [arr.first]
end
old_subsets + new_subsets
end
Upvotes: 0
Reputation: 29124
a = [1, 2, 3]
arr = []
for i in 0..(a.length) do
arr = arr + a.combination(i).to_a
end
> arr
# [[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]
Upvotes: 9
Reputation: 4078
Looks like you're looking at a starting point somewhere in the array and then looking at all sub arrays from that starting point on, after which you move the starting point down. That way, you're missing the sub arrays with gaps. For [1,2,3]
, the only sub array with a gap is [1,3]
.
For example (ignoring []
since you've hardcoded that)
[(1),2,3,4] -> [1]
[(1,2),3,4] -> [1,2]
[(1,2,3),4] -> [1,2,3]
[(1,2,3,4)] -> [1,2,3,4]
[1,(2),3,4] -> [2]
[1,(2,3),4] -> [2,3]
[1,(2,3,4)] -> [2,3,4]
[1,2,(3),4] -> [3]
[1,2,(3,4)] -> [3,4]
[1,2,3,(4)] -> [4]
So I'd expect your output for [1,2,3,4]
to be [[],[1],[1,2],[1,2,3],[1,2,3,4],[2],[2,3],[2,3,4],[3],[3,4],[4]]
.
You really need to rethink your algorithm. You could try recursion. Take the head of your array (1
), construct all possible sub arrays of the tail ([2,3]
), duplicate that, and prefix half of it with the head. Of course, to construct the sub arrays, you call the same function, all the way down to an empty array.
[1,2,3] ->
....[2,3] ->
........[3] ->
............[] ->
................# an empty array is its own answer
................[]
............# duplicating the empty array and prefixing one with 3
............[3], []
........# duplicating the result from the last step and prefixing half with 2
........[2,3], [2], [3], []
....# duplicating the result from the last step and prefixing half with 1
....[1,2,3], [1,2], [1,3], [1], [2,3], [2], [3], []
Upvotes: 1