diff --git a/katas/content/qft/binary_fraction_classical/Placeholder.qs b/katas/content/qft/binary_fraction_classical/Placeholder.qs
new file mode 100644
index 0000000000..e0fb6b14ad
--- /dev/null
+++ b/katas/content/qft/binary_fraction_classical/Placeholder.qs
@@ -0,0 +1,6 @@
+namespace Kata {
+ operation BinaryFractionClassical(q : Qubit, j : Bool[]) : Unit is Adj + Ctl {
+ // Implement your solution here...
+
+ }
+}
diff --git a/katas/content/qft/binary_fraction_classical/SolutionA.qs b/katas/content/qft/binary_fraction_classical/SolutionA.qs
new file mode 100644
index 0000000000..37881dabb1
--- /dev/null
+++ b/katas/content/qft/binary_fraction_classical/SolutionA.qs
@@ -0,0 +1,9 @@
+namespace Kata {
+ operation BinaryFractionClassical(q : Qubit, j : Bool[]) : Unit is Adj + Ctl {
+ for ind in 0 .. Length(j) - 1 {
+ if j[ind] {
+ R1Frac(2, ind + 1, q);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/katas/content/qft/binary_fraction_classical/SolutionB.qs b/katas/content/qft/binary_fraction_classical/SolutionB.qs
new file mode 100644
index 0000000000..91c055c5a0
--- /dev/null
+++ b/katas/content/qft/binary_fraction_classical/SolutionB.qs
@@ -0,0 +1,11 @@
+namespace Kata {
+ open Microsoft.Quantum.Arrays;
+ open Microsoft.Quantum.Convert;
+ open Microsoft.Quantum.Math;
+
+ operation BinaryFractionClassical(q : Qubit, j : Bool[]) : Unit is Adj + Ctl {
+ let n = Length(j);
+ let jIntBE = BoolArrayAsInt(Reversed(j));
+ R1(2.0 * PI() * IntAsDouble(jIntBE) / IntAsDouble(1 <<< n), q);
+ }
+}
\ No newline at end of file
diff --git a/katas/content/qft/binary_fraction_classical/Verification.qs b/katas/content/qft/binary_fraction_classical/Verification.qs
new file mode 100644
index 0000000000..3b2cc2b970
--- /dev/null
+++ b/katas/content/qft/binary_fraction_classical/Verification.qs
@@ -0,0 +1,32 @@
+namespace Kata.Verification {
+ open Microsoft.Quantum.Arrays;
+ open Microsoft.Quantum.Convert;
+ open Microsoft.Quantum.Katas;
+ open Microsoft.Quantum.Math;
+
+ operation BinaryFractionClassical_Alternative (q : Qubit, j : Bool[]) : Unit is Adj+Ctl {
+ // Convert the number to an integer and apply a single R1 rotation
+ R1(2.0 * PI() * IntAsDouble(BoolArrayAsInt(Reversed(j))) / IntAsDouble(1 <<< Length(j)), q);
+ }
+
+ @EntryPoint()
+ operation CheckSolution() : Bool {
+ for n in 1 .. 5 {
+ for exp in 0 .. (1 <<< n) - 1 {
+ let j = Reversed(IntAsBoolArray(exp, n));
+ let solution = qs => Kata.BinaryFractionClassical(qs[0], j);
+ let reference = qs => BinaryFractionClassical_Alternative(qs[0], j);
+ if not CheckOperationsAreEqualStrict(1, solution, reference) {
+ Message($"Incorrect for j = {j}.");
+ Message("Hint: examine the effect your solution has on the state 0.6|0〉 + 0.8|1〉 and compare it with the effect it " +
+ "is expected to have.");
+ ShowQuantumStateComparison(1, qs => Ry(ArcTan2(0.8, 0.6) * 2.0, qs[0]), solution, reference);
+ return false;
+ }
+ }
+ }
+
+ Message("Correct!");
+ true
+ }
+}
diff --git a/katas/content/qft/binary_fraction_classical/index.md b/katas/content/qft/binary_fraction_classical/index.md
new file mode 100644
index 0000000000..a3d57fddfd
--- /dev/null
+++ b/katas/content/qft/binary_fraction_classical/index.md
@@ -0,0 +1,9 @@
+**Inputs**:
+
+1. A qubit in state $\ket{\psi} = \alpha \ket{0} + \beta \ket{1}$.
+2. An array of $n$ bits $[j_1, j_2, ..., j_n]$, stored as `Bool[]`.
+
+**Goal**:
+Change the state of the qubit to $\alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0.j_1 j_2 ... j_n} \ket{1}$, where $0.j_1 j_2 ... j_n$ is a binary fraction in big endian notation, similar to decimal fractions:
+
+$$0.j_1 j_2 ... j_n = j_1 \cdot \frac{1}{2^1} + j_2 \cdot \frac{1}{2^2} + ... + j_n \cdot \frac{1}{2^n}$$
diff --git a/katas/content/qft/binary_fraction_classical/solution.md b/katas/content/qft/binary_fraction_classical/solution.md
new file mode 100644
index 0000000000..6d4ffd83d0
--- /dev/null
+++ b/katas/content/qft/binary_fraction_classical/solution.md
@@ -0,0 +1,56 @@
+Since you can express the exponent of a sum as a product of exponents ($e^{a+b} = e^a \cdot e^b$), you can implement the required transformation as a sequence of rotation gates from the previous task with increasing $k$.
+
+Each of the individual rotations will use the bit $j_k$ to decide whether to apply the rotation (you only want to apply the rotation if $j_k$ is true), and the index of that bit $k$ to define the rotation angle.
+The gate applied for each $k$ will be:
+
+$$U_k = \begin{cases}
+I, j_k=0 \\
+\textrm{R1Frac}(2, k), j_k=1
+\end{cases}$$
+
+Recall that
+
+$$ \textrm{R1Frac}(2, k)( \alpha \ket{0} + \beta \ket{1}) = \alpha \ket{0} + \beta \cdot e^{2\pi i/2^{k}} \ket{1} = \alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0. \underset{k-1}{\underbrace{0\dots0}} 1} \ket{1}$$
+
+This means that the overall effect of the gate $U_k$ for each $k$ is:
+
+$$U_k (\alpha \ket{0} + \beta \ket{1}) = \alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0. \underset{k-1}{\underbrace{0\dots0}} j_k} \ket{1}$$
+
+As you iterate over $k$, the resulting state will get closer and closer to the required one:
+
+
+
+ $k$ |
+ State after step $k$ |
+
+
+ $1$ |
+ $$\alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0.j_1} \ket{1}$$ |
+
+
+ $2$ |
+ $$\alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0.j_1j_2} \ket{1}$$ |
+
+
+ ... |
+ ... |
+
+
+ $n$ |
+ $$\alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0.j_1j_2 \dots j_n}\ket{1}$$ |
+
+
+
+@[solution]({
+"id": "qft__binary_fraction_classical_solution_a",
+"codePath": "./SolutionA.qs"
+})
+
+Alternatively, you can do this in a single rotation using the $R1$ gate if you convert the array $j$ into a rotation angle. You'll need the angle $2\pi \cdot 0.j_1j_2 \dots j_n$, and this fraction can be calculated by converting the bit string into an integer $j$ (using big endian notation) and dividing it by $2^n$.
+
+This solution is better when considered on its own, since it involves doing only a single rotation rather than a series of them. However, it will not be as helpful as the first one once you get to the next task!
+
+@[solution]({
+"id": "qft__binary_fraction_classical_solution_b",
+"codePath": "./SolutionB.qs"
+})
diff --git a/katas/content/qft/binary_fraction_inplace/Placeholder.qs b/katas/content/qft/binary_fraction_inplace/Placeholder.qs
new file mode 100644
index 0000000000..b4ab86ea12
--- /dev/null
+++ b/katas/content/qft/binary_fraction_inplace/Placeholder.qs
@@ -0,0 +1,6 @@
+namespace Kata {
+ operation BinaryFractionQuantumInPlace(j : Qubit[]) : Unit is Adj + Ctl {
+ // Implement your solution here...
+
+ }
+}
diff --git a/katas/content/qft/binary_fraction_inplace/Solution.qs b/katas/content/qft/binary_fraction_inplace/Solution.qs
new file mode 100644
index 0000000000..9102ce5b1e
--- /dev/null
+++ b/katas/content/qft/binary_fraction_inplace/Solution.qs
@@ -0,0 +1,8 @@
+namespace Kata {
+ operation BinaryFractionQuantumInPlace(j : Qubit[]) : Unit is Adj + Ctl {
+ H(j[0]);
+ for ind in 1 .. Length(j) - 1 {
+ Controlled R1Frac([j[ind]], (2, ind + 1, j[0]));
+ }
+ }
+}
\ No newline at end of file
diff --git a/katas/content/qft/binary_fraction_inplace/Verification.qs b/katas/content/qft/binary_fraction_inplace/Verification.qs
new file mode 100644
index 0000000000..e20e9bb0c4
--- /dev/null
+++ b/katas/content/qft/binary_fraction_inplace/Verification.qs
@@ -0,0 +1,26 @@
+namespace Kata.Verification {
+ open Microsoft.Quantum.Arrays;
+ open Microsoft.Quantum.Convert;
+ open Microsoft.Quantum.Katas;
+ open Microsoft.Quantum.Math;
+
+ operation BinaryFractionQuantumInPlace_Reference(j : Qubit[]) : Unit is Adj + Ctl {
+ H(j[0]);
+ for ind in 1 .. Length(j) - 1 {
+ Controlled R1Frac([j[ind]], (2, ind + 1, j[0]));
+ }
+ }
+
+ @EntryPoint()
+ operation CheckSolution() : Bool {
+ for n in 1 .. 5 {
+ if not CheckOperationsAreEqualStrict(n, Kata.BinaryFractionQuantumInPlace, BinaryFractionQuantumInPlace_Reference) {
+ Message($"Incorrect for n = {n}.");
+ return false;
+ }
+ }
+
+ Message("Correct!");
+ true
+ }
+}
diff --git a/katas/content/qft/binary_fraction_inplace/index.md b/katas/content/qft/binary_fraction_inplace/index.md
new file mode 100644
index 0000000000..71e15cf770
--- /dev/null
+++ b/katas/content/qft/binary_fraction_inplace/index.md
@@ -0,0 +1,11 @@
+**Input**:
+A register of $n$ qubits in state $\ket{j_1 j_2 ... j_n}$.
+
+**Goal**:
+Change the state of the register from $\ket{j_1} \otimes \ket{j_2 ... j_n}$ to $\frac1{\sqrt2}(\ket{0} + e^{2\pi i \cdot 0.j_1 j_2 ... j_n} \ket{1}) \otimes \ket{j_2 ... j_n}$.
+
+
+ Need a hint?
+
+This task is very similar to the previous task, but the digit $j_1$ has to be encoded in-place. You can do this using the first task of the kata, "Single-Qubit QFT".
+
diff --git a/katas/content/qft/binary_fraction_inplace/solution.md b/katas/content/qft/binary_fraction_inplace/solution.md
new file mode 100644
index 0000000000..614bcc5780
--- /dev/null
+++ b/katas/content/qft/binary_fraction_inplace/solution.md
@@ -0,0 +1,14 @@
+First, let's recall the first task of the kata: a Hadamard gate applied to a single qubit, $H\ket{j_1}$, will give either
+$\frac1{\sqrt2}(\ket{0} + \ket{1})$ or $\frac{1}{\sqrt{2}}(\ket{0} - \ket{1})$ depending on the state of $\ket{j_1}$. This operation can also be written as
+$$H\ket{j_1} = \frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot \frac{j_1}{2}}\ket{1} \big)= \frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_1}\ket{1} \big)$$
+
+So, if the starting register state is $\ket{j_1 j_2 ... j_n}$, applying a Hadamard gate to the first qubit will result in:
+
+$$\big(H_1\otimes I_{n-1} \big) \big(\ket{j_1} \otimes \ket{j_2 ... j_n} \big)= \frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_1}\ket{1} \big) \otimes \ket{j_2 ... j_n} $$
+
+After this, we can repeat the loop we used in the previous task for qubits $\ket{j_2 ... j_n}$ with the first qubit as the target to adjust the remaining phase terms via the controlled $\textrm{R1Frac}$ gate.
+
+@[solution]({
+"id": "qft__binary_fraction_inplace_solution",
+"codePath": "./Solution.qs"
+})
diff --git a/katas/content/qft/binary_fraction_quantum/Placeholder.qs b/katas/content/qft/binary_fraction_quantum/Placeholder.qs
new file mode 100644
index 0000000000..ff92f1e196
--- /dev/null
+++ b/katas/content/qft/binary_fraction_quantum/Placeholder.qs
@@ -0,0 +1,6 @@
+namespace Kata {
+ operation BinaryFractionQuantum(q : Qubit, j : Qubit[]) : Unit is Adj + Ctl {
+ // Implement your solution here...
+
+ }
+}
diff --git a/katas/content/qft/binary_fraction_quantum/Solution.qs b/katas/content/qft/binary_fraction_quantum/Solution.qs
new file mode 100644
index 0000000000..8b3c5d449c
--- /dev/null
+++ b/katas/content/qft/binary_fraction_quantum/Solution.qs
@@ -0,0 +1,7 @@
+namespace Kata {
+ operation BinaryFractionQuantum(q : Qubit, j : Qubit[]) : Unit is Adj + Ctl {
+ for ind in 0 .. Length(j) - 1 {
+ Controlled R1Frac([j[ind]], (2, ind + 1, q));
+ }
+ }
+}
\ No newline at end of file
diff --git a/katas/content/qft/binary_fraction_quantum/Verification.qs b/katas/content/qft/binary_fraction_quantum/Verification.qs
new file mode 100644
index 0000000000..586319774c
--- /dev/null
+++ b/katas/content/qft/binary_fraction_quantum/Verification.qs
@@ -0,0 +1,27 @@
+namespace Kata.Verification {
+ open Microsoft.Quantum.Arrays;
+ open Microsoft.Quantum.Convert;
+ open Microsoft.Quantum.Katas;
+ open Microsoft.Quantum.Math;
+
+ operation BinaryFractionQuantum_Reference(q : Qubit, j : Qubit[]) : Unit is Adj + Ctl {
+ for ind in 0 .. Length(j) - 1 {
+ Controlled R1Frac([j[ind]], (2, ind + 1, q));
+ }
+ }
+
+ @EntryPoint()
+ operation CheckSolution() : Bool {
+ for n in 1 .. 5 {
+ let solution = qs => Kata.BinaryFractionQuantum(qs[0], qs[1 ...]);
+ let reference = qs => BinaryFractionQuantum_Reference(qs[0], qs[1 ...]);
+ if not CheckOperationsAreEqualStrict(n + 1, solution, reference) {
+ Message($"Incorrect for n = {n}.");
+ return false;
+ }
+ }
+
+ Message("Correct!");
+ true
+ }
+}
diff --git a/katas/content/qft/binary_fraction_quantum/index.md b/katas/content/qft/binary_fraction_quantum/index.md
new file mode 100644
index 0000000000..6e11d50cd2
--- /dev/null
+++ b/katas/content/qft/binary_fraction_quantum/index.md
@@ -0,0 +1,10 @@
+**Inputs**:
+
+1. A qubit in state $\ket{\psi} = \alpha \ket{0} + \beta \ket{1}$.
+2. An array of $n$ qubits $j$ in state $\ket{j_1 j_2 ... j_n}$.
+
+**Goal**:
+Change the state of the input qubits from $(\alpha \ket{0} + \beta \ket{1}) \otimes \ket{j_1 j_2 ... j_n}$ to $(\alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0.j_1 j_2 ... j_n} \ket{1}) \otimes \ket{j_1 j_2 ... j_n}$, where $0.j_1 j_2 ... j_n$ is a binary fraction corresponding to the basis state $j_1 j_2 ... j_n$ of the qubit array $j$.
+
+> The qubit array can be in superposition as well;
+the behavior of the transformation in this case is defined by its behavior on the basis states and the linearity of unitary transformations.
diff --git a/katas/content/qft/binary_fraction_quantum/solution.md b/katas/content/qft/binary_fraction_quantum/solution.md
new file mode 100644
index 0000000000..5392665463
--- /dev/null
+++ b/katas/content/qft/binary_fraction_quantum/solution.md
@@ -0,0 +1,8 @@
+From the goal of the exercise, you can see that the register $j$ has to remain unchanged, while the first input qubit should acquire a phase that depends on the value of the qubits in the register $j$.
+
+Since $j$ is a quantum register and can be in a superposition of basis states, you cannot just measure the register and then apply the operation from the previous task using measurement results as the second argument. Instead, you have to convert the solution to the previous task from using $\textrm{R1Frac}$ gates with classical conditions to using them as controlled operations, with the qubits of the register $j$ as quantum conditions. You can do this using the `Controlled` functor.
+
+@[solution]({
+"id": "qft__binary_fraction_quantum_solution",
+"codePath": "./Solution.qs"
+})
diff --git a/katas/content/qft/index.md b/katas/content/qft/index.md
new file mode 100644
index 0000000000..219b758357
--- /dev/null
+++ b/katas/content/qft/index.md
@@ -0,0 +1,149 @@
+# Quantum Fourier Transform
+
+@[section]({
+ "id": "qft__overview",
+ "title": "Overview"
+})
+
+This kata introduces you to quantum Fourier transform (QFT) - an important tool in quantum phase estimation, integer factoring, and many other quantum computing algorithms.
+
+**This kata covers the following topics:**
+
+- The definition of quantum Fourier transform
+- The iterative implementation of QFT
+- Simple state preparation and state analysis tasks that can be solved using QFT
+
+**What you should know to start working on this kata:**
+
+- Basic knowledge of quantum states and quantum gates.
+
+If you need a refresher on these topics, you can check out the previous katas.
+
+
+@[section]({
+ "id": "qft__implement",
+ "title": "Implementing Quantum Fourier Transform"
+})
+
+*Discrete Fourier transform* (DFT) is a transform that acts on vectors of complex numbers of fixed length $N$. The effect of DFT on a vector $x_0, x_1, ..., x_{N-1}$ is another vector $y_0, y_1, ..., y_{N-1}$ defined as follows:
+
+$$y_k = \frac1{\sqrt{N}}\sum_{j=0}^{N-1} x_j e^{2\pi i jk/N}$$
+
+Quantum Fourier transform is the quantum version of the DFT. It acts on $n$-qubit quantum states and is defined via its effects on basis states as follows:
+
+$$\ket{j} \rightarrow \frac1{\sqrt{2^n}}\sum_{k=0}^{2^n-1} e^{2\pi i jk/2^n} \ket{k}$$
+
+The result of applying QFT to an arbitrary superposition state with amplitudes $x_j$ can thus be expressed as a superposition state with amplitudes $y_k$ that are exactly the DFT of the amplitudes $x_j$ for $N = 2^n$:
+
+$$\sum_{j=0}^{N-1} x_j\ket{j} \rightarrow \sum_{k=0}^{N-1} y_k\ket{k}$$
+
+In the first part of this kata, you will learn to implement quantum Fourier transform using the iterative algorithm.
+
+All the numbers used in this kata use big endian encoding: the most significant bit of the number is stored in the first (leftmost) bit/qubit.
+
+This means that you represent an integer as a binary bit string in the following format:
+
+$$x = x_1x_2...x_n = x_1 2^{n-1} + x_2 2^{n-2}+...x_n 2^{0}$$
+
+You can also use this notation for binary fractions:
+
+$$0.x_1x_2...x_n = \frac{x_1}{2^1}+ \frac{x_2}{2^2}+...\frac{x_n}{2^n}$$
+
+@[exercise]({
+ "id": "qft__single_qubit",
+ "title": "Single-Qubit QFT",
+ "path": "./single_qubit/"
+})
+
+@[exercise]({
+ "id": "qft__rotation_gate",
+ "title": "Rotation Gate",
+ "path": "./rotation_gate/"
+})
+
+@[exercise]({
+ "id": "qft__binary_fraction_classical",
+ "title": "Binary Fraction Exponent (Classical Input)",
+ "path": "./binary_fraction_classical/"
+})
+
+@[exercise]({
+ "id": "qft__binary_fraction_quantum",
+ "title": "Binary Fraction Exponent (Quantum Input)",
+ "path": "./binary_fraction_quantum/"
+})
+
+@[exercise]({
+ "id": "qft__binary_fraction_inplace",
+ "title": "Binary Fraction Exponent In-Place (Quantum Input)",
+ "path": "./binary_fraction_inplace/"
+})
+
+@[exercise]({
+ "id": "qft__qft",
+ "title": "Quantum Fourier Transform",
+ "path": "./qft/"
+})
+
+
+@[section]({
+ "id": "qft__equivalence",
+ "title": "The Equivalence of Two QFT Notations"
+})
+
+How to show that the transformation defined in the last exercise is the same as the original definition of QFT?
+In other words, how to prove the equality below?
+
+$$\frac1{\sqrt{2^n}} \sum_{k=0}^{2^n-1} e^{2\pi i \cdot \frac{jk}{2^{n}}} \ket{k} = $$
+$$\begin{align*}
+= &\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_n} \ket{1} \big) \otimes \\
+\otimes &\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_{n-1} j_n} \ket{1} \big) \otimes ... \otimes \\
+\otimes &\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_1 j_2 ... j_{n-1} j_n} \ket{1} \big)
+\end{align*}$$
+
+The tensor product state is defined in terms of the digits $j_1, j_2, ..., j_n$. Let's spell the exponents used in each term of the tensor product in terms of the integer $j$ instead:
+$$e^{2\pi i \cdot 0.j_1 j_2 ... j_{n-1} j_n} = e^{2\pi i \cdot \frac{j}{2^n}}$$
+$$e^{2\pi i \cdot 0.j_2 ... j_{n-1} j_n} = e^{2\pi i \cdot j_1} e^{2\pi i \cdot 0.j_2 ... j_{n-1} j_n} = e^{2\pi i \cdot j_1.j_2 ... j_{n-1} j_n} = e^{2\pi i \cdot \frac{j \cdot 2}{2^n}}$$
+(Remember that since $j_1$ can only be $0$ or $1$, $e^{2\pi i \cdot j_1}$ is either $e^0$ or $e^{2\pi i}$, which are both $1$. Any exponents of integer multiples of $e^{2\pi i}$ are $1$ and thus can be ignored.)
+
+And so on, until the last term:
+$$e^{2\pi i \cdot 0.j_n} = e^{2\pi i \cdot \frac{j \cdot 2^{n-1}}{2^n}}$$
+
+Now, the complete state looks as follows:
+$$\begin{align*}
+&\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot \frac{j \cdot 2^{n-1}}{2^n}} \ket{1} \big) \otimes \\
+\otimes &\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot \frac{j \cdot 2^{n-2}}{2^n}} \ket{1} \big) \otimes ... \otimes \\
+\otimes &\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot \frac{j}{2^n}} \ket{1} \big)
+\end{align*}$$
+
+What happens if you open the brackets and compare the results to the definition of the QFT?
+Let's do this exercise for $n = 2$.
+
+$$\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot \frac{j \cdot 2}{4}} \ket{1} \big) \otimes \frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot \frac{j}{4}} \ket{1} \big) = $$
+$$= \frac14 \big( \ket{00} + e^{2\pi i \cdot \frac{j}{4}}\ket{01} + e^{2\pi i \cdot \frac{j \cdot 2}{4}}\ket{10} + e^{2\pi i \cdot \frac{j \cdot 2 + j}{4}} \ket{11} \big)$$
+
+Remember that this kata uses big endian to map bit strings to integers, so this can be rewritten as follows:
+$$\frac14 \big( \ket{0} + e^{2\pi i \cdot \frac{j}{4}}\ket{1} + e^{2\pi i \cdot \frac{j \cdot 2}{4}}\ket{2} + e^{2\pi i \cdot \frac{j \cdot 3}{4}} \ket{3} \big)$$
+And that's exactly the original definition of QFT:
+$$\frac1{\sqrt{4}}\sum_{k=0}^{3} e^{2\pi i jk/4} \ket{k}$$
+
+The same can be done for an arbitrary $n$.
+
+
+@[section]({
+ "id": "qft__use",
+ "title": "Using Quantum Fourier Transform"
+})
+
+This section offers you tasks on state preparation and state analysis that can be solved using QFT or inverse QFT.
+You can solve them without QFT, but it is useful to try and come up with a QFT-based solution as an exercise.
+
+TODO: finish part 2
+
+
+@[section]({
+ "id": "qft__conclusion",
+ "title": "Conclusion"
+})
+
+Congratulations! In this kata you learned to implement the quantum Fourier transform and to use it in simple tasks. In the next kata, you will learn to use the QFT to solve a more complicated problem - the phase estimation task.
diff --git a/katas/content/qft/qft/Placeholder.qs b/katas/content/qft/qft/Placeholder.qs
new file mode 100644
index 0000000000..d2db8f75dc
--- /dev/null
+++ b/katas/content/qft/qft/Placeholder.qs
@@ -0,0 +1,14 @@
+namespace Kata {
+ operation QuantumFourierTransform(j : Qubit[]) : Unit is Adj + Ctl {
+ // Implement your solution here...
+
+ }
+
+ // You might find this helper operation from an earlier task useful.
+ operation BinaryFractionQuantumInPlace(j : Qubit[]) : Unit is Adj + Ctl {
+ H(j[0]);
+ for ind in 1 .. Length(j) - 1 {
+ Controlled R1Frac([j[ind]], (2, ind + 1, j[0]));
+ }
+ }
+}
diff --git a/katas/content/qft/qft/Solution.qs b/katas/content/qft/qft/Solution.qs
new file mode 100644
index 0000000000..0375cf45e6
--- /dev/null
+++ b/katas/content/qft/qft/Solution.qs
@@ -0,0 +1,18 @@
+namespace Kata {
+ operation QuantumFourierTransform(j : Qubit[]) : Unit is Adj + Ctl {
+ let n = Length(j);
+ for ind in 0 .. n - 1 {
+ BinaryFractionQuantumInPlace(j[ind ...]);
+ }
+ for ind in 0 .. n / 2 - 1 {
+ SWAP(j[ind], j[n - 1 - ind]);
+ }
+ }
+
+ operation BinaryFractionQuantumInPlace(j : Qubit[]) : Unit is Adj + Ctl {
+ H(j[0]);
+ for ind in 1 .. Length(j) - 1 {
+ Controlled R1Frac([j[ind]], (2, ind + 1, j[0]));
+ }
+ }
+}
\ No newline at end of file
diff --git a/katas/content/qft/qft/Verification.qs b/katas/content/qft/qft/Verification.qs
new file mode 100644
index 0000000000..10541c3e97
--- /dev/null
+++ b/katas/content/qft/qft/Verification.qs
@@ -0,0 +1,22 @@
+namespace Kata.Verification {
+ open Microsoft.Quantum.Arrays;
+ open Microsoft.Quantum.Katas;
+
+ operation LibraryQFT(qs : Qubit[]) : Unit is Adj + Ctl {
+ ApplyQFT(Reversed(qs));
+ SwapReverseRegister(qs);
+ }
+
+ @EntryPoint()
+ operation CheckSolution() : Bool {
+ for n in 1 .. 5 {
+ if not CheckOperationsAreEqualStrict(n, Kata.QuantumFourierTransform, LibraryQFT) {
+ Message($"Incorrect for n = {n}.");
+ return false;
+ }
+ }
+
+ Message("Correct!");
+ true
+ }
+}
diff --git a/katas/content/qft/qft/index.md b/katas/content/qft/qft/index.md
new file mode 100644
index 0000000000..2a7436e7a3
--- /dev/null
+++ b/katas/content/qft/qft/index.md
@@ -0,0 +1,22 @@
+**Input**:
+A register of $n$ qubits in state $\ket{j_1 j_2 ... j_n}$.
+
+**Goal**:
+Apply quantum Fourier transform to the input register, that is, transform it to a state
+
+$$\begin{align*}
+&\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_n} \ket{1} \big) \otimes \\
+\otimes &\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_{n-1} j_n} \ket{1} \big) \otimes ... \otimes \\
+\otimes &\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_1 j_2 ... j_{n-1} j_n} \ket{1} \big)
+\end{align*}$$
+
+The register of qubits can be in superposition as well;
+the behavior in this case is defined by behavior on the basis states and the linearity of unitary transformations.
+
+> Notice that this implementation will let you use inverse QFT without writing any extra code, just by using the adjoint of this operation!
+
+
+ Need a hint?
+
+Consider first preparing a state with the states of individual qubits reversed and then transforming it to the goal state.
+
\ No newline at end of file
diff --git a/katas/content/qft/qft/solution.md b/katas/content/qft/qft/solution.md
new file mode 100644
index 0000000000..6212f988da
--- /dev/null
+++ b/katas/content/qft/qft/solution.md
@@ -0,0 +1,33 @@
+Let's use the hint and start by preparing the described state with the qubits reversed:
+
+$$\begin{align*}
+&\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_1 j_2 ... j_{n-1} j_n} \ket{1} \big) \otimes \\
+&\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_2 ... j_{n-1} j_n} \ket{1} \big) \otimes ... \otimes \\
+\otimes &\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_{n-1} j_n} \ket{1} \big) \otimes \\
+\otimes &\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_n} \ket{1} \big)
+\end{align*}$$
+
+You've already found a way to prepare a binary fraction exponent (the desired state of the first qubit) in-place in the previous task. The state $\frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_1 j_2 ... j_{n-1} j_n} \ket{1} \big) \otimes \ket{j_2 ... j_n}$ can be prepared by first applying the Hadamard gate to the first qubit in state $\ket{j_1}$ and then applying a succession of controlled rotations using qubits $\ket{j_k}$ with increasing values of $k$ as controls, so that an extra phase terms from $e^{2\pi i \cdot j_2/2^2}$ all the way up to $e^{2\pi i \cdot j_n/2^{n}}$ are added with each rotation.
+
+This will prepare the first qubit in the right state. You can see that $j_1$ doesn't appear in the rest of the expression for the target state, so you won't need to use it in the rest of the code.
+
+To prepare the remaining qubits in the right states, you can work backwards from this state.
+The second qubit in the sequence needs to be prepared in the state $\frac{1}{\sqrt{2}} \big(\ket{0} + e^{2\pi i \cdot 0.j_2 ... j_{n-1} j_n} \ket{1} \big)$.
+Similarly to the first qubit, you can do this by applying a Hadamard gate to the qubit $\ket{j_2}$ and then using qubits $\ket{j_3}$ to $\ket{j_n}$ to apply $n-2$ controlled rotation gates to the second qubit.
+After this operation, the total system state will be:
+
+$$\frac{1}{\sqrt{2}} \big(\ket{0} + e^{2\pi i \cdot 0.j_1 j_2 ... j_{n-1} j_n} \ket{1} \big)\otimes
+\frac{1}{\sqrt{2}} \big(\ket{0} + e^{2\pi i \cdot 0.j_2 ... j_{n-1} j_n} \ket{1} \big) \otimes \ket{j_3 ... j_n}$$
+
+These two steps allow us to see a pattern: for each qubit $j_k, k = 1 .. n$ :
+
+1. Apply a Hadamard gate to $|j_k\rangle$.
+2. Apply the controlled rotation operator $n-k$ times to the qubit $|j_k\rangle$, using qubits $|j_{k+1}\rangle$ through $|j_n\rangle$ as the controls, with phases corresponding to fractions from $2^2$ to $2^{n-k+1}$.
+
+The effect of these steps will be preparing the state that almost matches the required state, but has the qubit order reversed compared to it.
+You can fix that by using a series of $\textrm{SWAP}$ gates to reverse the order of qubits in the state.
+
+@[solution]({
+"id": "qft__qft_solution",
+"codePath": "./Solution.qs"
+})
diff --git a/katas/content/qft/rotation_gate/Placeholder.qs b/katas/content/qft/rotation_gate/Placeholder.qs
new file mode 100644
index 0000000000..dac1dc5e19
--- /dev/null
+++ b/katas/content/qft/rotation_gate/Placeholder.qs
@@ -0,0 +1,6 @@
+namespace Kata {
+ operation Rotation(q : Qubit, k : Int) : Unit is Adj + Ctl {
+ // Implement your solution here...
+
+ }
+}
diff --git a/katas/content/qft/rotation_gate/Solution.qs b/katas/content/qft/rotation_gate/Solution.qs
new file mode 100644
index 0000000000..59d805f002
--- /dev/null
+++ b/katas/content/qft/rotation_gate/Solution.qs
@@ -0,0 +1,5 @@
+namespace Kata {
+ operation Rotation(q : Qubit, k : Int) : Unit is Adj + Ctl {
+ R1Frac(2, k, q);
+ }
+}
\ No newline at end of file
diff --git a/katas/content/qft/rotation_gate/Verification.qs b/katas/content/qft/rotation_gate/Verification.qs
new file mode 100644
index 0000000000..267e5b0a41
--- /dev/null
+++ b/katas/content/qft/rotation_gate/Verification.qs
@@ -0,0 +1,22 @@
+namespace Kata.Verification {
+ open Microsoft.Quantum.Katas;
+ open Microsoft.Quantum.Math;
+
+ @EntryPoint()
+ operation CheckSolution() : Bool {
+ for k in 0 .. 10 {
+ let solution = qs => Kata.Rotation(qs[0], k);
+ let reference = qs => R1Frac(2, k, qs[0]);
+ if not CheckOperationsAreEqualStrict(1, solution, reference) {
+ Message($"Incorrect for k = {k}.");
+ Message("Hint: examine the effect your solution has on the state 0.6|0〉 + 0.8|1〉 and compare it with the effect it " +
+ "is expected to have.");
+ ShowQuantumStateComparison(1, qs => Ry(ArcTan2(0.8, 0.6) * 2.0, qs[0]), solution, reference);
+ return false;
+ }
+ }
+
+ Message("Correct!");
+ true
+ }
+}
diff --git a/katas/content/qft/rotation_gate/index.md b/katas/content/qft/rotation_gate/index.md
new file mode 100644
index 0000000000..b647e00d2b
--- /dev/null
+++ b/katas/content/qft/rotation_gate/index.md
@@ -0,0 +1,10 @@
+**Inputs**:
+
+1. A qubit in state $\ket{\psi} = \alpha \ket{0} + \beta \ket{1}$.
+2. An integer $k \geq 0$.
+
+**Goal**:
+Change the state of the qubit to $\alpha \ket{0} + \beta \cdot e^{\frac{2\pi i}{2^{k}}} \ket{1}$
+
+> Be careful not to introduce an extra global phase!
+This is going to be important in the later exercises.
\ No newline at end of file
diff --git a/katas/content/qft/rotation_gate/solution.md b/katas/content/qft/rotation_gate/solution.md
new file mode 100644
index 0000000000..dee5fb6d7d
--- /dev/null
+++ b/katas/content/qft/rotation_gate/solution.md
@@ -0,0 +1,14 @@
+To avoid adding the extra global phase, we have to use a gate that does not modify the $\ket{0}$ state, and only impacts $\ket{1}$: that is, $U\ket{\psi} = \alpha\ket{0} + \beta \cdot U\ket{1}$.
+
+The built-in [R1Frac gate](https://learn.microsoft.com/qsharp/api/qsharp-lang/microsoft.quantum.intrinsic/r1frac) does exactly that:
+
+$$\textrm{R1Frac}(n,k) = \begin{bmatrix} 1 & 0 \\ 0 & e^{i\pi n/2^{k}} \end{bmatrix} $$
+
+We specify $n=2$ to get the transformation required:
+
+$$\textrm{R1Frac}(2,k) = \begin{bmatrix} 1 & 0 \\ 0 & e^{2\pi i/2^{k}} \end{bmatrix} $$
+
+@[solution]({
+"id": "qft__rotation_gate_solution",
+"codePath": "./Solution.qs"
+})
diff --git a/katas/content/qft/single_qubit/Placeholder.qs b/katas/content/qft/single_qubit/Placeholder.qs
new file mode 100644
index 0000000000..7f83dbccb6
--- /dev/null
+++ b/katas/content/qft/single_qubit/Placeholder.qs
@@ -0,0 +1,6 @@
+namespace Kata {
+ operation SingleQubitQFT(q : Qubit) : Unit is Adj + Ctl {
+ // Implement your solution here...
+
+ }
+}
diff --git a/katas/content/qft/single_qubit/Solution.qs b/katas/content/qft/single_qubit/Solution.qs
new file mode 100644
index 0000000000..188f4a6d14
--- /dev/null
+++ b/katas/content/qft/single_qubit/Solution.qs
@@ -0,0 +1,5 @@
+namespace Kata {
+ operation SingleQubitQFT(q : Qubit) : Unit is Adj + Ctl {
+ H(q);
+ }
+}
\ No newline at end of file
diff --git a/katas/content/qft/single_qubit/Verification.qs b/katas/content/qft/single_qubit/Verification.qs
new file mode 100644
index 0000000000..60acd6208e
--- /dev/null
+++ b/katas/content/qft/single_qubit/Verification.qs
@@ -0,0 +1,22 @@
+namespace Kata.Verification {
+ open Microsoft.Quantum.Katas;
+ open Microsoft.Quantum.Math;
+
+ @EntryPoint()
+ operation CheckSolution() : Bool {
+ let solution = qs => Kata.SingleQubitQFT(qs[0]);
+ let reference = qs => H(qs[0]);
+ let isCorrect = CheckOperationsAreEqualStrict(1, solution, reference);
+
+ // Output different feedback to the user depending on whether the solution was correct.
+ if isCorrect {
+ Message("Correct!");
+ } else {
+ Message("Incorrect.");
+ Message("Hint: examine the effect your solution has on the state 0.6|0〉 + 0.8|1〉 and compare it with the effect it " +
+ "is expected to have.");
+ ShowQuantumStateComparison(1, qs => Ry(ArcTan2(0.8, 0.6) * 2.0, qs[0]), solution, reference);
+ }
+ isCorrect
+ }
+}
diff --git a/katas/content/qft/single_qubit/index.md b/katas/content/qft/single_qubit/index.md
new file mode 100644
index 0000000000..0160ae193d
--- /dev/null
+++ b/katas/content/qft/single_qubit/index.md
@@ -0,0 +1,6 @@
+**Input**: A qubit in state $\ket{\psi} = x_0 \ket{0} + x_1 \ket{1}$.
+
+**Goal**:
+Apply quantum Fourier transform to this qubit, that is, transform it to a state $\frac1{\sqrt2} \big((x_0 + x_1) \ket{0} + (x_0 - x_1) \ket{1}\big)$.
+
+In other words, transform each basis state $\ket{j}$ into $\frac1{\sqrt2} (\ket{0} + e^{2\pi i \cdot \frac{j}{2}} \ket{1} )$.
\ No newline at end of file
diff --git a/katas/content/qft/single_qubit/solution.md b/katas/content/qft/single_qubit/solution.md
new file mode 100644
index 0000000000..300c796fb9
--- /dev/null
+++ b/katas/content/qft/single_qubit/solution.md
@@ -0,0 +1,11 @@
+The required transformation is actually just the expression for the transformation of an arbitrary state in the $Z$ basis (that is, the computational basis) to one in the $X$ basis (the Hadamard basis).
+
+For the starting state $\ket{0}$, $x_0=1$ and $x_1=0$, so the new state will be $\frac1{\sqrt2} (\ket{0} + \ket{1}) = \ket{+}$.
+Similarly, for the starting state $\ket{1}$, $x_0=0$ and $x_1=1$, so the new state will be $\frac1{\sqrt2} (\ket{0} - \ket{1}) = \ket{-}$.
+
+And you already know a gate that will do this: the Hadamard gate!
+
+@[solution]({
+"id": "qft__single_qubit_solution",
+"codePath": "./Solution.qs"
+})