2/19/2017

Ejercicio 42

Hay una gran cantidad de personas con tarjetas de crédito en este mundo, por lo que esos números son bastante largos: American Express utiliza números de 15 dígitos, MasterCard utiliza números de 16 dígitos, y Visa utiliza 13 y 16 dígitos. Y esos son números decimales (0 a 9), no binarios, lo que significa, por ejemplo, que American Express podría imprimir tantos como 10 ^ (15) = 1.000.000.000.000.000 tarjetas únicas! (Eso es, mil billones).

Tarjeta de crédito

Las tarjetas de crédito en realidad tienen algún tipo de estructura. Los números de todas las tarjetas American Express comienzan con 34 ó 37; números MasterCard todos comienzan con 51, 52, 53, 54, o 55; y números de visa todas comienzan con los números 4. Pero la tarjeta de crédito también tienen una "suma de comprobación" incorporado en ellos, una relación matemática entre al menos un número y otros. Esa suma de control permite a los ordenadores (o seres humanos que les gustan las matemáticas) detectar errores ortográficos (por ejemplo, transposiciones), sin tener que consultar una base de datos, que puede ser lento.

¿Cuál es la fórmula secreta? Bueno, la mayoría de las tarjetas utilizan un algoritmo inventado por Hans Peter Luhn. De acuerdo con el Algoritmo de Luhn, se puede determinar si un número de una tarjeta de crédito es (sintácticamente) válida de la siguiente manera:

  1. Multiplicar cada dos dígitos por 2, a partir de la segunda a la última cifra del número y luego agregar dígitos a esos productos juntos.

  2. Añadir la suma a la suma de los dígitos que no se multiplica por 2.

  3. Si el último dígito del total es 0 (o, dicho de manera más formal, si el módulo total de 10 es congruente a 0), el número es válido!

Eso es un poco confuso, así que vamos a probar un ejemplo con esta tarjeta AMERICAN EXPRESS: 378282246310005.
  1. Para no perdernos, primero vamos a subrayar cada dos dígitos, empezando por el número de segundo hasta el último dígito:

    3 7 8 2 8 2 2 4 6 3 1 0 0 0 5

    Bueno, vamos a multiplicar cada uno de los dígitos subrayados por 2:

    7 • 2 + 2 + 2 • 2 • 2 + 4 + 3 • 2 • 2 + 0 + 0 • 2 • 2

    Eso nos da:

    14 + 4 + 4 + 8 + 6 + 0 + 0

    Ahora vamos a añadir dígitos a esos productos "(es decir, no a los productos en sí) juntos:

    1 + 4 + 4 + 4 + 8 + 6 + 0 + 0 = 27

  2. Ahora vamos a añadir esa suma (27) a la suma de los dígitos que no se multiplican por 2:

    3 + 27 + 8 + 8 + 2 + 6 + 1 + 0 + 5 = 60

  3. Sí, el último dígito de esa suma (60) es un 0, entonces la tarjeta es de fiar!

Por lo tanto, la validación de números de tarjetas de crédito no es difícil, pero se hace un poco tediosa con la mano. Espero que hayas entendido, debajo esta el codigo!



#include <iostream>
// se incluye la clase Tarjeta para despues llamar a sus metodos 
#include "Tarjeta.h"

using namespace std;

int main(void)
{
    // se crea un objeto de la clase Tarjeta (Instanciaciación) 
    Tarjeta *obj = new Tarjeta();
    // declaramos e inicializamos la variable numerotarjeta en 0 
    long long numerotarjeta = 0;

    // preguntamos el numero de la tarjeta 
    do
    {
        cout << "Ingrese su numero de tarjeta" << endl;
        cout << ">> ";
        // guardamos en la variable numerotarjeta el valor ingresado 
        cin >> numerotarjeta;
    }
    while (numerotarjeta < 0);
    // encapsulamos la variable numerotarjeta  
    obj->setNumeroTarjeta(numerotarjeta);
    // mostramos que tipo de tarjeta es 
    cout << "Su numero de tarjeta es " << obj->validarTarjeta() << endl;
}

#ifndef TARJETA_H
#define TARJETA_H
#include <iostream>

using namespace std;

class Tarjeta
{
    public:
        Tarjeta();
        virtual ~Tarjeta();
        // se declaran los metodos publicos 
        void setNumeroTarjeta(long long val);
        long long getNumeroTarjeta();
        string validarTarjeta();
    protected:

    private:
        // se declara el atributo privado 
        long long numerotarjeta;
};

#endif // TARJETA_H

#include "Tarjeta.h"

Tarjeta::Tarjeta()
{
    numerotarjeta = 0;
}

Tarjeta::~Tarjeta()
{
    //dtor
}

void Tarjeta::setNumeroTarjeta(long long val)
{
    numerotarjeta = val;
}

long long Tarjeta::getNumeroTarjeta()
{
    return numerotarjeta;
}

