/**********************************************************************
 * Description of this file  'bloodtype1.c'
 *********************************************************************/

/*
 * FILE NAME:  bloodtype1.c
 *
 *
 * PROGRAM:    bloodtype1
 *
 *
 * LANGUAGE:   ANSI C
 *
 *
 * REVISION:   1.02 -- 02/19/08  Made minor improvements to several
 *                                 comments.
 *                               By Don Braun.
 *
 *             1.01 -- 04/25/07  Corrected handling of a read error
 *                                 before any characters on the input
 *                                 line, and improved many comments.
 *                               By Don Braun.
 *
 *             1.00 -- 04/17/07  Initial version.
 *                               By Don Braun.
 *
 *
 * USAGE #1:   bloodtype1
 * USAGE #2:   bloodtype1  < Blood1In.txt  > Blood1Out.txt
 *
 *
 * FOR HELP:   bloodtype1 -h  |  more            (prints 98 lines)
 *
 *
 * ARGUMENTS:  No arguments are expected on the command line, but
 *               text input and text output may be redirected.
 *
 *
 * PURPOSE:
 *
 *   This program  bloodtype1  solves  "Problem A+, Consanguine
 *     Calculations"  for the 2007 World Finals of the ACM
 *     (Association for Computing Machinery) International Collegiate
 *     Programming Contest.  This is the first problem described in
 *     the file at the Web address
 *     http://icpc.baylor.edu/icpc/Finals/2007WorldFinalProblemSet.pdf
 *     as follows.
 *
 *   Every person's blood has 2 markers called ABO alleles.  Each of
 *     the markers is represented by one of three letters:  A, B, or
 *     O.  This gives six possible combinations of these alleles that
 *     a person can have, each of them resulting in a particular ABO
 *     blood type for that person.
 *
 *                    Combination   ABO Blood Type
 *                    -----------   --------------
 *                         AA             A
 *                         AB             AB
 *                         AO             A
 *                         BB             B
 *                         BO             B
 *                         OO             O
 *
 *   Likewise, every person has two alleles for the blood Rh factor,
 *     represented by the characters + and -.  Someone who is
 *     "Rh positive" or "Rh+" has at least one + allele, but
 *     could have two.  Someone who is "Rh negative" always has
 *     two - alleles.
 *
 *   The blood type of a person is a combination of ABO blood type
 *     and Rh factor.  The blood type is written by suffixing the
 *     ABO blood type with the + or - representing the Rh factor.
 *     Examples include A+, AB-, and O-.
 *
 *   Blood types are inherited:  each biological parent donates one
 *     ABO allele (randomly chosen from their two) and one Rh factor
 *     allele to their child.  Therefore 2 ABO alleles and 2 Rh
 *     factor alleles of the parents determine the child's blood
 *     type.  For example, if both parents of a child have blood type
 *     A-, then the child could have either type A- or type O- blood.
 *     A child of parents with blood types A+ and B+ could have any
 *     blood type.
 *
 *   In this problem, you will be given the blood type of either both
 *     parents or one parent and a child;  you will then determine
 *     the (possibly empty) set of blood types that might
 *     characterize the child or the other parent.
 *
 *   Note:  an uppercase letter "Oh" is used in this problem to
 *     denote blood types, not a digit (zero).
 *
 *   Input
 *   -----
 *
 *   The input consists of multiple test cases.  Each test case is
 *     on a single line in the format:  the blood type of one parent,
 *     the blood type of the other parent, and finally the blood type
 *     of the child, except that the blood type of one parent or the
 *     child will be replaced by a question mark.  To improve
 *     readability, whitespace may be included anywhere on the line
 *     except inside a single blood type specification.
 *
 *   The last test case is followed by a line containing the letters
 *     E, N, and D separated by whitespace.
 *
 *   Output
 *   ------
 *
 *   For each test case in the input, print the case number
 *     (beginning with 1) and the blood type of the parents and the
 *     child.  If no blood type for a parent is possible, print
 *     "IMPOSSIBLE".  If multiple blood types for parents or child
 *     are possible, print all possible values in a comma-separated
 *     list enclosed in curly braces.  The order of the blood types
 *     inside the curly braces does not matter.
 *
 *   The sample output illustrates multiple output formats.  Your
 *     output format should be similar.
 *
 *       Sample Input          Output for the Sample Input
 *       ------------   ------------------------------------------
 *       O+  O-  ?      Case 1: O+ O- {O+, O-}
 *       O+  ?  O-      Case 2: O+ {A-, A+, B-, B+, O-, O+} O-
 *       AB-  AB+  ?    Case 3: AB- AB+ {A+, A-, B+, B-, AB+, AB-}
 *       AB+  ?  O+     Case 4: AB+ IMPOSSIBLE O+
 *       E N D
 *
 *
 * SECTION HEADINGS:
 *
 *   The section headings in this file are listed here as a summary:
 *
 * Description of this file  'bloodtype1.c'
 * Describe terminology and briefly summarize genetic inheritance
 * List prototypes for functions in this source file
 * Declare standard C '#include' header files
 * Define enum constants for some exit status values from this program
 * Globals  helpMsg1Format  and  helpMsg2Array[]  for the help messages
 * #define;  bloodTypeNames[];  'typedef enum { TypAP, ... } BloodType'
 * Global array 'BloodType typeFrom2AllelePairs[6][6] = {{Typ...},...}'
 * Global array 'BloodType allAllelePairs[6] = {Typ..., ...}'
 * Function 'void fprintMsg()'
 * Function 'int fgetline()'
 * Function 'void getMomsAndDadsAllelePairsFromKidsType()'
 * Function 'void sortUniqueTypes()'
 * Function 'void getTypesFromAnyAlleles1AndAnyAlleles2()'
 * Function 'void keepMomDadAllelesOnlyIfMomsType()'
 * Function 'void keepDadMomAllelesOnlyIfDadsType()'
 * Function 'BloodType getTypeEnumFromTypeStr()'
 * Function 'BloodType getStrFromTypeEnums()'
 * Declarations for program  main(...)
 * main(): Begin execution by printing a help message if necessary
 * main(): Begin 'while (1)' loop;  read and parse the next input line
 * main(): Find mom's allowed blood types if 1st input field was "?"
 * main(): Find dad's allowed blood types if 2nd input field was "?"
 * main(): Find kid's allowed blood types if 3rd input field was "?"
 * main(): End of loop 'while (1)';   end of function 'int main()'
 * End of this file  'bloodtype1.c'
 */



