# Ruby for arranging fencing competitions

**URL:** <https://www.ruby-forum.com/t/ruby-for-arranging-fencing-competitions/117394>\
**Category:** Ruby\
**Created:** [October 16, 2007, 4:30pm UTC](https://www.ruby-forum.com/t/ruby-for-arranging-fencing-competitions/117394 "2007-10-16T16:30:49Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![milo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85e7bf/32.png) [@milo](https://www.ruby-forum.com/u/milo)\
**Post date:** [October 16, 2007, 4:30pm UTC](https://www.ruby-forum.com/t/ruby-for-arranging-fencing-competitions/117394/1 "2007-10-16T16:30:49Z")

</div>

Sport fencing competitions are organised in pools, where every fencer  
fences every other and the total score is totted up at the end. Sheets  
like this are used to keep track of which bouts have been played and  
what the score is:  
[http://www.soton.ac.uk/~fencing/files/pool.pdf](http://www.soton.ac.uk/~fencing/files/pool.pdf)  
These sheets show an order of bouts for between 4-7 fencers, a typical  
number in a pool. An impending competition\* got me wondering how one  
might use Ruby to generate those lists of bouts. A simple list of what  
bouts need to be fought is easy, and I wrote a simple script that  
produces an array of the following values for any number of contestants  
(in this case 4):

1 - 2  
1 - 3  
1 - 4  
2 - 3  
2 - 4  
3 - 4

The difficult bit is that fencers need to be given a rest between bouts  
if possible, so this order won’t do. Simply randomising this array may  
still mean someone having to do more than one fight in a row. Not having  
a mathematical background I can’t think of a suitable method to approach  
this, and if anyone could suggest some hints I’d be interested to know.

- I can, of course, use the existing pool sheets for the competition;  
this is just for my amusement.

---

<div class="post-metadata">

**Author:** ![milo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85e7bf/32.png) [@milo](https://www.ruby-forum.com/u/milo)\
**Post date:** [October 16, 2007, 4:44pm UTC](https://www.ruby-forum.com/t/ruby-for-arranging-fencing-competitions/117394/2 "2007-10-16T16:44:02Z")

</div>

On 10/16/07, Milo T. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> (in this case 4):  
> still mean someone having to do more than one fight in a row. Not having  
> a mathematical background I can’t think of a suitable method to approach  
> this, and if anyone could suggest some hints I’d be interested to know.
> 
> - I can, of course, use the existing pool sheets for the competition;  
> this is just for my amusement.

Food for RubyQuiz?

Jesus.

---

<div class="post-metadata">

**Author:** ![milo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85e7bf/32.png) [@milo](https://www.ruby-forum.com/u/milo)\
**Post date:** [October 16, 2007, 4:50pm UTC](https://www.ruby-forum.com/t/ruby-for-arranging-fencing-competitions/117394/3 "2007-10-16T16:50:06Z")

</div>

JesÃºs Gabriel y GalÃ¡n wrote:

> Food for RubyQuiz?

Thanks - I’ll take a look.

---

<div class="post-metadata">

**Author:** ![milo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85e7bf/32.png) [@milo](https://www.ruby-forum.com/u/milo)\
**Post date:** [October 16, 2007, 8:22pm UTC](https://www.ruby-forum.com/t/ruby-for-arranging-fencing-competitions/117394/4 "2007-10-16T20:22:35Z")

</div>

On 10/16/07, Milo T. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> (in this case 4):  
> still mean someone having to do more than one fight in a row. Not having  
> a mathematical background I can’t think of a suitable method to approach  
> this, and if anyone could suggest some hints I’d be interested to know.

How about:

class RoundRobinPairsGenerator

attr\_reader :competitors, :full\_size

def initialize(n)  
@competitors = (1…n).to\_a  
@full\_size = (n\*n - n) / 2  
end

def pairings  
@pairings ||= compute\_pairings  
end

private

def more\_tired(played, pair)  
appearances = played.flatten  
pair.sort\_by {|comp| appearances.select { |e| e == comp  
}.length}.last  
end

def compute\_pairings  
pairings = []  
picks = competitors.dup  
while pairings.length \< full\_size  
trial\_pair = picks[0…1].sort  
if pairings.include?(trial\_pair)  
more\_tired = more\_tired(pairings, trial\_pair)  
picks.delete(more\_tired)  
picks \<\< more\_tired  
else  
pairings \<\< trial\_pair  
picks \<\< picks.shift  
picks \<\< picks.shift  
end  
end  
pairings  
end  
end  
puts “For n = 4”  
RoundRobinPairsGenerator.new(4).pairings.each { |p| p p }  
puts  
puts “For n = 10”  
RoundRobinPairsGenerator.new(10).pairings.each { |p| p p }

produces:  
For n = 4  
[1, 2]  
[3, 4]  
[1, 3]  
[2, 4]  
[1, 4]  
[2, 3]

For n = 10  
[1, 2]  
[3, 4]  
[5, 6]  
[7, 8]  
[9, 10]  
[1, 3]  
[4, 5]  
[6, 7]  
[8, 9]  
[2, 10]  
[1, 4]  
[5, 7]  
[8, 10]  
[2, 3]  
[1, 6]  
[5, 9]  
[2, 8]  
[3, 6]  
[7, 9]  
[4, 10]  
[1, 5]  
[2, 7]  
[3, 5]  
[4, 8]  
[6, 9]  
[1, 10]  
[3, 9]  
[2, 4]  
[5, 10]  
[6, 8]  
[1, 9]  
[4, 7]  
[2, 5]  
[3, 8]  
[7, 10]  
[4, 6]  
[2, 9]  
[1, 8]  
[6, 10]  
[3, 7]  
[1, 7]  
[3, 10]  
[2, 6]  
[5, 8]  
[4, 9]

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![milo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85e7bf/32.png) [@milo](https://www.ruby-forum.com/u/milo)\
**Post date:** [October 16, 2007, 10:52pm UTC](https://www.ruby-forum.com/t/ruby-for-arranging-fencing-competitions/117394/5 "2007-10-16T22:52:22Z")

</div>

On Oct 16, 1:22 pm, “Rick DeNatale” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > number in a pool. An impending competition\* got me wondering how one  
> > 3 - 4
> 
> ```
> while pairings.length < full_size
> end
> 
> ```
> 
> ## For n = 4 [5, 6] [2, 3] [6, 9] [4, 6]
> 
> Rick DeNatale
> 
> My blog on Rubyhttp://talklikeaduck.denhaven2.com/

Nice.

Just in case you (or anyone else) was interested, I quickly threw  
together something that would create the simple pairings (1.upto(x) { |  
i| (x+1).upto(x) { |j| … } }) and then attempt to re-order it  
afterwards. I didn’t have high hopes for it, and it didn’t seem to  
work for any number (well, any number \> 2).

I haven’t bothered to work out a mathematical proof or anything, but I  
believe it’s impossible to generate the pairings that way and then re-  
order them. It really should be done this way, taking the rest period  
into account when creating the pairings.

---

<div class="post-metadata">

**Author:** ![milo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/85e7bf/32.png) [@milo](https://www.ruby-forum.com/u/milo)\
**Post date:** [October 16, 2007, 8:51pm UTC](https://www.ruby-forum.com/t/ruby-for-arranging-fencing-competitions/117394/6 "2007-10-16T20:51:12Z")

</div>

Rick Denatale wrote:

> def compute\_pairings  
> pairings = []  
> picks = competitors.dup  
> while pairings.length \< full\_size  
> trial\_pair = picks[0…1].sort  
> if pairings.include?(trial\_pair)  
> more\_tired = more\_tired(pairings, trial\_pair)  
> picks.delete(more\_tired)  
> picks \<\< more\_tired  
> else  
> pairings \<\< trial\_pair  
> picks \<\< picks.shift  
> picks \<\< picks.shift  
> end  
> end  
> pairings  
> end  
> end

That is very interesting - I would never have thought of it.  
Many thanks!
