#include <bits/stdc++.h>
using namespace std;
vector<pair<int, int>> adj[200005];
vector<pair<int, int>> adj2[200005];
unordered_set<int> done;
vector<pair<int, pair<int, int>>> final;
void addedge(int u, int v, int id) {
  adj[u].push_back({v, id});
  adj[v].push_back({u, id});
}
bool visited[200005];
void dfs2(int u, int par) {
  visited[u] = true;
  for (auto k : adj[u]) {
    if (k.first == par || visited[k.first]) continue;
    adj2[u].push_back(k);
    dfs2(k.first, u);
  }
}
bool visited2[200005];
void dfs(int u, int par, int id) {
  vector<pair<int, int>> temp;
  if (adj2[u].empty()) {
    visited2[u] = true;
    return;
  }
  for (auto k : adj2[u]) dfs(k.first, u, k.second);
  for (auto k : adj[u]) {
    if (done.find(k.second) == done.end() && visited2[k.first])
      temp.push_back(k);
  }
  if (temp.size() > 0) {
    for (int i = 0; i < temp.size() - 1; i += 2) {
      final.push_back({temp[i].first, {u, temp[i + 1].first}});
      done.insert(temp[i].second);
      done.insert(temp[i + 1].second);
    }
  }
  if (temp.size() % 2 == 1) {
    if (par != -1) {
      final.push_back({temp.back().first, {u, par}});
      done.insert(id);
    }
  }
  visited2[u] = true;
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  ;
  int n, m;
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    int x, y;
    cin >> x >> y;
    addedge(x, y, i);
  }
  for (int i = 1; i <= n; i++) {
    if (!visited[i]) {
      dfs2(i, -1);
      dfs(i, -1, -1);
    }
  }
  cout << final.size() << endl;
  for (auto l : final) {
    cout << l.first << " " << l.second.first << " " << l.second.second << endl;
  }
}
