#include <iostream>
#include <cstring>
using namespace std;
class Secret{
    public:
    virtual double simpleEntropy() = 0;
    virtual int total() = 0;
};

//preoptovaruvanje na operator ==

//preoptovaruvanje na operator !=

class DigitSecret : public Secret { //da se dopolni so izraz za nasleduvanje
    private:
    int cifri[101];
    int n;
    
    public:
    DigitSecret() {}
    DigitSecret(int *c, int _n) {
        n = _n;
        for(int i = 0; i < n; i++) {
            cifri[i] = c[i];
        }
    }
    virtual double simpleEntropy() override {
        double unikatni = 0;
        for(int i = 0; i < n; i++) {
            int pom = 0;
            for(int j = 0; j < n; j++) {
                if(i != j) {
                    if(cifri[i] == cifri[j]) {
                        pom++;
                    }
                }
            }
            if(pom == 0) {
                unikatni++;
            }
        }
        return unikatni / (double) n;
    }
    virtual int total() override {
        return n;
    }
    bool operator == (DigitSecret ds) {
        if(ds.n != n) {
            return false;
        }
        for(int i = 0; i < n; i++) {
            if(ds.cifri[i] != cifri[i]) {
                return false;
            }
        }
        return true;
    }
    bool operator != (DigitSecret ds) {
        if(n == ds.n) {
            int tocno = 1;
            for(int i = 0; i < n; i++) {
                if(cifri[i] != ds.cifri[i]) {
                    tocno = 0;
                    break;
                }
            }
            if(tocno == 1) {
                return false;
            }
        }
        return true;
    }
    
    //preoptovaruvanje na operatorot za pechatenje <<
    friend ostream& operator << (ostream &stream, DigitSecret &ds);
    void printDigit() {
        for(int i = 0; i < n; i++) {
            cout << cifri[i];
        }
        cout << " ";
        cout << "Simple entropy: " << simpleEntropy() << " Total: " << total() << endl;
    }
    
};
ostream& operator << (ostream &stream, DigitSecret &ds) {
    for(int i = 0; i < ds.n; i++) {
        stream << ds.cifri[i];
    }
    stream << " ";
    stream << "Simple entropy: " << ds.simpleEntropy() << " Total: " << ds.total() << endl;
    return stream;
}

class CharSecret : public Secret { //da se dopolni so izraz za nasleduvanje
    private:
    char bukvi[101];
    
    public:
    CharSecret() {}
    CharSecret(const char * b) {
        strcpy(bukvi, b);
    }
    
    
    virtual double simpleEntropy() override {
        double unikatni = 0;
        for(int i = 0; i < strlen(bukvi); i++) {
            int pom = 0;
            for(int j = 0; j < strlen(bukvi); j++) {
                if(i != j) {
                    if(bukvi[i] == bukvi[j]) {
                        pom++;
                    }
                }
            }
            if(pom == 0) {
                unikatni++;
            }
        }
        return unikatni / (double) strlen(bukvi);
    }
    virtual int total() override {
        return (int) strlen(bukvi);
    }