/**********************************************************************
 * Describe terminology and briefly summarize genetic inheritance
 *********************************************************************/


 /*
  * 1.  Blood group
  *
  *     Four human blood groups exist, called A, B, O (letter "Oh"),
  *     and AB.  Those blood groups denote what antigens (particular
  *     kinds of proteins) are attached to the surface of each of a
  *     person's red blood cells.  The normal function of red blood
  *     cells is to carry oxygen from the lungs to parts of the body.
  *     Group A blood has only one kind of antigen (the "A" protein)
  *     attached to each red blood cell, group B blood has only a
  *     second kind of antigen (the "B" protein), group O blood has
  *     neither kind of antigen, and group AB blood has both kinds of
  *     antigen.
  *
  * 2.  Rhesus factor (or Rh Factor)
  *
  *     In addition to blood groups, two human blood Rh factors exist,
  *     denoted by the characters + and -.  Blood with Rh factor +
  *     (also called "RhD positive" or simply "Rh+") has a particular
  *     kind of antigen (called Rh D) attached to each red blood cell,
  *     but blood with Rh factor - (also called "RhD negative" or
  *     "Rh-") does not have that antigen.
  *
  * 3.  Blood type
  *
  *     Each person has one of 8 blood types consisting of the blood's
  *     ABO group and the Rh factor, denoted by A+, A-, B+, B-, O+, O-,
  *     AB+, or AB-.  Approximate percentages of the U.S. population
  *     with each of those blood types from common to rare are: 38% O+,
  *     34% A+,  9% B+,  7% O-,  6% A-,  3% AB+,  2% B-,  1% AB-
  *     (see Web address http://www.howstuffworks.com/question593.htm).
  *     Populations of different ethnic or racial groups typically have
  *     different percentages for blood types.  As an extreme example,
  *     essentially no people whose ancestors are all Indians of Peru
  *     have A or B antigens, so 100% of them have blood type O+ or O-.
  *     The Web page  http://www.bloodbook.com/world-abo.html  lists
  *     percentages of blood groups for many ethnic and racial groups.
  *
  * 4.  Immune system reaction to blood types
  *
  *     When a person receives whole blood by transfusion, the immune
  *     system (including white blood cells) can attack new red blood
  *     cells if those red blood cells have any of the antigens that
  *     are not naturally present in that person's blood.  Typically, a
  *     foreign antigen causes the immune system to generate antibodies
  *     to attack that antigen.  These antibodies cause blood with the
  *     corresponding antigen to clump together, and those clots may
  *     lead to organ failure or death.  Therefore, for example, a
  *     recipient with group A blood can be given blood safely from a
  *     donor with group A or O but not from a donor with group B or
  *     AB blood.  Likewise, a recipient with Rh factor - can get blood
  *     from a donor with Rh factor -, but not from a donor with Rh
  *     factor +.
  *
  *     The following matrix shows whether ("YES") or not ("no") every
  *     possible blood transfusion can be done safely with the
  *     recipient's immune system accepting the donor's blood.
  *
  *     ---------------------------------------------------------
  *     | Donor |             Recipient blood type              |
  *     | blood |===============================================|
  *     | type  | A+  | A-  | B+  | B-  | O+  | O-  | AB+ | AB- |
  *     |-------|-----|-----|-----|-----|-----|-----|-----|-----|
  *     |  A+   | YES | no  | no  | no  | no  | no  | YES | no  |
  *     |  A-   | YES | YES | no  | no  | no  | no  | YES | YES |
  *     |  B+   | no  | no  | YES | no  | no  | no  | YES | no  |
  *     |  B-   | no  | no  | YES | YES | no  | no  | YES | YES |
  *     |  O+   | YES | no  | YES | no  | YES | no  | YES | no  |
  *     |  O-   | YES | YES | YES | YES | YES | YES | YES | YES |
  *     |  AB+  | no  | no  | no  | no  | no  | no  | YES | no  |
  *     |  AB-  | no  | no  | no  | no  | no  | no  | YES | YES |
  *     ---------------------------------------------------------
  *
  *     A person with blood type O- is called a universal donor because
  *     that person can give blood to people with any blood type
  *     without an adverse reaction from the recipient's immune system.
  *     Likewise, a person with AB+ can be called a universal recipient
  *     because that person can receive blood of any type without an
  *     adverse reaction.  In contrast, a person with type O- blood can
  *     receive only type O- blood without an adverse reaction.
  *
  * 5. Genetic inheritance
  *
  *       (somatic cell;  chromosome;  DNA;  chromatid;  centromere;
  *        double helix;  nucleotide bases A, T, C, and G;
  *        tri-nucleotide codon;  RNA;  nucleotide base U;
  *        amino acid;  start codon;  stop codon;  gene;  protein;
  *        genome;  locus of a gene on a chromosome;  allele;
  *        diploid organism;  homologous pair of chromosomes;
  *        genotype;  homozygous genes;  heterozygous genes;
  *        phenotype;  dominant and recessive alleles of a gene,
  *        or co-dominant alleles of a gene)
  *
  *    Except for the sex cells called gametocytes from which the ova
  *    (that is, egg cells) in a female and sperm in a male are made
  *    and the undifferentiated stem cells, every cell type in the
  *    mammalian body is called a somatic cell.  Internal organs, skin,
  *    bones, blood, and connective tissue are all made up of somatic
  *    cells.  The nucleus of a somatic human cell contains 23 pairs
  *    of chromosomes of genetic material, giving a total of 46
  *    chromosomes per cell.  One of these chromosomes in each pair was
  *    inherited from the person's mother and the other one was
  *    inherited from the person's father.
  *
  *    Each of these chromosomes is a pair of linear macromolecules of
  *    DNA (deoxyribonucleic acid) that are joined at a region
  *    typically near the middle called the centromere.  Each of these
  *    two DNA macromolecules is called a chromatid and contains a pair
  *    of strands of nucleotides, which are tightly entwined around
  *    each other in the shape of a ladder with short stiff rungs whose
  *    two long flexible rails are twisted into a double helix.  In the
  *    actual DNA molecule where each rung of the twisted ladder shape
  *    meets one of the two rails there is one of 4 kinds of chemical
  *    nucleotide bases called adenine, thyamine, cytosine, and
  *    guanine, which are generally abbreviated by the letters A, T, C,
  *    and G, respectively.  An adenine (A) base where a rung meets one
  *    rail of the ladder shape is almost always paired by a hydrogen
  *    bond with a thyamine (T) base where the opposite end of that
  *    rung meets the other rail.  A cytosine (C) base where a rung
  *    meets one rail is almost always paired with a guanine (G) base
  *    where the opposite end of that rung meets the other rail.  Each
  *    ordered sequence of 3 DNA nucleotide bases (such as ACT or TGG)
  *    is called a codon.  Thus,  4*4*4 = 64  possible codons exist.
  *    After a DNA codon is transcribed into a related RNA (ribonucleic
  *    acid) codon, where DNA thyamine (T) bases are replaced by
  *    uracil (U) bases in RNA, the codon can be used either to direct
  *    the synthesis of one of 20 amino acids or else to specify the
  *    start (RNA codon AUG) or end (RNA codon UAA, UAG, or UGG) of a
  *    sequence of bases called a gene.  Codons in a DNA molecule
  *    between a stop codon and the next start codon are not part of
  *    any gene.  A gene usually directs the synthesis of a protein,
  *    which is built by chaining together the amino acids that are
  *    associated with the codons forming the gene.  Genes can interact
  *    with each other to influence physical development and behavior.
  *    A human DNA molecule consists of from 50,961,097 nucleotide base
  *    pairs including 231 genes in the shortest chromosome (called Y)
  *    up to 245,203,898 nucleotide base pairs including 2968 genes in
  *    the longest chromosome (called #1).  A typical gene consists of
  *    hundreds to thousands of codons of necleotide base triplets
  *    between the start codon and the next stop codon.  The human
  *    genome (that is, the hereditary information encoded in the
  *    sequences of DNA nucleotides on all 23 distinct chromosomes)
  *    includes about 20,000 to 25,000 protein-coding genes.
  *
  *    One or more genes in certain loci (that is, positions) on
  *    particular chromosomes can determine an inherited characteristic
  *    such as blood type or eye color.  An allele is one of perhaps
  *    several possible particular DNA sequences of the nucleotides
  *    A, T, C, and G that can code the gene at a specific locus (or
  *    sometimes can code a non-gene sequence of DNA).  An individual
  *    organism's genotype for that gene is the set of its alleles that
  *    person happens to possess.  A diploid organism, including a
  *    human, is one that has two homologous (or similarly structured)
  *    versions of each chromosome, where one of those two chromosomes
  *    is inherited from each parent.  For a diploid organism, the two
  *    alleles for a gene (with one on each of the two similar
  *    chromosomes) make up the individual's genotype for the
  *    corresponding gene.  A diploid organism in which the two copies
  *    of the gene are identical (that is, have the same allele) is
  *    called homozygous for that gene.  An organism that has two
  *    different alleles of the gene is called heterozygous.
  *
  *    Phenotypes (the expressed characteristics) associated with a
  *    certain allele can sometimes be dominant or recessive, but often
  *    they are neither.  A dominant phenotype will be expressed when
  *    at least one allele of its associated type is present, whereas a
  *    recessive phenotype will only be expressed when both alleles are
  *    of its associated type.  For blood, the Rh+ allele is dominant
  *    over the recessive Rh- allele.  However, the blood group A
  *    allele is co-dominant with the blood group B allele for that
  *    gene, which means that if an A or B allele is present in that
  *    gene inherited from either the mother or the father then that
  *    allele gets expressed in the phenotype of the child.
  *
  *    References:
  *    For example, see the Wikipedia articles  (under the Web address
  *    http://en.wikipedia.org/wiki/)  for Somatic_cell, Chromosome,
  *    Centromere, DNA, Codon, RNA, Gene, and Allele.
  *    Also see  http://waynesword.palomar.edu/lmexer3.htm  about the
  *    structure and function of DNA.
  *
  * 6. Blood genotype allele pair from mom or else from dad
  *
  *    Each person has two blood genotype allele pairs, inheriting one
  *    pair from the mother and the other pair from the father.  Each
  *    of these two allele pairs consists of an allele for any one of
  *    the 3 blood groups (A, B, or O) paired with an allele for one of
  *    the 2 Rh factors (+ or -).  The 6 possible values of such an
  *    allele pair are denoted by A+, A-, B+, B-, O+, and O-.
  *
  * 7. Blood phenotype (or blood type)
  *
  *    Each person exhibits one blood phenotype (which is usually
  *    simply called the blood type) based on the two blood genotype
  *    allele pairs inherited from the parents.  The 8 possible
  *    phenotypes consist of the exhibited blood group (A, B, O, or AB)
  *    and the exhibited Rh factor (+ or -), and so they are denoted by
  *    A+, A-, B+, B-, O+, O-, AB+, AB-.  The rules that determine a
  *    person's blood phenotype from the two inherited blood genotype
  *    allele pairs will be stored below in the global array
  *    typeFrom2AllelePairs[][] .
  *
  * 8. The importance of the Rh factor for pregnancy
  *
  *    The Rh factor is also important for pregnant women.  If an Rh+
  *    man and an Rh- woman have a child, the child can be Rh+ or Rh-,
  *    depending upon the genotype of the father.  If the fetus is Rh+,
  *    this can cause problems.  While in the womb, some blood cells
  *    from the fetus will cross the placenta into the mother's blood
  *    stream.  The mother will make antibodies against the Rh+ cells.
  *    If the woman becomes pregnant again and if the baby is Rh+, the
  *    mother's anti-Rh antibodies will cross into the baby's blood and
  *    destroy its red blood cells, which can kill the baby.  If
  *    diagnosed early, it is possible to save a baby under these
  *    circumstances by replacing the baby's blood with transfusions
  *    that are free of the Rh antibodies.  Also, if this situation is
  *    known, it is possible to treat an Rh- woman with anti-Rh
  *    antibodies (RhoGam) immediately after childbirth to inactivate
  *    the baby's Rh+ cells and prevent the mother from forming
  *    anti-Rh antibodies (desensitize her).  (This was quoted from the
  *    Web address  http://www.howstuffworks.com/question593.htm .)
  */



