Algoritmo en Java [SOLUCIONADO]

Iniciado por Azulf, 18 Octubre 2007, 00:14 AM

0 Miembros y 1 Visitante están viendo este tema.

Azulf

Pues aqui un ejercicio que me tomaron en una calificada de Progra (no se donde diablos el profe saco este problema), muy tedioso, ya lo he solucionado, pero quisiera saber si alguno de ustds podria hacerlo de una manera diferente o en todo caso mas eficiente, en fin como para que practiques.  ;)

Citar

PRACTICA CALIFICADA DE PROGRAMACION

La situacion del ejercito aliado es desesperada.El ejercito de Adolf Hitler amenza con adueñarse definitivamente de Europa y comenzar su expansion por el mundo.Sus comunicaciones, ademas, estan cifradas con una poderosa máquina llamada ENIMGMA, que desafia toda intercepcepcion.

En BletChley Par, las mentes más poderosas del mundo libre se han reunido en secreto para tratar de encontrar la forma de romper los codigos alemanes.Han conseguido comprender el funcionamiento de ENIGMA, pero no resulta viable descifrar los mensajes manualmente.Para dificultar las cosas los mensajes alemanes originales estan escritor en español.

En un proyecto ultrasecreto, un grupo de fisicos aliados consiguen secuestrar a un programador español del siglo XXI con su máquina de computo (o sea tú). Su única esperanza es que este individuo los ayude a descifrar los mensajes alemantes, antes de que sea demasiado tarde...

Los mensajes alemanes utilizan el juego de 29 carácteres siguientes, codificados a partir de 0(los tres últimos son el espacio, el punto y la coma).

A B C D E F G H I  J  K  L   M   N   O   P   Q   R   S  T   U   V  W  X   Y   Z       .    ,
0 1 2  3  4 5 6 7 8 9 10 11 12  13  14  15 16  17 18 19 20 21 22 23 24 25 26 27 28

La máquina enigma tiene ruedas con esta secuencia de caracteres igual que el cuentakilometros de un auto,tiene ruedas con los digitos del 0 al 9. Si una rueda esta en la posicion A y se avanza 1, pasara a B; si avanza 29 pasos, volvera a la posicion A.

Tras traducirlo al español, lo primero que hacen  los alemanes para codificar un mensaje es elegir una secuencia especial de 5 letras, que hara de semilla.Colocan esta secuencia al principio y el mensaje inmediatamente a continuacion.

EJEMPLO:

Supongase el mensaje MATAR A LOS HUMANOS

Para codificarlos, Enigma podia enteponder una semilla cualquiera, por ejemplo RUDER preparando el mensaje asi:

RUDERMATAR A LOS HUMANOS


Se multiplican y suman los codigos de RUDER (que son 17,20,3,4,17); por tanto tenemeros:
(17x20x3x4x17 + 17+20+3+4+17), y ese (69421 en este caso) es el numero de pasos que avanzará la rueda de la M. Eso nos lleva a la H. Por tanto, el mensaje pasa a ser:

RUDERHATAR A LOS HUMANOS

La misma operacion se haria para la A, con los codigos de las letras UDERH. Y así sucesivamente. Eso nos llevaría al mensaje codificado:

RUDERHRML.EMG,AKYRMRNGNU

Hay que realizar un programa que lea cadenas de textos y los alamcene en un vector(siempre limitando a los caracteres mencionados arriba)con un mensaje codificado, y grabe en otro vector dichos mensajes codificados.EL programa tendra que realizar los cáclculos segun la "codificacion alemana".


Y aqui mi solucion:

Código (java) [Seleccionar]

/**
* @(#)codificados.java
*
* @author  JEANS AZULF RUIZ
* @version 1.00 2007/6/8
*/
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
public class codificados extends JFrame implements ActionListener{
   
    JLabel label;
    JTextField texto;
    JTextArea area,area2;
    JButton b_deco;
    char Arreglo[]=new char[29];
   
    Vector codi=new Vector();
    Vector deco=new Vector();
   