    bool operator == (CharSecret cs) {
        if(strlen(cs.bukvi) == strlen(bukvi)) {
            for(int i = 0; i < strlen(bukvi); i++) {
                if(bukvi[i] != cs.bukvi[i]) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
    bool operator != (CharSecret cs) {
        if(strlen(cs.bukvi) == strlen(bukvi)) {
            int isti = 1;
            for(int i = 0; i < strlen(bukvi); i++) {
                if(bukvi[i] != cs.bukvi[i]) {
                    isti = 0;
                    break;
                }
            }
            if(isti == 1) {
                return false;
            }
        }
        return true;
    }
    
    void printChar() {
        for(int i = 0; i < strlen(bukvi); i++) {
            cout << bukvi[i];
        }
        cout << " ";
        cout << "Simple entropy: " << simpleEntropy() << " Total: " << total() << endl;
    }
    friend ostream& operator << (ostream& stream, CharSecret &cs);
    
};
ostream& operator << (ostream& stream, CharSecret &cs) {
    for(int i = 0; i < strlen(cs.bukvi); i++) {
        stream << cs.bukvi[i];
    }
    stream << " ";
    stream << "Simple entropy: " << cs.simpleEntropy() << " Total: " << cs.total() << endl;
    return stream;
}

void process(Secret ** secrets, int n){
    double maks = -2000000000;
    int indeks = -1;
    for(int i = 0; i < n; i++) {
        if(maks < secrets[i]->simpleEntropy()) {
            maks = secrets[i] -> simpleEntropy();
            indeks = i;
        }
    }
    if(dynamic_cast<CharSecret*>(secrets[indeks])) {
        CharSecret cs = *dynamic_cast<CharSecret*>(secrets[indeks]);
        cout << cs << endl;
    }
    else {
        DigitSecret ds = *dynamic_cast<DigitSecret*>(secrets[indeks]);
        cout << ds << endl;
    }
}

void printAll (Secret ** secrets, int n) {
    for(int i = 0; i < n; i++) {
        if(dynamic_cast<CharSecret*>(secrets[i])) {
            CharSecret cs = *dynamic_cast<CharSecret*>(secrets[i]);
            cout << cs << endl;
        }
        else {
            DigitSecret ds = *dynamic_cast<DigitSecret*>(secrets[i]);
            cout << ds << endl;
        }
    }
}

bool operator == (CharSecret cs, DigitSecret ds) {
    return false;
}
bool operator == (DigitSecret cs, CharSecret ds) {
    return false;
}
bool operator != (CharSecret cs, DigitSecret ds) {
    return true;
}
bool operator != (DigitSecret ds, CharSecret cs) {
    return true;
}

int main() {
    int n;
    cin >> n;
    if(n == 0) {
        cout << "Constructors" << endl;
        int numbers [] = {1,2,3,4,5};
        DigitSecret ds(numbers,5);
        CharSecret cs("abcabc");
        cout << "OK" << endl;
    } else if(n == 1) {
          cout << "operator <<" << endl;
        int numbers [] = {1,2,3,4,5};
        DigitSecret ds(numbers,5);
        CharSecret cs("abcabc");
        cout << ds << endl;
        cout << cs << endl;
    }  else if(n == 2) {
          cout << "== and !=" << endl;
        int numbers [] = {1,2,3,4,5};
        DigitSecret ds(numbers,5);
        CharSecret cs("abcabc");
        CharSecret css("abcabc");
        cout << (ds == cs) << endl;
        cout << (cs != ds) << endl;
        cout << (cs == css) << endl;
        cout << (cs != css) << endl;
    } else if(n == 3) {
          cout << "Secret processor" << endl;
        int numbers1 [] = {1,2,3,4,5,6,4,3,2,1,1,2,3,4,5};
        DigitSecret ds1(numbers1,15);
        int numbers2 [] = {1,2,3,4,5,0,0,0,5,5,4,4,3,3,2};
        DigitSecret ds2(numbers2,15);
        int numbers3 [] = {1,0,9,4,3,8,4,0,9,3,1,4,3,2,1,4,4,3,7,2};
        DigitSecret ds3(numbers3,20);
        CharSecret cs1("fhdaieowujkfjdsafjdsakjhueiqoyroq");
        CharSecret cs2("nvzcfsadrqipqhfjdfncxoqw");
        CharSecret cs3("uyoihfdsanmqeqrzvdhfeqyrq");
        Secret** s = new Secret*[6];
        s[0] = &ds1;
        s[1] = &ds2;
        s[2] = &ds3;
        s[3] = &cs1;
        s[4] = &cs2;
        s[5] = &cs3;
        process(s,6);
        delete [] s;
    }
    else if (n==4){
        cout << "Print all secrets" << endl;
        int numbers1 [] = {1,2,3,4,5,5,4,3,2,1,1,2,3,4,5};
        DigitSecret ds1(numbers1,15);
        int numbers2 [] = {1,2,3,4,5,0,0,0,5,5,4,4,3,3,2};
        DigitSecret ds2(numbers2,15);
        int numbers3 [] = {1,0,9,4,3,8,4,0,9,3,1,4,3,2,1,4,4,3,7,2};
        DigitSecret ds3(numbers3,20);
        CharSecret cs1("fhdaieowujkfjdsafjdsakjhueiqoyroq");
        CharSecret cs2("nvzcfsadrqipqhfjdfncxoqw");
        CharSecret cs3("uyoihfdsanmqeqrzvdhfeqyrq");
        Secret** s = new Secret*[6];
        s[0] = &ds1;
        s[1] = &ds2;
        s[2] = &ds3;
        s[3] = &cs1;
        s[4] = &cs2;
        s[5] = &cs3;
        printAll(s,6);
        delete [] s;
    }
    
    return 0;
}
/*
 n
 v
 z
 c
 f
 s
 a
 d
 r
 i
 p
 q
 h
j
 x
 o
 w
 */
