The game

Given an   N×N   square array of zeroes or ones in an initial configuration,   and a target configuration of zeroes and ones.



The game is to transform one to the other in as few moves as possible by inverting whole numbered rows or whole lettered
columns at once   (as one move).

In an inversion.   any  1  becomes  0,   and any  0  becomes  1  for that whole row or column.



Task

Create a program to score for the Flipping bits game.

 The game should create an original random target configuration and a starting configuration.
 Ensure that the starting position is never the target position.
 The target position must be guaranteed as reachable from the starting position.   (One possible way to do this is to generate the start position by legal flips from a random target position.   The flips will always be reversible back to the target from the given start position).
 The number of moves taken so far should be shown.


Show an example of a short game here, on this page, for a   3×3   array of bits.




(subscriptrange, stringrange, stringsize):
flip: procedure options (main);
   declare n fixed binary;
 
   put skip list ('This is the bit-flipping game.  What size of board do you want?');
   get list (n);
   put skip list
      ('Your task is to change your board so as match the board on the right (the objective)');
 
   begin;
      declare initial(n,n) bit (1), objective(n,n) bit (1);
      declare (i, j, k, move) fixed binary;
      declare ch character(1);
      declare alphabet character (26) initial ('abcdefghijklmnopqrstuvwxyz');
 
      on subrg
         begin; put skip list ('Your row or column ' || trim(ch) || ' is out of range'); stop; end;
 
      initial, objective = iand(random()*99, 1) = 1;
 
      /* Set up the objective array: */
      do i = 1 to n-1;
         j = random()*n+1;  objective(j,*) = ^objective(j,*);
         j = random()*n+1;  objective(*,j) = ^objective(*,j);
      end;
 
      do move = 0 by 1;
         put skip edit ( center('You', n*3), center('The objective', 3*n+4) ) (x(3), a);
         put skip edit ( (substr(alphabet, i, 1) do i = 1 to n) ) (x(5), (n) a(3));
         put      edit ( (substr(alphabet, i, 1) do i = 1 to n) ) (x(3), (n) a(3));
         do i = 1 to n;
            put skip edit (i, initial(i,*), objective(i,*)) ((n+1) f(3), x(3), (n) F(3));
         end;
 
         if all(initial = objective) then leave;
 
         put skip(2) list
            ('Please type a row number or column letter whose bits you want to flip: ');
         get edit (ch) (L); put edit (ch) (a);
         k = index(alphabet, ch);
         if k > 0 then
            initial(*, k) = ^initial(*,k); /* Flip column k */
         else
            initial(ch,*) = ^initial(ch,*); /* Flip row ch */
      end;
      put skip(2) list ('Congratulations. You solved it in ' || trim(move) || ' moves.');
   end;
 
end flip;