#include <bits/stdc++.h>
namespace fastIO {
bool IOerror = 0;
inline char nc() {
  static char buf[100000], *p1 = buf + 100000, *pend = buf + 100000;
  if (p1 == pend) {
    p1 = buf;
    pend = buf + fread(buf, 1, 100000, stdin);
    if (pend == p1) {
      IOerror = 1;
      return -1;
    }
  }
  return *p1++;
}
inline bool blank(char ch) {
  return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
inline void read(int &x) {
  char ch;
  while (blank(ch = nc()))
    ;
  if (IOerror) return;
  for (x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0')
    ;
}
};  // namespace fastIO
template <class T>
inline T lowbit(T x) {
  return x & (-x);
}
template <class T>
inline T sqr(T x) {
  return x * x;
}
template <class T>
inline bool scan(T &ret) {
  char c;
  int sgn;
  if (c = getchar(), c == EOF) return 0;
  while (c != '-' && (c < '0' || c > '9')) c = getchar();
  sgn = (c == '-') ? -1 : 1;
  ret = (c == '-') ? 0 : (c - '0');
  while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
  ret *= sgn;
  return 1;
}
const double pi = 3.14159265358979323846264338327950288L;
using namespace std;
const long long mod = 1000000007;
int n, m;
struct node {
  int u, v, next;
} edge[200005 * 2];
int head[200005], cnt;
vector<int> ans[200005];
bool vis[200005], is[200005];
void add_edge(int u, int v) {
  edge[cnt] = (node){u, v, head[u]};
  head[u] = cnt++;
}
vector<int> a;
int deep[200005];
void dfs(int u, int d) {
  deep[u] = d + 1;
  vis[u] = 1;
  a.push_back(u);
  for (int i = head[u]; i + 1; i = edge[i].next) {
    int v = edge[i].v;
    if (vis[v]) continue;
    dfs(v, d + 1);
  }
}
bool cmp(const int &a, const int &b) { return deep[a] > deep[b]; }
void solve() {
  sort(a.begin(), a.end(), cmp);
  int sz = a.size();
  for (int i = 0; i < sz; i++) {
    int u = a[i];
    is[u] = 1;
    for (int j = head[u]; j + 1; j = edge[j].next) {
      int v = edge[j].v;
      if (is[v]) continue;
      ans[u].push_back(v);
    }
    if (ans[u].size() % 2 == 1) {
      int tmp = *ans[u].rbegin();
      ans[u].pop_back();
      ans[tmp].push_back(u);
    }
  }
}
int main() {
  memset(head, -1, sizeof(head));
  cnt = 0;
  cin >> n >> m;
  for (int i = 1; i <= n; i++) {
    ans[i].clear();
  }
  for (int i = 1; i <= m; i++) {
    int u, v;
    cin >> u >> v;
    add_edge(u, v);
    add_edge(v, u);
  }
  memset(vis, 0, sizeof(vis));
  memset(is, 0, sizeof(is));
  for (int i = 1; i <= n; i++)
    if (!vis[i]) {
      a.clear();
      dfs(i, 0);
      solve();
    }
  int sum = 0;
  for (int i = 1; i <= n; i++) sum += ans[i].size() / 2;
  cout << sum << endl;
  for (int i = 1; i <= n; i++) {
    int sz = ans[i].size();
    for (int j = 0; j + 1 < sz; j += 2) {
      printf("%d %d %d\n", ans[i][j], i, ans[i][j + 1]);
    }
  }
  return 0;
}
