← Home
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 55
#define fir first
#define sec second
#define ll long long
#define pb push_back
#define eb emplace_back
//#define int long long
 
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}
 
int n, m;
int chess[N][N], rev[N][N];
pair<int, int> tar[N], pos[N];
vector<tuple<int,int,int,int>> ans;
 
void move(int p, int dltx, int dlty) {
	ans.pb({pos[p].fir, pos[p].sec, pos[p].fir+dltx, pos[p].sec+dlty});
	chess[pos[p].fir][pos[p].sec]=0;
	pos[p].fir+=dltx; pos[p].sec+=dlty;
	chess[pos[p].fir][pos[p].sec]=p;
}
 
namespace task1{
	random_device seed;
	mt19937 rand(seed());
	bool check() {
		for (int i=1; i<=m; ++i) if (pos[i]!=tar[i]) return 0;
		return 1;
	}
	void solve() {
		while (!check()) {
			int u=1+rand()%m, dltx=0, dlty=0;
			if (rand()&1) dltx=1-2*(rand()&1);
			else dlty=1-2*(rand()&1);
			int tarx=pos[u].fir+dltx, tary=pos[u].sec+dlty;
			if (1<=tarx && tarx<=n && 1<=tary && tary<=n && !chess[tarx][tary])
				move(u, dltx, dlty);
		}
	}
}
 
namespace task2{
	queue<int> que;
	void printChess() {
		for (int y=n; y; --y)
			for (int x=1; x<=n; ++x)
				printf("%d%c", chess[x][y], " \n"[x==n]);
	}
	void solve() {
		// 将y=1上的点向左移
		for (int i=1,u; i<=n; ++i) if (u=chess[i][1])
			for (int j=pos[u].fir; j>1&&!chess[j-1][1]; --j)
				move(u, -1, 0);
		// 将所有点下移至y=1
		for (int y=2; y<=n; ++y) {
			for (int x=n,u; x; --x) if (u=chess[x][y]) {
				for (int i=y; i>2; --i) move(u, 0, -1);
				for (int i=x; i<n&&chess[i][1]; ++i) move(u, 1, 0);
				move(u, 0, -1);
				for (int i=pos[u].fir; i>1&&!chess[i-1][1]; --i) move(u, -1, 0);
			}
		}
		// cout<<"pos1: step "<<ans.size()<<endl;
		// 通过交换处理目标位置在y=1上的点
		for (int i=1,u,v; i<=n; ++i) if ((u=chess[i][1])&&tar[u].sec==1) {
			if ((v=chess[tar[u].fir][tar[u].sec])==u) continue;
			// 将点v移至y=3以防挡路
			if (v) move(v, 0, 1), move(v, 0, 1);
			// 将点u移至目标位置
			int dlt=tar[u].fir<pos[u].fir?-1:1;
			move(u, 0, 1);
			while (pos[u].fir!=tar[u].fir) move(u, dlt, 0);
			move(u, 0, -1);
			// 将点v移至点u原来位置以完成交换
			if (v) {
				dlt*=-1;
				while (pos[v].fir!=i) move(v, dlt, 0);
				move(v, 0, -1), move(v, 0, -1);
			}
			// 交换来的点可能需要再交换走
			if (tar[v].sec==1) --i;
		}
		// cout<<"pos2: step "<<ans.size()<<endl;
		// 通过内部排序处理目标位置在y=2上的点
		for (int i=1,u; i<=n; ++i) if (tar[u=chess[i][1]].sec==2) {
			que.push(i);
			// 将这些点暂存至y=3
			move(u, 0, 1), move(u, 0, 1);
		}
		// cout<<"pos3: step "<<ans.size()<<endl;
		// 将暂存的点移回y=1
		for (int i=1,u; i<=n; ++i) if (u=rev[i][2]) {
			move(u, 0, -1);
			int dlt=pos[u].fir<que.front()?1:-1;
			while (pos[u].fir!=que.front()) move(u, dlt, 0);
			move(u, 0, -1);
			que.pop();
		}
		// cout<<"pos4: step "<<ans.size()<<endl;
		// 移回目标位置在y>=3的点
		for (int y=n; y>=3; --y) {
			for (int x=1,u; x<=n; ++x) if (u=rev[x][y]) {
				// cout<<"rev: "<<u<<endl;
				while (pos[u].sec<y-1) move(u, 0, 1);
				int dlt=pos[u].fir<x?1:-1;
				while (pos[u].fir!=x) move(u, dlt, 0);
				move(u, 0, 1);
			}
		}
		// printChess();
		// 移回目标位置在y=2上的点
		for (int l=1,r,sta=0; l<=n; l=r+1) {
			// cout<<"begin_while: l="<<l<<endl;
			// 通过类括号序列划分点集
			while (l<=n && tar[chess[l][1]].sec!=2 && !rev[l][2]) ++l;
			if (l>n) break;
			// cout<<"l="<<l<<' ';
			for (r=l; r==l||sta; ++r) {
				if (tar[chess[r][1]].sec==2) ++sta;
				if (rev[r][2]) --sta;
			} --r;
			// cout<<"r="<<r<<endl;
			// 扫描线移回点集内的点
			if (rev[l][2]) {
				// 将点向左移
				for (int i=l,u; i<=r; ++i) if (u=rev[i][2]) {
					move(u, 0, 1);
					while (pos[u].fir!=i) move(u, -1, 0);
				}
			}
			else {
				// 将点向右移
				for (int i=r,u; i>=l; --i) if (u=rev[i][2]) {
					move(u, 0, 1);
					while (pos[u].fir!=i) move(u, 1, 0);
				}
			}
		}
	}
}
 
signed main() {
	// freopen("a.in", "r", stdin);
	// freopen("a.out", "w", stdout);
 
	n=read(); m=read();
	for (int i=1; i<=m; ++i) {
		pos[i].fir=read(); pos[i].sec=read();
		chess[pos[i].fir][pos[i].sec]=i;
	}
	for (int i=1,x,y; i<=m; ++i) {
		x=read(); y=read();
		tar[i]={x, y}; rev[x][y]=i;
	}
	switch (n) {
		case 1: break;
		case 2: task1::solve(); break;
		default: task2::solve();
	}
	printf("%d\n", ans.size());
	for (auto& it:ans) {
		auto& [a, b, c, d]=it;
		printf("%d %d %d %d\n", a, b, c, d);
	}
 
	return 0;
}