# Model name   : fairies.mod
# Description  : Color Fairies puzzle
# Source       : Puzzling Adventures, Dennis E. Shasha
# Date written : 21/12/06
# Written by   : Martin Chlond, Lancashire Business School
# Email        : mchlond@uclan.ac.uk

param f integer > 0;   # fairy
param h integer > 0;   # child
param c integer > 0;   # color
param n integer > 0;   # night 

set fairy := 1..f;     # Cloe, Ariana, Oliviana, Anya, Caroline
set child := 1..h;     # Tyler, Jordan, David
set color := 1..c;     # silver, sage, gold, rose, turquoise, ivory, violet, emerald, earth
set night := 1..n;

param star{j in child,k in color};      # star{j,k} = 1 if child j has star color k, else 0
param pearl{j in child,m in night};     # pearl{j,m} = no of pearls received by child j during night m
param visit{i in fairy,m in night};     # visit{i,m} = 1 if fairy i visits children on night m, else 0

var x{i in fairy,k in color} binary;    # x{i,k} = 1 if fairy i attracted to color k, else 0

subject to
   
# pearls received by each child on each night consistent with visits and stars
  rec{j in child,m in night}: sum{i in fairy,k in color} 
          visit[i,m]*star[j,k]*x[i,k] = pearl[j,m];

# each fairy attracted to a single color
  one{i in fairy}: sum{k in color} x[i,k] = 1;
  
# at least one fairy attracted to turquoise
  turqu: sum{i in fairy} x[i,5] >= 1;           
  
# one fairy attracted to earth
  earth: sum{i in fairy} x[i,9] = 1;

solve;
  
# display results
for{i in fairy} {
  for{k in color} {
    printf x[i,k];
    printf " ";
  }
  printf "\n";
}
  
data;

param f := 5;
param c := 9;
param h := 3;
param n := 5;

param star:    1 2 3 4 5 6 7 8 9 :=
            1  0 0 0 1 1 0 1 0 0
            2  0 1 0 0 0 1 1 0 0
            3  0 1 0 0 0 0 1 1 0;
          
param pearl:   1 2 3 4 5 :=
            1  1 0 0 1 1
            2  1 2 1 1 2
            3  2 2 2 0 1;
  
param visit:   1 2 3 4 5 :=
            1  1 0 0 1 1
            2  0 0 1 1 0 
            3  0 1 0 1 1
            4  1 1 1 0 1
            5  1 1 1 0 0;

end;