/**********************************************************************
 * List prototypes for functions in this source file
 *********************************************************************/


/*
 * void fprintMsg(
 *   FILE               *pFileMsg,
 *   const char * const *msgPtrArray);
 *
 * int fgetline(
 *   FILE               *fp,
 *   char                str[],
 *   int                 lim);
 *
 * void getMomsAndDadsAllelePairsFromKidsType(
 *   const BloodType     kidsType,
 *   int                *pNumAllelePairs,
 *   BloodType           momsAllelePairs[DimGenotypes],
 *   BloodType           dadsAllelePairs[DimGenotypes]);
 *
 * void sortUniqueTypes(
 *   int                *pNumTypes,
 *   BloodType           typesArg[DimGenotypes]);
 *
 * void getTypesFromAnyAlleles1AndAnyAlleles2(
 *   const int           numAlleles1,
 *   const BloodType     allelePairs1[DimGenotypes],
 *   const int           numAlleles2,
 *   const BloodType     allelePairs2[DimGenotypes],
 *   int                *pNumTypes,
 *   BloodType           typesArg[DimGenotypes]);
 *
 * void keepMomDadAllelesOnlyIfMomsType(
 *   const BloodType     momsType,
 *   int                *pNumAlleles,
 *   BloodType           momsAllelePairs[DimGenotypes],
 *   BloodType           dadsAllelePairs[DimGenotypes]);
 *
 * void keepDadMomAllelesOnlyIfDadsType(
 *   const BloodType     dadsType,
 *   int                *pNumAlleles,
 *   BloodType           dadsAllelePairs[DimGenotypes],
 *   BloodType           momsAllelePairs[DimGenotypes]);
 *
 * BloodType getTypeEnumFromTypeStr(
 *   const char         *bloodTypeStr);
 *
 * const char *getStrFromTypeEnums(
 *   const int           numTypes,
 *   const BloodType     typeEnums[DimGenotypes]);
 *
 * int main(
 *   int                 argc,
 *   char               *argv[]);
 */



/**********************************************************************
 * Declare standard C '#include' header files
 *********************************************************************/


/*
 * The statement  '#include <stdio.h>'  declares types, macros, and
 *   input and output functions implemented in the ANSI C standard
 *   library.
 *
 * The standard ANSI C library input and output header file  stdio.h
 *   will '#define' or otherwise declare the following constants,
 *   'typedef's, and macros:
 *     FILE      - typedef for a structure used for buffered file I/O
 *     NULL      - typically  ((void *) 0)  or else  ((char *) 0)
 *     stdin     - standard input  FILE pointer (i.e., input  stream)
 *     stdout    - standard output FILE pointer (i.e., output stream)
 *     getc()    - macro that gets next character as 'int' from stream
 *   and will declare a prototype of the following standard ANSI C
 *   library function:
 *     sscanf()  - formatted input from a character string
 *     fprintf() - formatted printing to a FILE pointer (output stream)
 *     printf()  - formatted printing to standard output (stdout)
 */
#include  <stdio.h>

/*
 * The standard C header file  string.h  will declare prototypes for
 *   ANSI C standard library functions for manipulating null-terminated
 *   character strings.
 *
 * In the following table, the function arguments are assumed to have
 *   these type declarations in the function:
 *
 *             char   *s;    (The caller's argument for  s  must be a
 *                            pointer to a string of alterable
 *                            characters which is generally terminated
 *                            by a null character,  (char) '\0'.
 *                            The characters in that string may be
 *                            altered by the function.)
 *
 *       const char   *cs;   (The caller's argument for  cs  must be a
 *                            pointer to a string of alterable or
 *                            unalterable characters which is generally
 *                            terminated by a null character.
 *                            The characters in that string will not be
 *                            altered by the function.)
 *
 *       const char   *ct;   (The caller's argument for  ct  must be a
 *                            pointer to a string of alterable or
 *                            unalterable characters which is generally
 *                            terminated by a null character.
 *                            The characters in that string will not be
 *                            altered by the function.)
 *
 * As an example, in the following code fragment the first call to
 *   function  strcpy()  is acceptable because its first argument
 *   (myStr)  passed is a pointer to a string of alterable characters,
 *   which is required.  The second argument passed for this first call
 *   is a pointer to a string of unalterable characters.
 * However, the second call to  strcpy()  is unacceptable because the
 *   first argument passed is a pointer to a string of unalterable
 *   characters, which is not allowed.  The second argument  (myStr)
 *   passed for this second call is a pointer to a string of alterable
 *   characters.
 *
 *       char myStr[80];
 *       strcpy(myStr, "A constant source string is OKAY");
 *       strcpy("A constant destination string is NOT ALLOWED", myStr);
 *
 *   C library function                     Description
 * =======================  ===========================================
 * char   *strcpy(s,ct)     Copy string  ct  to string  s,  including
 *                            '\0';   return  s .
 * char   *strcat(s,ct)     Concatenate string  ct  to end of string
 *                            s;  return  s .
 * char   *strcmp(cs,ct)    Compare string  cs  to string  ct;
 *                            return   <0  if  cs<ct,   0  if  cs==ct,
 *                            >0  if  cs>ct .
 */
#include  <string.h>



/**********************************************************************
 * Define enum constants for some exit status values from this program
 *********************************************************************/


enum
{

  ExitStatusSuccess       =  0,
                              /* Exit status to be returned to the
                               *   operating system upon successful
                               *   completion of this program,
                               *   indicating that all input lines
                               *   contained proper information with
                               *   the expected format and were
                               *   processed successfully
                               */

  ExitStatusHelp          =  1,
                              /* Exit status code to be returned to the
                               *   operating system if this program
                               *   successfully completes printing
                               *   its detailed online help message
                               *   because the option -h was specified
                               */

  ExitStatusBadCmdArgs    =  2,
                              /* Exit status code to be returned to the
                               *   operating system if this program
                               *   detects any command line arguments
                               *   except one  '-h'
                               */

