#include <bits/stdc++.h>
using namespace std;
using tint = long long;
using ld = long double;
using pi = pair<tint, int>;
using pl = pair<tint, tint>;
using vi = vector<int>;
using vpi = vector<pi>;
using vpl = vector<pl>;
using vvi = vector<vi>;
using vl = vector<tint>;
using vb = vector<bool>;
const int MOD = 1e9 + 7;
const tint mod = 998244353;
const int MX = 2e5 + 5;
const tint INF = 1e18;
const int inf = 2e9;
const ld PI = acos(ld(-1));
const ld eps = 1e-8;
const int dx[4] = {1, -1, 0, 0};
const int dy[4] = {0, 0, 1, -1};
template <class T>
void remDup(vector<T>& v) {
  sort(begin(v), end(v));
  v.erase(unique(begin(v), end(v)), end(v));
}
template <class T>
bool ckmin(T& a, const T& b) {
  return b < a ? a = b, 1 : 0;
}
template <class T>
bool ckmax(T& a, const T& b) {
  return a < b ? a = b, 1 : 0;
}
bool valid(int x, int y, int n, int m) {
  return (0 <= x && x < n && 0 <= y && y < m);
}
tint cdiv(tint a, tint b) { return a / b + ((a ^ b) > 0 && a % b); }
tint fdiv(int a, int b) { return a / b - ((a ^ b) < 0 && a % b); }
void NACHO(string name = "") {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  if ((int)(name).size()) {
    freopen((name + ".in").c_str(), "r", stdin);
    freopen((name + ".out").c_str(), "w", stdout);
  }
}
vi adj[MX];
int visited[MX];
int tim = 1;
vvi ret;
bool dfs(int node, int pa) {
  visited[node] = tim++;
  vi second;
  for (auto& u : adj[node]) {
    if (u == pa) continue;
    if (!visited[u]) {
      if (dfs(u, node)) second.push_back(u);
    } else if (visited[u] < visited[node]) {
      second.push_back(u);
    }
  }
  for (int i = (0); i < ((int)(second).size() / 2); ++i)
    ret.push_back({second[2 * i], node, second[2 * i + 1]});
  if ((int)(second).size() % 2 == 0) return 1;
  if (pa != -1) ret.push_back({second.back(), node, pa});
  return 0;
}
int main() {
  NACHO();
  int n, m;
  cin >> n >> m;
  for (int i = (0); i < (m); ++i) {
    int u, v;
    cin >> u >> v;
    --u, --v;
    adj[u].push_back(v);
    adj[v].push_back(u);
  }
  for (int i = (0); i < (n); ++i)
    if (!visited[i]) dfs(i, -1);
  cout << (int)(ret).size() << "\n";
  for (auto& u : ret) {
    cout << u[0] + 1 << " " << u[1] + 1 << " " << u[2] + 1 << "\n";
  }
}
