#include <stdlib.h>
#include <stdio.h>
#include <ctime>
#include <vector>
#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

template<class T> class T_array {
  T *data;
  int sirka;
  long int alloc;
  string name;
public:

  T_array() {
    data = NULL;
    sirka = 0;
    alloc = 0;
  }
  T_array(string n) {
    name = n;
    data = NULL;
    sirka = 0;
    alloc = 0;
  }
  ~T_array() {
    free(data);
    data = NULL;
  }
  T_array(const T_array& s) {
    free(data);
    name = s.name;
    CreateArray(s.sirka);
    for (int i = 0; i < sirka; i++)
      data[i] = s.data[i];
  }

  T_array operator=(const T_array& s) {
    free(data);
    name = s.name;
    CreateArray(s.sirka);
    for (int i = 0; i < sirka; i++)
      data[i] = s.data[i];
    return s;
  }

  void SetConstValue(T value) {
    for (int i =0; i < sirka; i++)
      data[i] = value;
  }

  void CreateArray(int s) {
    sirka = s;
    alloc = sirka*sizeof(T);
    data = (T*) malloc(alloc);
    SetConstValue(0);
  }

  T &operator[] (int i) const 
  {
    return data[i];
  }

  int size() {
    return sirka;
  }

  void vypis(ostream &os) {
    for (int i = 0; i < sirka; i++) {
      os << setw(1) << (*this)[i] << " ";
      }
    os << endl;
  }

  void vypis_ns(ostream &os) {
    for (int i = 0; i < sirka; i++) {
      os << setw(1) << (*this)[i];
      }
    os << endl;
  }

  void vypis_bin(ostream &os) {
    for (int i = 0; i < sirka; i++) {
      if ((*this)[i] == 0 || (*this)[i] == 1) os << (*this)[i];
      else os << "-";
    }
    os << endl;
  }

};

template<class T> class T_matrix {
  string name;
  T *data;
  T **rows;
  int sirka;
  int vyska;
  long int alloc;

public:

  T_matrix() {
    data = NULL;
    rows = NULL;
    sirka = 0;
    vyska = 0;
    alloc = 0;
  }
  T_matrix(string n) {
    name = n;
    data = NULL;
    rows = NULL;
    sirka = 0;
    vyska = 0;
    alloc = 0;
  }
  ~T_matrix() {
    free(data);
    free(rows);
    data = NULL;
    rows = NULL;
  }
  T_matrix(const T_matrix& s) {
    free(data);
    free(rows);
    name = s.name;
    CreateMatrix(s.vyska, s.sirka);
    for (int i = 0; i < vyska * sirka; i++)
      data[i] = s.data[i];
  }

  void CreateMatrix(int v, int s) {
    if (alloc == 0) {
      vyska = v;
      sirka = s;
      alloc = vyska*sirka*sizeof(T);
      data = (T*) malloc(alloc);
      rows = (T**) malloc(vyska * sizeof(T*));
      for (int i = 0; i < vyska; i++) {
        rows[i] = data + i * sirka;
      }
      SetConstValue(0);
    } else if (vyska == v && sirka == s) {
      SetConstValue(0);
    } else {
      exit(2);
    }
  }

  T* &operator[] (int i) const 
  {
    return rows[i];
  }

  void copy(const T_matrix& s)
   {
     if (alloc == 0) {
       CreateMatrix(s.vyska, s.sirka);
     } else if (alloc != s.alloc || vyska != s.vyska || sirka != s.sirka) {
       exit(2);
     }
     for (int i = 0; i < vyska * sirka; i++)
     {
       data[i] = s.data[i];
     }
  }

  void SetConstValue(T value) {
    for (int i =0; i < vyska * sirka; i++)
      data[i] = value;
  }

  void vypis(ostream &os) {
    for (int i = 0; i < vyska; i++) {
      for (int j = 0; j < sirka; j++) {
        os << setw(1) << (*this)[i][j] << " ";
      }
      os << endl;
    }
  }

  void vypis_ns(ostream &os) {
    for (int i = 0; i < vyska; i++) {
      for (int j = 0; j < sirka; j++) {
        os << setw(1) << (*this)[i][j];
      }
      os << endl;
    }
  }

  void vypis_bin(ostream &os) {
    for (int i = 0; i < vyska; i++) {
      for (int j = 0; j < sirka; j++) {
        if ((*this)[i][j] == 0 || (*this)[i][j] == 1) os << (*this)[i][j];
        else os << "-";
      }
      os << endl;
    }
  }

  void vypisRadek(ostream &os, int r) {
    for (int i = 0; i < sirka; i++) {
      os << setw(1) << (*this)[r][i] << " ";
      }
    os << endl;
  }

  void vypisRadek_ns(ostream &os, int r) {
    for (int i = 0; i < sirka; i++) {
      os << setw(1) << (*this)[r][i];
      }
    os << endl;
  }

  void vypisRadek_bin(ostream &os, int r, bool do_endl = true) {
    for (int i = 0; i < sirka; i++) {
      if ((*this)[r][i] == 0 || (*this)[r][i] == 1) os << (*this)[r][i];
      else os << "-";
    }
    if (do_endl) os << endl;
  }

};
/*
int	main(int argc, char* argv[])
{
return 0;
}*/

/*  // zakodovani
  vector<int> matches;		// prirazeni sloupcu matice C k sloupcum matice TP
  vector<int> rank;		// poradi prirazeni sloupcu matice TP - index = poradi, hodnota = sloupec T
  vector<int> NM;		// priznak negovani sloupcu matice TP

  // fitness a kvalita jedince
  double fitness;		// hodnota fitness (kvalita) jedince
  int columnsT_matched;		// pocet nalezenych sparovani
  int direct_matches;
  int direct_neg_matches;
  double penalty;
  double loss;

  // informativni a pomocne
  vector<int> X;		// prirazeni radku matice C k radkum matice T - vypocitava se spolu s fitnes
  vector<int> columnsT_mapping;	// mapovani sloupcu T na sloupce TP - vypocitava se spolu s fitnes
  bool crossover_flag;		// flag indikujici, ze jedinec byl krizen
  bool rank_mutation_flag;	// flag indikujici mutaci proti degeneraci pole rank
  bool matches_mutation_flag;	// flag indikujici mutaci proti degeneraci pole matches

  vector<int> columnsT_matches; // prirazeni sloupcu matice C k sloupcum matice T
  vector<int> columnsT_NM;	// pole priznaku negovani sloupcu matice T

  vector<double> columnsTP_loss;*/

