|
| 1 | + |
| 2 | + |
| 3 | +F1 = {'Name': 'O', 'Number': 1, 'Color': 'Rose', |
| 4 | + 'Height': 1, 'Width': 5, 'Angle': 0, 'Mirror': False, 'Shape': [[1, 1, 1, 1, 1]], |
| 5 | + 'Options': [[0, False], [90, False]]} |
| 6 | +F2 = {'Name': 'Q', 'Number': 2, 'Color': 'Orange', |
| 7 | + 'Height': 2, 'Width': 4, 'Angle': 0, 'Mirror': False, 'Shape': [[1, 1, 1, 1], [1, 0, 0, 0]], |
| 8 | + 'Options': [[0, False], [90, False], [180, False], [270, False], [0, True], [90, True], [180, True], [270, True]]} |
| 9 | +F3 = {'Name': 'Y', 'Number': 3, 'Color': 'Brown', |
| 10 | + 'Height': 2, 'Width': 4, 'Angle': 0, 'Mirror': False, 'Shape': [[1, 1, 1, 1], [0, 1, 0, 0]], |
| 11 | + 'Options': [[0, False], [90, False], [180, False], [270, False], [0, True], [90, True], [180, True], [270, True]]} |
| 12 | +F4 = {'Name': 'S', 'Number': 4, 'Color': 'Black', |
| 13 | + 'Height': 2, 'Width': 4, 'Angle': 0, 'Mirror': False, 'Shape': [[0, 1, 1, 1], [1, 1, 0, 0]], |
| 14 | + 'Options': [[0, False], [90, False], [180, False], [270, False], [0, True], [90, True], [180, True], [270, True]]} |
| 15 | +F5 = {'Name': 'V', 'Number': 5, 'Color': 'Dark Blue', |
| 16 | + 'Height': 3, 'Width': 3, 'Angle': 0, 'Mirror': False, 'Shape': [[1, 1, 1], [1, 0, 0], [1, 0, 0]], |
| 17 | + 'Options': [[0, False], [90, False], [180, False], [270, False]]} |
| 18 | +F6 = {'Name': 'P', 'Number': 6, 'Color': 'Light Blue', |
| 19 | + 'Height': 2, 'Width': 3, 'Angle': 0, 'Mirror': False, 'Shape': [[1, 1, 1], [1, 1, 0]], |
| 20 | + 'Options': [[0, False], [90, False], [180, False], [270, False], [0, True], [90, True], [180, True], [270, True]]} |
| 21 | +F7 = {'Name': 'U', 'Number': 7, 'Color': 'Yellow', |
| 22 | + 'Height': 2, 'Width': 3, 'Angle': 0, 'Mirror': False, 'Shape': [[1, 1, 1], [1, 0, 1]], |
| 23 | + 'Options': [[0, False], [90, False], [180, False], [270, False]]} |
| 24 | +F8 = {'Name': 'Z', 'Number': 8, 'Color': 'Grey', |
| 25 | + 'Height': 3, 'Width': 3, 'Angle': 0, 'Mirror': False, 'Shape': [[1, 0, 0], [1, 1, 1], [0, 0, 1]], |
| 26 | + 'Options': [[0, False], [90, False], [0, True], [90, True]]} |
| 27 | +F9 = {'Name': 'R', 'Number': 9, 'Color': 'Light Green', |
| 28 | + 'Height': 3, 'Width': 3, 'Angle': 0, 'Mirror': False, 'Shape': [[1, 0, 0], [1, 1, 1], [0, 1, 0]], |
| 29 | + 'Options': [[0, False], [90, False], [180, False], [270, False], [0, True], [90, True], [180, True], [270, True]]} |
| 30 | +FA = {'Name': 'T', 'Number': 10, 'Color': 'Dark Green', |
| 31 | + 'Height': 3, 'Width': 3, 'Angle': 0, 'Mirror': False, 'Shape': [[1, 1, 1], [0, 1, 0], [0, 1, 0]], |
| 32 | + 'Options': [[0, False], [90, False], [180, False], [270, False]]} |
| 33 | +FB = {'Name': 'W', 'Number': 11, 'Color': 'Cherry', |
| 34 | + 'Height': 3, 'Width': 3, 'Angle': 0, 'Mirror': False, 'Shape': [[1, 1, 0], [0, 1, 1], [0, 0, 1]], |
| 35 | + 'Options': [[0, False], [90, False], [180, False], [270, False]]} |
| 36 | +FC = {'Name': 'X', 'Number': 12, 'Color': 'Red', |
| 37 | + 'Height': 3, 'Width': 3, 'Angle': 0, 'Mirror': False, 'Shape': [[0, 1, 0], [1, 1, 1], [0, 1, 0]], |
| 38 | + 'Options': [[0, False]]} |
| 39 | + |
| 40 | +ARR = [F1, F2, F3, F4, F5, F6, F7, F8, F9, FA, FB, FC] |
| 41 | + |
| 42 | + |
| 43 | +def rotate(source: dict, angle: int) -> dict: |
| 44 | + result = {'Name': source['Name'], 'Number': source['Number'], 'Color': source['Color'], |
| 45 | + 'Height': source['Height'], 'Width': source['Width'], 'Angle': angle, |
| 46 | + 'Mirror': source['Mirror'], 'Shape': source['Shape']} |
| 47 | + if angle == 90 or angle == -270: |
| 48 | + result['Height'] = source['Width'] |
| 49 | + result['Width'] = source['Height'] |
| 50 | + result['Shape'] = [[0 for i in range(result['Width'])] for j in range(result['Height'])] |
| 51 | + for j in range(source['Height']): |
| 52 | + for i in range(source['Width']): |
| 53 | + result['Shape'][i][result['Width'] - 1 - j] = source['Shape'][j][i] |
| 54 | + elif angle == 180 or angle == -180: |
| 55 | + result['Shape'] = [[0 for i in range(result['Width'])] for j in range(result['Height'])] |
| 56 | + for j in range(source['Height']): |
| 57 | + for i in range(source['Width']): |
| 58 | + result['Shape'][result['Height'] - 1 - j][result['Width'] - 1 - i] = source['Shape'][j][i] |
| 59 | + elif angle == 270 or angle == -90: |
| 60 | + result['Height'] = source['Width'] |
| 61 | + result['Width'] = source['Height'] |
| 62 | + result['Shape'] = [[0 for i in range(result['Width'])] for j in range(result['Height'])] |
| 63 | + for j in range(source['Height']): |
| 64 | + for i in range(source['Width']): |
| 65 | + result['Shape'][result['Height'] - 1 - i][j] = source['Shape'][j][i] |
| 66 | + return result |
| 67 | + |
| 68 | + |
| 69 | +def mirror(source: dict) -> dict: |
| 70 | + result = {'Name': source['Name'], 'Number': source['Number'], 'Color': source['Color'], |
| 71 | + 'Height': source['Height'], 'Width': source['Width'], 'Angle': source['Angle'], |
| 72 | + 'Mirror': not(source['Mirror']), 'Shape': source['Shape']} |
| 73 | + result['Shape'] = [[0 for i in range(result['Width'])] for j in range(result['Height'])] |
| 74 | + for j in range(source['Height']): |
| 75 | + for i in range(source['Width']): |
| 76 | + result['Shape'][j][result['Width'] - 1 - i] = source['Shape'][j][i] |
| 77 | + return result |
| 78 | + |
| 79 | + |
| 80 | +def multiprint(source: dict): |
| 81 | + caption = '#' + str(source['Number']) + ' - ' + source['Name'] + ' - ' + str(source['Angle']) + ' - ' + str(source['Mirror']) |
| 82 | + print(caption) |
| 83 | + print(''.join(['-' for i in range(len(caption))])) |
| 84 | + for j in range(source['Height']): |
| 85 | + print(' '.join(map(str,source['Shape'][j]))) |
| 86 | + print(''.join(['-' for i in range(len(caption))])) |
| 87 | + |
| 88 | + |
| 89 | +def print_shape(shape: list): |
| 90 | + print(''.join(['-' for i in range(2* len(shape[0]) - 1)])) |
| 91 | + for j in range(len(shape)): |
| 92 | + print(' '.join(map(str,shape[j]))) |
| 93 | + #print(''.join(['-' for i in range(2 * len(shape[0]) - 1)])) |
| 94 | + |
| 95 | + |
| 96 | +def orientate(task: dict) -> dict: |
| 97 | + l = [] |
| 98 | + c = 0 |
| 99 | + f = 0 |
| 100 | + for figure in task['Figures']: |
| 101 | + l.append([]) |
| 102 | + for option in figure['Options']: |
| 103 | + ready_figure = rotate(mirror(figure) if option[1] else figure, option[0]) |
| 104 | + if task['Width'] < ready_figure['Width'] or task['Height'] < ready_figure['Height']: |
| 105 | + continue |
| 106 | + #multiprint(ready_figure) |
| 107 | + for j in range(task['Height'] - ready_figure['Height'] + 1): |
| 108 | + for i in range(task['Width'] - ready_figure['Width'] + 1): |
| 109 | + field = [[0 for a in range(task['Width'])] for b in range(task['Height'])] |
| 110 | + for n in range(ready_figure['Height']): |
| 111 | + for m in range(ready_figure['Width']): |
| 112 | + field[j+n][i+m] = ready_figure['Shape'][n][m] |
| 113 | + #print_shape(field) |
| 114 | + checker = True |
| 115 | + for n in range(len(field)): |
| 116 | + for m in range(len(field[n])): |
| 117 | + if field[n][m] == 0: |
| 118 | + checker = trace(field, m, n, m, n, 0) == 4 |
| 119 | + if not checker: |
| 120 | + break |
| 121 | + if not checker: |
| 122 | + break |
| 123 | + if checker: |
| 124 | + l[f].append(field) |
| 125 | + c = c + 1 |
| 126 | + f = f + 1 |
| 127 | + return {'Height': task['Height'], 'Width': task['Width'], 'Figures': task['Figures'], 'Counter': c, 'List': l} |
| 128 | + |
| 129 | + |
| 130 | +def merge(field_a: list, field_b: list) -> (list, bool): |
| 131 | + if field_a is None: |
| 132 | + return field_b[:], True |
| 133 | + elif field_b is None: |
| 134 | + return field_a[:], True |
| 135 | + else: |
| 136 | + result = [[0 for a in range(len(field_a[0]))] for b in range(len(field_a))] |
| 137 | + checker = True |
| 138 | + for j in range(len(field_a)): |
| 139 | + for i in range(len(field_a[j])): |
| 140 | + tmp = field_a[j][i] + field_b[j][i] |
| 141 | + result[j][i] = tmp |
| 142 | + if tmp > 1: |
| 143 | + checker = False |
| 144 | + if checker: |
| 145 | + for j in range(len(result)): |
| 146 | + for i in range(len(result[j])): |
| 147 | + if result[j][i] == 0: |
| 148 | + checker = trace(result, i, j, i, j, 0) == 4 |
| 149 | + if not checker: |
| 150 | + break |
| 151 | + if not checker: |
| 152 | + break |
| 153 | + #test_left = result[j][i - 1] > 0 if i > 0 else True |
| 154 | + #test_right = result[j][i + 1] > 0 if i < len(result[j]) - 1 else True |
| 155 | + #test_top = result[j - 1][i] > 0 if j > 0 else True |
| 156 | + #test_bottom = result[j + 1][i] > 0 if j < len(result) - 1 else True |
| 157 | + #if test_left and test_right and test_top and test_bottom: |
| 158 | + # checker = False |
| 159 | + #if (not test_left) and test_right and test_top and test_bottom: |
| 160 | + # checker = trace(result, i-1, j, i, j, 1) |
| 161 | + return result, checker |
| 162 | + |
| 163 | + |
| 164 | +def trace(field: list, i: int, j: int, pi: int, pj: int, r: int) -> int: |
| 165 | + test_left = True if i > pi else (field[j][i - 1] > 0 if i > 0 else True) |
| 166 | + test_right = True if i < pi else (field[j][i + 1] > 0 if i < (len(field[j]) - 1) else True) |
| 167 | + test_top = True if j > pj else (field[j - 1][i] > 0 if j > 0 else True) |
| 168 | + test_bottom = True if j < pj else (field[j + 1][i] > 0 if j < (len(field) - 1) else True) |
| 169 | + if r > 0: |
| 170 | + if test_left and test_right and test_top and test_bottom: |
| 171 | + return r |
| 172 | + elif (not test_left) and test_right and test_top and test_bottom: |
| 173 | + return trace(field, i - 1, j, i, j, r + 1) if r < 3 else 4 |
| 174 | + elif test_left and (not test_right) and test_top and test_bottom: |
| 175 | + return trace(field, i + 1, j, i, j, r + 1) if r < 3 else 4 |
| 176 | + elif test_left and test_right and (not test_top) and test_bottom: |
| 177 | + return trace(field, i, j - 1, i, j, r + 1) if r < 3 else 4 |
| 178 | + elif test_left and test_right and test_top and (not test_bottom): |
| 179 | + return trace(field, i, j + 1, i, j, r + 1) if r < 3 else 4 |
| 180 | + elif (not test_left) and (not test_right) and test_top and test_bottom: |
| 181 | + return max(trace(field, i - 1, j, i, j, r + 2), trace(field, i + 1, j, i, j, r + 2)) if r < 2 else 4 |
| 182 | + elif test_left and test_right and (not test_top) and (not test_bottom): |
| 183 | + return max(trace(field, i, j - 1, i, j, r + 2), trace(field, i, j + 1, i, j, r + 2)) if r < 2 else 4 |
| 184 | + elif (not test_left) and test_right and (not test_top) and test_bottom: |
| 185 | + return max(trace(field, i - 1, j, i, j, r + 2), trace(field, i, j - 1, i, j, r + 2)) if r < 2 else 4 |
| 186 | + elif (not test_left) and test_right and test_top and (not test_bottom): |
| 187 | + return max(trace(field, i - 1, j, i, j, r + 2), trace(field, i, j + 1, i, j, r + 2)) if r < 2 else 4 |
| 188 | + elif test_left and (not test_right) and (not test_top) and test_bottom: |
| 189 | + return max(trace(field, i + 1, j, i, j, r + 2), trace(field, i, j - 1, i, j, r + 2)) if r < 2 else 4 |
| 190 | + elif test_left and (not test_right) and test_top and (not test_bottom): |
| 191 | + return max(trace(field, i + 1, j, i, j, r + 2), trace(field, i, j + 1, i, j, r + 2)) if r < 2 else 4 |
| 192 | + elif (not test_left) and (not test_right) and (not test_top) and test_bottom: |
| 193 | + return max(trace(field, i - 1, j, i, j, r + 3), trace(field, i + 1, j, i, j, r + 3), |
| 194 | + trace(field, i, j - 1, i, j, r + 3)) if r < 1 else 4 |
| 195 | + elif (not test_left) and (not test_right) and test_top and (not test_bottom): |
| 196 | + return max(trace(field, i - 1, j, i, j, r + 3), trace(field, i + 1, j, i, j, r + 3), |
| 197 | + trace(field, i, j + 1, i, j, r + 3)) if r < 1 else 4 |
| 198 | + elif (not test_left) and test_right and (not test_top) and (not test_bottom): |
| 199 | + return max(trace(field, i - 1, j, i, j, r + 3), trace(field, i, j - 1, i, j, r + 3), |
| 200 | + trace(field, i, j + 1, i, j, r + 3)) if r < 1 else 4 |
| 201 | + elif test_left and (not test_right) and (not test_top) and (not test_bottom): |
| 202 | + return max(trace(field, i + 1, j, i, j, r + 3), trace(field, i, j - 1, i, j, r + 3), |
| 203 | + trace(field, i, j + 1, i, j, r + 3)) if r < 1 else 4 |
| 204 | + elif (not test_left) and (not test_right) and (not test_top) and (not test_bottom): |
| 205 | + return 4 |
| 206 | + else: |
| 207 | + if test_left and test_right and test_top and test_bottom: |
| 208 | + return r |
| 209 | + elif (not test_left) and test_right and test_top and test_bottom: |
| 210 | + return trace(field, i - 1, j, i, j, r + 1) if r < 3 else 4 |
| 211 | + elif test_left and (not test_right) and test_top and test_bottom: |
| 212 | + return trace(field, i + 1, j, i, j, r + 1) if r < 3 else 4 |
| 213 | + elif test_left and test_right and (not test_top) and test_bottom: |
| 214 | + return trace(field, i, j - 1, i, j, r + 1) if r < 3 else 4 |
| 215 | + elif test_left and test_right and test_top and (not test_bottom): |
| 216 | + return trace(field, i, j + 1, i, j, r + 1) if r < 3 else 4 |
| 217 | + else: |
| 218 | + return 4 |
| 219 | + |
| 220 | + |
| 221 | + |
| 222 | +def check(field: list) -> bool: |
| 223 | + s = 0 |
| 224 | + z = 0 |
| 225 | + for j in range(len(field)): |
| 226 | + for i in range(len(field[j])): |
| 227 | + s = s + field[j][i] |
| 228 | + if field[j][i] == 0: z = z + 1 |
| 229 | + return s == len(field) * len(field[0]) and z == 0 |
| 230 | + |
| 231 | + |
| 232 | +def solve(task: dict, shift: int = 0, field: list = None) -> (dict, bool): |
| 233 | + l = task['List'] |
| 234 | + for c in range(len(l[shift])): |
| 235 | + merged, checker = merge(field, l[shift][c]) |
| 236 | + if checker: |
| 237 | + if len(l) > shift + 1: |
| 238 | + fields, checker = solve(task, shift + 1, merged) |
| 239 | + if checker: |
| 240 | + fields[shift] = l[shift][c] |
| 241 | + return fields, checker |
| 242 | + else: |
| 243 | + checker = check(merged) |
| 244 | + if checker: |
| 245 | + return {shift: l[shift][c]}, checker |
| 246 | + return {}, False |
| 247 | + |
| 248 | + |
| 249 | +def print_result(fields: dict): |
| 250 | + separator = ''.join(['-' for i in range((2 * len(fields[0][0]) - 1 + 3) * len(fields) - 3)]) |
| 251 | + print(separator) |
| 252 | + for j in range(len(fields[0])): |
| 253 | + content = '' |
| 254 | + for f in range(len(fields)): |
| 255 | + content = content + ' '.join(map(str, fields[f][j])) + ' ' |
| 256 | + print(content) |
| 257 | + print(separator) |
| 258 | + |
| 259 | + |
| 260 | +T3A = {'Height': 5, 'Width': 3, 'Figures': [F2, F3, FA]} |
| 261 | +T3B = {'Height': 5, 'Width': 3, 'Figures': [F4, F6, F7]} |
| 262 | + |
| 263 | +T4A = {'Height': 5, 'Width': 4, 'Figures': [F2, F3, F6, FA]} |
| 264 | + |
| 265 | +T5A = {'Height': 5, 'Width': 5, 'Figures': [F2, F3, F6, FA, FB]} |
| 266 | + |
| 267 | +T6A = {'Height': 5, 'Width': 6, 'Figures': [F2, F3, F6, F8, FA, FB]} |
| 268 | + |
| 269 | +T7A = {'Height': 5, 'Width': 7, 'Figures': [F2, F3, F5, F6, F8, FA, FB]} |
| 270 | + |
| 271 | +T8A = {'Height': 5, 'Width': 8, 'Figures': [F2, F3, F4, F5, F6, F8, FA, FB]} |
| 272 | + |
| 273 | +T12 = {'Height': 5, 'Width': 12, 'Figures': ARR} |
| 274 | +T20 = {'Height': 3, 'Width': 20, 'Figures': ARR} |
| 275 | + |
| 276 | +fields, rc = solve(orientate(T6A)) |
| 277 | +print_result(fields) |
| 278 | + |
| 279 | + |
| 280 | + |
| 281 | +#print(F2) |
| 282 | +#print(rotate(mirror(F2), 0)) |
| 283 | +#print(mirror(rotate(F2, 90))) |
0 commit comments