    public codificados() {
   
    label =new JLabel("Ingrese aqui Texo Codificado");
    texto=new JTextField();
   
    texto.addKeyListener(new ValidaNumero() );
   
    area=new JTextArea();
    area.setEditable(false);
    area.setToolTipText("Esta ***** no se Edita");
    area2=new JTextArea();
    area2.setEditable(false);
    area2.setToolTipText("Esta ***** no se Edita");
   
    b_deco=new JButton("Decodificalo!!!");
   
    JPanel panel=new JPanel( new GridLayout(1,2) );
    panel.add(label);
    panel.add(texto);
   
    JPanel panel2=new JPanel(new GridLayout(1,2) );
   
    JPanel sub_panel= new JPanel(new BorderLayout() );
    sub_panel.setBorder(BorderFactory.createTitledBorder("Textos Codificados... :"));
    sub_panel.add(new JScrollPane(area) ,BorderLayout.CENTER);
   
   
    JPanel sub_panel2=new JPanel(new BorderLayout() );
    sub_panel2.setBorder(BorderFactory.createTitledBorder("Textos Decodificados... :"));
    sub_panel2.add(new JScrollPane(area2),BorderLayout.CENTER);
   
    panel2.add(sub_panel);
    panel2.add(sub_panel2);
   
    add(panel,BorderLayout.NORTH);
    add(panel2,BorderLayout.CENTER);
    add(b_deco,BorderLayout.SOUTH);
   
    b_deco.addActionListener(this);
   
    iniciar();
   
    setTitle(".::CODIFICADOS::.");
    setSize(450,300);
    setLocation(300,300);
    setResizable(false);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setVisible(true);
    }
   
    public void actionPerformed(ActionEvent e){
    if(b_deco==e.getSource()){
    if( texto.getText().length()<=5 ) JOptionPane.showMessageDialog(this,"Por favor ingrese Texto a decodificar VALIDO.\nRecuerde que el texto debe tener mas de 5 caracteres","Title",JOptionPane.INFORMATION_MESSAGE);
    else decodificar();
    }
    }
   
   
    public void iniciar(){
    for (int i = 0; i<26; i++)
    Arreglo[ i ]=(char)(i+65) ;
   
    Arreglo[26]=(char)(32) ;
    Arreglo[27]=(char)(46) ;
    Arreglo[28]=(char)(44) ;
   
    System.out.println(Arrays.toString(Arreglo) );
    }
   
    public int buscar(char car){
    for(int i=0;i<Arreglo.length;i++ )
    if( Arreglo[ i ]==car  ) return i;
    return (-1);
    }
   
    public void decodificar(){
   
    //Creo mi arreglo con la longitud del texto menos los 05 caractereres que son los que han servido de semilla
    char arreglo[]=new char[ ( texto.getText().length() ) -5 ];
   
    //agrego al vector
    codi.addElement( texto.getText().toUpperCase() );
       
    String N=texto.getText().toUpperCase();
    int tope= N.length()-5;
    for(int i=0;i<tope;i++){
    //formo la subcadena que contiene los numeros antecesores
    String n= N.substring(tope-i-1 , tope+5-i-1);
   
   
    //multiplico los digitos
    int Pro=1;
    int Sum=0;
   
    for(int j=0;j<n.length();j++ ){
    Pro*= buscar(n.charAt(j));
    Sum+= buscar(n.charAt(j));
    }
    Pro+=Sum;
    //obtengo el residuo
    Pro=(Pro%29);
   
   
    int t=0,k=0;
    int resi= buscar( N.charAt(N.length()-1-i ) );
   
    do{
    t= (29*k)+ resi;
    k++;
    }while(Pro>t);
   
    arreglo[arreglo.length-i-1]= Arreglo[t-Pro];
   
    }
   
    String s_deco=new String(arreglo);
    //agrego al otro vector
    deco.addElement(s_deco);
    String s_codi=new String();
    String s_decodi=new String();
    for(int h=0;h<deco.size();h++ ){
    s_codi+=(String)codi.elementAt(h);
    s_decodi+= (String)deco.elementAt(h);
    s_codi+="\n";
    s_decodi+="\n";
    }
   
    area.setText(s_codi);
    area2.setText(s_decodi);
   
    texto.setText("");
    }
   
    //clase para que la caja de texto solo acepte LETRAS
class ValidaNumero extends KeyAdapter {
  public void keyTyped(KeyEvent e) {
      char c = e.getKeyChar();
      if ( !(!Character.isDigit(c) || (c == KeyEvent.VK_BACK_SPACE) ||(c == KeyEvent.VK_DELETE)) ) {
            getToolkit().beep();
            e.consume();
      }
     
      if(c==KeyEvent.VK_ENTER ){
      if( texto.getText().length()<=5 ) JOptionPane.showMessageDialog(null,"Por favor ingrese Texto a decodificar VALIDO.\nRecuerde que el texto debe tener mas de 5 caracteres","Title",JOptionPane.INFORMATION_MESSAGE);
    else decodificar();
           
      }
     
  }
}

   
   
    public static void main(String[] args) {
       new codificados();
    }
}



