tags:

views:

64

answers:

3

Let's say i have an array called teams.
I want to plan matches for every team with every other team.

This is almost what i want except that same matches are added twice:

teams.each do |red_team|
  teams.each do |blue_team|
    if red_team != blue_team
      @planned_matches << Match.new(red_team, blue_team)
    end
  end
end

How to do that?

+2  A: 

check if it works

for i in 0..teams.length-1
  if i != teams.last
    for j in (i+1)..teams.length-1
      @planned_matches << Match.new(teams[i], teams[j])
    end
  end
end

EXAMPLE

teams = ['GERMANY', 'NETHERLAND', 'PARAGUAY', 'ARGENTINA']
for i in 0..teams.length-1
  if i != teams.last
    for j in (i+1)..teams.length-1
      puts " #{teams[i]}  Vs  #{teams[j]}"
    end
  end
end

O/P

 GERMANY  Vs  NETHERLAND
 GERMANY  Vs  PARAGUAY
 GERMANY  Vs  ARGENTINA
 NETHERLAND  Vs  PARAGUAY
 NETHERLAND  Vs  ARGENTINA
 PARAGUAY  Vs  ARGENTINA
Salil
It does work. I hoped for better looking solution though. :)
Arnis L.
The if statement doesn't do anything, i is an int and you are comparing it to a team name that is a String. But yeah, other than that, this is the best solution.
Joshua Cheek
@Joshua :- oohhhhhhhhh yes i think it should be teams[i] != teams.last. I think it will work w/o if condition then. nocheck though.
Salil
You may want to use `upto` or `...` or `each_index`. Also, `for` isn't idiosyncratic ruby.
Andrew Grimm
A: 

In your class Match, assuming internal attributes are red and blue

class Match
#...
  def ==(anOther)
    red == anOther.blue and anOther.red == blue
  end
#...
end

and the loop :

teams.each do |red_team|
  teams.each do |blue_team|
    if red_team != blue_team
      new_match = Match.new(red_team, blue_team)
      planned_matches << new_match if !planned_matches.include?(new_match)
    end
  end
end

Explanation :

The include? function of Array uses the == methods, so you just have to override it and giving it the behaviour you want for your Matches.

Romain Deveaud
This looks a bit better to me than solution by Salil. :)
Arnis L.
@Arnis L :- performance wise it will iterate 16 times for array of length 4 where mine is iterate for just 7 times.
Salil
@Salil ty for that tip. Performance ain't issue though.
Arnis L.
Arnis L.
This kind of iterating doesn't conform well to the Ruby way, but nonetheless, Salil's answer is a many many times more efficient. Also, the implementation of == in this answer is very questionable. For example, with that definition, an instance of Match is not equal to itself.
Joshua Cheek
@Joshua mind if i ask - what is 'Ruby way'?
Arnis L.
@Arnis iterating over collections rather than accessing them by index.
Joshua Cheek
+4  A: 

In Ruby 1.8.7+ you can use Array#combination:

teams = %w(A B C D)
matches = teams.combination(2).to_a

In 1.8.6, you can use Facets to do the same:

require 'facets/array/combination'
# Same code as above.
FM
If only i knew how to install ruby 1.8.7+ on my fedora13 :)
Arnis L.