#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
struct info {
  int x, y, z;
};
vector<info> ans;
int dep[N], n, m, fa[N];
vector<int> g[N], edge[N];
void dfs(int x) {
  dep[x] = dep[fa[x]] + 1;
  for (int v : g[x]) {
    if (!dep[v]) {
      fa[v] = x;
      dfs(v);
    } else if (v != fa[x] && dep[v] < dep[x]) {
      edge[v].push_back(x);
    }
  }
}
int solve(int x) {
  for (int i = 0; i < edge[x].size() >> 1; i++) {
    ans.push_back((info){edge[x][i << 1], x, edge[x][i << 1 | 1]});
  }
  int res = 0;
  if (edge[x].size() & 1) {
    res = edge[x].back();
  }
  edge[x].clear();
  if (res) {
    edge[x].push_back(res);
  }
  for (int v : g[x]) {
    if (fa[v] == x) {
      int t = solve(v);
      if (t) {
        ans.push_back((info){x, v, t});
      } else {
        edge[x].push_back(v);
      }
    }
  }
  for (int i = 0; i < edge[x].size() >> 1; i++) {
    ans.push_back((info){edge[x][i << 1], x, edge[x][i << 1 | 1]});
  }
  return (edge[x].size() & 1) ? edge[x].back() : 0;
}
int main(void) {
  scanf("%d%d", &n, &m);
  for (int i = 1, u, v; i <= m; i++) {
    scanf("%d%d", &u, &v);
    g[u].push_back(v);
    g[v].push_back(u);
  }
  for (int i = 1; i <= n; i++) {
    if (!dep[i]) {
      dfs(i);
      solve(i);
    }
  }
  printf("%d\n", ans.size());
  for (info cur : ans) {
    printf("%d %d %d\n", cur.x, cur.y, cur.z);
  }
  return 0;
}
