#include <bits/stdc++.h>
using namespace std;
const int S = 2e5 + 10;
vector<int> tab[S], sons[S], extra[S];
vector<tuple<int, int, int>> ans;
int active[S], met[S], gb[S], x, y, n, m;
void dfs(int w, int par) {
  met[w] = 1;
  for (int v : tab[w]) {
    if (!met[v]) {
      gb[v] = gb[w] + 1;
      dfs(v, w);
      if (active[v]) sons[w].push_back(v);
    } else {
      if (gb[w] - gb[v] > 1) {
        extra[w].push_back(v);
      }
    }
  }
  while (sons[w].size() >= 2) {
    x = sons[w].back();
    sons[w].pop_back();
    y = sons[w].back();
    sons[w].pop_back();
    ans.push_back(make_tuple(x, w, y));
  }
  while (extra[w].size()) {
    if (extra[w].size() >= 2) {
      x = extra[w].back();
      extra[w].pop_back();
      y = extra[w].back();
      extra[w].pop_back();
      ans.push_back(make_tuple(x, w, y));
    } else {
      if (sons[w].size()) {
        ans.push_back(make_tuple(sons[w][0], w, extra[w][0]));
        sons[w].pop_back();
        extra[w].pop_back();
      } else {
        ans.push_back(make_tuple(par, w, extra[w][0]));
        extra[w].pop_back();
        active[w] = 0;
      }
    }
  }
  if (sons[w].size() && par != -1) {
    ans.push_back(make_tuple(par, w, sons[w][0]));
    active[w] = 0;
    sons[w].pop_back();
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> n >> m;
  for (int a = 1; a <= n; a++) active[a] = 1;
  for (int a = 1; a <= m; a++) {
    cin >> x >> y;
    tab[x].push_back(y);
    tab[y].push_back(x);
  }
  for (int a = 1; a <= n; a++) {
    if (!met[a]) dfs(a, -1);
  }
  cout << ans.size() << endl;
  for (auto v : ans) {
    cout << get<0>(v) << " " << get<1>(v) << " " << get<2>(v) << endl;
  }
  return 0;
}