string Tarjeta::validarTarjeta()
{
    // determinamos si tiene un número válido de dígitos 
    // recuerda para poder entender esto debes leer o averiguar sobre el Algoritmo de Luhn ;) 
    int contador = 0;
    long long digitos = numerotarjeta;
    while (digitos > 0)
    {
        digitos = digitos/10;
        contador++;
    }
    if ((contador != 13) && (contador != 15) && (contador != 16))
    {
        return "INVALIDO.";
    }
    int numero[contador];

    for (int i = 0; i < contador; i++)
    {
        numero[i] = numerotarjeta % 10;
        numerotarjeta = numerotarjeta / 10;
    }

    int numero_original[contador];
    for (int i = 1; i < contador; i++)
    {
        numero_original[i] = numero[i];
    }

    for (int i = 1; i < contador; i+=2)
    {
        numero[i] = numero[i] * 2;
    }

    int v = 0;
    int temp;

    if (contador == 13)
    {
        for (int i = 0; i < contador; i++)
        {
            temp = (numero[i] % 10) + (numero[i]/10 % 10);
            v = v + temp;
        }
        if (numero_original[12] == 4 && v % 10 == 0)
        {
            return "VISA.";
        }
        else
        {
            return "INVALIDO.";
        }
    }
    if (contador == 15)
    {
        for (int i = 0; i < contador; i++)
        {
            temp = (numero[i] % 10) + (numero[i]/10 % 10);
            v = v + temp;
        }
        if (numero_original[14] == 3 && v % 10 == 0 && (numero_original[13] == 4 || numero_original[13] == 7))
        {
            return "AMERICAN EXPRESS.";
        }
        else
        {
            return "INVALIDO.";
        }
    }
    if (contador == 16)
    {
        for (int i = 0; i < contador; i++)
        {
            temp = (numero[i] % 10) + (numero[i]/10 % 10);
            v = v + temp;
        }
        if (numero_original[15] == 4 && v % 10 == 0)
        {
            return "VISA.";
        }
        else
        {
            return "MASTERCARD.";
        }
    }
    return "INVALIDO.";
}

// se importa paquete JOptionPane para dibujar un cuadro de dialogo en pantalla
// que muestre información o para llenar información 
import javax.swing.JOptionPane;


import javax.swing.JOptionPane;

public class Main
{
    public static void main(String[] args)
    {
        Tarjeta obj = new Tarjeta();
        // declaramos e inicializamos la variable numerotarjeta en 0
        long numerotarjeta = 0;

        // preguntamos el numero de la tarjeta
        do
        {
            numerotarjeta = Long.parseLong(JOptionPane.showInputDialog("Ingrese su numero de tarjeta"));
        }
        while (numerotarjeta < 0);
        // encapsulamos la variable numerotarjeta
        obj.setNumeroTarjeta(numerotarjeta);
        // mostramos que tipo de tarjeta es
        JOptionPane.showMessageDialog(null, "Su numero de tarjeta es " + obj.validarTarjeta());
    }
}

public class Tarjeta
{
    private long numerotarjeta;
    
    public void setNumeroTarjeta(long val)
    {
        numerotarjeta = val;
    }
    
    public long getNumeroTarjeta()
    {
        return numerotarjeta;
    }
    
    public String validarTarjeta()
    {
        // determinamos si tiene un número válido de dígitos
        // recuerda para poder entender esto debes leer o averiguar sobre el Algoritmo de Luhn ;)
        int contador = 0;
        long digitos = numerotarjeta;
        while (digitos > 0)
        {
            digitos = digitos/10;
            contador++;
        }
        if ((contador != 13) && (contador != 15) && (contador != 16))
        {
            return "INVALIDO.";
        }
        long [] numero =  new long[contador];

        for (int i = 0; i < contador; i++)
        {
            numero[i] = numerotarjeta % 10;
            numerotarjeta = numerotarjeta / 10;
        }

        long [] numero_original = new long[contador];
        for (int i = 1; i < contador; i++)
        {
            numero_original[i] = numero[i];
        }

        for (int i = 1; i < contador; i+=2)
        {
            numero[i] = numero[i] * 2;
        }

        long v = 0;
        long temp;

        if (contador == 13)
        {
            for (int i = 0; i < contador; i++)
            {
                temp = (numero[i] % 10) + (numero[i]/10 % 10);
                v = v + temp;
            }
            if (numero_original[12] == 4 && v % 10 == 0)
            {
                return "VISA.";
            }
            else
            {
                return "INVALIDO.";
            }
        }
        if (contador == 15)
        {
            for (int i = 0; i < contador; i++)
            {
                temp = (numero[i] % 10) + (numero[i]/10 % 10);
                v = v + temp;
            }
            if (numero_original[14] == 3 && v % 10 == 0 && (numero_original[13] == 4 || numero_original[13] == 7))
            {
                return "AMERICAN EXPRESS.";
            }
            else
            {
                return "INVALIDO.";
            }
        }
        if (contador == 16)
        {
            for (int i = 0; i < contador; i++)
            {
                temp = (numero[i] % 10) + (numero[i]/10 % 10);
                v = v + temp;
            }
            if (numero_original[15] == 4 && v % 10 == 0)
            {
                return "VISA.";
            }
            else
            {
                return "MASTERCARD.";
            }
        }
        return "INVALIDO.";
    }
}