bulls-and-cows.a68

     
   1  COMMENT
   2  
   3  @section Synopsis
   4  
   5  Break a unique code of `n' pegs and `m' colours you think of.
   6  
   7  After the program published on Rosetta Code by Marcel van der Veer.
   8  
   9  COMMENT
  10  
  11  INT pegs = 4, colours = 6;
  12  
  13  MODE LIST = FLEX [1 : 0] COMBINATION, 
  14       COMBINATION = [pegs] COLOUR, 
  15       COLOUR = INT;
  16  
  17  OP +:= = (REF LIST u, COMBINATION v) REF LIST:
  18     # Add one combination to a list. #
  19     ([UPB u + 1] COMBINATION w; w[ : UPB u] := u; w[UPB w] := v; u := w);
  20  
  21  PROC gen = (REF COMBINATION part, INT peg) VOID:
  22       # Generate all unique [colours!/(colours-pegs)!] combinations. #
  23       IF peg > pegs
  24       THEN all combinations +:= part
  25       ELSE FOR i TO colours
  26            DO IF BOOL unique := TRUE;
  27                  FOR j TO peg - 1 WHILE unique
  28                  DO unique := part[j] ~= i
  29                  OD;
  30                  unique
  31               THEN part[peg] := i;
  32                    gen (part, peg + 1)
  33               FI
  34            OD
  35       FI;
  36  
  37  LIST all combinations;
  38  gen (LOC COMBINATION, 1);
  39  
  40  PROC break code = (LIST sieved) VOID:
  41       # Present a trial and sieve the list with the entered score. #
  42       CASE UPB sieved + 1
  43       IN # No elements. # printf ($l"Inconsistent scores"$),
  44          # One element. # printf (($l"Solution is "4(xd)$, sieved[1]))
  45       OUT printf (($l"["g(0)"]"x4(xd)": "$, UPB sieved, sieved[1]));
  46       # Read the score as a sequence of "w" and "b". #
  47           INT col ok := 0, pos ok := 0, STRING z := "";
  48           WHILE z = ""
  49           DO read ((z, new line))
  50           OD;
  51           FOR i TO UPB z
  52           DO (z[i] = "c" | col ok |: z[i] = "b" | pos ok) +:= 1 
  53           OD;
  54           (pos ok = pegs | stop);
  55       # Survivors are combinations with score as entered. #
  56           LIST survivors;
  57           FOR i FROM 2 TO UPB sieved
  58           DO INT col ok i := 0, pos ok i := 0;
  59              FOR u TO pegs
  60              DO FOR v TO pegs
  61                 DO IF sieved[1][u] = sieved[i][v]
  62                    THEN (u = v | pos ok i | col ok i) +:= 1 
  63                    FI
  64                 OD
  65              OD;
  66              (col ok = col ok i AND pos ok = pos ok i | survivors +:= sieved[i])
  67           OD;
  68       # Solution must be among the survivors. #
  69           break code (survivors) 
  70       ESAC;
  71  
  72  break code (all combinations)