Allen dreams of one day owning a enormous fleet of electric cars, the car of the future! He knows that this will give him a big status boost. As Allen is planning out all of the different types of cars he will own and how he will arrange them, he realizes that he has a problem. 

Allen's future parking lot can be represented as a rectangle with $4$ rows and $n$ ($n \le 50$) columns of rectangular spaces, each of which can contain at most one car at any time. He imagines having $k$ ($k \le 2n$) cars in the grid, and all the cars are initially in the second and third rows. Each of the cars also has a different designated parking space in the first or fourth row. Allen has to put the cars into corresponding parking places.

 [Image] Illustration to the first example. 

However, since Allen would never entrust his cars to anyone else, only one car can be moved at a time. He can drive a car from a space in any of the four cardinal directions to a neighboring empty space. Furthermore, Allen can only move one of his cars into a space on the first or fourth rows if it is the car's designated parking space. 

Allen knows he will be a very busy man, and will only have time to move cars at most $20000$ times before he realizes that moving cars is not worth his time. Help Allen determine if he should bother parking his cars or leave it to someone less important.


-----Input-----

The first line of the input contains two space-separated integers $n$ and $k$ ($1 \le n \le 50$, $1 \le k \le 2n$), representing the number of columns and the number of cars, respectively.

The next four lines will contain $n$ integers each between $0$ and $k$ inclusive, representing the initial state of the parking lot. The rows are numbered $1$ to $4$ from top to bottom and the columns are numbered $1$ to $n$ from left to right.

