diff --git a/exercises/ex05_skeleton/qsimulator_skeleton.cpp b/exercises/ex05_skeleton/qsimulator_skeleton.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5161440a98731a01aa31c31e1bb534de267911a6
--- /dev/null
+++ b/exercises/ex05_skeleton/qsimulator_skeleton.cpp
@@ -0,0 +1,145 @@
+#include <vector>
+#include <iostream>
+#include <complex>
+#include <string>
+#include <random>
+
+
+class QSimulator
+{
+public:
+    typedef unsigned state_type;
+    typedef double scalar_type;
+    typedef std::complex<scalar_type> complex_type;
+    typedef std::vector<complex_type> wf_type;
+    typedef std::pair<scalar_type,scalar_type> dmatr_type;
+    QSimulator(unsigned n, bool v);
+    
+    void H(const wf_type& iwf, wf_type& owf, unsigned qubitId) const;
+    void CNOT(const wf_type& iwf, wf_type& owf, unsigned cqid, unsigned qid) const;
+    void Z(wf_type& wf, unsigned qid) const;
+    void X(const wf_type& iwf, wf_type& owf, unsigned qid) const;
+    void Uf(const wf_type& iwf, wf_type& owf, state_type(*f)(state_type st, unsigned hqid)) const;
+    
+    bool measureQubit(wf_type& wf, unsigned qid) const; // physical measurement
+    dmatr_type tomography(const wf_type& iwf, unsigned qid) const; // state of the qubit qid
+    void printWF(wf_type wf) const;
+    state_type maxState() const { return maxState_; }
+
+private:
+    const unsigned n_;
+    const state_type maxState_;
+    const bool verbose_;
+    
+    mutable std::mt19937 rndEngine_;
+    mutable std::uniform_real_distribution<scalar_type> probDist_;
+    mutable std::uniform_int_distribution<unsigned> qidDist_;
+};
+
+QSimulator::QSimulator(unsigned n, bool v)
+:  verbose_(v), n_(n), maxState_( (1<<n)-1 ), probDist_(0.0,1.0), qidDist_(1,n-1), rndEngine_(time(NULL))
+{
+}
+
+
+void QSimulator::CNOT(const wf_type& iwf, wf_type& owf, unsigned cqid, unsigned qid) const{
+    owf = iwf;
+    for(state_type st=0; st<=maxState(); st++){
+        if(std::abs(iwf[st])!=0.0){
+            if (st & (1<<cqid)){ // control qubit set
+                state_type flippedSt = st ^ (1<<qid); // flip the other qubit
+                owf[flippedSt] = iwf[st];
+                owf[st] = iwf[flippedSt];
+            }
+        }
+    }
+    if(verbose_){
+        std::cout << "wavefunction after the CNOT gate:" << std::endl;
+        printWF(owf);
+    }
+}
+
+
+bool QSimulator::measureQubit(wf_type& wf, unsigned qid) const{
+    dmatr_type dmatr = // calculate probabilities to measure 0 or 1
+    
+    scalar_type randNum = probDist_(rndEngine_);
+    bool measured1 = (randNum<dmatr.second)? 1: 0;
+    if(verbose_){
+        std::cout << "probability to measure |0>: " << dmatr.first << ", for |1>: " << dmatr.second << std::endl;
+        std::cout << "randNum = " << randNum << ",measured1 = " << measured1 << std::endl;
+    }
+    
+// ====== drop projected out components, renormalize the rest
+//..............
+// ====== drop projected out components, renormalize the rest
+    
+    if(verbose_){
+        std::cout << "wavefunction after the measurement:" << std::endl;
+        printWF(wf);
+    }
+    
+    if(measured1){
+        return true;
+    }else{
+        return false;
+    }
+}
+
+void QSimulator::printWF(wf_type wf) const{
+    for(state_type st=0; st<=maxState(); st++){
+        std::cout << wf[st] << "\t";
+    }
+    std::cout << std::endl;
+}
+
+std::string usage(const std::string& prog)
+{
+    return "usage: " + prog + " nQubitsForDeutschJosza";
+}
+int main(int argc, const char** argv)
+{
+    if( argc != 2 ){
+        std::cerr << usage(argv[0]) << std::endl;
+        return -1;
+    }
+    unsigned DJN = stoi(argv[1],nullptr,10);
+    if(DJN<2){
+        std::cerr << "At least 2 qubits will be needed for the Deutsch-Josza algorithm" << std::endl;
+        return -1;
+
+    }
+// ============== Teleportation begin
+    // qubit index convention: unknown id=0, Alice Bell id=1, Bob Bell id=2
+    bool verbose = false;
+    int n = 3;
+    std::cout << "Teleportation:" << std::endl;
+    QSimulator teleport(n, verbose);
+    QSimulator::wf_type iwf(teleport.maxState()+1,0);
+    QSimulator::wf_type owf(teleport.maxState()+1,0);
+    
+    iwf[1] = 1/3.0;
+    iwf[0] = 2*std::sqrt(2)/3; // 1/3 |001> + 2sqrt(2)/3 |000> "unknown" state to teleport
+    
+    std::cout << "initial wavefunction:" << std::endl;
+    teleport.printWF(iwf);
+    
+    QSimulator::dmatr_type dmatr = teleport.tomography(iwf, 0);
+    std::cout << "State of the Alice's |psi> qubit (id=0) is " << std::sqrt(dmatr.first) << "|0> + " << std::sqrt(dmatr.second) << "|1>" << std::endl;
+    
+// ====== generate Bell00 state
+    teleport.H(iwf,owf,1);
+    iwf.swap(owf);
+    teleport.CNOT(iwf,owf,1,2);
+    iwf.swap(owf);
+// ====== generate Bell00 state
+
+// ...........
+    
+// ============== Teleportation end
+    
+// ============== DJ begin
+    //.........
+// ============== DJ end
+
+}
diff --git a/exercises/exercise05.pdf b/exercises/exercise05.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..544f8b2952a685fa73805c162f0bb48d001b25ae
Binary files /dev/null and b/exercises/exercise05.pdf differ