  ExitStatusBadInputData  =  3
                              /* Exit status code to be returned to the
                               *   operating system if at least one
                               *   input line contained improper
                               *   information or had an unexpected
                               *   format that could not be processed
                               */

};   /* End of 'enum { ExitStatus... }' */



/**********************************************************************
 * Globals  helpMsg1Format  and  helpMsg2Array[]  for the help messages
 *********************************************************************/


/*
 * Initialize a null-terminated unalterable character string to be used
 *   as a format string for printing a brief help message about how to
 *   use this program, to be used if command line arguments are bad.
 */
const char  *helpMsg1Format  =
  "USAGE #1:   bloodtype1\n"
  "USAGE #2:   bloodtype1  < Blood1In.txt  > Blood1Out.txt\n"
  "\n"
  "FOR HELP:   bloodtype1 -h  |  more            (prints %d lines)\n";


/*
 * Initialize an array of pointers to null-terminated unalterable
 *   character strings, where each string is one line of a detailed
 *   help message to be printed when running the command line
 *   'bloodtype1 -h'.
 */
const char  *helpMsg2Array[]  =
{
  "",
  "ARGUMENTS:  No arguments are expected on the command line, but",
  "              text input and text output may be redirected.",
  "",
  "REVISION:   1.02 -- 02/19/2008  by Don Braun",
  "",
  "PURPOSE:",
  "",
  "  This program  bloodtype1  solves  \"Problem A+, Consanguine",
  "    Calculations\"  for the 2007 World Finals of the ACM",
  "    (Association for Computing Machinery) International Collegiate",
  "    Programming Contest.  This is the first problem described in",
  "    the file at the Web address",
  "    http://"
      "icpc.baylor.edu/icpc/Finals/2007WorldFinalProblemSet.pdf",
  "    as follows.",
  "",
  "  Every person's blood has 2 markers called ABO alleles.  Each of",
  "    the markers is represented by one of three letters:  A, B, or",
  "    O.  This gives six possible combinations of these alleles that",
  "    a person can have, each of them resulting in a particular ABO",
  "    blood type for that person.",
  "",
  "                   Combination   ABO Blood Type",
  "                   -----------   --------------",
  "                        AA             A",
  "                        AB             AB",
  "                        AO             A",
  "                        BB             B",
  "                        BO             B",
  "                        OO             O",
  "",
  "  Likewise, every person has two alleles for the blood Rh factor,",
  "    represented by the characters + and -.  Someone who is",
  "    \"Rh positive\" or \"Rh+\" has at least one + allele, but",
  "    could have two.  Someone who is \"Rh negative\" always has",
  "    two - alleles.",
  "",
  "  The blood type of a person is a combination of ABO blood type",
  "    and Rh factor.  The blood type is written by suffixing the",
  "    ABO blood type with the + or - representing the Rh factor.",
  "    Examples include A+, AB-, and O-.",
  "",
  "  Blood types are inherited:  each biological parent donates one",
  "    ABO allele (randomly chosen from their two) and one Rh factor",
  "    allele to their child.  Therefore 2 ABO alleles and 2 Rh",
  "    factor alleles of the parents determine the child's blood",
  "    type.  For example, if both parents of a child have blood type",
  "    A-, then the child could have either type A- or type O- blood.",
  "    A child of parents with blood types A+ and B+ could have any",
  "    blood type.",
  "",
  "  In this problem, you will be given the blood type of either both",
  "    parents or one parent and a child;  you will then determine",
  "    the (possibly empty) set of blood types that might",
  "    characterize the child or the other parent.",
  "",
  "  Note:  an uppercase letter \"Oh\" is used in this problem to",
  "    denote blood types, not a digit (zero).",
  "",
  "  Input",
  "  -----",
  "",
  "  The input consists of multiple test cases.  Each test case is",
  "    on a single line in the format:  the blood type of one parent,",
  "    the blood type of the other parent, and finally the blood type",
  "    of the child, except that the blood type of one parent or the",
  "    child will be replaced by a question mark.  To improve",
  "    readability, whitespace may be included anywhere on the line",
  "    except inside a single blood type specification.",
  "",
  "  The last test case is followed by a line containing the letters",
  "    E, N, and D separated by whitespace.",
  "",
  "  Output",
  "  ------",
  "",
  "  For each test case in the input, print the case number",
  "    (beginning with 1) and the blood type of the parents and the",
  "    child.  If no blood type for a parent is possible, print",
  "    \"IMPOSSIBLE\".  If multiple blood types for parents or child",
  "    are possible, print all possible values in a comma-separated",
  "    list enclosed in curly braces.  The order of the blood types",
  "    inside the curly braces does not matter.",
  "",
  "  The sample output illustrates multiple output formats.  Your",
  "    output format should be similar.",
  "",
  "      Sample Input          Output for the Sample Input",
  "      ------------   ------------------------------------------",
  "      O+  O-  ?      Case 1: O+ O- {O+, O-}",
  "      O+  ?  O-      Case 2: O+ {A-, A+, B-, B+, O-, O+} O-",
  "      AB-  AB+  ?    Case 3: AB- AB+ {A+, A-, B+, B-, AB+, AB-}",
  "      AB+  ?  O+     Case 4: AB+ IMPOSSIBLE O+",
  "      E N D",
  NULL
};


const int   numLinesHelpMsg1  =  4;

const int   numLinesHelpMsg2  =
                          sizeof(helpMsg2Array) / sizeof(char *)  -  1;




/**********************************************************************
 * #define;  bloodTypeNames[];  'typedef enum { TypAP, ... } BloodType'
 *********************************************************************/


/*
 * Each input line (terminated by a newline character '\n') will be
 *   read as a null-terminated string into buffer array  inpLin[]
 *   declared below in the function  main() .
 * No input will contain more than  DimInputLine - 2  characters before
 *   the newline, or else an error message will be printed and this
 *   program will terminate immediately while returning
 *   ExitStatusBadInputData  to the operating system.
 */
#define      DimInputLine     5120

/*
 * DimAllelePairs  =  (the total number of allele pairs, consisting
 *                     of any one of the 3 blood groups [A, B, or O]
 *                     paired with one of the 2 Rh factors [+ or -]:
 *                     A+, A-, B+, B-, O+, O-)
 */
#define      DimAllelePairs   6

/*
 * DimBloodTypes   =  (the total number of possible blood phenotypes:
 *                     A+, A-, B+, B-, O+, O-, AB+, AB-)
 */
#define      DimBloodTypes    8

/*
 * DimBloodTypeStr =  (the number characters, including the terminating
 *                     null character, of the longest output blood type
 *                     string for any person:
 *                     "{A+, A-, B+, B-, O+, O-, AB+, AB-}"
 *                      123456789-123456789-123456789-1234)
 */
#define      DimBloodTypeStr  35

/*
 * Initialize the array of pointers to null-terminated constant
 *   character strings for each of the  DimBloodTypes = 8   possible
 *   blood phenotypes.
 */
const char  *bloodTypeNames[DimBloodTypes]  =
  { "A+", "A-", "B+", "B-", "O+", "O-", "AB+", "AB-" };

/*
 * Assign integers  0  through  5  to enum names of the
 *   DimAllelePairs = 6  possible allele pairs.
 * Assign integers  0  through  7  to enum names of the
 *   DimBloodTypes = 8   possible blood phenotypes.
 * Assign integer  8  to the enum name  TypUnknown, which indicates
 *   an unknown allele pair or blood phenotype.
 *
 * Define the typedef 'BloodType' for those  DimBloodTypes + 1  = 9
 *   enumeration names.
 */
typedef enum
{
  TypAP = 0,   /* A+   allele pair or blood type */
  TypAN,       /* A-   allele pair or blood type */
  TypBP,       /* B+   allele pair or blood type */
  TypBN,       /* B-   allele pair or blood type */
  TypOP,       /* O+   allele pair or blood type */
  TypON,       /* O-   allele pair or blood type */
  TypABP,      /* AB+  blood type only */
  TypABN,      /* AB-  blood type only */
  TypUnknown   /* Unknown blood type (none of the 8 above */
}  BloodType;



/**********************************************************************
 * Global array 'BloodType typeFrom2AllelePairs[6][6] = {{Typ...},...}'
 *********************************************************************/