Y aparte de decodificar los mensajes, para verificiar que estaba en lo correcto, tuve que hacer otra aplicacion en la cual me codificara los mensajes, que es esta:

Código (java) [Seleccionar]

/**
* @(#)decodificados.java
*
* @author JEANS AZULF RUIZ
* @version 1.00 2007/6/8
*
* APLICACION EN JAVA QUE ME VA A CODIFICAR MENSAJES,PARA LUEGO UTILIZARLOS EN LA OTRA APLICACION
*/
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
public class decodificados extends JFrame implements ActionListener{
   
    JLabel label;
    JTextField texto;
    JTextArea area,area2;
    JButton b_deco;
    char Arreglo[]=new char[29];
   
    public decodificados() {
    crea_objetos();
    agrega_objetos();
    listar_objetos();
    propiedades_ventana();
    }
   
    public void crea_objetos(){
   
    label =new JLabel("Ingrese aqui Texo A codificar");
    texto=new JTextField();
   
    area=new JTextArea();
    area.setEditable(false);
    area.setToolTipText("Esta ***** no se Edita");
   
    area2=new JTextArea();
    area2.setEditable(false);
    area2.setToolTipText("Esta ***** no se Edita");
   
    b_deco=new JButton("Codificalo!!!");
    }
   
    public void agrega_objetos(){
    JPanel panel=new JPanel( new GridLayout(1,2) );
    panel.add(label);
    panel.add(texto);
   
    JPanel panel2=new JPanel(new GridLayout(1,2) );
   
    JPanel sub_panel= new JPanel(new BorderLayout() );
    sub_panel.setBorder(BorderFactory.createTitledBorder("Textos Sin Codificar... :"));
    sub_panel.add(new JScrollPane(area) ,BorderLayout.CENTER);
       
    JPanel sub_panel2=new JPanel(new BorderLayout() );
    sub_panel2.setBorder(BorderFactory.createTitledBorder("Textos Codificados... :"));
    sub_panel2.add(new JScrollPane(area2),BorderLayout.CENTER);
   
    panel2.add(sub_panel);
    panel2.add(sub_panel2);
   
    add(panel,BorderLayout.NORTH);
    add(panel2,BorderLayout.CENTER);
    add(b_deco,BorderLayout.SOUTH);
    }
   
    public void listar_objetos(){
    b_deco.addActionListener(this);
    texto.addKeyListener(new ValidaNumero() );
    iniciar();
    }
   
    public void propiedades_ventana(){
    setTitle(".::DECODIFICADOS::.");
    setSize(450,300);
    setLocation(300,300);
    setResizable(false);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setVisible(true);
    }
   
   
    public void actionPerformed(ActionEvent e){   
    if(b_deco==e.getSource()){
    if(texto.getText().length()<=5) JOptionPane.showMessageDialog(this,"Por favor ingrese datos validos");
    else codificar();
    }   
    }
     
   
   
    //METODO QUE ME PERMITE CODIFICAR LAS CADENAS
    public void codificar(){
    String semilla=crea_semilla();
    String cadena= ( texto.getText() ).toUpperCase();
    int limite=cadena.length() ;
   
    cadena= semilla.concat(cadena);
    String cadena_codificada=new String(semilla);
   
    for(int i=0;i<limite;i++){
    String sub= cadena_codificada.substring(i,i+5);
    int suma=0,produc=1;
    for(int j=0;j<5;j++){
    suma+= buscar(sub.charAt(j) );
    produc*= buscar(sub.charAt(j) );
    }
    suma+=produc;
    suma%=29;
    int tempo= suma+ buscar(cadena.charAt(i+5));
    int resul=tempo%29;
    cadena_codificada+=String.valueOf(Arreglo[resul]);
    }
   
    area.append( (texto.getText()).toUpperCase() +"\n" );
    area2.append(cadena_codificada +"\n" );
    texto.setText("");
    }
   
   
   
    public void iniciar(){
    for (int i = 0; i<26; i++)
    Arreglo[ i ]=(char)(i+65) ;
   
    Arreglo[26]=(char)(32) ;
    Arreglo[27]=(char)(46) ;
    Arreglo[28]=(char)(44) ;
   
    System.out.println(Arrays.toString(Arreglo) );
    }
   
