Create a Maze (Codeforces 715D)
Tags: Others, constructive algorithms

ZS the Coder loves mazes. Your job is to create one so that he can play with it. A maze consists of n × m rooms, and the rooms are arranged in n rows (numbered from the top to the bottom starting from 1) and m columns (numbered from the left to the right starting from 1). The room in the i-th row and j-th column is denoted by (i, j). A player starts in the room (1, 1) and wants to reach the room (n, m).Each room has four doors (except for ones at the maze border), one on each of its walls, and two adjacent by the wall rooms shares the same door. Some of the doors are locked, which means it is impossible to pass through the door. For example, if the door connecting (i, j) and (i, j + 1) is locked, then we can't go from (i, j) to (i, j + 1). Also, one can only travel between the rooms downwards (from the room (i, j) to the room (i + 1, j)) or rightwards (from the room (i, j) to the room (i, j + 1)) provided the corresponding door is not locked.  This image represents a maze with some doors locked. The colored arrows denotes all the possible paths while a red cross denotes a locked door. ZS the Coder considers a maze to have difficulty x if there is exactly x ways of travelling from the room (1, 1) to the room (n, m). Two ways are considered different if they differ by the sequence of rooms visited while travelling.Your task is to create a maze such that its difficulty is exactly equal to T. In addition, ZS the Coder doesn't like large mazes, so the size of the maze and the number of locked doors are limited. Sounds simple enough, right?

Input: The first and only line of the input contains a single integer T (1 ≤ T ≤ 1018), the difficulty of the required maze.

Output: The first line should contain two integers n and m (1 ≤ n, m ≤ 50) — the number of rows and columns of the maze respectively.The next line should contain a single integer k (0 ≤ k ≤ 300) — the number of locked doors in the maze.Then, k lines describing locked doors should follow. Each of them should contain four integers, x1, y1, x2, y2. This means that the door connecting room (x1, y1) and room (x2, y2) is locked. Note that room (x2, y2) should be adjacent either to the right or to the bottom of (x1, y1), i.e. x2 + y2 should be equal to x1 + y1 + 1. There should not be a locked door that appears twice in the list.It is guaranteed that at least one solution exists. If there are multiple solutions, print any of them.

Note: Here are how the sample input and output looks like. The colored arrows denotes all the possible paths while a red cross denotes a locked door.In the first sample case:  In the second sample case:  

Sample Inputs:
3

4

Sample Outputs:
3 2
0

4 3
3
1 2 2 2
3 2 3 3
1 3 2 3

Solution (Python):
corr = lambda x, y: 1 <= x <= n and 1 <= y <= m
T = int(input())
a = []
while T:
    a.append(T % 6)
    T //= 6
L = len(a)
n = m = L * 2 + 2
ans = [(1, 2, 2, 2), (2, 1, 2, 2)]
f = [[1] * 9 for i in range(7)]
f[1][2] = f[2][2] = f[2][6] = f[3][5] = 0
f[4][5] = f[4][6] = f[5][2] = f[5][5] = f[5][6] = 0
p = [0] * 9
p[1] = (3, 1, 3, 2)
p[2] = (4, 1, 4, 2)
p[3] = (4, 2, 5, 2)
p[4] = (4, 3, 5, 3)
p[5] = (1, 3, 2, 3)
p[6] = (1, 4, 2, 4)
p[7] = (2, 4, 2, 5)
p[8] = (3, 4, 3, 5)
for i in range(L):
    bit = a[L - i - 1]
    for j in range(1, 9):
        if not f[bit][j]:
            continue
        (x1, y1, x2, y2) = p[j]
        D = 2 * i
        x1 += D
        y1 += D
        x2 += D
        y2 += D
        if corr(x2, y2):
            ans.append((x1, y1, x2, y2))
for i in range(L - 1):
    (x1, y1) = (5 + i * 2, 1 + i * 2)
    (x2, y2) = (1 + i * 2, 5 + i * 2)
    ans.append((x1, y1, x1 + 1, y1))
    ans.append((x1, y1 + 1, x1 + 1, y1 + 1))
    ans.append((x2, y2, x2, y2 + 1))
    ans.append((x2 + 1, y2, x2 + 1, y2 + 1))
