#include <bits/stdc++.h>
using namespace std;
const long long maxn = 2e6;
const long long mod = 1e9 + 7;
const long double PI = 4 * atan((long double)1);
long long pw(long long a, long long b) {
  return (!b ? 1
             : (b & 1 ? a * pw(a * a % mod, b / 2) % mod
                      : pw(a * a % mod, b / 2) % mod));
}
struct trio {
  int f, s, t;
};
int n, m;
vector<int> adj[maxn], back[maxn], child[maxn];
map<pair<int, int>, bool> mp;
int par[maxn];
bool mark[maxn];
vector<trio> ans;
void dfs(int v) {
  mark[v] = 1;
  for (auto u : adj[v]) {
    if (!mark[u]) {
      child[v].push_back(u);
      ;
      par[u] = v;
      dfs(u);
    } else if (u != par[v]) {
      back[v].push_back(u);
      ;
    }
  }
  int f = 0, s = 0, cnt = 0, moond = -1;
  int be = -1;
  for (int i = 0; i < back[v].size(); i++) {
    if (!mp[pair<int, int>(v, back[v][i])]) {
      be = back[v][i];
      break;
    }
  }
  cnt = 0, moond = -1, s = 0, f = 0;
  while (child[v].size()) {
    if (cnt == 0 and !mp[pair<int, int>(child[v].back(), v)]) {
      f = child[v].back();
      cnt++;
    } else if (cnt == 1 and !mp[pair<int, int>(child[v].back(), v)]) {
      s = child[v].back();
      cnt = 2;
    }
    if (cnt == 2) {
      cnt = 0;
      trio boz;
      mp[pair<int, int>(v, f)] = mp[pair<int, int>(f, v)] = 1;
      mp[pair<int, int>(v, s)] = mp[pair<int, int>(s, v)] = 1;
      boz.f = f, boz.s = v, boz.t = s;
      ans.push_back(boz);
      ;
    }
    if (!mp[pair<int, int>(child[v].back(), v)]) {
      moond = child[v].back();
    }
    child[v].pop_back();
  }
  if (moond != -1 and !mp[pair<int, int>(be, v)] and
      !mp[pair<int, int>(moond, v)] and be != -1) {
    trio boz;
    boz.f = moond, boz.s = v, boz.t = be;
    mp[pair<int, int>(v, moond)] = mp[pair<int, int>(moond, v)] = 1;
    mp[pair<int, int>(v, be)] = mp[pair<int, int>(be, v)] = 1;
    ans.push_back(boz);
    ;
  }
  if (moond != -1 and !mp[pair<int, int>(par[v], v)] and par[v] != -1 and
      !mp[pair<int, int>(moond, v)]) {
    trio boz;
    boz.f = moond, boz.s = v, boz.t = par[v];
    mp[pair<int, int>(v, moond)] = mp[pair<int, int>(moond, v)] = 1;
    mp[pair<int, int>(v, par[v])] = mp[pair<int, int>(par[v], v)] = 1;
    ans.push_back(boz);
    ;
  }
  cnt = 0, moond = -1, f = 0, s = 0;
  while (back[v].size()) {
    if (cnt == 0 and !mp[pair<int, int>(back[v].back(), v)]) {
      f = back[v].back();
      cnt++;
    } else if (cnt == 1 and !mp[pair<int, int>(back[v].back(), v)]) {
      s = back[v].back();
      cnt = 2;
    }
    if (cnt == 2) {
      cnt = 0;
      trio boz;
      mp[pair<int, int>(v, f)] = mp[pair<int, int>(f, v)] = 1;
      mp[pair<int, int>(v, s)] = mp[pair<int, int>(s, v)] = 1;
      boz.f = f, boz.s = v, boz.t = s;
      ans.push_back(boz);
      ;
    }
    if (!mp[pair<int, int>(back[v].back(), v)]) {
      moond = back[v].back();
    }
    back[v].pop_back();
  }
  if (moond != -1 and !mp[pair<int, int>(par[v], v)] and par[v] != -1 and
      !mp[pair<int, int>(v, moond)]) {
    trio boz;
    boz.f = moond, boz.s = v, boz.t = par[v];
    mp[pair<int, int>(v, moond)] = mp[pair<int, int>(moond, v)] = 1;
    mp[pair<int, int>(v, par[v])] = mp[pair<int, int>(par[v], v)] = 1;
    ans.push_back(boz);
    ;
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    adj[v].push_back(u);
    ;
    adj[u].push_back(v);
    ;
    mp[pair<int, int>(u, v)] = mp[pair<int, int>(v, u)] = 0;
  }
  for (int i = 1; i <= n; i++) {
    if (!mark[i]) {
      par[i] = -1;
      dfs(i);
    }
  }
  cout << ans.size() << '\n';
  for (int i = 0; i < ans.size(); i++) {
    trio out;
    out = ans[i];
    cout << out.f << ' ' << out.s << ' ' << out.t << '\n';
  }
  return (0);
}
