// pi-ea-1.cpp   (C) 2006 adolfo@di-mare.com

/** \file  pi-ea-1.cpp
    \brief CI-0202 Primer examen Parcial.

    - Cámbiele el nombre al archivo por su número de carnet.
    - Cambie el valor de la hilera \c carnet por su propio carnet.
    - Reordene los bloques { UNO } ... { CUATRO } en \c Trituradora().
    - Si su \c permutacion es 3214, deje los bloques de código de
      \c Trituradora() en este orden:
      \code
      TRES: {
        // ...
      }
      DOS: {
        // ...
      }
      UNO: {
        // ...
      }
      CUATRO: {
        // ...
      }
      \endcode
    - Envíe por correo electrónico su programa modificado.
    - En el ASUNTO ponga CI-0202: Examen Parcial.

    \author Adolfo Di Mare <adolfo@di-mare.com>
    \date   2006
*/
unsigned permutacion   =    3214;  ///< GLOBAL: permutacion del estudiante.
unsigned char carnet[] = "A00006"; ///< GLOBAL: carnet del estudiante.

#include <iostream.h> // Lectura y escritura C++
#include  <iomanip.h> // setw()

/// Obtiene el \c i-ésimo dígito del número \c n.
unsigned Formula2(unsigned n, unsigned i) {
    unsigned mult = 1;
    for (unsigned k=1; k<i; ++k) {
        mult *= 10;
    }

    return ( ( (n/mult) * mult) / mult ) % 10;
}

/// Usa \c hilera para codificar el valor del \c carnet del estudiante.
/// - \c permutacion es el orden de intercambio de los bloques.
void Trituradora(
    unsigned        permutacion, // orden de intercambio de bloque
    unsigned char * hilera       // hilera resultado
) {
    enum { UNO=1, DOS=2, TRES=3, CUATRO=4 };
    permutacion %= 10000;
    #define V(j) ( (d*j) % 5 + 1 ) ///< Macro para el módulo \c 5.
    #define Formula(x,d) (1+4-d)   ///< Macro identidad.

    for (int k=4; k>0; --k) {
        for (int d=4; d>0; --d) {
            unsigned l =  Formula2(permutacion, d); // Deduce la permutación...
            switch (l) {
                case UNO: { // caso UNO: bloque de código número "1"
                    unsigned j = V(22);
                    unsigned k = V(44);

                    hilera[j] *= j; // multiplicación loca
                    hilera[j]  = hilera[j] % (0x7A - 0x61 + 1) + 0x61; // ASCII

                    hilera[k] *= k;
                    hilera[k]  = hilera[k] % (0x7A - 0x61 + 1) + 0x61;
                    break;
                }

                case DOS: {
                    unsigned j = V(33);
                    unsigned k = V(55);

                    hilera[j] *= j;
                    hilera[j]  = hilera[j] % (0x7A - 0x61 + 1) + 0x61;

                    hilera[k] *= k;
                    hilera[k]  = hilera[k] % (0x7A - 0x61 + 1) + 0x61;
                    break;
                }

                case TRES: {
                    unsigned j = V(68);
                    unsigned k = V(76);

                    hilera[j] *= j;
                    hilera[j]  = hilera[j] % (0x7A - 0x61 + 1) + 0x61;

                    hilera[k] *= k;
                    hilera[k]  = hilera[k] % (0x7A - 0x61 + 1) + 0x61;
                    break;
                }

                case CUATRO: {
                    unsigned j = V(20);
                    unsigned k = V(13);

                    hilera[j] *= j;
                    hilera[j]  = hilera[j] % (0x7A - 0x61 + 1) + 0x61;

                    hilera[k] *= k;
                    hilera[k]  = hilera[k] % (0x7A - 0x61 + 1) + 0x61;
                    break;
                }
            }

        } // for
    } // for

    #undef V       // borra la macro
    #undef Formula1
    #undef Formula2
} // Trituradora()

#include <string.h> // strcpy()

/// Contienen los datos de respuesta de un estudiante.
struct CPT {
    unsigned char* carnet;
    unsigned       permutacion;
    unsigned char* resultado;
};

/// Valores para el primer examen parcial.
/// - Ejemplo de cómo inicializar una estructura grande.
CPT Clase[24] = {
    "A42473"  ,  3142  ,  "A42a7v"  ,


    "994156"  ,  3421  ,  "994150"  ,
    "A01460"  ,  4312  ,  ""        ,
    "A02068"  ,  3421  ,  ""        ,
    "A10706"  ,  2431  ,  ""        ,
    "A32793"  ,  3142  ,  ""        ,
    "A34529"  ,  2413  ,  ""        ,
    "A41749"  ,  4312  ,  ""        ,
    "A42473"  ,  3142  ,  "A42a7v"  ,
    "A43121"  ,  2431  ,  ""        ,
    "A43269"  ,  4312  ,  ""        ,
    "A43527"  ,  3142  ,  "A0000"   ,
    "A44479"  ,  3142  ,  "A44a7d"  ,
    "A45048"  ,  3421  ,  ""        ,
    "A45357"  ,  3142  ,  ""        ,
    "A45397"  ,  4312  ,  ""        ,
    "A50445"  ,  3214  ,  ""        ,
    "A50519"  ,  3142  ,  "A50d1d"  ,
    "A52076"  ,  2431  ,  "Ab2076"  ,
    "A52169"  ,  3142  ,  "A52r6d"  ,
    "A53444"  ,  3142  ,  "A53000"  ,
    "A53636"  ,  3214  ,  "A00o0o"  ,
    "A54972"  ,  3142  ,  ""        ,
    "A62970"  ,  2413  ,  "Ac2p70"  ,
};


/// Calcula la cantidad de valores almacenados en un vector.
#define DIM(V) (sizeof(V) / sizeof(*V)) // *V == *(V+0) == V[0]

/// Programa principal C++
int main() {
    cout << endl << endl << "===== COMIENZO =====" << endl << endl;
    unsigned char resultado[ sizeof("A12345") ]; // 7 == 6+1

    cout << "CARNET " << "  PERMUTACION ";
    cout << " CORRECTO " << "  RESULTADO";
    for (unsigned i=0; i<DIM(Clase); ++i)
    { // Bloque de ejecución

         // En "resultado" queda lo que Trituradora() calcula

        // copia en "resultado" la hilera "carnet"
        strcpy( resultado, Clase[i].carnet );

        // Invocación del procedimiento que hace el trabajo principal
        Trituradora( Clase[i].permutacion, resultado );

        // Graba los resultados en "cout"
        cout << endl;
        cout << setw(6) << Clase[i].carnet << "    ";
        cout << "  " << setw(4) << Clase[i].permutacion << "      ";
        cout << '\"' << setw(6) << resultado << '\"' << "   ";
        cout << '\"' << setw(0) << Clase[i].resultado<< '\"' ;
    }
    cout << endl << endl << "===== FINALIZO =====" << endl;

    return 0; // código de retorno del programa completo [main()]
}

// EOF: pi-ea-1.cpp