Sorting arrays, and selecting lowest numbers? - ruby

I have created several arrays, containing multiple integers. Now i want the integers to be sorted, lowest first. Say for instance, i have this in an array: 6,6,1,2,4,4, i want it to be sorted: 1,2,4,4,6,6. Also, is there anyway i can make ruby recognize the 4 lowest values, and display them somehow? I have tried to mess around with .show, but since im quite new to programming i'm rather confused by the results i receive.

did you try this?
a = [6,6,1,2,4,4]
p a.sort
#=> [1, 2, 4, 4, 6, 6]
sort will sort in ascending order.
if you need them sorted in descending order, use sort with a block:
p a.sort {|a,b| b <=> a}
#=> [6, 6, 4, 4, 2, 1]
UPDATE: not sure how i missed the part about lowest values ...
thank you #Mladen
a.sort.take(4)
#=> [1, 2, 4, 4]

Related

Find exact value overlap between two arrays [duplicate]

This question already has answers here:
Ruby - array intersection (with duplicates)
(7 answers)
Closed 1 year ago.
I have two arrays
a1 = [1, 1, 1, 2, 3, 3, 3]
a2 = [1, 1, 3, 3, 5, 5]
I want to return the values that appear in both arrays AND the exact amount that they appear
# => [1, 1, 3, 3]
I can't use a1 & a2 because that will return unique values ([1, 3])
What's the best way to achieve this?
It looks like what you have there are not really arrays, they are multisets or bags.
There is a general rule in programming: if you choose your data representation right, your algorithms become simpler.
So, if you use multisets instead of arrays, your problem will become trivial, since what you are looking for is literally just the intersection of two multisets.
Unfortunately, there is no multiset implementation in the core or standard libraries, but there are a couple of multiset gems available on the web. For example, there is the multimap gem, which also includes a multiset. Unfortunately, it needs a little bit of love and care, since it uses a C extension that only works until YARV 2.2. There is also the multiset gem.
require 'multiset'
m1 = Multiset.new(a1)
#=> #<Multiset:#3 1, #1 2, #3 3>
m2 = Multiset.new(a2)
#=> #<Multiset:#2 1, #2 3, #2 5>
m = m1 & m2
#=> #<Multiset:#2 1, #2 3>
Personally, I am not too big a fan of the inspect output, but we can see what's going on and that the result is correct: m contains 2 × 1 and 2 × 3.
If you really need the result as an Array, you can use Multiset#to_a:
m.to_a
#=> [1, 1, 3, 3]
At first I do get the intersection between a1 and a2 with (a1 & a2). After that I iterate over the intersection and check which array has a lower count of each element. The element gets than added to the result array as many times as it occurs in the array with the lower count using result.fill
a1 = [1, 1, 1, 2, 3, 3, 3]
a2 = [1, 1, 3, 3, 5, 5]
result = []
(a1 & a2).each do |e|
a1.count(e) < a2.count(e) ? result.fill(e, result.size, a1.count(e)) : result.fill(e, result.size, a2.count(e))
end
pp result

How to achieve all elements swapped in an array

