3

I have no idea how to formulate the question correctly, but what I want is the following:

Let's say there's an array like

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

How can I sort it, until this becomes the output:

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

To make the output a bit more readable:

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

What I've come up so far is:

array = [1,1,1,1,2,2,2,3,3,3,4,4,5]
array.group_by{|n| n }.values.transpose.flatten

But this throws an error due to not having the same amount of numbers.

Can anybody help?

Biketire
  • 2,019
  • 1
  • 23
  • 41
  • It's not so hard to state your question succinctly and unambiguously: "Given an array `a` and an empty array `b`, I wish to obtain an array `c` comprised of the unique elements of `a`, add `c` to `b`, remove one of each element of `c` from `a`, repeat these steps until `a` is empty, and return `b`." Once stated clearly, translating each element of the question to code is fairly straightforward. – Cary Swoveland Apr 30 '15 at 14:23

4 Answers4

3

it took a while to do this but here is what you want:

array = [1,1,1,1,2,2,2,3,3,3,4,4,5]

a = array.group_by{|n| n }.values.sort_by(&:length).reverse

a.each{|q| (a[0].size-q.size).times{q<<nil}}

a.sort.transpose.flatten.compact

it produces:

  => [1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 1]

*you have 3 number of twos

Abdul Baig
  • 3,683
  • 3
  • 21
  • 48
  • This works, but only if `a[0]` is the largest group. – Biketire Apr 30 '15 at 12:09
  • see the edit now. the sub array with maximum length will always be on the first index – Abdul Baig Apr 30 '15 at 12:11
  • Yes it is in this specific case. But let's say your array contains 5 2's, like: `[1,1,1,1,2,2,2,2,2,3,3,3,4,4,5]` . Than sort will not sort on the maximum length. But thanks for the answer, I came up with my own answer which does hold that thing into account. It's just a matter of finetuning. – Biketire Apr 30 '15 at 12:28
1
▶ array = [1,1,1,1,2,2,2,3,3,3,4,4,5]
▶ tap = array.group_by(&:to_i).values.sort do |i, j| 
▷   result = j.length <=> i.length
▷   result.zero? ? i <=> j : result
▷ end
▶ tap.map do |e| 
▷   e.fill nil, (e.length...tap.first.length)
▷ end.transpose.flatten.compact
#⇒ [1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 1]
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
0

Came up with my own answer as well.

array = [1,1,1,1,2,2,2,3,3,3,4,4,5]

# group all the values in single array
a = array.group_by{|n| n }.values.sort{|a,b| b.size <=> a.size }

# fill every other space in the other subarrays with nil
a.each{|q| q.fill(nil, (a[0].size...q.size)) }

# transpose, flatten and remove all the nil values
a.transpose.flatten.compact

If anyone knows a 'smaller' more readable answer, please tell.

rick
  • 1,675
  • 3
  • 15
  • 28
Biketire
  • 2,019
  • 1
  • 23
  • 41
0

Let arr be your array. Then:

def transform(arr)
  a = arr.sort
  b = []
  until a.empty?
    u = a.uniq
    b << u
    a = a.difference(u)
  end
  b
end

The helper Array#difference is defined in my answer here.

Let's try it:

transform(arr)
  #=> [[1,2,3,4,5], [1,2,3,4], [1,2,3], [1]]
Community
  • 1
  • 1
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100