/*
 * Initialize the 2-dimensional array  typeFrom2AllelePairs[][]  with
 *   data for the blood type exhibited by a child (that is, the
 *   phenotype consisting of an ABO group and a Rhesus factor) whose
 *   genes (that is, whose genotype) include two allele pairs (one
 *   allele pair from each of that child's two parents, respectively).
 * This array represents the genetic rules of inheritance for blood
 *   types, on which the computations of this program are based.
 */

/*                                     Row:           Column:      */
/*                                  allele pair     allele pair    */
/*                                   from mom        from dad      */
/*                                --------------  --------------   */
BloodType    typeFrom2AllelePairs[DimAllelePairs][DimAllelePairs]  =
{
  /*  Allele                  Allele pair from dad              */
  /*   pair      ============================================== */
  /* from mom      A+      A-      B+      B-      O+      O-   */
  /* --------    ------- ------- ------- ------- ------- ------ */
     /* A+ */  { TypAP,  TypAP,  TypABP, TypABP, TypAP,  TypAP },
     /* A- */  { TypAP,  TypAN,  TypABP, TypABN, TypAP,  TypAN },
     /* B+ */  { TypABP, TypABP, TypBP,  TypBP,  TypBP,  TypBP },
     /* B- */  { TypABP, TypABN, TypBP,  TypBN,  TypBP,  TypBN },
     /* O+ */  { TypAP,  TypAP,  TypBP,  TypBP,  TypOP,  TypOP },
     /* O- */  { TypAP,  TypAN,  TypBP,  TypBN,  TypOP,  TypON }
};   /* End of 'BloodType typeFrom2AllelePairs[][] =' */

/*
 * As a check, the blood phenotype values in the array
 *   typeFrom2AllelePairs[][]  defined just above form a symmetrical
 *   2-dimensional square matrix as it should;  that is, the matrix
 *   equals the transpose of itself because
 *       typeFrom2AllelePairs[allelePair1][allelePair2]   =
 *       typeFrom2AllelePairs[allelePair2][allelePair1]
 *   whenever   0 <= allelePair1 <= DimAllelePairs - 1 = 5
 *   and        0 <= allelePair2 <= DimAllelePairs - 1 = 5 .
 *   That symmetry is necessary because inheriting the first particular
 *   allele pair from mom and the second particular allele pair from
 *   dad determines the same blood phenotype in the child as inheriting
 *   that first particular allele pair from dad and that second
 *   particular allele pair from mom.
 */

/*
 * The array  typeFrom2AllelePairs[][]  that was allocated and
 *   initialized just above contains the following number of elements
 *   equal to each typedef  BloodType  enum constant for a blood
 *   phenotype.
 *
 *                                     (# of array elements
 *                                      equal to that phenotype)
 *                                   = (# of distinct genotype
 *              child's                 combinations of an
 *              typedef                 allele pair from mom and
 *             BloodType   child's      an allele pair from dad
 *       int     enum       blood       which could produce
 *      value  constant   phenotype     that phenotype)
 *      -----  ---------  ---------  ---------------------------
 *        0   =  TypAP       A+                   9
 *        1   =  TypAN       A-                   3
 *        2   =  TypBP       B+                   9
 *        3   =  TypBN       B-                   3
 *        4   =  TypOP       O+                   3
 *        5   =  TypON       O-                   1
 *        6   =  TypABP      AB+                  6
 *        7   =  TypABN      AB-                  2
 *                                   ---------------------------
 *                                       TOTAL = 36 = 6 * 6
 *
 * Therefore, the largest number of genotype combinations of allele
 *   pairs from mom and dad that can produce any particular blood type
 *   in a child is  DimGenotypes = 9,  because the child's blood
 *   types A+ and B+ exhibited most frequently each are caused by
 *   DimGenotypes = 9  genotypes as shown by the values in the table
 *   just above.
 *
 * DimGenotypes = 9  will be used as the dimension of various arrays
 *   below, especially because  DimGenotypes  is greater than both
 *   DimAllelePairs  and  DimBloodTypes:
 *   DimAllelePairs = 6 < DimBloodTypes = 8 < DimGenotypes = 9 .
 */
#define      DimGenotypes     9



/**********************************************************************
 * Global array 'BloodType allAllelePairs[DimGenotypes] = {Typ...,...}'
 *********************************************************************/


/*
 * Initialize the 1-dimensional array  allAllelePairs[]  with the
 *   DimAllelePairs = 6  enum constants for all possible allele pairs
 *   in increasing arithmetic order.
 * Extend the array to a usual length of  DimGenotypes = 9  elements
 *   by appending    DimGenotypes - DimAllelePairs  =  9 - 6  =  3
 *   arbitrary values (each equal to TypUnknown).
 */

BloodType    allAllelePairs[DimGenotypes]  =
  { TypAP, TypAN, TypBP, TypBN, TypOP, TypON,
    TypUnknown, TypUnknown, TypUnknown };



/**********************************************************************
 * Function 'void fprintMsg()'
 *********************************************************************/


/*
 * Purpose of function  fprintMsg():
 *
 *   This function prints a message to the open FILE pointer
 *     specified by argument  pFileMsg .
 *
 *   Argument  msgPtrArray  points to the first element of an array of
 *     pointers to null-terminated text strings.  Each one of these
 *     strings will be printed on a line by itself using the  fprintf
 *     format  "%s\n" .   The printing will stop when an element of
 *     array  msgPtrArray[]  is found which contains a null pointer
 *     (NULL  or  (char *) 0) .
 */

void fprintMsg(

  FILE               *pFileMsg,      /* Pointer to the open FILE
                                      *   descriptor to which the
                                      *   message will be written
                                      */

  const char * const *msgPtrArray)   /* Pointer to the first element
                                      *   of an array of (constant)
                                      *   pointers to the (constant)
                                      *   first character on each line
                                      *   of the message to be printed
                                      */

{

  while (*msgPtrArray)
    fprintf(pFileMsg, "%s\n", *msgPtrArray++);

  return;

}   /* End of 'void fprintMsg(...)' */



/********************************************************************
 * Function 'int fgetline()'
 ********************************************************************/


/*
 * Get the next text line from file pointer  fp  into string  str
 *   up to a maximum of  lim  characters (including the
 *   terminating null), and return the number of non-null
 *   characters that were read and stored into array  str[].
 *
 * If the k'th character to be read  (where  1 <= k <= lim-1)
 *   is a newline, the value  k  will be returned by the function
 *   name  fgetline()  with   str[k-1] = '\n'   and   str[k] = '\0',
 *   and no additional characters will be read.
 *
 * If no newline, null, or end-of-file (EOF) is found while
 *   reading the first  lim-1  characters from file  *fp  and
 *   storing them into  str[0]  through  str[lim-2],  subsequent
 *   characters from file  *fp  will be read and thrown away until
 *   the next newline, null, or the EOF is found, a null will be
 *   stored into  str[lim-1],  and the value  lim-1  will be
 *   returned.
 *
 * Let  k  denote the value returned by function name  fgetline() .
 *   0 <= k <= lim-1  is always true.
 *   str[k] = '\0'    is returned whenever  lim >= 1;  no characters
 *                    are stored into  str[j]  for any  j > k .
 *   k = 0            indicates that  lim <= 1  on entry, or an error,
 *                    a null character, or the end-of-file was found
 *                    before reading or storing any characters.
 *   1 <= k <= lim-1  and  str[k-1] != '\n'
 *                    indicates that a read error, a null character,
 *                    or the end-of-file was found after reading
 *                    and storing  k-1  characters.
 *   1 <= k <= lim-1  and  str[k-1]  = '\n'
 *                    indicates that a newline was found before
 *                    any characters were thrown away.
 *
 * On entry,  lim >= 1  is required to allow the string stored into
 *   the argument array  str[]  to be terminated by a null character.
 *
 * Use the STanDard I/O Header  "#include <stdio.h>"  for the
 *   "#define EOF"  constant and for the  "#define getc()"  macro.
 *
 * This function  fgetline()  is partially based on the function
 *   getline()  in the book "The C Programming Language" by Brian W.
 *   Kernighan and Dennis M. Ritchie, Second Edition (ANSI C), section
 *   "4.1 Basics of Functions", page 69.
 */