I have an ordered array which contain 1 to 1000000 elements.
I want to achieve an array such that the elements in the array are swapped with its next element.For instance if we assume the array elements are
[1,2,3,4,5,6]
I want to return an array with elements as
[2,1,4,3,6,5]
How do I achieve this in ruby for 100000 such elements? Can anyone guide me?
a = [1,2,3,4,5,6]
a.each_slice(2).map{|inner_a| inner_a.reverse}.flatten
# => [2, 1, 4, 3, 6, 5]
Description:
a.each_slice(2)returns an enumerator (#<Enumerator: [1, 2, 3, 4, 5, 6]:each_slice(2)>) with two element couples from your array. To see try a.each_slice(2).to_a. This returns [[1, 2], [3, 4], [5, 6]] with I only have to flatten for your expected result.
See also the first comment if you prefer a shorter notation of it.
Assuming you want to use a minimum amount of memory (since you chose a large array), and assuming the result is to be a mutated array (i.e. not a new array, but a change to the existing array) and finally assuming a is always an even number of elements...
a.each_index{|x| a[x], a[x+1] = a[x+1], a[x] if x.even?}
Possibly more performant...
(0...a.size).step(2) {|x| a[x], a[x+1] = a[x+1], a[x]}
You can try this.
arr = (1..100000).to_a
arr.each_with_index.each_slice(2){|(_,i), (_,j)| arr[i], arr[j] = arr[j], arr[i]}

Ruby - pushing values from an array combination to a new array

I am trying to print all the different sums of all combinations in this array [1,2,3]. I want to first push every sum result to a new array b, then print them using b.uniq so that non of the sum results are repeated.
However, with the code I have, the 3 repeats itself, and I think it is because of the way it is pushed into the array b.
Is there a better way of doing this?
a = [1,2,3]
b = []
b.push a
b.push a.combination(2).collect {|a,b| (a+b)}
b.push a.combination(3).collect {|a,b,c| (a+b+c)}
puts b.uniq
p b #[[1, 2, 3], [3, 4, 5], [6]]
Can someone please help me with this? I am still new in ruby.
Because an Array of arbitrary length can be summed using inject(:+), we can create a more general solution by iterating over the range 1..n, where n is the length of the Array.
(1..(a.size)).flat_map do |n|
a.combination(n).map { |c| c.inject(&:+) }
end.uniq
#=> [1, 2, 3, 4, 5, 6]
By using flat_map, we can avoid getting the nested Array result, and can call uniq directly on it. Another option to ensure uniqueness would be to pass the result to a Set, for which Ruby guarantees uniqueness internally.
require "set"
sums = (1..(a.size)).flat_map do |n|
a.combination(n).map { |c| c.inject(&:+) }
end
Set.new(sums)
#=> #<Set: {1, 2, 3, 4, 5, 6}>
This will work for an any Array, as long as all elements are Fixnum.
If all you want is an array of the possible sums, flatten the array before getting the unique values.
puts b.flatten.uniq
What is happening is uniq is running over a multi-dimensional array. This causes it to look for duplicate arrays in your array. You'll need the array to be flattened first.

split the contents of the array into two other arrays

Simple example but I want to understand how it is done so I can apply it else where I have a main array with 6 elements. I want to take 3 of the elements from the main array and put it in a array and then take the other 3 from main array and put them in b array. I will use this to apply it to dealing cards to two players
main = [1, 2, 3, 4, 5, 6]
a = [ ]
b = [ ]
main = [1, 2, 3, 4, 5, 6]
#=> [1, 2, 3, 4, 5, 6]
main.first(3)
#=> [1, 2, 3]
main.last(3)
#=> [4, 5, 6]
a = [1, 2, 3, 4, 5, 6]
#=> [1, 2, 3, 4, 5, 6]
b = a.take(3)
#=> [1, 2, 3]
c = a.drop(3)
#=> [4, 5, 6]
All may have given the right answer, But as I understood from your question (I will use this to apply it to dealing cards to two players) When you dealing cards, as you deal cards to player main array should remove that element from self array to overcome Redundancy Problem (duplication). When you deal the all cards main array must be empty.
For this solution have a look at Array#shift
> main = [1,2,3,4,5,6] # I have 6 cards on my hand before dealing cards to players
=> [1, 2, 3, 4, 5, 6]
> a = main.shift(3) # given 3 cards to Player a
=> [1, 2, 3]
> b = main.shift(3) # given 3 cards to Player b
=> [4, 5, 6]
> main # after dealing all cards to two players I should not have any card on my hand
=> []
You have many ways to do the same thing in Ruby. Splitting arrays isn't an exception. Many answers (and comments) told you some of the ways to do that. If your program is dealing cards, you won't stop there. First, you'll probably have more than 6 cards. Second, you're probably going to have more than 2 players. Let's say the cards are C and the players are P. You need to write a method that, no matter how many Cs or Ps there are, the method is going to give each Player an equal number of Ccards (or return an error if it can't give it an equal number of cards). So for 6 cards and 2 players, it will give 3 cards each. For 12 cards and 3 players, 4 cards each. For 3 cards and 2 players, it's going to produce an error because the cards can't be evenly split:
def split_cards_evenly_between_players(cards, players)
if cards.size % players != 0
raise 'Cannot split evenly!'
else
groups_to_split_into = cards.size / players
cards.each_slice(groups_to_split_into).to_a
end
end
Let's go through the code. If the cards can't be evenly split between players, then the remainder by dividing them won't be 0 (6 cards / 3 players = remainder 0. 7 cards / 3 players = remainder 1). That's what line 2 checks. If the cards CAN be split, then we first find the groups to split into (which is dividing the number of cards by the number of players). Then we just split the array into that many groups with Enumerable#each_slice. Finally, since this doesn't produce an array, we need .to_a to convert it. The return value in Ruby is always the value of the last expression executed. The only expression in this method is the if/then expression which also returns the value of the last expression executed (which is the line where each_slice is). Let's try it out:
p split_cards_evenly_between_players([1,2,3,4,5,6,7,8,9,10,11,12],2) #=> [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]
p split_cards_evenly_between_players([4,5,1,2,5,3], 3) #=> [[4, 5], [1, 2], [5, 3]]
p split_cards_evenly_between_players([1,2,3],2) #=> Error: Cannot split evenly!
The nice thing about Ruby is its simple syntax and the fact it tries to get out of your way while solving a problem so you can focus more on the actual problem than the code.

