#include <bits/stdc++.h>
using namespace std;
int m, n;
vector<vector<int>> adj;
vector<bool> used;
vector<int> tin;
vector<tuple<int, int, int>> ans;
int timer = 0;
map<pair<int, int>, bool> mp;
void dfs(int v, int p = -1) {
  used[v] = true;
  tin[v] = timer++;
  stack<int> q;
  for (int it : adj[v]) {
    if (it == p) continue;
    if (!used[it]) {
      dfs(it, v);
      if (mp[{it, v}]) {
        q.push(it);
        mp[{it, v}] = 0;
        mp[{v, it}] = 0;
      }
    } else {
      if (tin[v] < tin[it] && mp[{it, v}]) {
        q.push(it);
        mp[{it, v}] = 0;
        mp[{v, it}] = 0;
      }
    }
  }
  if (q.size() % 2 && p != -1) {
    q.push(p);
    mp[{p, v}] = 0;
    mp[{v, p}] = 0;
  }
  while (q.size() >= 2) {
    int a = q.top();
    q.pop();
    int b = q.top();
    q.pop();
    ans.push_back({a + 1, v + 1, b + 1});
  }
}
void solve() {
  cin >> n >> m;
  adj.resize(n);
  used.resize(n);
  tin.resize(n);
  for (int i = 0; i < m; ++i) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    adj[a].push_back(b);
    adj[b].push_back(a);
    mp[{a, b}] = 1;
    mp[{b, a}] = 1;
  }
  for (int i = 0; i < n; ++i) {
    if (!used[i]) {
      dfs(i);
    }
  }
  cout << ans.size() << '\n';
  for (int i = 0; i < ans.size(); ++i) {
    cout << get<0>(ans[i]) << ' ' << get<1>(ans[i]) << ' ' << get<2>(ans[i])
         << '\n';
  }
}
int main() {
  ios::sync_with_stdio(false);
  solve();
}