print(n, m)
print(len(ans))
[print(*i) for i in ans]

Solution (Python):
corr = lambda x, y: 1 <= x <= n and 1 <= y <= m
T = int(input())
a = []
while T:
    a.append(T % 6)
    T //= 6
L = len(a)
n = m = L * 2 + 2
ans = [(1, 2, 2, 2), (2, 1, 2, 2)]
f = [[1] * 9 for i in range(7)]
f[1][2] = f[2][2] = f[2][6] = f[3][5] = 0
f[4][5] = f[4][6] = f[5][2] = f[5][5] = f[5][6] = 0
p = [0] * 9
p[1] = (3, 1, 3, 2)
p[2] = (4, 1, 4, 2)
p[3] = (4, 2, 5, 2)
p[4] = (4, 3, 5, 3)
p[5] = (1, 3, 2, 3)
p[6] = (1, 4, 2, 4)
p[7] = (2, 4, 2, 5)
p[8] = (3, 4, 3, 5)
for i in range(L):
    bit = a[L - i - 1]
    for j in range(1, 9):
        if not f[bit][j]:
            continue
        (x1, y1, x2, y2) = p[j]
        D = 2 * i
        x1 += D
        y1 += D
        x2 += D
        y2 += D
        if corr(x2, y2):
            ans.append((x1, y1, x2, y2))
for i in range(L - 1):
    (x1, y1) = (5 + i * 2, 1 + i * 2)
    (x2, y2) = (1 + i * 2, 5 + i * 2)
    ans.append((x1, y1, x1 + 1, y1))
    ans.append((x1, y1 + 1, x1 + 1, y1 + 1))
    ans.append((x2, y2, x2, y2 + 1))
    ans.append((x2 + 1, y2, x2 + 1, y2 + 1))
print(n, m)
print(len(ans))
[print(*i) for i in ans]

Solution (Python):
ans = []
open = [[[True, True] for _ in range(52)] for _ in range(52)]
print(42, 50)
n = int(input())
for i in range(52):
    for j in range(52):
        open[i][j][0] = open[i][j][1] = True
for i in range(13):
    (r, c) = (3 * i + 3, 3 * i + 11)
    open[r][c + 3][0] = open[r + 1][c + 3][0] = open[r + 2][c + 3][0] = False
    open[r + 3][c][1] = open[r + 3][c + 1][1] = open[r + 3][c + 2][1] = False
from_val = 1
for i in range(1, 43):
    open[i][from_val][0] = False
    if i >= 7 and i % 3 == 1:
        open[i][from_val][0] = True
        open[i][from_val][1] = open[i][from_val + 1][1] = open[i][from_val + 2][1] = open[i][from_val + 3][0] = False
        from_val += 3
for i in range(12, -2, -1):
    (r, c) = (3 * i + 3, 3 * i + 11)
    va = n % 20
    n //= 20
    if va == 0:
        continue
    bone = c - 10
    if bone <= 0:
        bone = 1
    for j in range(bone + 1, c + 3):
        open[r + 3][j][1] = False
    open[r + 3][bone][0] = True
    if va == 1:
        continue
    open[r + 2][bone][0] = True
    if va <= 10:
        open[r + 2][bone + va - 1][0] = False
    else:
        open[r + 2][bone + 9][0] = False
        wh = bone + 20 - va
        open[r + 1][bone][0] = True
        for j in range(bone + 1, wh):
            open[r + 1][j][1] = False
        open[r + 1][wh][0] = False
for i in range(1, 43):
    for j in range(1, 51):
        if not open[i][j][0] and j != 50:
            ans.append([(i, j), (i, j + 1)])
        if not open[i][j][1] and i != 42:
            ans.append([(i, j), (i + 1, j)])
print(len(ans))
for u in ans:
    print(u[0][0], u[0][1], u[1][0], u[1][1])