int fgetline(

  FILE               *fp,          /* In:  Pointer to the open  FILE
                                    *        to read from
                                    */

  char                str[],       /* Out: Character string to store
                                    *        characters into,
                                    *        preallocated to allow
                                    *        storage into  str[0]
                                    *        through  str[lim-1]
                                    */

  int                 lim)         /* In:  Maximum number of
                                    *        characters that can be
                                    *        stored into array
                                    *        argument  str[],
                                    *        including the
                                    *        terminating null byte.
                                    *      lim >= 1  is typical.
                                    */

{

  int   c = 'a';     /* Just in case  lim < 2 */
  int   i = 0;

  while (--lim > 0  &&  (c=getc(fp)) != EOF  &&  c != '\0'  &&
         c != '\n')
    str[i++] = (char) c;

  if (c == '\n')
    str[i++] = (char) c;
  else if (c != '\0'  &&  c != EOF)
    while ((c=getc(fp)) != EOF  &&  c != '\0'  &&  c != '\n')
      ;

  if (lim >= 0)
    str[i] = (char) '\0';
  return(i);

}   /* End of 'int fgetline (fp, str, lim)' */



/**********************************************************************
 * Function 'void getMomsAndDadsAllelePairsFromKidsType()'
 *********************************************************************/


/*
 * This function  getMomsAndDadsAllelePairsFromKidsType()  finds the
 *   set of all allowed genotypes (that is, one of the inherited
 *   allele pairs A+, A-, B+, B-, O+, or O- from each of the parents)
 *   for a person with the phenotype (that is, the exhibited blood type
 *   that is A+, A-, B+, B-, O+, O-, AB+, or AB-) of  kidsType .
 *
 * The number of possible genotypes will be stored into the caller's
 *   *pNumAllelePairs  where   1 <= *pNumAllelePairs <= DimGenotypes,
 *   and those genotypes inherited from the two parents will be stored
 *   by this function into  momsAllelePairs[k]  and
 *   dadsAllelePairs[k]  for each subscript  k  in the interval
 *   0 <= k <= *pNumAllelePairs - 1 .
 *
 * In the exceptional (error) case when  kidsType  on entry has none of
 *   the expected  DimBloodTypes = 8  blood phenotype enum values
 *   TypAP, TypAN, TypBP, TypBN, TypOP, TypON, TypABP, or TypABN,
 *   this function will only store  *pNumAllelePairs = 0  and will then
 *   return to the caller.
 */

void getMomsAndDadsAllelePairsFromKidsType(

  const BloodType     kidsType,     /* In:  The phenotype (i.e., the
                                     *   blood type exhibited) for a
                                     *   person.
                                     */

  int                *pNumAllelePairs,
                                    /* Out:  This function will store
                                     *   *pNumAllelePairs  =
                                     *     (the number of genotypes
                                     *      [i.e., allele pairs]
                                     *      that will be stored into
                                     *      the argument arrays
                                     *      momsAllelePairs[]  and
                                     *      dadsAllelePairs[]) .
                                     *   On return,
                                     *     0 <= *pNumAllelePairs
                                     *       <= DimGenotypes .
                                     */

  BloodType           momsAllelePairs[DimGenotypes],
  BloodType           dadsAllelePairs[DimGenotypes])
                                    /* Out:  This function will store
                                     *   the genotypes inherited from
                                     *   parents into
                                     *   momsAllelePairs[k]  and
                                     *   dadsAllelePairs[k]  for
                                     *   each subscript  k  bounded by
                                     *   0 <= k <= *pNumAllelePairs-1 .
                                     */

{

  /*
   * Declare local storage on the runtime stack
   */

  int                 momsAllele;   /* Moving 'int' value corresponding
                                     *   to the enum value of type
                                     *   BloodType  of the allele pair
                                     *   inherited from mom.
                                     */

  int                 dadsAllele;   /* Moving 'int' value corresponding
                                     *   to the enum value of type
                                     *   BloodType  of the allele pair
                                     *   inherited from dad.
                                     */

  int                 numAllelePairs  =  0;
                                    /* Moving count of the number of
                                     *   genotypes stored so far into
                                     *   the argument arrays
                                     *   momsAllelePairs[]  and
                                     *   dadsAllelePairs[] .
                                     */

  /*
   * Begin execution of  getMomsAndDadsAllelePairsFromKidsType()
   */

  for (momsAllele = 0;  momsAllele < DimAllelePairs;  momsAllele++)
    for (dadsAllele = 0;  dadsAllele < DimAllelePairs;  dadsAllele++)
    {
      if (typeFrom2AllelePairs[momsAllele][dadsAllele] == kidsType)
      {
        momsAllelePairs[numAllelePairs] = (BloodType) momsAllele;
        dadsAllelePairs[numAllelePairs] = (BloodType) dadsAllele;
        numAllelePairs++;
      }   /* End 'if (typeFrom2AllelePairs[...][...] == kidsType)' */
    }   /* End 'for (dadsAllele=0; dadsAllele<DimAllelePairs; ...)' */

  *pNumAllelePairs = numAllelePairs;
  return;

}   /* End of 'void getMomsAndDadsAllelePairsFromKidsType()' */



/**********************************************************************
 * Function 'void sortUniqueTypes()'
 *********************************************************************/


/*
 * This function  sortUniqueTypes()  assumes that on entry each of the
 *   elements of the argument array  typesArg[i]  is an enum value
 *   TypAP, TypAN, TypBP, TypBN, TypOP, TypON, TypABP, TypABN, or
 *   TypUnknown, for all subscripts  i  in the interval
 *   0 <= i <= *pNumTypes - 1 .   More than one of those array elements
 *   on entry may contain the same enum value.  Some of the enumeration
 *   constants of typedef  BloodType  may not be stored in any of the
 *   *pNumTypes  active elements of array  typesArg[]  on entry.
 *   The values in active elements of array  typesArg[]  on entry
 *   need not be sorted.
 *
 * In effect, this function will sort the active values that were
 *   initially in array  typesArg[]  into arithmetically increasing
 *   order and will discard duplicate values.  In other words, this
 *   function will overwrite the value of 'int' argument  *pNumTypes
 *   with the number of distinct typedef  BloodType  enum values that
 *   were initially among the active elements of array  typesArg[],
 *   and this function will overwrite the contents of the first
 *   (returned value of  *pNumTypes)  elements of array  typesArg[]  by
 *   those distinct typedef  BloodType  enum values sorted into
 *   arithmetically increasing order.
 *
 * The 'int' value of argument  *pNumTypes  on return will always be
 *   less than or equal to the value of that argument on entry,
 *   because any duplicate values initially in that array will be
 *   discarded.
 *
 * For the example, if on entry the arguments have the values
 *       *pNumTypes  = 7,
 *       typesArg[0] = TypBP,
 *       typesArg[1] = TypAP,
 *       typesArg[2] = typUnknown,
 *       typesArg[3] = typBP,
 *       typesArg[4] = TypABP,
 *       typesArg[5] = typBP,        and
 *       typesArg[6] = typAP,
 *   then on return the arguments will have the values
 *       *pNumTypes  = 4,
 *       typesArg[0] = TypAP,
 *       typesArg[1] = TypBP,
 *       typesArg[2] = typABP,       and
 *       typesArg[3] = typUnknown,
 *   while the following 3 array elements still keep the values they
 *   had on entry although they are no longer considered to be active
 *   on return:
 *       typesArg[4] = TypABP,
 *       typesArg[5] = typBP,        and
 *       typesArg[6] = typAP .
 */

void sortUniqueTypes(

  int                *pNumTypes,    /* In/Out:  *pNumTypes  =
                                     *   (the number of active
                                     *    elements used in argument
                                     *    array  typesArg[],  where
                                     *    0 <= (*pNumTypes  on return)
                                     *      <= (*pNumTypes  on entry)
                                     *      <= DimBloodTypes + 1
                                     *       = 9 = DimGenotypes).
                                     */

  BloodType           typesArg[DimGenotypes])
                                    /* In/Out:  On entry or return,
                                     *   for each subscript  i  bounded
                                     *   by   0 <= i <= *pNumTypes,
                                     *   typesArg[i]  is an enum value
                                     *   for one of the blood genotypes
                                     *   or phenotypes A+, A-, B+, B-,
                                     *   O+, or O-, or one of the
                                     *   phenotypes AB+ or AB-, or the
                                     *   special enum value
                                     *   TypUnknown .
                                     */

