Ruby - 在另一个未知长度的数组中均匀分布和交错/交织一个数组的元素

时间:2014-01-19 22:13:03

标签: ruby arrays algorithm

我有两个未知长度的数组。一个元素需要均匀(尽可能均匀地)分布在另一个 中。

假设数组中的+元素是实际值的占位符的示例。我省略了数组逗号分隔符以消除视觉噪音并使模式更明显。

a = [++++++++++] # 10 element array with + characters representing array items

b = [] # empty array
a.interweave(b) #=> [++++++++++]

b = [1]
a.interweave(b) #=> [+++++1+++++]

b = (1..2).to_a
a.interweave(b) #=> [+++1+++2++++]

b = (1..3).to_a
a.interweave(b) #=> [++1++2+++3+++]  # any remaining + are distributed to the end chunks.

b = (1..4).to_a
a.interweave(b) #=> [++1++2++3++4++]

b = (1..5).to_a
a.interweave(b) #=> [+1+2++3++4++5++]

b = (1..6).to_a
a.interweave(b) #=> [+1+2+3+4++5++6++]

b = (1..7).to_a
a.interweave(b) #=> [+1+2+3+4+5+6++7++]

b = (1..8).to_a
a.interweave(b) #=> [+1+2+3+4+5+6+7+8++]

b = (1..9).to_a
a.interweave(b) #=> [+1+2+3+4+5+6+7+8+9+]

b = (1..10).to_a
a.interweave(b) #=> [+1+2+3+4+5+6+7+8+9+10]

b = (1..11).to_a
a.interweave(b) #=> [+,1,+,2,+,3,+,4,+,5,+,6,+,7,+,8,+,9,+,10,11] # the remaining elements from b are added to the end

我正在寻找Ruby中的高性能算法。

2 个答案:

答案 0 :(得分:2)

class Array
  def interweave(a2)
    a1 = self.dup
    arrays = [a1, a2].sort_by {|a| a.length}.reverse
    offset, remainder = arrays[0].length.divmod(arrays[1].length + 1)
    prev_jump = 0
    arrays[1].reverse.each_with_index do |e, i|
      remainder > 0 ? (adjust = 1; remainder -= 1) : adjust = 0
      jump = offset + adjust + 1
      arrays[0].insert( -(prev_jump + jump), e)
      prev_jump += jump
    end
    arrays[0]
  end
end

a1 = [0,0,0,0,0,0,0,0,0,0]

p a1.interweave [1] # => [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
p a1.interweave (1..2).to_a # => [0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0]
p a1.interweave (1..3).to_a # => [0, 0, 1, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0]
p a1.interweave (1..4).to_a # => [0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0]
p a1.interweave (1..5).to_a # => [0, 1, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0]
p a1.interweave (1..6).to_a # => [0, 1, 0, 2, 0, 3, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0]
p a1.interweave (1..7).to_a # => [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 0, 7, 0, 0]
p a1.interweave (1..8).to_a # => [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 0]
p a1.interweave (1..9).to_a # => [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0]
p a1.interweave (1..10).to_a # => [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10]
p a1.interweave (1..11).to_a # => [1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11]
p a1.interweave (1..12).to_a # => [1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 12]

我做到这一点,所以最短的阵列交织成最长的阵列,然后才注意到你想要在最后添加剩余的剩余物。现在太累了,但你可以根据需要进行调整。

答案 1 :(得分:2)

另一种方式:

def weave(xx,yy)
  x = xx.dup
  y = yy.dup
  n_extra = [y.size - x.size + 1, 0].max
  y_extra = y.slice!(y.size - n_extra, n_extra)
  z = x.class.new
  loop do
    z += (x.slice!(0,((x.size)/(y.size+1.0)).floor) + y.slice!(0,1))
    break if y.empty?
  end
  z + x + y_extra
end         

x = ('-'*10).chars
  # => ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-"]

p weave(x, ['a', 'b', 'c'])
  # => ["-", "-", "a", "-", "-", "b", "-", "-", "-", "c", "-", "-", "-"]

p weave(x, ['a', 'b', 'c']).join # => "--a--b---c---"
p weave('----------', 'abc')     # => "--a--b---c---"

y = (1..12).each_with_object([]) {|i,a| a << ('a'..'z').to_a.first(i)}

y.each {|e| p weave(x, e).join}
"-----a-----"
"---a---b----"
"--a--b---c---"
"--a--b--c--d--"
"-a-b--c--d--e--"
"-a-b-c-d--e--f--"
"-a-b-c-d-e-f--g--"
"-a-b-c-d-e-f-g-h--"
"-a-b-c-d-e-f-g-h-i-"
"-a-b-c-d-e-f-g-h-i-j"
"-a-b-c-d-e-f-g-h-i-jk"
"-a-b-c-d-e-f-g-h-i-jkl"

编辑:我对原始解决方案进行了一些更改:

  • 添加了weave的前两行,因此参数不会被更改。
  • 简化了循环。
  • 在@ Kal的建议下,从.join的末尾删除了(arr + x + y_extra)
  • z = []更改为z = x.class.new,以允许weave的参数为数组或字符串。

关于((x.size)/(y.size+1.0)).floor的一句话。假设x = ['-','-','-','-','-','-'] and y = ['a', 'b', 'c']。然后:

  • 在循环的第一次迭代后,z => ['-', 'a']x => ['-','-','-','-','-']y => ['b', 'c']
  • 如果可以划分x的元素,则y.size+1.0 => 3.0的剩余部分将被划分为x.size/3.0 => 5/3.0 => 1.67个时间间隔,每个时间间隔都包含x个元素。由于它们无法分割,而较大的群组位于右侧,我们会从1.67.floor => 1中剥离x元素,将y的下一个元素追加到{{} 1}},然后重复,直到z