#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <class T>
inline bool setmin(T &a, T b) {
  if (a > b) return a = b, 1;
  return 0;
}
template <class T>
inline bool setmax(T &a, T b) {
  if (a < b) return a = b, 1;
  return 0;
}
template <class T>
inline T fast(T a, T b, T mod) {
  long long res = 1;
  while (b) {
    if (b & 1) res = (res * a) % mod;
    a = (a * a) % mod;
    b >>= 1;
  }
  return res;
}
template <class T>
istream &operator>>(istream &os, vector<T> &container) {
  for (auto &u : container) os >> u;
  return os;
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &container) {
  for (auto &u : container) os << u << " ";
  return os;
}
template <class T>
inline T gcd(T a, T b) {
  while (b) swap(a %= b, b);
  return abs(a);
}
const long long INF = 1e9 + 7;
const long long mod = 998244353;
const long long BIG_INF = 1e18 + 7;
const long long N = 1e6 + 7;
const long long T = 1 << 20;
const long double inf = 1e18;
struct kubek {
  vector<int> wierzcholki;
  int kolor;
  kubek *przodek;
  vector<kubek *> potomkowie;
  kubek(int v, int k, kubek *p = nullptr)
      : wierzcholki({v}), kolor(k), przodek(p), potomkowie() {}
  void add(int val) { wierzcholki.push_back(val); }
};
bool operator<(const kubek a, const kubek b) {
  if (a.kolor != b.kolor) return a.kolor < b.kolor;
  if (a.kolor == 0) {
    if ((int)(a.potomkowie).size() == (int)(b.potomkowie).size())
      return a.wierzcholki[0] < b.wierzcholki[0];
    return (int)(a.potomkowie).size() > (int)(b.potomkowie).size();
  }
  if ((int)(a.potomkowie).size() == (int)(b.potomkowie).size())
    return a.wierzcholki[0] < b.wierzcholki[0];
  return (int)(a.potomkowie).size() < (int)(b.potomkowie).size();
}
struct set_cmp {
  bool operator()(const kubek *a, const kubek *b) const { return *a < *b; }
};
void wywal(kubek *k) {
  if ((int)(k->potomkowie).size() == 0) {
    delete k;
    return;
  }
  for (auto &u : k->potomkowie) wywal(u);
  delete k;
}
void usun(set<kubek *, set_cmp> &korzenie, vector<vector<int> > &ans,
          set<kubek *, set_cmp>::iterator it, int kol) {
  assert((*it)->kolor == kol);
  ans.push_back((*it)->wierzcholki);
  for (auto &u : (*it)->potomkowie) korzenie.insert(u);
  korzenie.erase(it);
}
void solve() {
  int n;
  cin >> n;
  vector<int> kolor(6 * n + 1);
  vector<int> tab(n * 3);
  cin >> tab;
  for (auto &u : tab) kolor[u] = 1;
  vector<kubek *> stos;
  set<kubek *, set_cmp> korzenie;
  vector<kubek *> vec_korzenie;
  for (int i = 1; i <= n * 6; i++) {
    if ((int)(stos).size() == 0) {
      kubek *nowy = new kubek(i, kolor[i], nullptr);
      vec_korzenie.push_back(nowy);
      stos.push_back(nowy);
    } else if (stos.back()->kolor == kolor[i]) {
      stos.back()->add(i);
      if ((int)(stos.back()->wierzcholki).size() == 3) stos.pop_back();
    } else {
      kubek *nowy = new kubek(i, kolor[i], stos.back());
      stos.back()->potomkowie.push_back(nowy);
      stos.push_back(nowy);
    }
  }
  for (auto &u : vec_korzenie) korzenie.insert(u);
  vector<vector<int> > ans;
  for (int i = 0; i < n; i++) {
    usun(korzenie, ans, korzenie.begin(), 0);
    usun(korzenie, ans, prev(korzenie.end()), 1);
  }
  reverse((ans).begin(), (ans).end());
  for (auto &u : ans) cout << u << '\n';
  for (auto &u : vec_korzenie) wywal(u);
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int t = 1;
  while (t--) solve();
}