    public int buscar(char car){
    for(int i=0;i<Arreglo.length;i++ )
    if( Arreglo[ i ]==car  ) return i;
    return (-1);
    }
   
   
    //clase para que la caja de texto solo acepte LETRAS
class ValidaNumero extends KeyAdapter {
  public void keyTyped(KeyEvent e) {
      char c = e.getKeyChar();
      if (!( !Character.isDigit(c) || (c == KeyEvent.VK_BACK_SPACE) ||(c == KeyEvent.VK_DELETE)) ) {
            getToolkit().beep();
            e.consume();
      }
     
      if(c==KeyEvent.VK_ENTER ){
      if(texto.getText().length()<=5) JOptionPane.showMessageDialog(null,"Por favor ingrese datos validos");
    else codificar();      
      }
     
  }
}


/* A ----> 65
    * Z ----> 90
    * ESTE METODO CREA UNA SEMILLA  AL AZAR DE CINCO CARACTERES PARA UN TEXTO QUE SE VA A CODIFICAR*/
    public  String crea_semilla(){
   int temporal=0;
       int k=0;
       String cadena="";
       do{
        temporal=(int)(Math.random()*91);
        if(temporal>=65 && temporal <=90){
        //char tmp= (char)temporal;
        cadena+=String.valueOf( (char)temporal);
        k++;
        }
       }
       while(k!=5);
       return cadena;
}




// EL MAIN   
    public static void main(String[] args) {
       new decodificados();
       
       
       
    }
}



Pd: me falto validar para cuando el usuario ingrese caracteres como : "  "" ! · $ % & / () = ? ¿ etc."

Si crees que ya lo haz terminado, puedes probar con estos codigos, o en todo caso codicarlos con la segunda aplicacion, esa que se llama decodificados

Citar
MATAR A LOS HUMANOS          WCNBIXRAU. DPVFHF.ON,GYY
ENCONTRAR EL TESORO          JRHOAWPCJD UKJSIQKDOFWQP
APAGA EL COMPUTADOR         WJVASMRKFFG.WQMOG,FDORUU
QUITATE LAS MEDIAS             NTJSE THR.WYAOAU OUZEPC
ROMPE LA VENTANA                VGVYWIYB,KERSOZH,EWLY


Saludos

Azulf

Ragnarok

#1
En ningún sitio pone que la aplicación tenga que tener interfaz gráfica, eso la haría mucho menos tediosa.

¿Coincide que  ' ', '.' y ',' son los caracteres siguientes a la 'Z' conforme a la codificación utilizada o cómo es eso? (por ahorrarme el mirarlo)

El código lo miraré con más detalle en otro momento, pero parece que te ha quedado al menos bastante corto considerando que incluye la interfaz gráfica.

PD: por cierto, tenemos instalado un plugin que hace coloreado sintáctico, se usa poniendo: [c­ode=­ja­va][­/co­de]
No olvidéis leer las normas generales, además de las específicas de cada tablón.sgae, ladrones

Azulf

#2
1.- Disculpa si me falto especificar, lo que pasa es que en ese curso estamos llevando swing y por ende se deduce que todos los ejercicios que nos dejan deben estar hechos en interfaz grafica.

2.- Bueno he transcrito lo que decia en la hoja que me dieron, y resulta que esos caracteres de la [A-Z] tienen asignado un numero [0-25] y los caracteres
'espacio ' tiene asignado el 26
'punto' el 27
'coma' el 28

Y esos numeros que cada caracter tiene asignado, son los que se usan para codificar los mensajes(valga la redundancia) segun la codificacion ALemana.Espero me hayas entendido

Saludos

Pd: ia modifique mi codigo

marioly

Muy bueno :D , me parece que esta bien hecho aunque se podria hacer un poco mas limpio, usando como por ejemplo listas y asi no liarte tanto con los index, y asi tmb eliminamos el metodo "buscar" :) , ejemplo:

Código (java) [Seleccionar]

import java.util.ArrayList;


public class Codificador {
private ArrayList table;

Codificador()
{
table = new ArrayList(29);

makeTable();
}

void makeTable()
{
for(int i = 0; i < 29; i++)
table.add((char)(65+i));

    table.add((char)(32));
    table.add((char)(46));
    table.add((char)(44));
}

void Decodificar(String sd)
{
String dec = "";
int uid;

int mul = 1, sum = 0;
for( int i = 5; i < sd.length(); i++)
{
for(int j = 0; j < 5; j++)
{
char c = sd.charAt(j);
int pos = table.indexOf(c);
mul *= pos;
sum += pos;
}

uid = sum + mul;
uid %= 29;

int t=0, k=0;

int resi = table.indexOf(sd.charAt(i));

do
{
t = (29*k) + resi;
k++;
}
while( uid > t );

dec += table.get((t-uid));
}

System.out.println("Cadena cifrada: " + sd + " descifrada: " + dec);
}

static public void main(String[] args)
{
Codificador eni = new Codificador();
eni.Decodificar("WCNBIX");
}
}



saludos