Permutations and arrangements

Permutations and arrangements are common concepts in many kinds of problems.

This article is not about the number of permutations

This article discusses permutations of a set, rather than the number of arrangements counted in permutations and combinations. For the latter topic, see Permutations and combinations.

Convention

Unless otherwise stated, this article always discusses finite sets.

Definition

A bijection (that is, a one-to-one correspondence) from a set XX to itself, denoted by σ\sigma, is a permutation of XX. If the set XX also has a total order, its permutation is also commonly called a (full) arrangement. This total order is called the natural order on the set.

“Permutation” and “arrangement”

In Chinese, “permutation” usually refers to changing the order of elements, while “arrangement” usually refers to putting elements into a sequence. When the elements have a natural order, the two concepts are the same: an “arrangement” can be viewed as the result of a “permutation”; relative to the natural order of the elements, the order of the elements in an “arrangement” specifies the “permutation”. Since this article assumes that a natural order exists on the set whenever it uses the word “arrangement”, it does not deliberately distinguish between the two concepts.

Of course, elements without a natural order can also be “arranged”. Such “arrangements” often occur in combinatorial counting problems, which are outside the scope of this article.

If the size of a set XX is nn, then the total number of permutations of XX is n!n!. In particular, 0!=10!=1: the empty set has exactly one permutation, namely the empty permutation.

Notation

Permutations concern the correspondences between elements, not what the elements specifically are. Therefore, when discussing a set of size nn, we usually assume that the set is {1,2,⋯ ,n}\{1,2,\cdots,n\}; when a natural order is needed, we usually use the natural order on the natural numbers.

Representations

There are several ways to represent a permutation. We use the following permutation as an example to discuss them.

σ(1)=2, σ(2)=6, σ(3)=5, σ(4)=4, σ(5)=3, σ(6)=1.\sigma(1) = 2,\ \sigma(2) = 6,\ \sigma(3) = 5,\ \sigma(4) = 4,\ \sigma(5) = 3,\ \sigma(6) = 1.

Two-line notation

A permutation on the set X={x1,x2,⋯ ,xn}X=\{x_1,x_2,\cdots,x_n\} can be represented as

σ=(x1x2⋯xnxp1xp2⋯xpn).\sigma=\begin{pmatrix}x_1&x_2&\cdots&x_n\\ x_{p_1}&x_{p_2}&\cdots&x_{p_n} \end{pmatrix}.

This means that permutation σ\sigma maps xix_i to xpix_{p_i}. Of course, we need X={xp1,xp2,⋯ ,xpn}X=\{x_{p_1},x_{p_2},\cdots,x_{p_n}\}. In the two-line notation of a permutation, the order in which elements appear in the first row is not important; what matters is the correspondence between the two rows.

For example, the example above can be written in two-line notation as

σ=(123456265431),\sigma= \begin{pmatrix} 1 & 2 & 3 & 4 & 5 & 6 \\ 2 & 6 & 5 & 4 & 3 & 1 \end{pmatrix},

and it can of course also be written as

σ=(654321134562).\sigma= \begin{pmatrix} 6 & 5 & 4 & 3 & 2 & 1 \\ 1 & 3 & 4 & 5 & 6 & 2 \end{pmatrix}.

One-line notation

In many cases, the set XX has a natural order. If the first row in two-line notation is assumed to be written in natural order and is omitted, the permutation can be represented as

σ=σ(1)σ(2)⋯σ(n).\sigma=\sigma(1)\sigma(2)\cdots\sigma(n).

This is closer to the concept of an arrangement in natural language. Therefore, “arrangement” is sometimes used to refer to this ordered tuple.

The example above can be written in one-line notation as

σ=265431.\sigma=265431.

This one-line notation is often used to compare the sizes of different permutations.

Cycle notation

A permutation also has a more compact representation called its cycle notation. It represents a permutation as a product of pairwise disjoint cycles. The steps for writing a given permutation in cycle notation are described below.

Given a permutation σ\sigma, write it in cycle notation as follows:

  1. If XX still contains an element that has not been written, write a left parenthesis and then write any such element;
  2. If the most recently written element is xx,
    • if σ(x)\sigma(x) has already been written, write a right parenthesis and return to step 1;
    • if σ(x)\sigma(x) has not yet been written, write σ(x)\sigma(x) and continue with step 2;
  3. Stop when every element of XX has been written.

