#include <bits/stdc++.h>
using namespace std;
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
const int N = 4e5 + 5;
int deg[N];
vector<pair<int, int>> Graph[N];
int visited[N];
int visited_edge[N];
vector<pair<int, int>> ans;
void dfs(int u, int p) {
  visited[u] = true;
  vector<int> tree_edges;
  vector<int> back_edges;
  for (auto e : Graph[u]) {
    int v = e.first;
    int in = e.second;
    if (!visited[v]) {
      tree_edges.push_back(in);
      dfs(v, in);
    } else if (in != p) {
      back_edges.push_back(in);
    }
  }
  vector<int> all_edges;
  for (auto in : tree_edges) {
    if (!visited_edge[in]) {
      all_edges.push_back(in);
    }
  }
  for (auto in : back_edges) {
    if (!visited_edge[in]) {
      all_edges.push_back(in);
    }
  }
  if (all_edges.size() % 2 == 1) {
    if (p) {
      visited_edge[p] = 1;
      all_edges.push_back(p);
    } else
      all_edges.pop_back();
  }
  assert(all_edges.size() % 2 == 0);
  for (int i = 0; i + 1 < all_edges.size(); i += 2) {
    ans.push_back({all_edges[i], all_edges[i + 1]});
    visited_edge[all_edges[i]] = 1;
    visited_edge[all_edges[i + 1]] = 1;
  }
}
int uu[N];
int vv[N];
int main() {
  int n, m;
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    scanf("%d %d", uu + i, vv + i);
    Graph[uu[i]].push_back({vv[i], i});
    Graph[vv[i]].push_back({uu[i], i});
  }
  for (int i = 1; i <= n; i++) {
    if (!visited[i]) {
      dfs(i, 0);
    }
  }
  cout << ans.size() << endl;
  for (auto e : ans) {
    int u1 = uu[e.first];
    int v1 = vv[e.first];
    int u2 = uu[e.second];
    int v2 = vv[e.second];
    int a, b, c;
    if (u1 == u2) {
      a = v1;
      b = u1;
      c = v2;
    } else if (u1 == v2) {
      a = v1;
      b = u1;
      c = u2;
    } else if (v1 == u2) {
      a = u1;
      b = v1;
      c = v2;
    } else {
      a = u1;
      b = v1;
      c = u2;
    }
    printf("%d %d %d\n", a, b, c);
  }
}