{

  /*
   * Declare local storage on the runtime stack
   */

  int                 iArg;         /* Moving 'int' subscript for
                                     *   argument array  typesArg[] .
                                     */

  int                 jCnt;         /* Moving 'int' subscript for
                                     *   local array typesCount[],
                                     *   which corresponds to blood
                                     *   type '(BloodType) jCnt'.
                                     */

  int                 typesCount[DimBloodTypes + 1];
                                    /* typesCount[j]  =
                                     *   (the number of elements found
                                     *    so far among active elements
                                     *    of argument array  typesArg[]
                                     *    equal to  (BloodType) j).
                                     */

  /*
   * Begin execution of  sortUniqueTypes()  by initializing the values
   *   of all  DimBloodTypes + 1 = 9  elements of array  typesCount[]
   *   to zero.
   */
  for (jCnt = 0;  jCnt <= DimBloodTypes;  jCnt++)
    typesCount[jCnt]  =  0;

  /*
   * For each integer  j  bounded by  0 <= j <= DimBloodTypes = 8,
   *   store into  typesCount[j]  the number of times that the enum
   *   value  '(BloodType) j'  occurs among the active elements of the
   *   argument array  typesArg[] .
   */
  for (iArg = 0;  iArg < *pNumTypes;  iArg++)
    typesCount[typesArg[iArg]]++;

  /*
   * Store into the beginning elements of the argument array
   *   typesArg[]  only the blood types that were found in the
   *   original contents of that array based on the counts in local
   *   array  typesCount[],  overwriting the contents that were present
   *   in array  typesArg[]  on entry.
   * This allows all those blood types with nonzero counts to be stored
   *   easily in arithmetically increasing order with all duplicate
   *   blood types removed.
   */
  iArg  =  0;

  for (jCnt = 0;  jCnt <= DimBloodTypes;  jCnt++)
    if (typesCount[jCnt] > 0)
      typesArg[iArg++]  =  (BloodType) jCnt;

  /*
   * Return with argument  *pNumTypes  set to the number of distinct
   *   blood types that were found.
   */
  *pNumTypes  =  iArg;
  return;

}   /* End of 'void sortUniqueTypes()' */



/**********************************************************************
 * Function 'void getTypesFromAnyAlleles1AndAnyAlleles2()'
 *********************************************************************/


/*
 * This function  getTypesFromAnyAlleles1AndAnyAlleles2()  assumes
 *   that on entry each of the elements of the argument array
 *   allelePairs1[i]  for all  i  bounded by  0 <= i <= numAlleles1 - 1
 *   and each of the elements of the argument array  allelePairs2[j]
 *   for all  j  bounded by  0 <= j <= numAlleles2 - 1  is an enum
 *   value TypAP, TypAN, TypBP, TypBN, TypOP, or TypON.   More than one
 *   of those array elements on entry may contain the same enum value.
 *   Some of the enumeration constants of typedef  BloodType  may not
 *   be stored in any of the active elements of those two arrays on
 *   entry.  The values in active elements of arrays  allelePairs1[]
 *   and  allelePairs2[]  on entry need not be sorted.
 *
 * This function computes a sorted list of all distinct blood types (in
 *   the order TypAP, TypAN, TypBP, TypBN, TypOP, TypON, TypABP, and
 *   TypABN) that will result from a kid inheriting any one of the
 *   numAlleles1  allele pairs stored in array  allelePairs1[]
 *   from mom and any one of the allele pairs stored in array
 *   allelePairs2[]  from dad.  The number of distinct blood types in
 *   that list will be stored into argument  *pNumTypes  so that
 *   0 <= *pNumTypes <= DimBloodTypes = 8,  and the sorted list itself
 *   will be stored into argument  typesArg[k]  for all  k  bounded by
 *   0 <= k <= *pNumTypes - 1 .
 */

void getTypesFromAnyAlleles1AndAnyAlleles2(


  const int           numAlleles1,
  const BloodType     allelePairs1[DimGenotypes],
                                    /* In:  The first set of allele
                                     *   pairs are  allelePairs1[i]
                                     *   for all subscripts  i  where
                                     *   0 <= i <= numAlleles1 - 1 .
                                     */

  const int           numAlleles2,
  const BloodType     allelePairs2[DimGenotypes],
                                    /* In:  The second set of allele
                                     *   pairs are  allelePairs2[i]
                                     *   for all subscripts  i  where
                                     *   0 <= i <= numAlleles2 - 1 .
                                     */

  int                *pNumTypes,    /* Out:  *pNumTypes  =
                                     *   (the number of active
                                     *    elements used in argument
                                     *    array  typesArg[],  where
                                     *    0 <= *pNumTypes
                                     *      <= DimBloodTypes =  8
                                     *      <  DimGenotypes  =  9 .
                                     */

  BloodType           typesArg[DimGenotypes])
                                    /* Out:  On return,
                                     *   for each subscript  m  bounded
                                     *   by   0 <= m <= *pNumTypes - 1,
                                     *   typesArg[m]  is an enum value
                                     *   for one of the blood
                                     *   phenotypes A+, A-, B+, B-, O+,
                                     *   O-, AB+, or AB- that can
                                     *   result from a child inheriting
                                     *   any one of the  numAlleles1
                                     *   allele pairs in array
                                     *   allelePairs1[]  from mom and
                                     *   any one of the  numAlleles2
                                     *   allele pairs in array
                                     *   allelePairs2[]  from dad.
                                     */

{

  /*
   * Declare local storage on the runtime stack
   */

  int                 i1;           /* Moving 'int' subscript for
                                     *   argument array  allelePairs1[]
                                     */

  int                 j2;           /* Moving 'int' subscript for
                                     *   argument array  allelePairs2[]
                                     */

  int                 kArg;         /* Moving 'int' subscript for
                                     *   argument array  typesArg[].
                                     */

  int                 mCnt;         /* Moving 'int' subscript for
                                     *   local array typesCount[],
                                     *   which corresponds to blood
                                     *   type '(BloodType) mCnt'.
                                     */

  int                 typesCount[DimBloodTypes];
                                    /* typesCount[m]  =
                                     *  (the number of blood
                                     *   phenotypes of the child
                                     *   found so far equal to
                                     *   (BloodType) m,  for each
                                     *   integer  m  bounded by
                                     *   0 <= m <= DimBloodTypes-1 = 7)
                                     */

  /*
   * Begin execution of  getTypesFromAnyAlleles1AndAnyAlleles2()  by
   *   initializing the values of all  DimBloodTypes = 8  elements of
   *   array  typesCount[]  to zero.
   */
  for (mCnt = 0;  mCnt < DimBloodTypes;  mCnt++)
    typesCount[mCnt]  =  0;

  /*
   * For each integer  m  bounded by  0 <= m <= DimBloodTypes - 1 = 7,
   *   store into  typesCount[m]  the number of times that the blood
   *   type of the child has the enum value  '(BloodType) m'  when that
   *   child inherits from mom any one of the allele pairs
   *   allelePairs1[i]  for each  i  in the interval
   *   0 <= i <= numAlleles1 - 1   and when that child inherits from
   *   dad any one of the allele pairs  allelePairs2[j]  for each  j
   *   in the interval   0 <= j <= numAlleles2 - 1 .
   */
  for (i1 = 0;  i1 < numAlleles1;  i1++)
    for (j2 = 0;  j2 < numAlleles2;  j2++)
      typesCount
      [ typeFrom2AllelePairs [allelePairs1[i1]] [allelePairs2[j2]] ]++;

  /*
   * Store into the beginning elements of the argument array
   *   typesArg[]  only the blood types that have counts of at least 1
   *   in local array  typesCount[],  overwriting the contents that
   *   were present in array  typesArg[]  on entry.
   * This allows all those blood types with nonzero counts to be stored
   *   easily in arithmetically increasing order with all duplicate
   *   blood types removed.
   */
  kArg  =  0;

  for (mCnt = 0;  mCnt < DimBloodTypes;  mCnt++)
    if (typesCount[mCnt] > 0)
      typesArg[kArg++]  =  (BloodType) mCnt;

  /*
   * Return with argument  *pNumTypes  set to the number of distinct
   *   blood types that were found.
   */
  *pNumTypes  =  kArg;
  return;

}   /* End of 'void getTypesFromAnyAlleles1AndAnyAlleles2()' */