The elements inside each pair of parentheses form a cycle. The number of elements inside the parentheses is called the length of the corresponding cycle. In practice, cycles of length one are often omitted.

The example above can be written in cycle notation as

σ=(126)(35)(4)=(126)(35).\sigma=(126)(35)(4)=(126)(35).

In the identity transformation, all cycles have length one, and it is common to write (1)(1) rather than omit them all.

Composition

Composition of permutations is composition of mappings. It is also commonly called multiplication of permutations.

Given two permutations

σ=(x1x2⋯xnxp1xp2⋯xpn), π=(xp1xp2⋯xpnxq1xq2⋯xqn),\sigma=\begin{pmatrix}x_1&x_2&\cdots&x_n\\ x_{p_1}&x_{p_2}&\cdots&x_{p_n}\end{pmatrix},\ \pi=\begin{pmatrix}x_{p_1}&x_{p_2}&\cdots&x_{p_n}\\ x_{q_1}&x_{q_2}&\cdots&x_{q_n}\end{pmatrix},

the product π∘σ\pi\circ\sigma is

π∘σ=(x1x2⋯xnxq1xq2⋯xqn).\pi\circ\sigma=\begin{pmatrix}x_1&x_2&\cdots&x_n\\ x_{q_1}&x_{q_2}&\cdots&x_{q_n}\end{pmatrix}.

In simple terms, first apply the mapping σ\sigma, then apply the mapping π\pi. Note that in the two-line notation above, the order of the second row of the inner mapping σ\sigma is the same as the order of the first row of the outer mapping π\pi.

Because permutations σ\sigma and π\pi are fundamentally mappings, (π∘σ)(x)=π(σ(x))(\pi\circ\sigma)(x)=\pi(\sigma(x)). The order of composition of permutations is from right to left. Multiplication of permutations is not commutative, so using the wrong order can produce an incorrect result.

The product of several consecutive copies of a permutation is called a power of the permutation, and binary exponentiation can accelerate its computation.

Inverse permutation

Because a permutation is a bijection, it always has an inverse permutation.

Given the permutation

σ=(x1x2⋯xnxp1xp2⋯xpn),\sigma=\begin{pmatrix}x_1&x_2&\cdots&x_n\\ x_{p_1}&x_{p_2}&\cdots&x_{p_n}\end{pmatrix},

its inverse is

σ−1=(xp1xp2⋯xpnx1x2⋯xn).\sigma^{-1}=\begin{pmatrix}x_{p_1}&x_{p_2}&\cdots&x_{p_n}\\x_1&x_2&\cdots&x_n\end{pmatrix}.

In cycle notation, invert each cycle to obtain the inverse permutation. To invert a cycle, simply reverse the order in which its elements are written. For example, the inverse of the permutation σ\sigma above has cycle notation

σ−1=(621)(53)=(162)(35).\sigma^{-1} = (621)(53) = (162)(35).

A permutation of 1∼n1\sim n and the sequence of the ranks of its elements are inverse permutations of each other.

Cycles

A cycle is itself a special permutation. The defining property of a cycle is that, starting from any point xx in the cycle, repeatedly applying the permutation σ\sigma reaches any other point yy in the cycle. A cycle of length kk is also called a kk-cycle (also written as a kk-cycle). Repeatedly applying a kk-cycle kk times gives the identity transformation: every element returns to its original position.

The cycle notation of a permutation can be viewed as expressing it as a product of these special permutations (cycles), so it can also be viewed as the cycle decomposition of the permutation. For every permutation, its decomposition into a product of cycles is unique up to the order of the cycles. Cycles can be viewed as the basic building blocks of a permutation.

The cycle decomposition of a permutation has a clear geometric meaning. If a permutation on a set SS is represented by treating each ordered pair (x,σ(x))(x,\sigma(x)) in it as an edge of a directed graph whose vertices are SS, then the cycles are the loops in this graph. If permutation σ\sigma decomposes into mm cycles, the corresponding directed graph has mm loops in total, including self-loops. These loops are naturally pairwise disjoint.

Fixed points

A 11-cycle is a fixed point of a permutation. For a set XX and a permutation σ\sigma on it, XσX^\sigma usually denotes the set of fixed points of σ\sigma, namely Xσ={x∈X:σ(x)=x}X^\sigma=\{x\in X:\sigma(x)=x\}.

Transpositions

A 22-cycle is also called a transposition. In other words, a transposition is a permutation that swaps exactly one pair of elements. Its cycle notation is (xixj)(x_ix_j), meaning that it swaps the positions of xix_i and xjx_j.

Every permutation can be written as a product of transpositions. This means that any ordering of elements can be restored to a specified sorted order by repeatedly swapping two elements. This is exactly what comparison-based sorting algorithms do.

Moreover, the correctness of bubble sort actually shows that every permutation can be written as a product of adjacent transpositions. An adjacent transposition is a transposition that swaps two adjacent elements.

Properties

Applications often require us to consider properties of an individual permutation.

Parity

The decomposition of a cycle into transpositions is not unique. For example,

(123)=(13)(12)=(12)(23)=(12)(13)(12)(13).(123)=(13)(12)=(12)(23)=(12)(13)(12)(13).

However, when a permutation is decomposed into a sequence of transpositions, the parity of the number of transpositions required is fixed. The parity of the number of transpositions in a decomposition of a permutation is also called the parity of the permutation.

A permutation that can be decomposed into a product of an even number of transpositions is called an even permutation; one that can be decomposed into a product of an odd number is called an odd permutation. When n≥2n\ge2, the numbers of odd and even permutations of size nn are equal.

Sign

Based on the parity of a permutation, we can define its sign, denoted by sgn⁡σ\operatorname{sgn}\sigma. The sign of an even permutation is defined as +1+1, and that of an odd permutation as −1-1.

The sign of a product of permutations equals the product of their signs:

sgn⁡(π∘σ)=sgn⁡π⋅sgn⁡σ.\operatorname{sgn}(\pi\circ\sigma)=\operatorname{sgn} \pi\cdot\operatorname{sgn}\sigma.

In other words, composing two permutations with the same parity gives an even permutation, while composing two permutations with different parities gives an odd permutation. From the viewpoint of decomposing into transpositions, this conclusion is immediate.

In particular, a single transposition necessarily changes the parity of a permutation. This also explains why, although the decomposition into transpositions is not unique, the parity of the required number of transpositions is fixed.

The sign of a permutation appears in the Leibniz expansion of the determinant.

Order of a permutation

The order of a permutation is the smallest positive integer aa satisfying the following condition: after applying the permutation repeatedly aa times, every element returns to its original position. That is,

ord⁡σ=min⁡{a∈N+:σa=(1)}.\operatorname{ord}\sigma=\min\{a\in\mathbf N_+:\sigma^a=(1)\}.

On a finite set, every permutation has finite order. This means that, starting from an initial ordering, repeatedly scrambling a given sequence according to a fixed pattern will always restore the original arrangement in finite time.

Cycle type

Decompose a permutation of nn elements into cycles. The cycle type of the permutation is the multiset of the cycle lengths in the decomposition. These lengths form an integer partition of nn. If cycles of length kk occur in the decomposition, with αk\alpha_k of them, the cycle type is commonly written as

1α12α2⋯nαn,1^{\alpha_1}2^{\alpha_2}\cdots n^{\alpha_n},

where the coefficients satisfy ∑k=1nkαk=n\sum_{k=1}^nk\alpha_k=n.

Given a cycle type, the number of distinct permutations is

n!1α12α2⋯nαnα1!α2!⋯αn!.\frac{n!}{1^{\alpha_1}2^{\alpha_2}\cdots n^{\alpha_n}\alpha_1!\alpha_2!\cdots\alpha_n!}.
Analysis

This is because every permutation of 1∼n1\sim n can be partitioned according to the cycle type into a corresponding cycle decomposition. However, the order of cycles of the same length does not affect the permutation, so we divide by ∏kαk!\prod_k\alpha_k!. In addition, each individual cycle is actually a circular arrangement, and choosing its starting point does not affect the permutation, so we divide by ∏kkαk\prod_kk^{\alpha_k}. This gives the formula above.

If only the number of cycles c(σ)c(\sigma) in the permutation decomposition is given, the number of distinct permutations is the Stirling number of the first kind [nk]\begin{bmatrix}n\\ k\end{bmatrix}. The number of distinct cycle types for permutations of length nn is the partition number pnp_n.

The cycle type makes it easy to determine properties such as the order and parity of a permutation.

Because the order of a kk-cycle is kk and distinct cycles are disjoint, the order of permutation σ\sigma is

lcm⁡{k:αk>0}.\operatorname{lcm}\{k:\alpha_k>0\}.

Likewise, because the parity of a kk-cycle is opposite to the parity of kk, the parity of permutation σ\sigma is the parity of

∑k(k−1)αk=∑kkαk−∑kαk=n−c(σ)\sum_k(k-1)\alpha_k=\sum_{k}k\alpha_k-\sum_{k}\alpha_k=n-c(\sigma)

Here, c(σ)c(\sigma) is the number of cycles, including 11-cycles (fixed points).

Cycle types play an important role in Pólya enumeration.

If the set XX itself has a natural order, permutation σ\sigma is commonly called an arrangement and represented in one-line notation as

σ(1)σ(2)⋯σ(n)\sigma(1)\sigma(2)\cdots\sigma(n)

Do not confuse this with a cycle.

Inversions

In an arrangement, if a larger number appears before a smaller number, the two numbers form an inversion. The comparison here uses the natural order.

The total number of inversions in an arrangement is called the inversion count of the permutation. The inversion count is the minimum number of adjacent transpositions needed to restore it to the sorted sequence. Therefore, the parity of the inversion count agrees with the parity of the corresponding permutation. This gives an equivalent definition of permutation parity.

Algorithms for computing inversion counts include merge sort and the binary indexed tree, both with time complexity O(nlog⁡n)O(n\log n). Their explanations are given in the corresponding sections; reference implementations are provided here.

Reference implementation

Merge sort

#include <iostream>
#include <vector>

// Merge sort and count inversions.
long long merge_sort(std::vector<int>& nums, int b, int e) {
  // Return 0 when length <= 1.
  if (e - b <= 1) return 0;
  long long res = 0;
  int m = (b + e) / 2;
  // Merge_sort two halves.
  res += merge_sort(nums, b, m);
  res += merge_sort(nums, m, e);
  // Temporary vector to store sorted array.
  std::vector<int> tmp(e - b);
  int i = b, j = m, k = 0;
  while (i < m && j < e) {
    if (nums[j] < nums[i]) {
      tmp[k] = nums[j++];
      // In this case, all elements in [i,m) are larger than element j.
      res += m - i;
    } else {
      tmp[k] = nums[i++];
    }
    ++k;
  }
  // Deal with remaining elements.
  for (; i < m; ++i, ++k) {
    tmp[k] = nums[i];
  }
  for (; j < e; ++j, ++k) {
    tmp[k] = nums[j];
  }
  // Copy back to original vector.
  for (i = b, k = 0; i < e; ++i, ++k) {
    nums[i] = tmp[k];
  }
  return res;
}

int main() {
  int n;
  std::cin >> n;
  std::vector<int> nums(n);
  for (int& num : nums) {
    std::cin >> num;
  }
  std::cout << merge_sort(nums, 0, n);
  return 0;
}

Binary indexed tree

#include <algorithm>
#include <iostream>
#include <unordered_map>
#include <vector>

// A simple BIT implementation.
class BIT {
  int n;
  std::vector<int> su;

 public:
  BIT(int n) : n(n), su(n + 1) {}

  // Add v to the x-th number.
  void add(int x, int v) {
    for (; x <= n; x += x & (-x)) {
      su[x] += v;
    }
  }

  // Get the cumulative sum till the x-th number.
  int query(int x) {
    int res = 0;
    for (; x; x &= x - 1) {
      res += su[x];
    }
    return res;
  }
};

// Count inversions.
long long solve(const std::vector<int>& nums) {
  // Discretization.
  std::vector<int> sorted(nums);
  std::sort(sorted.begin(), sorted.end());
  sorted.erase(std::unique(sorted.begin(), sorted.end()), sorted.end());
  std::unordered_map<int, int> ids;
  int m = sorted.size();
  for (int i = 0; i < m; ++i) {
    // Reverse the order.
    // Now a smaller id means a larger element.
    ids[sorted[i]] = m - i;
  }
  // Main part.
  BIT bit(m);
  long long res = 0;
  for (int num : nums) {
    int id = ids[num];
    // Get inversion pair (i,j) with j the current element.
    // Namely, count the number of elements larger than
    //     the current one but located before it.
    res += bit.query(id - 1);
    // Insert the current element to the BIT.
    bit.add(id, 1);
  }
  return res;
}

int main() {
  int n;
  std::cin >> n;
  std::vector<int> nums(n);
  for (int& num : nums) {
    std::cin >> num;
  }
  std::cout << solve(nums);
  return 0;
}

Order

Permutations can be compared by size. Since each one-line notation is a string, the order of permutations is the lexicographic order of these strings.

In the C++ STL library <algorithm>, prev_permutation and next_permutation can be used to find the previous and next permutations of the current one in lexicographic order.

Rank

List all permutations of nn elements in lexicographic order from smallest to largest. The position of a permutation in this sequence is its rank. This establishes a one-to-one correspondence between permutations and positive integers, and is often used for state compression in permutation problems.

In Chinese competitive programming, this rank is often called the “Cantor expansion” of a permutation, but that name is not standard. More precisely, the Cantor expansion of a permutation's rank corresponds to its Lehmer code.

About “Cantor expansion”

As the name suggests, a Cantor expansion is a method of expanding a natural number into a sequence. It can be viewed as a special numeral system, also called the factorial number system. In this system, the bases (radices) corresponding to different digits are not the same. For example, the decimal number 46310463_{10} can be represented in the factorial number system as

46310=341010!.463_{10}=341010_{!}.

This representation means

463=3×5!+4×4!+1×3!+0×2!+1×1!+0×0!.463=3\times 5!+4\times 4!+1\times 3!+0\times 2!+1\times 1!+0\times 0!.

Cantor studied numeral systems with such mixed bases, so the digit representation of a natural number in this system is also called its Cantor expansion.

Example

Readers unfamiliar with how to compute a rank can use this simple example to understand the basic idea of the algorithm below.

To compute the rank of the permutation σ=452631\sigma=452631, count how many permutations are lexicographically smaller than σ\sigma, then add one. The idea is similar to digit DP: consider the positions one by one.

  • At position 11, the value must be smaller than that in σ\sigma, so it can only be one of {1,2,3}\{1,2,3\}. The remaining 55 positions can be chosen arbitrarily, giving 3×5!3\times 5! possible permutations;
  • If position 11 also contains 44, then at position 22 the value must be smaller than that in σ\sigma, so it can only be one of {1,2,3}\{1,2,3\} (the 44 has already been used). The remaining 44 positions can be chosen arbitrarily, giving 3×4!3\times 4! possible permutations;
  • Similarly, if the first 22 positions agree with σ\sigma, the value at position 33 must be smaller than that in σ\sigma, so it can only be {1}\{1\}. The remaining 33 positions can be chosen arbitrarily, giving 1×3!1\times 3! possible permutations;
  • If the first 33 positions agree with σ\sigma, the value at position 44 must be smaller than that in σ\sigma, so it can only be one of {1,3}\{1,3\}. The remaining 22 positions can be chosen arbitrarily, giving 2×2!2\times 2! possible permutations;
  • If the first 44 positions agree with σ\sigma, the value at position 55 must be smaller than that in σ\sigma, so it can only be {1}\{1\}. The remaining 11 position can be chosen arbitrarily, giving 1×1!1\times 1! possible permutation;
  • If the first 55 positions agree with σ\sigma, no choice at position 66 can produce a permutation smaller than σ\sigma, so there are 0×0!0\times 0! possible permutations.

Therefore, the rank of permutation σ\sigma is

1+3×5!+3×4!+1×3!+2×2!+1×1!+0×0!=444.1+3\times 5!+3\times 4!+1\times 3!+2\times 2!+1\times 1!+0\times 0!=444.

For different permutations, the key is determining the coefficients before the factorials. In fact, each coefficient is the number of elements that appear after the element at that position but are smaller than it.

From the example, the algorithm for finding the rank of a given permutation can be divided into two steps:

  1. Convert the given permutation, of length nn, into its Lehmer code, a sequence of length nn called LσL_\sigma, where the ii-th entry is

    Lσ(i)=#{j>i:σ(j)<σ(i)},L_\sigma(i)=\#\{j>i:\sigma(j)<\sigma(i)\},

    that is, the number of elements after position ii in the permutation that are smaller than σ(i)\sigma(i). This is equal to the rank minus one of the given element among the unused elements.

  2. Treat the Lehmer code as the Cantor expansion of a natural number, recover the original natural number, and add one. In other words, the final rank is

    rank⁡σ=1+Lσ(1)(n−1)!+Lσ(2)(n−2)!+⋯+Lσ(n)0!.\operatorname{rank}\sigma=1+L_\sigma(1)(n-1)!+L_\sigma(2)(n-2)!+\cdots+L_\sigma(n)0!.

To solve the inverse problem—given a rank, find the corresponding permutation—simply perform the above process in reverse. The sum of the digits in the Lehmer code obtained during this process is the inversion count of the permutation.

When implementing this, the key is to quickly compute the rank of a given element among the unused elements (when finding a rank) and the element with a given rank among the unused elements (when finding a permutation). Both can be maintained with data structures such as a binary indexed tree or a segment tree. Both forward and reverse operations take O(nlog⁡n)O(n\log n) time.

Reference implementation

Find the rank of a given permutation

#include <iostream>
#include <vector>

// A simple BIT implementation.
class BIT {
  int n;
  std::vector<int> su;

 public:
  BIT(int n) : n(n), su(n + 1) {}

  // Add v to the x-th number.
  void add(int x, int v) {
    for (; x <= n; x += x & (-x)) {
      su[x] += v;
    }
  }

  // Get the cumulative sum till the x-th number.
  int query(int x) {
    int res = 0;
    for (; x; x &= x - 1) {
      res += su[x];
    }
    return res;
  }
};

// Get the rank of a permutation of 1~n.
long long find_rank(const std::vector<int>& nums) {
  int n = nums.size();
  BIT bit(n);
  long long fac = 1;
  long long res = 0;
  // Reverse iteration.
  for (int i = n - 1; i >= 0; --i) {
    // Count the number of elements smaller than the current one.
    res += bit.query(nums[i] - 1) * fac;
    // Insert the current element into the BIT.
    bit.add(nums[i], 1);
    // Update the factorial.
    fac *= n - i;
  }
  return res + 1;
}

int main() {
  int n;
  std::cin >> n;
  std::vector<int> nums(n);
  for (int& num : nums) {
    std::cin >> num;
  }
  std::cout << find_rank(nums);
  return 0;
}

Find the permutation with a given rank

#include <cmath>
#include <iostream>
#include <vector>

// A simple BIT implementation.
class BIT {
  int n;
  std::vector<int> su;

 public:
  BIT(int n) : n(n), su(n + 1) {}

  // Fill the BIT with one.
  void fill() {
    for (int x = 1; x <= n; ++x) {
      su[x] += x & (-x);
    }
  }

  // Add v to the x-th number.
  void add(int x, int v) {
    for (; x <= n; x += x & (-x)) {
      su[x] += v;
    }
  }

  // Get the k-th smallest element.
  int find_kth(int k) {
    int ps = 0, x = 0;
    for (int i = log2(n); i >= 0; --i) {
      x += 1 << i;
      if (x >= n || ps + su[x] >= k) {
        x -= 1 << i;
      } else {
        ps += su[x];
      }
    }
    return x + 1;
  }
};

// Find the k-th permutation of 1~n.
std::vector<int> find_permutation(int n, long long k) {
  --k;
  // Expand rank to Lehmer code.
  std::vector<int> lehmer(n);
  for (int i = 1; i <= n; ++i) {
    lehmer[n - i] = k % i;
    k /= i;
  }
  BIT bit(n);
  // Set all values in BIT to one.
  bit.fill();
  std::vector<int> res(n);
  for (int i = 0; i < n; ++i) {
    // Find the lehmer[i]-th smallest unused element.
    res[i] = bit.find_kth(lehmer[i] + 1);
    // Remove it from the BIT.
    bit.add(res[i], -1);
  }
  return res;
}

int main() {
  int n;
  long long k;
  std::cin >> n >> k;
  auto res = find_permutation(n, k);
  for (int num : res) {
    std::cout << num << ' ';
  }
  return 0;
}

References and notes

This content comes from OI Wiki: Permutations and arrangements. See the original for authors and revision history. AIOJ has adapted the formatting, in-site links, and resource paths.

Content is shared under CC BY-SA 4.0 and SATA license; additional terms are governed by the original notice. Thanks to the OI Wiki authors and contributors; per the SATA terms, please visit the OI Wiki repository and star it to show your support.