Laborator 3 PC FAIMA - Rezolvare

Problema rezolvarii codului lui Cezar, ghicind ROT corect pe baza celui mai frecvent caracter din text.


package caesarcypher;

/**
 *
 * @author Deroude
 */
public class CaesarCypher {

    private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";
    private static final String CLEAR_TEXT = "hello";
    private static final String CODED_TEXT = "PK XA, KN JKP PK XA: PDWP EO PDA MQAOPEKJ:SDAPDAN 'PEO JKXHAN EJ PDA IEJZ PK OQBBANPDA OHEJCO WJZ WNNKSO KB KQPNWCAKQO BKNPQJA,KN PK PWGA WNIO WCWEJOP W OAW KB PNKQXHAO,WJZ XU KLLKOEJC AJZ PDAI? PK ZEA: PK OHAAL;JK IKNA; WJZ XU W OHAAL PK OWU SA AJZPDA DAWNP-WYDA WJZ PDA PDKQOWJZ JWPQNWH ODKYGOPDWP BHAOD EO DAEN PK, 'PEO W YKJOQIIWPEKJZARKQPHU PK XA SEOD'Z. PK ZEA, PK OHAAL;PK OHAAL: LANYDWJYA PK ZNAWI: WU, PDANA'O PDA NQX;BKN EJ PDWP OHAAL KB ZAWPD SDWP ZNAWIO IWU YKIASDAJ SA DWRA ODQBBHAZ KBB PDEO IKNPWH YKEH,IQOP CERA QO LWQOA: PDANA'O PDA NAOLAYPPDWP IWGAO YWHWIEPU KB OK HKJC HEBA;BKN SDK SKQHZ XAWN PDA SDELO WJZ OYKNJO KB PEIA,PDA KLLNAOOKN'O SNKJC, PDA LNKQZ IWJ'O YKJPQIAHU,PDA LWJCO KB ZAOLEOAZ HKRA, PDA HWS'O ZAHWU,PDA EJOKHAJYA KB KBBEYA WJZ PDA OLQNJOPDWP LWPEAJP IANEP KB PDA QJSKNPDU PWGAO,SDAJ DA DEIOAHB IECDP DEO MQEAPQO IWGASEPD W XWNA XKZGEJ? SDK SKQHZ BWNZAHO XAWN,PK CNQJP WJZ OSAWP QJZAN W SAWNU HEBA,XQP PDWP PDA ZNAWZ KB OKIAPDEJC WBPAN ZAWPD,PDA QJZEOYKRAN'Z YKQJPNU BNKI SDKOA XKQNJJK PNWRAHHAN NAPQNJO, LQVVHAO PDA SEHHWJZ IWGAO QO NWPDAN XAWN PDKOA EHHO SA DWRAPDWJ BHU PK KPDANO PDWP SA GJKS JKP KB?PDQO YKJOYEAJYA ZKAO IWGA YKSWNZO KB QO WHH;WJZ PDQO PDA JWPERA DQA KB NAOKHQPEKJEO OEYGHEAZ K'AN SEPD PDA LWHA YWOP KB PDKQCDP,WJZ AJPANLNEOAO KB CNAWP LEPD WJZ IKIAJPSEPD PDEO NACWNZ PDAEN YQNNAJPO PQNJ WSNU,WJZ HKOA PDA JWIA KB WYPEKJ. - OKBP UKQ JKS!PDA BWEN KLDAHEW! JUILD, EJ PDU KNEOKJOXA WHH IU OEJO NAIAIXAN'Z.";
    private static final int ROT = 1;
    private static final char MAX_FREQ_CHAR = 'e';

    public static void main(String[] args) {
        System.out.println(encode(CLEAR_TEXT.toLowerCase(), ROT));
        int[] F = getFrequencies2(CODED_TEXT.toLowerCase());
        int maxFreq = 0, maxFreqIndex = 0;

        //Afiseaza numarul de aparitie a literelor in text; in acelasi timp afla litera cu cele mai multe aparitii

        for (int i = 0; i < F.length; i++) {
            System.out.printf(" %c - %d; ", ALPHABET.charAt(i), F[i]);
            if (F[i] > maxFreq) {
                maxFreq = F[i];
                maxFreqIndex = i;
            }
        }
        int rot = ALPHABET.indexOf(MAX_FREQ_CHAR) - maxFreqIndex;
        System.out.printf("%nCoded text:%s%nMost probable decode: ROT%d%n%s ", CODED_TEXT, rot, encode(CODED_TEXT, rot));
    }

    /**
     * 
     * @param source Textul care trebuie decodat sau codificat (operatia este simetrica)
     * @param rot Numarul de caractere de salt conform algoritmului de codificare
     * @return Textul codificat
     */
    public static String encode(String source, int rot) {
        if (rot < 0) {
            rot = ALPHABET.length() + rot;
        }

        /*Formez alfabetul de codificare, spargand alfabetul natural in doua bucati,
        la indexul corespunzator numarului "rot" -  de fapt operatiunea de codificare a alfabetului in sine
         * 
         */
        String codeAlphabet = (ALPHABET.substring(rot) + ALPHABET.substring(0, rot)).toUpperCase();
        String encoded = source.toLowerCase();
        for (int i = 0; i < ALPHABET.length(); i++) {

            //Inlocuiesc fiecare caracter din alfabetul natural cu caracterul de pe aceeasi pozitie din alfabetul codificat

            encoded = encoded.replace(ALPHABET.charAt(i), codeAlphabet.charAt(i));
        }
        return encoded;
    }

    /**
     * Metoda de calculare a vectorului cu numar de aparitie a literelor
     * Foloseste calcularea recursiva a numarului de aparitie a fiecarei litere
     * @param source Textul sursa 
     * @return Vector cu numerele de aparitie ale literelor in ordinea din alfabetul natural
     */
    public static int[] getFrequencies(String source) {
        int[] frequencies = new int[ALPHABET.length()];
        for (int i = 0; i < frequencies.length; i++) {
            frequencies[i] = getFrequency(source, ALPHABET.charAt(i));
        }
        return frequencies;
    }

    /**
     * Metoda de calculare a vectorului cu numar de aparitie a literelor
     * Calculeaza in bloc numarul de aparitii
     * Aceasta varianta este mai rapida si mai eficienta - insa in unele situatii 
     * ar putea fi de folos calcularea individuala a frecventei de aparitie a unei litere
     * @param source Textul sursa 
     * @return Vector cu numerele de aparitie ale literelor in ordinea din alfabetul natural
     */
    public static int[] getFrequencies2(String source) {
        int[] frequencies = new int[ALPHABET.length()];
        for (char c : source.toCharArray()) {
            if (ALPHABET.indexOf(c) > -1) {
                frequencies[ALPHABET.indexOf(c)]++;
            }
        }
        return frequencies;
    }

    /**
     * Metoda recursiva de calculare a numarului de aparitii a unei litere in text     
     * @param Textul sursa
     * @param Litera pentru care dorim sa aflam numarul de aparitii
     * @return Numarul de aparitii a literei in text
     */
    public static int getFrequency(String source, char letter) {
        int z = source.indexOf(letter);
        if (z > -1) {
            return 1 + getFrequency(source.substring(z + 1), letter);
        } else {
            return 0;
        }
    }
}


0 comentarii: