尝试使用递归在 Ruby 中创建一个方法到 return 数组的所有可能组合(不是像 combination/permutation 这样的内置方法)
Trying to create a method in Ruby to return all possible combinations of an array using recursion (not built in methods like combination/permutation)
我正在学习 Ruby 并且想创建一种方法 returns 使用递归对数组进行所有可能的组合,而不使用组合或排列等内置方法。
具体来说,我想将以下 Javascript 代码转换为类似于 Ruby 的代码:
const combinations = (elements) => {
if (elements.length === 0) return [ [] ];
const firstEl = elements[0]
const rest = elements.slice(1);
const combsWithoutFirst = combinations(rest);
const combsWithFirst = [];
combsWithoutFirst.forEach(comb => {
const combWithFirst = [...comb, firstEl];
combsWithFirst.push(combWithFirst);
});
return [ ...combsWithoutFirst, ...combsWithFirst ];
}
我对编程还很陌生,我仍在努力了解递归,如果有任何帮助,我们将不胜感激!
上面的代码来自这个 youtube 视频:https://www.youtube.com/watch?v=NA2Oj9xqaZQ
您可以按如下方式进行。
def recurse(first, *rest)
return [[first], rest] if rest.empty?
recurse(*rest).flat_map { |a| [a, [first] + a] }
end
arr = [1,2,3,4,5]
a = recurse(*arr)
#=> [[5], [1, 5], [2, 5], [1, 2, 5], [3, 5], [1, 3, 5], [2, 3, 5],
# [1, 2, 3, 5], [4, 5], [1, 4, 5], [2, 4, 5], [1, 2, 4, 5], [3, 4, 5],
# [1, 3, 4, 5], [2, 3, 4, 5], [1, 2, 3, 4, 5], [], [1], [2], [1, 2],
# [3], [1, 3], [2, 3], [1, 2, 3], [4], [1, 4], [2, 4], [1, 2, 4],
# [3, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]]
a.sort
#=> [[],
# [1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5],
# [1, 2, 3, 5], [1, 2, 4], [1, 2, 4, 5], [1, 2, 5], [1, 3],
# [1, 3, 4], [1, 3, 4, 5], [1, 3, 5], [1, 4], [1, 4, 5], [1, 5],
# [2], [2, 3], [2, 3, 4], [2, 3, 4, 5], [2, 3, 5], [2, 4], [2, 4, 5], [2, 5],
# [3], [3, 4], [3, 4, 5], [3, 5],
# [4], [4, 5],
# [5]]
理解递归的最好方法是在代码中添加一些 puts 语句,并在视觉上将方法的每个实例分开。这可以在这里完成,如下所示。
INDENT = 6
def indent; $col += INDENT; end
def undent; $col -= INDENT; end
def pu(s); puts "#{" "*$col}#{s}"; end
def puhline; pu('-'*(65-$col)); end
def recurse(first, *rest)
indent
puhline
pu "recurse called with arguments first = #{first}, rest = #{rest}"
if rest.empty?
c = [[first], rest]
pu "returning #{c}"
puhline
undent
return c
end
pu "calling recurse(#{rest})"
a = recurse(*rest)
pu "#{a} is returned"
b = a.flat_map { |a| [a, [first] + a] }
pu "returning a.flat_map { |a| [a, [#{first}] + a] } = #{b}"
puhline
undent
b
end
$col = -INDENT
recurse(1,2,3,4)
显示如下。请注意,该方法的每个实例执行的计算在下方垂直对齐。
-----------------------------------------------------------------
recurse called with arguments first = 1, rest = [2, 3, 4]
calling recurse([2, 3, 4])
-----------------------------------------------------------
recurse called with arguments first = 2, rest = [3, 4]
calling recurse([3, 4])
-----------------------------------------------------
recurse called with arguments first = 3, rest = [4]
calling recurse([4])
-----------------------------------------------
recurse called with arguments first = 4, rest = []
returning [[4], []]
-----------------------------------------------
a = [[4], []] is returned
returning a.flat_map { |a| [a, [3] + a] } = [[4], [3, 4], [], [3]]
-----------------------------------------------------
a = [[4], [3, 4], [], [3]] is returned
returning a.flat_map { |a| [a, [2] + a] } = [[4], [2, 4], [3, 4], [2, 3, 4], [], [2], [3], [2, 3]]
-----------------------------------------------------------
a = [[4], [2, 4], [3, 4], [2, 3, 4], [], [2], [3], [2, 3]] is returned
returning a.flat_map { |a| [a, [1] + a] } = [[4], [1, 4], [2, 4], [1, 2, 4], [3, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4], [], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
-----------------------------------------------------------------
我正在学习 Ruby 并且想创建一种方法 returns 使用递归对数组进行所有可能的组合,而不使用组合或排列等内置方法。 具体来说,我想将以下 Javascript 代码转换为类似于 Ruby 的代码:
const combinations = (elements) => {
if (elements.length === 0) return [ [] ];
const firstEl = elements[0]
const rest = elements.slice(1);
const combsWithoutFirst = combinations(rest);
const combsWithFirst = [];
combsWithoutFirst.forEach(comb => {
const combWithFirst = [...comb, firstEl];
combsWithFirst.push(combWithFirst);
});
return [ ...combsWithoutFirst, ...combsWithFirst ];
}
我对编程还很陌生,我仍在努力了解递归,如果有任何帮助,我们将不胜感激!
上面的代码来自这个 youtube 视频:https://www.youtube.com/watch?v=NA2Oj9xqaZQ
您可以按如下方式进行。
def recurse(first, *rest)
return [[first], rest] if rest.empty?
recurse(*rest).flat_map { |a| [a, [first] + a] }
end
arr = [1,2,3,4,5]
a = recurse(*arr)
#=> [[5], [1, 5], [2, 5], [1, 2, 5], [3, 5], [1, 3, 5], [2, 3, 5],
# [1, 2, 3, 5], [4, 5], [1, 4, 5], [2, 4, 5], [1, 2, 4, 5], [3, 4, 5],
# [1, 3, 4, 5], [2, 3, 4, 5], [1, 2, 3, 4, 5], [], [1], [2], [1, 2],
# [3], [1, 3], [2, 3], [1, 2, 3], [4], [1, 4], [2, 4], [1, 2, 4],
# [3, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]]
a.sort
#=> [[],
# [1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5],
# [1, 2, 3, 5], [1, 2, 4], [1, 2, 4, 5], [1, 2, 5], [1, 3],
# [1, 3, 4], [1, 3, 4, 5], [1, 3, 5], [1, 4], [1, 4, 5], [1, 5],
# [2], [2, 3], [2, 3, 4], [2, 3, 4, 5], [2, 3, 5], [2, 4], [2, 4, 5], [2, 5],
# [3], [3, 4], [3, 4, 5], [3, 5],
# [4], [4, 5],
# [5]]
理解递归的最好方法是在代码中添加一些 puts 语句,并在视觉上将方法的每个实例分开。这可以在这里完成,如下所示。
INDENT = 6
def indent; $col += INDENT; end
def undent; $col -= INDENT; end
def pu(s); puts "#{" "*$col}#{s}"; end
def puhline; pu('-'*(65-$col)); end
def recurse(first, *rest)
indent
puhline
pu "recurse called with arguments first = #{first}, rest = #{rest}"
if rest.empty?
c = [[first], rest]
pu "returning #{c}"
puhline
undent
return c
end
pu "calling recurse(#{rest})"
a = recurse(*rest)
pu "#{a} is returned"
b = a.flat_map { |a| [a, [first] + a] }
pu "returning a.flat_map { |a| [a, [#{first}] + a] } = #{b}"
puhline
undent
b
end
$col = -INDENT
recurse(1,2,3,4)
显示如下。请注意,该方法的每个实例执行的计算在下方垂直对齐。
-----------------------------------------------------------------
recurse called with arguments first = 1, rest = [2, 3, 4]
calling recurse([2, 3, 4])
-----------------------------------------------------------
recurse called with arguments first = 2, rest = [3, 4]
calling recurse([3, 4])
-----------------------------------------------------
recurse called with arguments first = 3, rest = [4]
calling recurse([4])
-----------------------------------------------
recurse called with arguments first = 4, rest = []
returning [[4], []]
-----------------------------------------------
a = [[4], []] is returned
returning a.flat_map { |a| [a, [3] + a] } = [[4], [3, 4], [], [3]]
-----------------------------------------------------
a = [[4], [3, 4], [], [3]] is returned
returning a.flat_map { |a| [a, [2] + a] } = [[4], [2, 4], [3, 4], [2, 3, 4], [], [2], [3], [2, 3]]
-----------------------------------------------------------
a = [[4], [2, 4], [3, 4], [2, 3, 4], [], [2], [3], [2, 3]] is returned
returning a.flat_map { |a| [a, [1] + a] } = [[4], [1, 4], [2, 4], [1, 2, 4], [3, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4], [], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
-----------------------------------------------------------------