在数组中返回彼此回文的元素

时间:2016-07-28 19:06:27

标签: arrays ruby

如何返回给定数组中的回文数组?不是回文数字,如11,22,33,44和& c。,而是与同一数组中其他数字的回文数字。假设所有元素都是正数,结果不应返回单个数字(例如下面的代码)

假设我有array = [13, 31, 51, 79, 83, 97]。从13& 31和79& 97是回文,我希望它返回array_pali = [13, 31, 79, 97]

def pali_array(array)
    array_reverse = array.map{|el| el.to_s.reverse.to_i}
    array_pali = array & array_reverse
    return array_pali
end

我的初步计划是提出该数组的反向,array_reverse = array.map{|el| el.to_s.reverse.to_i}并将它们相交:array & array_reverse

如果我想从2-100返回素数数组,则会出现一个问题:

array = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

我改变了它:

array_reverse = array.map{|el| el.to_s.reverse.to_i}
=> [2, 3, 5, 7, 11, 31, 71, 91, 32, 92, 13, 73, 14, 34, 74, 35, 95, 16, 76, 17, 37, 97, 38, 98, 79]

它返回:

array & array_reverse
=> [2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, 97]

这种方法的问题:

2,3,5,7和11不是与其他元素的回文。单个数字的反转是该数字本身,它使代码返回所有单个数字和所有回文数字(如11,22,33)。它应该只返回[13, 17, 31, 37, 71, 73, 79, 97]

如何让它将元素作为回文返回到同一数组中的其他元素

3 个答案:

答案 0 :(得分:2)

这是一个非常天真和懒惰的实现。不保留元素的原始顺序。应该是O(N)。

我希望代码不言自明。

array = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

require 'set'
seen_numbers = Set.new
result = []

array.each do |elem|
  next if elem < 10

  normal_str = elem.to_s
  rev_str = normal_str.reverse

  if seen_numbers.include?(rev_str)
    result << rev_str.to_i
    result << elem
  end

  seen_numbers << normal_str
end

result # => [13, 31, 17, 71, 37, 73, 79, 97]

答案 1 :(得分:1)

如果您想要替代方案,请认为这是有效的:

array = [13, 31, 51, 79, 83, 97]
array.combination(2)
     .select {|pair| pair.first.to_s == pair.last.to_s.reverse }
     .flatten

#=> [13, 31, 79, 97]

使用Array#combination获取每对组合,然后我们仅选择那些回文对。然后压扁你的阵列。

答案 2 :(得分:1)

arr = [7, 13, 31, 51, 31, 60, 70, 13, 79, 83, 79, 97]

请注意arr中有各种重复值。

arr.reject { |n| n < 10 || (n%10).zero? }.
    group_by { |n| n.to_s.each_char.sort }.
    values.
    reject { |arr| arr.size == 1 }.
    flat_map { |arr| arr.group_by(&:itself).values.min_by(&:size) }
  #=> [13, 13, 97]

如果需要,匹配值很容易计算。

添加

|| (n%10).zero?只是为了加快速度。

步骤如下。

a = arr.reject { |n| n < 10 || (n%10).zero? }
  #=> [13, 31, 51, 31, 13, 79, 83, 79, 97] 
b = a.group_by { |n| n.to_s.each_char.sort }
  #=> {["1", "3"]=>[13, 31, 31, 13], ["1", "5"]=>[51],
  #    ["7", "9"]=>[79, 79, 97], ["3", "8"]=>[83]} 
c = b.values
  #=> [[13, 31, 31, 13], [51], [79, 79, 97], [83]] 
d = c.reject { |arr| arr.size == 1 }
  #=> [[13, 31, 31, 13], [79, 79, 97]] 
d.flat_map { |arr| arr.group_by(&:itself).values.min_by(&:size) }
  #=> [13, 13, 97]

考虑最后一步。 flat_mapd的第一个元素传递给其块,并将块变量设置为该值:

arr = d[0]
  #=> [13, 31, 31, 13]

并执行块计算:

e = arr.group_by(&:itself)
  #=> {13=>[13, 13], 31=>[31, 31]}
f = e.values
  #=> [[13, 13], [31, 31]]
f.min_by(&:size)
  #=> [13, 13]

接下来,

arr = d[1]
  #=> [79, 79, 97]
e = arr.group_by(&:itself)
  #=> {79=>[79, 79], 97=>[97]} 
f = e.values
  #=> [[79, 79], [97]] 
f.min_by(&:size)
  #=> [97] 

flat_map因此返回

[*[13, 13], *[97]]
  #=> [13, 13, 97]