“金字塔化”数组/列表(在Ruby中,但可能会实现一般解决方案)

时间:2010-09-15 01:06:17

标签: ruby algorithm language-agnostic

我不确定这里最好的词是什么。通过“金字塔化”,我的意思是:

[1,2,3,4].pyramidize  # => [1,1,1,1,2,2,2,3,3,4]
["a","b","c","d"].pyramidize  # => ["a","a","a","a","b","b","b","c","c","d"]

为了直观地表示,可以将其视为:

[ 1,1,1,1,
   2,2,2,
    3,3,
     4    ]

有没有办法做到最大化优雅?最像红宝石的方式?

我遇到了“需要”在我的一个项目中这样做。在考虑之后,我放弃了,决定以丑陋的方式解决问题。我想知道是否有一个很好的方法来做到这一点。到目前为止,为了直接进行,我最终为每个索引创建了一个单独的数组,并将每个数组拉伸到适当的长度并将它们组合在一起。但我不知道该怎么做,所以它看起来很漂亮;我的解决方案非常难看。

添加了代码高尔夫标签,因为一行中的任何解决方案都可能会成为我的一天,但不一定如此。

如果你的解决方案使第一个索引成为金字塔的“基础”或最后一个索引,那真的无关紧要,因为我可以在运行之前反转数组。

5 个答案:

答案 0 :(得分:3)

irb(main):001:0> [2,1,3,5].flat_map.with_index{|i,j|[i]*(j+1)}
=> [2, 1, 1, 3, 3, 3, 5, 5, 5, 5]
irb(main):002:0> [1,2,3,4].flat_map{|i|[i]*i}
=> [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

答案 1 :(得分:3)

在Ruby 1.9中需要新的迭代器功能。

class Array
  def pyramidize
    reverse.map.with_index do |object, index|
      [object] * (index + 1)
    end.flatten.reverse
  end
end

[1,2,3,4].pyramidize
 => [1, 1, 1, 1, 2, 2, 2, 3, 3, 4] 
["a","b","c","d"].pyramidize
 => ["a", "a", "a", "a", "b", "b", "b", "c", "c", "d"] 

答案 2 :(得分:0)

我不确定是否要使用列表或索引的值来确定列表应该重复多少,但是python中的一个简单解决方案可能很容易转移到ruby:

>>> import operator
>>> input = range(6)
>>> reduce(operator.add, [[i]*idx for idx, i in enumerate(input)])
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5]

<强>更新

哦,反转计数:

>>> import operator
>>> input = range(1, 6)
>>> reduce(operator.add, [[i]*(max(input) - idx) for idx, i in enumerate(input)])
[1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5]

当然,你在一个例子中颠倒了这个列表:

>>> import operator
>>> input = range(1, 6)
>>> reduce(operator.add, [[i]*(max(input) - idx) for idx, i in enumerate(input)])[::-1]
[     5,
     4, 4, 
   3, 3, 3,
  2, 2, 2, 2,
 1, 1, 1, 1, 1]

答案 3 :(得分:0)

FWIW,这是一种糟糕的做法:

>>> A = [1, 2, 3, 4]
>>> [ A[int((sqrt(8*k+1)-1) / 2)] for k in range(len(A)*(len(A)+1) / 2) ]
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

不可否认,使用sqrt非常难看。

答案 4 :(得分:-1)

这是另一种在Python中执行此操作的方法

>>> A=[1,2,3,4]
>>> [y for i,x in enumerate(A) for y in [x]*(len(A)-i)]
[1, 1, 1, 1, 2, 2, 2, 3, 3, 4]

但是不要创建所有这些临时列表

>>> from itertools import repeat
>>> [y for i,x in enumerate(A) for y in repeat(x, len(A)-i)]
[1, 1, 1, 1, 2, 2, 2, 3, 3, 4]