/**********************************************************************
 * Function 'void keepMomDadAllelesOnlyIfMomsType()'
 *********************************************************************/


/*
 * This function  keepMomDadAllelesOnlyIfMomsType()  will remove the
 *   inherited allele pair elements  momsAllelePairs[i]  and
 *   dadsAllelePairs[i]  from those argument arrays for each subscript
 *   i  in the range  0 <= i <= (*pNumAlleles  on entry) - 1  if mom's
 *   blood genotype allele pair  momsAllelePairs[i]  would not allow
 *   her to have the blood phenotype given by argument  momsType .
 *
 * On return, the value of argument  *pNumAlleles  will be reduced if
 *   necessary to contain the number of mom's allele pairs that are
 *   compatible with her given blood type  momsType,  and those
 *   compatible allele pairs for mom and the corresponding allele pairs
 *   for dad (that were originally at the same subscripts as mom's)
 *   will be stored into the elements  momsAllelePairs[j]  and
 *   dadsAllelePairs[j]  respectively for each  j  in the interval
 *   0 <= j <= (*pNumAlleles  on return) - 1 .
 *
 * In the case when none of mom's allele pairs on entry is compatible
 *   with her given blood type, the argument value  *pNumAlleles = 0
 *   will be returned and the values of
 *   momsAllelePairs[(*pNumAlleles  on entry) - 1]  and of
 *   dadsAllelePairs[(*pNumAlleles  on entry) - 1]  will be copied
 *   over all originally active elements of those two arrays,
 *   respectively.
 */

void keepMomDadAllelesOnlyIfMomsType(

  const BloodType     momsType,     /* In:  The given phenotype (that
                                     *   is, one of the blood types
                                     *   A+, A-, B+, B-, O+, O-, AB+,
                                     *   or AB-) exhibited by mom.
                                     */

  int                *pNumAlleles,  /* In/Out:  On entry or return,
                                     *   *pNumAlleles  =
                                     *   (the number of active elements
                                     *    used at the beginning of each
                                     *    of the argument arrays
                                     *    momsAllelePairs[]  and
                                     *    dadsAllelePairs[],  where
                                     *    0 <= (*pNumAlleles on return)
                                     *      <= (*pNumAlleles on entry)
                                     *      <= DimGenotypes = 9).
                                     */

  BloodType           momsAllelePairs[DimGenotypes],
  BloodType           dadsAllelePairs[DimGenotypes])
                                    /* In/Out:  On entry or return,
                                     *   for each subscript  i  bounded
                                     *   by 0 <= i <= *pNumAlleles - 1,
                                     *   elements  momsAllelePairs[i]
                                     *   and  dadsAllelePairs[i]  are
                                     *   enum values for mom or dad,
                                     *   respectively, selected from
                                     *   blood allele pair genotypes
                                     *   A+, A-, B+, B-, O+, or O-,
                                     *   such that the child has the
                                     *   proper blood phenotype if
                                     *   those two genotypes were
                                     *   inherited from the parents.
                                     * This function will overwrite any
                                     *   of these array elements
                                     *   required to remove any
                                     *   corresponding genotype allele
                                     *   pairs  momsAllelePairs[i]  and
                                     *   dadsAllelePairs[i]  (on entry)
                                     *   from mom and dad for each
                                     *   subscript  i  when mom's
                                     *   allele type momsAllelePairs[i]
                                     *   would prevent her from having
                                     *   the phenotype given by
                                     *   argument  momsType .
                                     * As usual, the blood genotype
                                     *   allele pairs in all active
                                     *   elements of arrays
                                     *   momsAllelePairs[]  and
                                     *   dadsAllelePairs[]  must be
                                     *   selected from the set
                                     *   { A+, A-, B+, B-, O+, O- }.
                                     */

{

  /*
   * Declare local storage on the runtime stack
   */

  int                 iA;           /* Moving subscript for elements
                                     *   momsAllelePairs[iA]  and
                                     *   dadsAllelePairs[iA]  now being
                                     *   tested for compatibility with
                                     *   blood type argument  momsType.
                                     */

  int                 jA;           /* Moving subscript for elements
                                     *   momsAllelePairs[jA]  and
                                     *   dadsAllelePairs[jA]  now being
                                     *   copied onto elements
                                     *   momsAllelePairs[jA - 1]  and
                                     *   dadsAllelePairs[jA - 1]
                                     *   to remove the elements
                                     *   momsAllelePairs[iA]  and
                                     *   dadsAllelePairs[iA] .
                                     */

  int                 kT;           /* Moving subscript of dad's allele
                                     *   pair for the elements
                                     *   typeFrom2AllelePairs[][kT]
                                     *   now being used to compare with
                                     *   blood type argument  momsType.
                                     */

  int                 isAlleleOK;   /* This value is nonzero (that is,
                                     *   true) if and only if it is
                                     *   known for sure that mom can
                                     *   have the genotype allele pair
                                     *   momsAllelePair[iA]  and also
                                     *   have the phenotype  momsType .
                                     * This value is zero (that is,
                                     *   false) if the truth of that
                                     *   condition is still uncertain
                                     *   or if mom's allele pair
                                     *   momsAllelePair[iA]  is
                                     *   finally known to be
                                     *   inconsistent with mom's
                                     *   phenotype  momsType .
                                     */

  /*
   * Begin execution of  keepMomDadAllelesOnlyIfMomsType()
   */

  for (iA = 0;  iA < *pNumAlleles;  iA++)
  {

    for (kT = 0;  kT < DimAllelePairs;  kT++)
      if (isAlleleOK  =  (typeFrom2AllelePairs[momsAllelePairs[iA]][kT]
                          == momsType))
        break;   /* Exit from this 'for (kT ...)' loop */

    /*
     * Remove the allele pairs with subscript  iA  if it is known for
     *   sure  (indicated by  isAlleleOK = 0)  that mom cannot have the
     *   genotype allele pair  momsAllelePair[iA]  while she also has
     *   the phenotype  momsType .
     */
    if (! isAlleleOK)
    {

      /*
       * Remove element  momsAllelePairs[iA]  by overwriting elements
       *   momsAllelePairs[iA]   thru  momsAllelePairs[*pNumAlleles-2]
       *   respectively by elements
       *   momsAllelePairs[iA+1] thru  momsAllelePairs[*pNumAlleles-1].
       * Remove element  dadsAllelePairs[iA]  by overwriting elements
       *   dadsAllelePairs[iA]   thru  dadsAllelePairs[*pNumAlleles-2]
       *   respectively by elements
       *   dadsAllelePairs[iA+1] thru  dadsAllelePairs[*pNumAlleles-1].
       */
      for (jA = iA + 1;  jA < *pNumAlleles;  jA++)
      {
        momsAllelePairs[jA - 1]  =  momsAllelePairs[jA];
        dadsAllelePairs[jA - 1]  =  dadsAllelePairs[jA];
      }   /* End of 'for (jA = iA + 1;  jA < *pNumAlleles;  jA++)' */

      /*
       * Decrement by one the number  (argument  *pNumAlleles)  of
       *   allele pairs still active in each of the arrays
       *   momsAllelePairs[]  and  dadsAllelePairs[] .
       */
      (*pNumAlleles)--;

      /*
       * Because the previous  'for (jA ...)'  loop changed the value
       *   of  momsAllelePairs[iA],  the current value of index  iA
       *   must be decremented by one so the next iteration of this
       *   'for (iA ...)'  loop will examine that changed value in
       *   array  momsAllelePairs[] .
       */
      iA--;

    }   /* End of 'if (! isAlleleOK)' */

  }   /* End of 'for (iA = 0;  iA < *pNumAlleles;  iA++)' */

  return;

}   /* End of 'void keepMomDadAllelesOnlyIfMomsType()' */



/**********************************************************************
 * Function 'void keepDadMomAllelesOnlyIfDadsType()'
 *********************************************************************/


/*
 * This function  keepDadMomAllelesOnlyIfDadsType()  will remove the
 *   inherited allele pair elements  dadsAllelePairs[i]  and
 *   momsAllelePairs[i]  from those argument arrays for each subscript
 *   i