Suppose you have developers A
, B
, C
, D
, E
, F
and they review each other's work.
How can you develop an algorithm to generate a review rotation telling each developer whose work they have to review each week AND satisfy these criteria:
A
reviews B
, B
reviews A
)I think I can make it work with an odd number of developers, but I am struggling with an even number.
There is simple round-robin tournament algorithm to get all possible pairs without repetitions.
Arrange developers in two columns, left column reviews right one.
Fix A place
Move all others in cyclic way.
A->F
B->E
C->D
A->B
C->F
D->E
A->C
D->B
E->F
A->D
E->C
F->B
A->E
F->D
B->C
I'd go the nieve route and rotate through a circular array. So week 1 everyone reviews the person to their right + 0. Week 2 everyone reviews the person to their right + 1. Week 3, right + 2, etc.
Week 1:
A -> B
B -> C
...
F -> A
Week 2:
A -> C
B -> D
...
F -> B
I seem to have found a solution inspired by the Round Robin rotation.
For Developers A
, B
, C
, D
, E
, F
You fix a developer, say A
. Then rotate the rest in a clockwise manner.
Then:
Week 1:
A B C
D E F
AD
BE
CF
DB
EC
FA
Week 2:
A D B
E F C
AE
DF
BC
ED
FB
CA
Week 3:
A E D
F C B
AF
EC
DB
FE
CD
BA
Week 4:
A F E
C B D
AC
FB
ED
CF
BE
DA
Week 5:
A C F
B D E
AB
CD
FE
BC
DF
EA
Although it still exhibits unwanted properties where some people will never meet others such as B
avoiding D
.
Here's a brute-force in Haskell (takes about 10 seconds to get going).
Code:
import Control.Monad (guard, replicateM)
developers = ["A", "B", "C", "D", "E", "F"]
combinations = filter (\x -> head x /= last x) . replicateM 2 $ developers
makeWeek week =
if length week == length developers
then [week]
else do
review <- combinations
guard (notElem (take 1 review) (map (take 1) week)
&& notElem (drop 1 review) (map (drop 1) week)
&& notElem (reverse review) week
&& notElem review week)
makeWeek (review:week)
solve = solve' [] where
solve' weeks =
if length weeks == length developers - 1
then [weeks]
else do
week' <- makeWeek []
guard (all (\x -> notElem x (concat . take (length developers - 1) $ weeks)) week')
solve' (week':weeks)
Sample Output:
*Main> solve
[[[["F","B"],["E","A"],["D","C"],["C","E"],["B","D"],["A","F"]]
,[["F","C"],["E","B"],["D","A"],["C","D"],["B","F"],["A","E"]]
,[["F","A"],["E","C"],["D","B"],["C","F"],["B","E"],["A","D"]]
,[["F","E"],["E","D"],["D","F"],["C","B"],["B","A"],["A","C"]]
,[["F","D"],["E","F"],["D","E"],["C","A"],["B","C"],["A","B"]]],...etc
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With