intelligently generating combinations of combinations

Let's say I have a class of 30 students and want generate every possible way in which they can be partitioned into groups of 5 (order is irrelevant).
I know how to find all the combinations of students to form one group individually (http://www.merriampark.com/comb.htm). By using that iterator and some recursion, I can find PERMUTATIONS of the possible group combinations. However, order in which the groups are selected isn't relevant and I'd like to minimize my execution time. So how do I find the unique COMBINATIONS of the possible groups?
The above algorithm uses lexicographical ordering to avoid generating duplicate combinations... is there a way that I can use that idea on groups instead of on objects?
I know Ruby well and Java/Python less well. Thanks in advance for any advice!
Well, there's (30C5*25C5*20C5*15C5*10C5*5C5)/6! = 30!/(6!*5!6) = 123,378,675,083,039,376 different partitons of 30 into groups of 5, so generating them all will take some time, no matter what method you use.
In general, though, a good method to selecting such a partition is to use some ordering on the elements, and find the grouping for the highest ungrouped element, and then group the rest.
find_partition = lambda do |elts|
if elts.empty?
[[]]
else
highest = elts.pop
elts.combination(4).map do |others|
find_partition[elts - others].map { |part| part << [highest,*others] }
end.inject(:+)
end
end
find_partition[(1..30).to_a]
This way you're only generating each partition once
This is an old question, but anyway, for the record, that's how I would it in Ruby:
class Array
def groups_of_size(n)
Enumerator.new do |yielder|
if self.empty?
yielder.yield([])
else
self.drop(1).combination(n-1).map { |vs| [self.first] + vs }.each do |values|
(self - values).groups_of_size(n).each do |group|
yielder.yield([values] + group)
end
end
end
end
end
end
I use an enumerator because the output can grow very quickly, a strict output (an array for example) wouldn't be useful. A usage example:
>> pp [0, 1, 2, 3, 4, 5].groups_of_size(3).to_a
=>
[[[0, 1, 2], [3, 4, 5]],
[[0, 1, 3], [2, 4, 5]],
[[0, 1, 4], [2, 3, 5]],
[[0, 1, 5], [2, 3, 4]],
[[0, 2, 3], [1, 4, 5]],
[[0, 2, 4], [1, 3, 5]],
[[0, 2, 5], [1, 3, 4]],
[[0, 3, 4], [1, 2, 5]],
[[0, 3, 5], [1, 2, 4]],
[[0, 4, 5], [1, 2, 3]]]
You could do some post-processing on the permutations. Some pseudo-code (implement in the language of your choice...):
// We have a list of lists called 'permutations'
// combinations is an (empty) list of lists
for each permutation in permutations
{
sortedPermutation = permutation.sort()
if (! combinations.find(sortedPermutation) )
{
combinations.add(sortedPermutation);
}
}
Probably not the most efficient; I'd add the sort & compare to the code that generates the permutations personally.
One possibility would be to find all combinations to form an individual group, then go through and generate combinations that don't contain members of that individual group. Something like:
List<List<Student>> combinations=Combinations(students);
public void GenerateCombinations(int startingIndex, List<List<Student>> currentGroups, int groupsLeft)
{
if(groupsLeft==0) ProcessCombination(currentGroups);
for(int i=startingIndex; i<combinations.Count; i++)
{
if combinations[i] does not contain a student in current groups
GenerateCombinations(i+1, currentGroups + combinations[i], groupsLeft -1);
}
}
It won't be the most efficient method to go about it, but it should generate all combinations of groups. I suspect better performance could be had if you were to generate temporary lists of combinations, where in all groups that can't occur were removed, but that would be a bit more complex.
As a slight aside, there should be 142,506 combinations of 30 students to form a single group of 5. My <sarcasm> awesome </sarcasm> math skills suggest that there should be about 10^17 = 100 quadrillion combinations of groups of students (30!/((5!^6)*6!); 30! orderings of students, ordering of 6 groups of 5 does not matter, and ordering of those 6 groups doesn't matter). You might be sitting there a while waiting for this to finish.

Resources