function [ v_num, v, v_p ] = variomino_variants ( mp, np, p_num, p, d )

%*****************************************************************************80
%
%% variomino_variants() finds variants of variominoes in an array.
%
%  Discussion:
%
%    A polyomino is a shape formed by connecting unit squares edgewise.
%
%    A variomino is a polyomino in which each square has been assigned
%    a value between 1 and v.
%
%    A variomino can be represented by an MxN matrix, whose entries are
%    between 1 and v for squares that are part of the variomino, 
%    and 0 otherwise.
%
%    We are supplied with an array P of variominoes.  We wish to "tile" a
%    region R, using, for each I, D(I) copies of variomino P(I).
%    We are asked to return an array containing all the variants of these 
%    variominos that can be generated by rotation and reflection.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    17 April 2023
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    integer mp, np: the rows and columns in P.
%
%    integer p_num: the number of variominoes stored in P.
%
%    integer p(mp,np,p_num): for each value K, P(:,:,K) is a matrix 
%    representing the K-th variomino.  Each matrix should be 
%    "top-left tight", that is, there should be a nonzero in row 1, and in 
%    column 1.  However, there may be trailing rows and columns of zeros.
%
%    integer d(p_num): the number of copies of each variomino that
%    may be used.  If D(I) <= 0, no variants of variomino I will be generated.
%
%  Output:
%
%    integer v_num: the number of variants found.
%
%    integer v(mp,np,v_num): the variants.
%
%    integer v_p(v_num): if V(:,:,I) is a variant of the variomino
%    P(:,:,L), then V_P(I) is set to L.
%
  v_num = 0;
  v = [];
  v_p = [];

  for l = 1 : p_num
%
%  Only use variominoes for which the user has set D to at least 1.
%
    if ( 1 <= d(l) )
%
%  Make a condensed version of the variomino called "Q".
%
      q = variomino_condense ( p(1:mp,1:np,l) );

      [ mq, nq ] = size ( q );
%
%  Generate all variants.
%
      for reflect = 0 : 1
        for rotate = 0 : 4

          s = variomino_transform ( q, rotate, reflect );

          [ ms, ns ] = size ( s );
%
%  Only proceed if this variant S will fit in [MP,NP].
%
          if ( ms <= mp & ns <= np )
%
%  Expand S to an [MP,NP] array T.
%
            t = zeros(mp,np);
            t(1:ms,1:ns) = s;
%
%  Compare T to all previous variants.
%  This could probably be cut down to only look at variants of current
%  variomino, index L.
%
            different = true;
            for k = 1 : v_num
              if ( t(1:mp,1:np) == v(1:mp,1:np,k) )
                different = false;
                break;
              end
            end

            if ( different )
              v_num = v_num + 1;
              v(1:mp,1:np,v_num) = t(1:mp,1:np);
              v_p(v_num) = l;
            end

          end

        end
      end

    end

  end

  return
end