In the first and last line, an integer $1 \le x \le k$ represents a parking spot assigned to car $x$ (you can only move this car to this place), while the integer $0$ represents a empty space (you can't move any car to this place).

In the second and third line, an integer $1 \le x \le k$ represents initial position of car $x$, while the integer $0$ represents an empty space (you can move any car to this place).

Each $x$ between $1$ and $k$ appears exactly once in the second and third line, and exactly once in the first and fourth line.


-----Output-----

If there is a sequence of moves that brings all of the cars to their parking spaces, with at most $20000$ car moves, then print $m$, the number of moves, on the first line. On the following $m$ lines, print the moves (one move per line) in the format $i$ $r$ $c$, which corresponds to Allen moving car $i$ to the neighboring space at row $r$ and column $c$.

If it is not possible for Allen to move all the cars to the correct spaces with at most $20000$ car moves, print a single line with the integer $-1$.


-----Examples-----
Input
4 5
1 2 0 4
1 2 0 4
5 0 0 3
0 5 0 3

Output
6
1 1 1
2 1 2
4 1 4
3 4 4
5 3 2
5 4 2

Input
1 2
1
2
1
2

Output
-1

Input
1 2
1
1
2
2

Output
2
1 1 1
2 4 1



-----Note-----

In the first sample test case, all cars are in front of their spots except car $5$, which is in front of the parking spot adjacent. The example shows the shortest possible sequence of moves, but any sequence of length at most $20000$ will be accepted.

In the second sample test case, there is only one column, and the cars are in the wrong order, so no cars can move and the task is impossible.

Difficulty: HARD
Tags: Implementation

Constructive algorithms

Starter code:

Solutions:
numbers = list(map(int, input().split()))
n = numbers[0]
k = numbers[1]
left = 0
left = k
table = []
x = 4
while x > 0:
	table.append(list(map(int, input().split())))
	x = x - 1
moves = []
for i in range(n):
	if table[1][i] == table[0][i] and table[1][i] != 0:
		moves.append((table[1][i], 1, i + 1))
		table[0][i] = table[1][i]
		table[1][i] = 0
	if table[2][i] == table[3][i] and table[2][i] != 0:
		moves.append((table[2][i], 4, i + 1))
		table[3][i] = table[2][i]
		table[2][i] = 0
ok = 0
for i in range(n):
	if table[1][i] == 0:
		ok = 1
		break
	if table[2][i] == 0:
		ok = 1
		break
if ok == 0:
	print(-1)
	exit(0)
for i in range(20000):
	if table[1][0] != 0 and table[2][0] == 0:
		moves.append((table[1][0], 3, 1))
		table[2][0] = table[1][0]
		table[1][0] = 0
		if n == 1:
			continue
	for j in range(1, n):
		if table[1][j - 1] == 0 and table[1][j] != 0:
			moves.append((table[1][j], 2, j))
			table[1][j - 1] = table[1][j]
			table[1][j] = 0
	for j in range(n):
		if table[1][j] == table[0][j] and table[1][j] != 0:
			moves.append((table[1][j], 1, j + 1))
			table[0][j] = table[1][j]
			table[1][j] = 0
		if table[2][j] == table[3][j] and table[2][j] != 0:
			moves.append((table[2][j], 4, j + 1))
			table[3][j] = table[2][j]
			table[2][j] = 0
	if table[1][n - 1] == 0 and table[2][n - 1] != 0:
		moves.append((table[2][n - 1], 2, n))
		table[1][n - 1] = table[2][n - 1]
		table[2][n - 1] = 0
	for j in range(n - 2, -1, -1):
		if table[2][j + 1] == 0 and table[2][j] != 0:
			moves.append((table[2][j], 3, j + 2))
			table[2][j + 1] = table[2][j]
			table[2][j] = 0
	for j in range(n):
		if table[1][j] == table[0][j] and table[1][j] != 0:
			moves.append((table[1][j], 1, j + 1))
			table[0][j] = table[1][j]
			table[1][j] = 0
		if table[2][j] == table[3][j] and table[2][j] != 0:
			moves.append((table[2][j], 4, j + 1))
			table[3][j] = table[2][j]
			table[2][j] = 0
if len(moves) > 20000:
	print(-1)
	exit(0)
print(len(moves))
for j in moves:
	print(*j)


import collections
from functools import cmp_to_key
import math
import sys

def getIntList():
	return list(map(int, input().split()))
import bisect
try:
	import numpy
	dprint = print
	dprint('debug mode')
except ModuleNotFoundError:

	def dprint(*args, **kwargs):
		pass

def makePair(z):
	return [(z[i], z[i + 1]) for i in range(0, len(z), 2)]

def memo(func):
	cache = {}

	def wrap(*args):
		if args not in cache:
			cache[args] = func(*args)
		return cache[args]
	return wrap

@memo
def comb(n, k):
	if k == 0:
		return 1
	if n == k:
		return 1
	return comb(n - 1, k - 1) + comb(n - 1, k)
(N, K) = getIntList()
z1 = getIntList()
z2 = getIntList()
z3 = getIntList()
z4 = getIntList()
blank = [0 for i in range(N + 2)]
zz = [blank, [0] + z1 + [0], [0] + z2 + [0], [0] + z3 + [0], [0] + z4 + [0], blank]
res = []

def checkpark():
	for x in range(2, 4):
		for y in range(1, N + 1):
			if zz[x][y] == 0:
				continue
			if x == 2:
				x0 = 1
			else:
				x0 = 4
			if zz[x][y] == zz[x0][y]:
				res.append((zz[x][y], x0, y))
				zz[x][y] = 0

def ifallin():
	for x in range(2, 4):
		for y in range(1, N + 1):
			if zz[x][y] != 0:
				return False
	return True

def rotate():
	ex = 0
	ey = 0
	for x in range(2, 4):
		for y in range(1, N + 1):
			if zz[x][y] == 0:
				ex = x
				ey = y
				break
		if ex > 0:
			break
	if ex == 0:
		return False
	tx = ex
	ty = ey

	def nextcircle(x, y):
		if x == 2:
			if y > 1:
				return (x, y - 1)
			return (x + 1, y)
		else:
			assert x == 3
			if y < N:
				return (x, y + 1)
			return (x - 1, y)
	(tx1, ty1) = nextcircle(tx, ty)
	while (tx1, ty1) != (ex, ey):
		t = zz[tx1][ty1]
		if t != 0:
			res.append((t, tx, ty))
			zz[tx][ty] = t
			zz[tx1][ty1] = 0
		(tx, ty) = (tx1, ty1)
		(tx1, ty1) = nextcircle(tx, ty)
	return True
while True:
	for x in range(1, 5):
		dprint(zz[x])
	dprint()
	checkpark()
	ok = ifallin()
	if ok:
		break
	ok = rotate()
	if not ok:
		print(-1)
		sys.exit()
print(len(res))
for x in res:
	print(x[0], x[1], x[2])


(k, n) = [int(x) for x in input().split()]
a = []
for i in range(4):
	a.append([int(x) - 1 for x in input().split()])
pos = []
for i in range(k):
	pos.append([1, i])
for i in range(k):
	pos.append([2, k - i - 1])
lft = n
ans = []
for i in range(2 * k):
	for j in range(2 * k):
		if a[pos[j][0]][pos[j][1]] != -1 and a[pos[j][0]][pos[j][1]] == a[pos[j][0] ^ 1][pos[j][1]]:
			lft -= 1
			ans.append([a[pos[j][0]][pos[j][1]], pos[j][0] ^ 1, pos[j][1]])
			a[pos[j][0]][pos[j][1]] = -1
	if lft == 0:
		break
	fst = -1
	for j in range(2 * k):
		if a[pos[j][0]][pos[j][1]] != -1 and a[pos[(j + 1) % (2 * k)][0]][pos[(j + 1) % (2 * k)][1]] == -1:
			fst = j
			break
	if fst == -1:
		print(-1)
		exit(0)
	for j in range(2 * k - 1):
		if a[pos[(fst - j) % (2 * k)][0]][pos[(fst - j) % (2 * k)][1]] != -1:
			a[pos[(fst - j + 1) % (2 * k)][0]][pos[(fst - j + 1) % (2 * k)][1]] = a[pos[(fst - j) % (2 * k)][0]][pos[(fst - j) % (2 * k)][1]]
			a[pos[(fst - j) % (2 * k)][0]][pos[(fst - j) % (2 * k)][1]] = -1
			ans.append([a[pos[(fst - j + 1) % (2 * k)][0]][pos[(fst - j + 1) % (2 * k)][1]], pos[(fst - j + 1) % (2 * k)][0], pos[(fst - j + 1) % (2 * k)][1]])
print(len(ans))
for i in ans:
	print(' '.join([str(x + 1) for x in i]))


def all_parked(parked):
	result = True
	for p in parked:
		result = result and p
	return result

class CodeforcesTask995ASolution:

	def __init__(self):
		self.result = ''
		self.n_k = []
		self.parking = []

	def read_input(self):
		self.n_k = [int(x) for x in input().split(' ')]
		for x in range(4):
			self.parking.append([int(y) for y in input().split(' ')])

	def process_task(self):
		parked = [False for x in range(self.n_k[1])]
		moves = []
		for x in range(self.n_k[0]):
			if self.parking[0][x] == self.parking[1][x] and self.parking[1][x]:
				moves.append([self.parking[0][x], 1, x + 1])
				self.parking[1][x] = 0
				parked[self.parking[0][x] - 1] = True
			if self.parking[3][x] == self.parking[2][x] and self.parking[3][x]:
				moves.append([self.parking[3][x], 4, x + 1])
				self.parking[2][x] = 0
				parked[self.parking[3][x] - 1] = True
		if sum([1 if not x else 0 for x in parked]) == self.n_k[1] and self.n_k[1] == self.n_k[0] * 2:
			self.result = '-1'
		else:
			while not all_parked(parked):
				moved = [False for x in range(self.n_k[0])]
				if self.parking[1][0] and (not self.parking[2][0]):
					moves.append([self.parking[1][0], 3, 1])
					self.parking[2][0] = self.parking[1][0]
					self.parking[1][0] = 0
					moved[0] = True
				for x in range(1, self.n_k[0]):
					if not self.parking[1][x - 1] and self.parking[1][x]:
						moves.append([self.parking[1][x], 2, x])
						self.parking[1][x - 1] = self.parking[1][x]
						self.parking[1][x] = 0
				if not self.parking[1][self.n_k[0] - 1] and self.parking[2][self.n_k[0] - 1] and (not moved[self.n_k[0] - 1]):
					moves.append([self.parking[2][self.n_k[0] - 1], 2, self.n_k[0]])
					self.parking[1][self.n_k[0] - 1] = self.parking[2][self.n_k[0] - 1]
					self.parking[2][self.n_k[0] - 1] = 0
				for x in range(self.n_k[0] - 1):
					if not self.parking[2][x + 1] and self.parking[2][x] and (not moved[x]):
						moves.append([self.parking[2][x], 3, x + 2])
						self.parking[2][x + 1] = self.parking[2][x]
						self.parking[2][x] = 0
						moved[x + 1] = True
				for x in range(self.n_k[0]):
					if self.parking[0][x] == self.parking[1][x] and self.parking[1][x]:
						moves.append([self.parking[0][x], 1, x + 1])
						self.parking[1][x] = 0
						parked[self.parking[0][x] - 1] = True
					if self.parking[3][x] == self.parking[2][x] and self.parking[3][x]:
						moves.append([self.parking[3][x], 4, x + 1])
						self.parking[2][x] = 0
						parked[self.parking[3][x] - 1] = True
			self.result = '{0}\n{1}'.format(len(moves), '\n'.join([' '.join([str(x) for x in move]) for move in moves]))

	def get_result(self):
		return self.result
Solution = CodeforcesTask995ASolution()
Solution.read_input()
Solution.process_task()
print(Solution.get_result())


from sys import exit
(n, k) = map(int, input().split())
a = [list(map(int, input().split())) for q in range(4)]
d = [[-1, 0], [0, 1], [1, 0], [0, -1]]
x = y = -1
ans = []

def move(k):
	global x, y, a
	x += d[k][0]
	y += d[k][1]
	if a[x][y]:
		ans.append([a[x][y], x - d[k][0] + 1, y - d[k][1] + 1])
		(a[x][y], a[x - d[k][0]][y - d[k][1]]) = (a[x - d[k][0]][y - d[k][1]], a[x][y])
if k == 2 * n:
	for q in range(n):
		if a[1][q] == a[0][q]:
			ans.append([a[1][q], 1, q + 1])
			a[1][q] = 0
			break
	else:
		for q in range(n):
			if a[2][q] == a[3][q]:
				ans.append([a[2][q], 4, q + 1])
				a[2][q] = 0
				break
		else:
			print(-1)
			exit(0)
for q in range(1, 2 * n + 1):
	if q in a[1]:
		(x1, y1) = (1, a[1].index(q))
	elif q in a[2]:
		(x1, y1) = (2, a[2].index(q))
	else:
		continue
	if q in a[0]:
		(x2, y2) = (0, a[0].index(q))
	else:
		(x2, y2) = (3, a[3].index(q))
	if 0 in a[1]:
		(x, y) = (1, a[1].index(0))
	else:
		(x, y) = (2, a[2].index(0))
	if x == x1 and x == 1:
		move(2)
	elif x == x1 and x == 2:
		move(0)
	while y < y1:
		move(1)
	while y > y1:
		move(3)
	if x1 == 1 and x2 == 3:
		move(0)
		x1 += 1
	elif x1 == 2 and x2 == 0:
		move(2)
		x1 -= 1
	if x1 == 1:
		if y1 < y2:
			move(1)
			move(0)
			move(3)
			y1 += 1
			while y1 < y2:
				move(2)
				move(1)
				move(1)
				move(0)
				move(3)
				y1 += 1
		elif y1 > y2:
			move(3)
			move(0)
			move(1)
			y1 -= 1
			while y1 > y2:
				move(2)
				move(3)
				move(3)
				move(0)
				move(1)
				y1 -= 1
	elif y1 < y2:
		move(1)
		move(2)
		move(3)
		y1 += 1
		while y1 < y2:
			move(0)
			move(1)
			move(1)
			move(2)
			move(3)
			y1 += 1
	elif y1 > y2:
		move(3)
		move(2)
		move(1)
		y1 -= 1
		while y1 > y2:
			move(0)
			move(3)
			move(3)
			move(2)
			move(1)
			y1 -= 1
	ans.append([a[x1][y1], x2 + 1, y2 + 1])
	a[x1][y1] = 0
print(len(ans))
for q in ans:
	print(*q)


def main():
	(n, k) = map(int, input().split())
	(a, b, c, d) = (list(map(int, input().split())) for _ in 'abcd')
	(ss, tt, n2, res) = ([*b, *c[::-1]], [*a, *d[::-1]], n * 2, [])
	yx = [*[(2, i + 1) for i in range(n)], *[(3, i) for i in range(n, 0, -1)]]

	def park():
		for (i, s, t, (y, x)) in zip(range(n2), ss, tt, yx):
			if s == t != 0:
				ss[i] = 0
				res.append(f'{s} {(1, 4)[y == 3]} {x}')

	def rotate():
		start = ss.index(0)
		for i in range(start - n2, start - 1):
			s = ss[i] = ss[i + 1]
			if s:
				(y, x) = yx[i]
				res.append(f'{s} {y} {x}')
		ss[start - 1] = 0
	park()
	if all(ss):
		print(-1)
		return
	while any(ss):
		rotate()
		park()
	print(len(res), '\n'.join(res), sep='\n')

def __starting_point():
	main()
__starting_point()


(n, k) = map(int, input().split())
grid = [list(map(int, input().split())) for _ in range(4)]
possible = True
if all((c != 0 for cars in (grid[1], grid[2]) for c in cars)):
	if all((a != b for (a, b) in zip(grid[0], grid[1]))):
		if all((a != b for (a, b) in zip(grid[3], grid[2]))):
			possible = False
			print(-1)
sol = []
if possible:
	while True:
		for col in range(n):
			if grid[1][col] != 0 and grid[1][col] == grid[0][col]:
				sol.append((grid[1][col], 1, col + 1))
				grid[1][col] = 0
				k -= 1
			if grid[2][col] != 0 and grid[2][col] == grid[3][col]:
				sol.append((grid[2][col], 4, col + 1))
				grid[2][col] = 0
				k -= 1
		if k == 0:
			break
		row = None
		col = None
		while True:
			if grid[2][0] != 0 and grid[1][0] == 0:
				row = 2
				col = 0
				break
			if grid[1][n - 1] != 0 and grid[2][n - 1] == 0:
				row = 1
				col = n - 1
				break
			for idx in range(n - 1):
				if grid[1][idx] != 0 and grid[1][idx + 1] == 0:
					row = 1
					col = idx
					break
			if col is not None:
				break
			for idx in range(n - 1):
				if grid[2][idx] == 0 and grid[2][idx + 1] != 0:
					row = 2
					col = idx + 1
					break
			break
		for _ in range(k):
			if row == 1 and col == n - 1:
				sol.append((grid[row][col], 3, n))
				grid[2][col] = grid[row][col]
				grid[row][col] = 0
			elif row == 2 and col == 0:
				sol.append((grid[row][col], 2, 1))
				grid[1][col] = grid[row][col]
				grid[row][col] = 0
			elif row == 2:
				sol.append((grid[row][col], row + 1, col))
				grid[row][col - 1] = grid[row][col]
				grid[row][col] = 0
			else:
				sol.append((grid[row][col], row + 1, col + 2))
				grid[row][col + 1] = grid[row][col]
				grid[row][col] = 0
			while True:
				if row == 1 and col == 0:
					row = 2
				elif row == 2 and col == n - 1:
					row = 1
				elif row == 2:
					col += 1
				else:
					col -= 1
				if grid[row][col] != 0:
					break
	print(len(sol))
	for move in sol:
		print(*move)


import time
max = 20000

def test(x1, x2, n, s):
	for i in range(x1 + 1, x2 + 1):
		if s[n][i] != 0:
			return False
	return True

def lastshift(n, s, a):
	m = 0
	for i in range(n):
		if s[1][i] != 0 and s[1][i] == s[0][i]:
			s[1][i] = 0
			m += 1
			a.append([s[0][i], 1, i + 1])
		if s[2][i] != 0 and s[2][i] == s[3][i]:
			s[2][i] = 0
			m += 1
			a.append([s[3][i], 4, i + 1])
	return m
(n, k) = (int(i) for i in input().split())
s = []
s.append([int(i) for i in input().split()])
s.append([int(i) for i in input().split()])
s.append([int(i) for i in input().split()])
s.append([int(i) for i in input().split()])
start = time.time()
a = []
m = lastshift(n, s, a)
I = -1
z = 0
for i in range(n):
	if s[1][i] == 0:
		l = 1
		I = i
		break
	if s[2][i] == 0:
		l = 2
		I = i
		break
if I >= 0:
	while m < k:
		b = s[1][0]
		e = s[2][n - 1]
		if l == 1:
			for i in range(I, n - 1):
				s[1][i] = s[1][i + 1]
				if s[1][i + 1] != 0:
					a.append([s[1][i + 1], 2, i + 1])
			if e != 0:
				a.append([e, 2, n])
			for i in range(n - 1, 0, -1):
				s[2][i] = s[2][i - 1]
				if s[2][i] != 0:
					a.append([s[2][i], 3, i + 1])
			if b != 0:
				a.append([b, 3, 1])
			for i in range(I - 1):
				s[1][i] = s[1][i + 1]
				if s[1][i + 1] != 0:
					a.append([s[1][i + 1], 2, i + 1])
			s[1][n - 1] = e
			s[2][0] = b
		else:
			for i in range(I, 0, -1):
				s[2][i] = s[2][i - 1]
				if s[2][i] != 0:
					a.append([s[2][i], 3, i + 1])
			if b != 0:
				a.append([b, 3, 1])
			for i in range(n - 1):
				s[1][i] = s[1][i + 1]
				if s[1][i] != 0:
					a.append([s[1][i], 2, i + 1])
			if e != 0:
				a.append([e, 2, n])
			s[1][n - 1] = e
			s[2][0] = b
			for i in range(n - 1, I + 1, -1):
				s[2][i] = s[2][i - 1]
				if s[2][i] != 0:
					a.append([s[2][i], 3, i + 1])
		I += 2 * l - 3
		if I == -1:
			I = 0
			l = 2
		if I == n:
			I = n - 1
			l = 1
		s[l][I] = 0
		m += lastshift(n, s, a)
	print(len(a))
	for i in range(len(a)):
		print(a[i][0], a[i][1], a[i][2])
else:
	print(-1)
finish = time.time()


import sys
input = sys.stdin.readline
(n, k) = map(int, input().split())
cars = [list(map(int, input().split())) for _ in range(4)]
out = []
for _ in range(20000):
	for i in range(n)[::-1]:
		if cars[1][i] == 0:
			continue
		if cars[1][i] == cars[0][i]:
			out.append([cars[1][i], 0, i])
			cars[1][i] = 0
			cars[0][i] = 0
		elif i == n - 1 and cars[2][i] == 0:
			out.append([cars[1][i], 2, i])
			cars[2][i] = cars[1][i]
			cars[1][i] = 0
		elif i < n - 1 and cars[1][i + 1] == 0:
			out.append([cars[1][i], 1, i + 1])
			cars[1][i + 1] = cars[1][i]
			cars[1][i] = 0
	for i in range(n):
		if cars[2][i] == 0:
			continue
		if cars[2][i] == cars[3][i]:
			out.append([cars[2][i], 3, i])
			cars[2][i] = 0
			cars[3][i] = 0
		elif i == 0 and cars[1][i] == 0:
			out.append([cars[2][i], 1, i])
			cars[1][i] = cars[2][i]
			cars[2][i] = 0
		elif i > 0 and cars[2][i - 1] == 0:
			out.append([cars[2][i], 2, i - 1])
			cars[2][i - 1] = cars[2][i]
			cars[2][i] = 0
if sum(cars[1]) + sum(cars[2]) == 0 and len(out) <= 20000:
	print(len(out))
	for (i, j, k) in out:
		print('%d %d %d' % (i, j + 1, k + 1))
else:
	print('-1')


(n, k) = list(map(int, input().split()))
table = []
for row in range(4):
	table.append(list(map(int, input().split())))
moves = []

def make_move(start, finish):
	moves.append((table[start[0]][start[1]], finish[0] + 1, finish[1] + 1))
	table[finish[0]][finish[1]] = table[start[0]][start[1]]
	table[start[0]][start[1]] = 0

def move_all_to_places():
	for pos in range(n):
		if table[1][pos] == table[0][pos] and table[1][pos]:
			make_move((1, pos), (0, pos))
		if table[2][pos] == table[3][pos] and table[2][pos]:
			make_move((2, pos), (3, pos))
move_all_to_places()
found = False
for pos in range(n):
	if table[1][pos] == 0:
		found = True
		break
	if table[2][pos] == 0:
		found = True
		break
if not found:
	print(-1)
	exit()
for cnt in range(20000):
	if table[1][0] != 0 and table[2][0] == 0:
		make_move((1, 0), (2, 0))
		if n == 1:
			continue
	for pos in range(1, n):
		if table[1][pos - 1] == 0 and table[1][pos] != 0:
			make_move((1, pos), (1, pos - 1))
	move_all_to_places()
	if table[1][n - 1] == 0 and table[2][n - 1] != 0:
		make_move((2, n - 1), (1, n - 1))
	for pos in range(n - 2, -1, -1):
		if table[2][pos + 1] == 0 and table[2][pos] != 0:
			make_move((2, pos), (2, pos + 1))
	move_all_to_places()
if len(moves) > 20000:
	print(-1)
	exit()
print(len(moves))
for m in moves:
	print(*m)


(n, k) = map(int, input().split())
grid = [list(map(int, input().split())) for _ in range(4)]

def it():
	for i in range(1, n):
		yield ((1, i), (1, i - 1), (0, i))
	yield ((2, n - 1), (1, n - 1), (3, n - 1))
	for i in reversed(range(n - 1)):
		yield ((2, i), (2, i + 1), (3, i))
	yield ((1, 0), (2, 0), (0, 0))
for ((cx, cy), _, (px, py)) in it():
	if grid[cx][cy] == 0 or grid[cx][cy] == grid[px][py]:
		break
else:
	print(-1)
	exit()
result = []
parked = 0
while parked < k:
	for ((cx, cy), (nx, ny), (px, py)) in it():
		car = grid[cx][cy]
		if car == 0:
			continue
		if grid[px][py] == car:
			result.append((car, px, py))
			grid[cx][cy] = 0
			parked += 1
		elif grid[nx][ny] == 0:
			result.append((car, nx, ny))
			grid[nx][ny] = car
			grid[cx][cy] = 0
print(len(result))
for (c, x, y) in result:
	print(c, x + 1, y + 1)


(n, k) = map(int, input().strip().split())
p = list()
for _ in range(4):
	p.append(list(map(int, input().strip().split())))

def find():
	for i in range(n):
		if p[1][i] != 0 and p[0][i] == p[1][i]:
			car = p[1][i]
			p[1][i] = 0
			return [car, 1, i + 1]
		if p[2][i] != 0 and p[3][i] == p[2][i]:
			car = p[2][i]
			p[2][i] = 0
			return [car, 4, i + 1]
	return list()

def rotate():
	for c in range(n):
		if p[1][c] != 0:
			nc = c + 1
			nr = 1
			if nc == n:
				nc = n - 1
				nr = 2
			if p[nr][nc] == 0:
				ans.append([p[1][c], nr + 1, nc + 1])
				p[nr][nc] = p[1][c]
				p[1][c] = 0
				return
	for c in range(n):
		if p[2][c] != 0:
			nc = c - 1
			nr = 2
			if nc == -1:
				nc = 0
				nr = 1
			if p[nr][nc] == 0:
				ans.append([p[2][c], nr + 1, nc + 1])
				p[nr][nc] = p[2][c]
				p[2][c] = 0
				return
cnt = 0
ans = list()
while cnt < k:
	cur = find()
	if len(cur) == 0 and k == 2 * n and (cnt == 0):
		print(-1)
		exit(0)
	if cur:
		ans.append(cur)
		cnt += 1
	rotate()
print(len(ans))
for e in ans:
	print(' '.join(map(str, e)))


import os, sys
(n, k) = list(map(int, input().split()))
p0 = list(map(int, input().split()))
b0 = list(map(int, input().split()))
b1 = list(map(int, input().split()))
p1 = list(map(int, input().split()))
ops = []
for i in range(n):
	if p0[i] == 0:
		p0[i] = -1
	if p1[i] == 0:
		p1[i] = -1

def park():
	global p0, b0, b1, p1
	parked = 0
	for i in range(n):
		if p0[i] == b0[i]:
			ops.append(' '.join(map(str, (p0[i], 1, i + 1))))
			b0[i] = 0
			parked += 1
		if p1[i] == b1[i]:
			ops.append(' '.join(map(str, (p1[i], 4, i + 1))))
			b1[i] = 0
			parked += 1
	return parked

def nextpos(p):
	if p[0] == 0:
		if p[1] < n - 1:
			return (0, p[1] + 1)
		else:
			return (1, n - 1)
	elif p[1] > 0:
		return (1, p[1] - 1)
	else:
		return (0, 0)

def rotate():
	global b0, b1, p0, p1
	stpos = None
	for i in range(n):
		if b0[i] == 0:
			stpos = (0, i)
			break
	if stpos is None:
		for i in range(n):
			if b1[i] == 0:
				stpos = (1, i)
				break
	if stpos is None:
		return False
	cars = []
	if stpos[0] == 0:
		cars = b0[:stpos[1]][::-1] + b1 + b0[stpos[1]:][::-1]
		cars = list(filter(lambda x: x != 0, cars))
	else:
		cars = b1[stpos[1]:] + b0[::-1] + b1[:stpos[1]]
		cars = list(filter(lambda x: x != 0, cars))
	ppos = [None] * (k + 1)
	for i in range(n):
		if b0[i] != 0:
			ppos[b0[i]] = (0, i)
		if b1[i] != 0:
			ppos[b1[i]] = (1, i)
	for i in cars:
		if ppos[i] is not None:
			np = nextpos(ppos[i])
			ops.append(' '.join(map(str, (i, np[0] + 2, np[1] + 1))))
			ppos[i] = np
	b0 = [0] * n
	b1 = [0] * n
	for i in range(1, k + 1):
		if ppos[i] is not None:
			if ppos[i][0] == 0:
				b0[ppos[i][1]] = i
			else:
				b1[ppos[i][1]] = i
	return True

def checkfin():
	for i in range(n):
		if b0[i] != 0 or b1[i] != 0:
			return False
	return True
while not checkfin():
	park()
	if not rotate():
		print(-1)
		sys.exit(0)
print(len(ops))
print('\n'.join(ops))


(n, k) = list(map(int, input().split()))
m = []
c = 0
for i in range(4):
	m.append(list(map(int, input().split())))
res = []
for i in range(n):
	if m[1][i] != 0:
		if m[1][i] == m[0][i]:
			res.append([m[1][i], 1, i + 1])
			m[1][i] = 0
			k -= 1
for i in range(n):
	if m[2][i] != 0:
		if m[2][i] == m[3][i]:
			res.append([m[2][i], 4, i + 1])
			m[2][i] = 0
			k -= 1
if k >= n * 2:
	print(-1)
	return
if True:
	while True:
		c += 1
		for i in range(n):
			if m[1][i] != 0:
				if i != 0:
					if m[1][i - 1] == 0:
						res.append([m[1][i], 2, i])
						m[1][i - 1] = m[1][i]
						m[1][i] = 0
						if m[0][i - 1] == m[1][i - 1]:
							res.append([m[1][i - 1], 1, i])
							m[0][i - 1] = m[1][i - 1]
							m[1][i - 1] = 0
							k -= 1
				elif i == 0:
					if m[2][i] == 0:
						res.append([m[1][i], 3, i + 1])
						m[2][i] = m[1][i]
						m[1][i] = 0
						if m[3][i] == m[2][i]:
							res.append([m[2][i], 4, i + 1])
							m[3][i] = m[2][i]
							m[2][i] = 0
							k -= 1
		for i in range(n):
			if m[2][i] != 0:
				if i != n - 1:
					if m[2][i + 1] == 0:
						res.append([m[2][i], 3, i + 2])
						m[2][i + 1] = m[2][i]
						m[2][i] = 0
						if m[3][i + 1] == m[2][i + 1]:
							res.append([m[2][i + 1], 4, i + 2])
							m[3][i + 1] = m[2][i + 1]
							m[2][i + 1] = 0
							k -= 1
				elif m[1][i] == 0:
					res.append([m[2][i], 2, i + 1])
					m[1][i] = m[2][i]
					m[2][i] = 0
					if m[0][i] == m[1][i]:
						res.append([m[1][i], 1, i + 1])
						m[0][i] = m[1][i]
						m[1][i] = 0
						k -= 1
		if k <= 0:
			break
else:
	print(-1)
	return
print(len(res))
for i in res:
	print(*i)


a = [0] * 4
(n, k) = list(map(int, input().split()))
for i in range(4):
	a[i] = list(map(int, input().split()))
for i in range(n - 1, -1, -1):
	a[0].append(a[3][i])
	a[1].append(a[2][i])
ans = []

def check():
	nonlocal k
	for i in range(2 * n):
		if a[0][i] == a[1][i] and a[0][i] != 0:
			if i < n:
				ans.append([a[1][i], 0, i])
			else:
				ans.append([a[1][i], 3, 2 * n - i - 1])
			k -= 1
			a[0][i] = a[1][i] = 0

def fuck():
	step = -1
	for i in range(2 * n):
		if a[1][i] == 0:
			step = i
			break
	if step == -1:
		return False
	else:
		for i in range(2 * n - 1):
			x = (step + i) % (2 * n)
			y = (step + 1 + i) % (2 * n)
			if a[1][y] != 0:
				a[1][x] = a[1][y]
				if x == n - 1 and y == n:
					ans.append([a[1][y], 1, n - 1])
				elif x == 0 and y == 0:
					ans.append([a[1][y], 2, 0])
				elif x < n:
					ans.append([a[1][y], 1, x])
				else:
					ans.append([a[1][y], 2, 2 * n - x - 1])
				a[1][y] = 0
		return True
check()
while k != 0:
	if fuck() == False:
		print(-1)
		return
	check()
print(len(ans))
for i in ans:
	(x, y, z) = i
	print(x, y + 1, z + 1)


(n, k) = map(int, input().split())
m = [list(map(int, input().split())) for _ in range(4)]

def move():
	is_move = False
	is_park = False
	(ind, r, c) = (None, None, None)
	for (i, x) in enumerate(m[1]):
		if x != 0:
			if m[0][i] == x:
				is_move = True
				is_park = True
				m[1][i] = 0
				(ind, r, c) = (x, 0, i)
				break
			elif i + 1 < n and m[1][i + 1] == 0:
				m[1][i] = 0
				m[1][i + 1] = x
				is_move = True
				(ind, r, c) = (x, 1, i + 1)
				break
			elif i == n - 1 and m[2][i] == 0:
				m[1][i] = 0
				m[2][i] = x
				is_move = True
				(ind, r, c) = (x, 2, i)
				break
	if is_move == True:
		return (is_move, is_park, ind, r, c)
	for (i, x) in enumerate(m[2]):
		if x != 0:
			if m[3][i] == x:
				is_move = True
				is_park = True
				m[2][i] = 0
				(ind, r, c) = (x, 3, i)
				break
			elif i - 1 >= 0 and m[2][i - 1] == 0:
				m[2][i] = 0
				m[2][i - 1] = x
				is_move = True
				(ind, r, c) = (x, 2, i - 1)
				break
			elif i == 0 and m[1][i] == 0:
				m[2][i] = 0
				m[1][i] = x
				is_move = True
				(ind, r, c) = (x, 1, i)
				break
	return (is_move, is_park, ind, r, c)
cnt = 0
is_solve = True
move_arr = []
while cnt < k:
	(is_move, is_park, ind, r, c) = move()
	if is_move == False:
		is_solve = False
		break
	move_arr.append([ind, r + 1, c + 1])
	if is_park == True:
		cnt += 1
if is_solve == False:
	print(-1)
else:
	print(len(move_arr))
	print('\n'.join([' '.join([str(x) for x in move_]) for move_ in move_arr]))


all_the_moves = []
parked = 0
(n, k) = map(int, input().split())
park = []
park += [[int(x) for x in input().split()]]
park += [[int(x) for x in input().split()]]
park += [[int(x) for x in input().split()]]
park += [[int(x) for x in input().split()]]

def add_move(car, r, c):
	global all_the_moves
	if car == 0:
		return
	all_the_moves += [(car, r, c)]

def cycle():
	if len(park[1]) == 1:
		if park[1][0] != 0:
			add_move(park[1][0], 2, 0)
			(park[1][0], park[2][0]) = (park[2][0], park[1][0])
		elif park[2][0] != 0:
			add_move(park[2][0], 1, 0)
			(park[1][0], park[2][0]) = (park[2][0], park[1][0])
		return
	if 0 not in park[1]:
		i = park[2].index(0)
		(park[2][i], park[1][i]) = (park[1][i], park[2][i])
		add_move(park[2][i], 2, i)
	i = park[1].index(0)
	for j in range(i, 0, -1):
		add_move(park[1][j - 1], 1, j)
		(park[1][j], park[1][j - 1]) = (park[1][j - 1], park[1][j])
	add_move(park[2][0], 1, 0)
	(park[1][0], park[2][0]) = (park[2][0], park[1][0])
	for j in range(n - 1):
		add_move(park[2][j + 1], 2, j)
		(park[2][j], park[2][j + 1]) = (park[2][j + 1], park[2][j])
	if i < n - 1:
		add_move(park[1][n - 1], 2, n - 1)
		(park[1][n - 1], park[2][n - 1]) = (park[2][n - 1], park[1][n - 1])
	for j in range(n - 2, i, -1):
		add_move(park[1][j], 1, j + 1)
		(park[1][j], park[1][j + 1]) = (park[1][j + 1], park[1][j])

def cars_to_their_places():
	global all_the_moves
	global parked
	for i in range(n):
		if park[0][i] != 0 and park[0][i] == park[1][i]:
			all_the_moves += [(park[0][i], 0, i)]
			park[1][i] = 0
			parked += 1
	for i in range(n):
		if park[3][i] != 0 and park[3][i] == park[2][i]:
			all_the_moves += [(park[3][i], 3, i)]
			park[2][i] = 0
			parked += 1
cars_to_their_places()
if k == 2 * n and parked == 0:
	print(-1)
else:
	while parked < k:
		cycle()
		cars_to_their_places()
	if len(all_the_moves) <= 2 * 10 ** 4:
		print(len(all_the_moves))
		for (i, r, c) in all_the_moves:
			print(i, r + 1, c + 1)
	else:
		print(-1)


import bisect
import heapq
import math
import random
import sys
from collections import Counter, defaultdict
from decimal import ROUND_CEILING, ROUND_HALF_UP, Decimal
from functools import lru_cache, reduce
from itertools import combinations, combinations_with_replacement, product, permutations
sys.setrecursionlimit(10000)

def read_int():
	return int(input())

def read_int_n():
	return list(map(int, input().split()))

def read_float():
	return float(input())

def read_float_n():
	return list(map(float, input().split()))

def read_str():
	return input()

def read_str_n():
	return list(map(str, input().split()))

def error_print(*args):
	print(*args, file=sys.stderr)

def mt(f):
	import time

	def wrap(*args, **kwargs):
		s = time.time()
		ret = f(*args, **kwargs)
		e = time.time()
		error_print(e - s, 'sec')
		return ret
	return wrap

@mt
def slv(N, K, S):
	error_print('------')
	for s in S:
		error_print(s)
	ans = []
	for (i, (p, c)) in enumerate(zip(S[0], S[1])):
		if c != 0 and p == c:
			ans.append((c, 1, i + 1))
			S[1][i] = 0
	for (i, (p, c)) in enumerate(zip(S[3], S[2])):
		if c != 0 and p == c:
			ans.append((c, 4, i + 1))
			S[2][i] = 0
	while len(ans) <= 20000 and sum(S[1]) + sum(S[2]) != 0:
		error_print('------')
		m = len(ans)
		for s in S:
			error_print(s)
		S1 = [c for c in S[1]]
		S2 = [c for c in S[2]]
		for i in range(N):
			c = S[1][i]
			if i == 0:
				if c != 0 and S[2][0] == 0:
					ans.append((c, 3, i + 1))
					S1[i] = 0
					S2[i] = c
			elif c != 0 and S[1][i - 1] == 0:
				ans.append((c, 2, i))
				S1[i] = 0
				S1[i - 1] = c
		for i in range(0, N)[::-1]:
			c = S[2][i]
			if i == N - 1:
				if c != 0 and S[1][i] == 0:
					ans.append((c, 2, i + 1))
					S2[i] = 0
					S1[i] = c
			elif c != 0 and S[2][i + 1] == 0:
				ans.append((c, 3, i + 2))
				S2[i] = 0
				S2[i + 1] = c
		S[1] = S1
		S[2] = S2
		for (i, (p, c)) in enumerate(zip(S[0], S[1])):
			if c != 0 and p == c:
				ans.append((c, 1, i + 1))
				S[1][i] = 0
		for (i, (p, c)) in enumerate(zip(S[3], S[2])):
			if c != 0 and p == c:
				ans.append((c, 4, i + 1))
				S[2][i] = 0
		if len(ans) == m:
			break
	if len(ans) > 20000:
		return -1
	if sum(S[1]) + sum(S[2]) != 0:
		return -1
	error_print('------')
	for s in S:
		error_print(s)
	return str(len(ans)) + '\n' + '\n'.join(map(lambda x: ' '.join(map(str, x)), ans))

def main():
	(N, K) = read_int_n()
	S = [read_int_n() for _ in range(4)]
	print(slv(N, K, S))
main()


def parknext(N, P, sq, rem):
	for i in range(N):
		if P[0][i] == P[1][i] and P[0][i] > 0:
			sq.append((P[0][i], 1, i + 1))
			P[0][i] = P[1][i] = 0
			rem[0] -= 1
		if P[3][i] == P[2][i] and P[3][i] > 0:
			sq.append((P[3][i], 4, i + 1))
			P[3][i] = P[2][i] = 0
			rem[0] -= 1

def rotnext(N, pos):
	(c, r) = pos
	assert r == 1 or r == 2
	if r == 1 and c == N - 1:
		return (N - 1, 2)
	if r == 2 and c == 0:
		return (0, 1)
	if r == 1:
		return (c + 1, r)
	return (c - 1, r)

def rot(N, P, sq):
	pos = None
	for c in range(N):
		for r in (1, 2):
			if P[r][c] == 0:
				pos = (c, r)
				break
		if pos is not None:
			break
	if pos is None:
		return False
	origpos = pos
	prev = pos
	cur = rotnext(N, pos)
	while cur != origpos:
		(pc, pr) = prev
		(cc, cr) = cur
		assert P[pr][pc] == 0
		if P[cr][cc] > 0:
			sq.append((P[cr][cc], pr + 1, pc + 1))
			P[pr][pc] = P[cr][cc]
			P[cr][cc] = 0
		prev = cur
		cur = rotnext(N, cur)
	return True

def solve(N, K, P):
	sq = []
	rem = [K]
	parknext(N, P, sq, rem)
	while rem[0] > 0:
		if not rot(N, P, sq):
			return -1
		parknext(N, P, sq, rem)
	return sq

def main():
	(N, K) = [int(e) for e in input().split(' ')]
	P = []
	for _ in range(4):
		a = [int(e) for e in input().split(' ')]
		assert len(a) == N
		P.append(a)
	ans = solve(N, K, P)
	if ans == -1:
		print('-1')
	else:
		print(len(ans))
		for l in ans:
			print(' '.join(map(str, l)))
main()


(n, k) = map(int, input().split())
m = []
for _ in range(4):
	m.extend(list(map(int, input().split())))
moves = []
ans = 0
zeros = 0
d = {1: 1, 2: 4}

def park():
	global ans, moves, m, zeros
	zeros = 0
	for i in range(n, 3 * n):
		r = d[i // n]
		if m[i] == 0:
			zeros += 1
		elif m[i] == m[(r - 1) * n + i % n]:
			moves.append(f'{m[i]} {r} {i % n + 1}')
			m[i] = 0
			ans += 1
			zeros += 1

def rotate():
	global ans, moves, m
	t1 = m[2 * n]
	zero_found = False
	ls1 = []
	ls2 = []
	ll = [(n + i, 2) for i in range(n)] + [(3 * n - 1 - i, 3) for i in range(n)]
	for i in ll:
		if not zero_found and t1 != 0 and (m[i[0]] == 0):
			zero_found = True
			moves.append(f'{t1} {i[1]} {i[0] % n + 1}')
			ans += 1
		elif t1 != 0:
			if zero_found:
				ls2.append(f'{t1} {i[1]} {i[0] % n + 1}')
			else:
				ls1.append(f'{t1} {i[1]} {i[0] % n + 1}')
			ans += 1
		t2 = m[i[0]]
		m[i[0]] = t1
		t1 = t2
	ls1.reverse()
	ls2.reverse()
	moves.extend(ls1 + ls2)
park()
if zeros == 0:
	print(-1)
else:
	while zeros != 2 * n:
		rotate()
		park()
	print(ans)
	for i in moves:
		print(i)


class CarAlgorithm:

	def __init__(self, n, k, parking):
		self.n = n
		self.k = k
		self.parking = parking
		self._steps = []
		self._done = False
		for i in range(4):
			assert len(parking[i]) == n, '%s != %s' % (len(parking[i]), n)

	def do(self):
		if self._done:
			return self._steps
		self._done = True
		(n, k, parking) = (self.n, self.k, self.parking)
		car_target_cells = {}
		for (park_str, car_str) in [(0, 1), (3, 2)]:
			for i in range(n):
				car_number = parking[park_str][i]
				if car_number == 0:
					continue
				elif parking[car_str][i] == car_number:
					self._move_car(parking, car_str, i, park_str, i)
				else:
					car_target_cells[car_number] = (park_str, i)
		while True:
			target_shortest_path = None
			target_car_cell = None
			(target_dst_str, target_dst_col) = (None, None)
			free_cell = None
			for j in range(1, 3):
				for i in range(n):
					if parking[j][i] == 0:
						if not free_cell:
							free_cell = (j, i)
					else:
						cur_car = parking[j][i]
						(target_str, target_col) = car_target_cells[cur_car]
						cur_shortest_path = find_path(j, i, target_str, target_col)
						if target_shortest_path is None or len(cur_shortest_path) < len(target_shortest_path):
							target_shortest_path = cur_shortest_path
							target_car_cell = (j, i)
							(target_dst_str, target_dst_col) = (target_str, target_col)
			if target_shortest_path is None:
				return self._steps
			(car_cell_str, car_cell_col) = target_car_cell
			for (path_next_cell_str, path_next_cell_col) in target_shortest_path:
				if parking[path_next_cell_str][path_next_cell_col] != 0:
					if not free_cell:
						self._steps = -1
						return self._steps
					(free_cell_str, free_cell_col) = free_cell
					if free_cell_str == car_cell_str == path_next_cell_str and (free_cell_col < car_cell_col < path_next_cell_col or path_next_cell_col < car_cell_col < free_cell_col):
						if free_cell_str == 1:
							if parking[2][free_cell_col] != 0:
								self._move_car(parking, 2, free_cell_col, 1, free_cell_col)
							free_cell_str = 2
						else:
							if parking[1][free_cell_col] != 0:
								self._move_car(parking, 1, free_cell_col, 2, free_cell_col)
							free_cell_str = 1
					free_cell_step = 1 if free_cell_col < path_next_cell_col else -1
					for free_cell_next_col in range(free_cell_col + free_cell_step, path_next_cell_col + free_cell_step, free_cell_step):
						if parking[free_cell_str][free_cell_next_col] != 0:
							self._move_car(parking, free_cell_str, free_cell_next_col, free_cell_str, free_cell_col)
						free_cell_col = free_cell_next_col
					if (free_cell_str, path_next_cell_str) in [(1, 2), (2, 1)]:
						self._move_car(parking, path_next_cell_str, path_next_cell_col, free_cell_str, free_cell_col)
						free_cell = (path_next_cell_str, path_next_cell_col)
				self._move_car(parking, car_cell_str, car_cell_col, path_next_cell_str, path_next_cell_col)
				(car_cell_str, car_cell_col) = (path_next_cell_str, path_next_cell_col)
			self._move_car(parking, car_cell_str, car_cell_col, target_dst_str, target_dst_col)

	def _move_car(self, parking, from_str, from_col, to_str, to_col):
		car_number = parking[from_str][from_col]
		self._steps.append((car_number, to_str + 1, to_col + 1))
		parking[to_str][to_col] = parking[from_str][from_col]
		parking[from_str][from_col] = 0

	class Cell:

		def __init__(self, str_n: int, col_n: int):
			self.str = str_n
			self.col = col_n

def find_path(from_str, from_col, to_str, to_col):
	str_direct = 1 if from_col < to_col else -1
	path = [(from_str, i) for i in range(from_col + str_direct, to_col + str_direct, str_direct)]
	if from_str == 1 and to_str == 3:
		path.append((2, to_col))
	elif from_str == 2 and to_str == 0:
		path.append((1, to_col))
	return path

def do():
	(n, k) = [int(str_i) for str_i in input().split()]
	p = [[int(str_i) for str_i in input().split()] for _ in range(4)]
	steps = f(p)
	if isinstance(steps, list):
		if len(steps) > 20000:
			print(-1)
		else:
			print(len(steps))
			for s in steps:
				print('%s %s %s' % s)
	else:
		print(steps)

def f(square: list):
	assert len(square) == 4
	n = len(square[0])
	for s in square:
		assert len(s) == n
	steps = []
	(free_cell_str, free_cell_col) = (None, None)
	all_cars_are_parked = True
	for (from_str, to_str) in [(1, 0), (2, 3)]:
		for j in range(n):
			if square[from_str][j] == 0:
				(free_cell_str, free_cell_col) = (from_str, j)
			elif square[from_str][j] == square[to_str][j]:
				move_car(steps, square, from_str, j, to_str, j)
				(free_cell_str, free_cell_col) = (from_str, j)
			else:
				all_cars_are_parked = False
	if not all_cars_are_parked and (not free_cell_str) and (not free_cell_col):
		return -1
	while not all_cars_are_parked:
		all_cars_are_parked = True
		(start_str, start_col) = (free_cell_str, free_cell_col)
		while True:
			(prev_str, prev_col) = prev(n, free_cell_str, free_cell_col)
			if prev_col == -1:
				exit()
			car_number = square[prev_str][prev_col]
			if car_number != 0:
				move_car(steps, square, prev_str, prev_col, free_cell_str, free_cell_col)
				(car_new_str, car_new_col) = (free_cell_str, free_cell_col)
				if car_new_str == 1:
					parking_str = 0
				else:
					parking_str = 3
				if square[parking_str][car_new_col] == car_number:
					move_car(steps, square, car_new_str, car_new_col, parking_str, car_new_col)
				else:
					all_cars_are_parked = False
			(free_cell_str, free_cell_col) = (prev_str, prev_col)
			if (free_cell_str, free_cell_col) == (start_str, start_col):
				break
	return steps

def move_car(steps, square, from_str, from_col, to_str, to_col):
	car_number = square[from_str][from_col]
	steps.append((car_number, to_str + 1, to_col + 1))
	square[to_str][to_col] = square[from_str][from_col]
	square[from_str][from_col] = 0

def prev(n, cur_str, cur_col):
	if n == 1:
		return (2 if cur_str == 1 else 1, 0)
	elif cur_col == 0:
		return (1, 0 if cur_str == 2 else 1)
	elif cur_col == n - 1:
		return (2, n - 1 if cur_str == 1 else n - 2)
	else:
		return (cur_str, cur_col + 1 if cur_str == 1 else cur_col - 1)

def test():
	r = f([[1], [1], [2], [2]])
	assert r == [(1, 1, 1), (2, 4, 1)], r
	r = f([[1], [2], [1], [2]])
	assert r == -1, r
	r = f([[1, 2], [2, 3], [1, 0], [3, 0]])
	assert r == [(1, 3, 2), (2, 3, 1), (3, 2, 1), (1, 2, 2), (2, 3, 2), (3, 3, 1), (3, 4, 1), (1, 2, 1), (1, 1, 1), (2, 2, 2), (2, 1, 2)], r
	r = f([[1, 2], [3, 1], [0, 2], [3, 0]])
	assert r == [(3, 3, 1), (3, 4, 1), (1, 2, 1), (1, 1, 1), (2, 2, 2), (2, 1, 2)], r
do()