#include <bits/stdc++.h>
using namespace std;
int n, i, j, k, x, y, z, m, q, h, l, timer;
int used[200500], p[200500], w[200500], w2[200500];
vector<int> g[200500];
vector<int> comp;
set<int> tree[200500], g2[200500];
vector<pair<pair<int, int>, int>> ans;
set<pair<pair<int, int>, int>> f;
void dfs(int v) {
  comp.push_back(v);
  used[v] = 1;
  for (int i = 0; i < g[v].size(); i++) {
    int to = g[v][i];
    if (!used[to]) {
      tree[v].insert(to);
      p[to] = v;
      dfs(to);
    } else if (p[v] != to) {
      g2[v].insert(to);
    }
  }
}
void dfs_tree(int v) {
  for (auto itr = tree[v].begin(); itr != tree[v].end(); itr++) {
    dfs_tree(*itr);
  }
  while (g2[v].size() >= 2) {
    auto itr = g2[v].begin();
    int dlfjl = (*itr);
    g2[dlfjl].erase(v);
    g2[v].erase(itr);
    itr = g2[v].begin();
    int dkfj = (*itr);
    g2[dkfj].erase(v);
    g2[v].erase(itr);
    ans.push_back(make_pair(make_pair(dlfjl, v), dkfj));
  }
  if (p[v] == -1) return;
  if (g2[v].size() == 1) {
    auto itr = g2[v].begin();
    int dlfjl = (*itr);
    g2[dlfjl].erase(v);
    ans.push_back(make_pair(make_pair(dlfjl, v), p[v]));
  } else {
    g2[p[v]].insert(v);
  }
}
int main() {
  cin >> n >> m;
  for (i = 0; i < m; i++) {
    scanf("%d %d", &x, &y);
    g[x].push_back(y);
    g[y].push_back(x);
  }
  for (i = 1; i <= n; i++)
    if (!used[i]) {
      f.clear();
      comp.clear();
      dfs(i);
      p[i] = -1;
      dfs_tree(i);
    }
  cout << ans.size() << endl;
  for (i = 0; i < ans.size(); i++) {
    printf("%d %d %d\n", ans[i].first.first, ans[i].first.second,
           ans[i].second);
  }
  return 0;
}
