A linda gaveta de padrões
Bom dia PPCG!
Outro dia, quando eu estava tentando ajudar alguém no Stack Overflow, uma parte do problema dele me deu uma ideia para esse desafio.
Antes de tudo, verifique a seguinte forma:
Onde todos os números em preto são o índice dos pontos na forma e todos os números em azul escuro são o índice dos links entre os pontos.
Agora, dado um número hexadecimal de 0x00000 a 0xFFFFF, você precisa desenhar uma forma no console usando apenas o espaço de caracteres e "■" (usar o caractere "o" também é bom).
Aqui estão alguns exemplos em que o número hexadecimal é inserido e a forma é gerada:
0xE0C25 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■
0xC1043 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■
■
■
■
■
■
■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xE4F27 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xF1957 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xD0C67 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0x95E30 :
■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■
0x95622 :
■ ■ ■ ■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■
■
■
■ ■ ■ ■ ■
0xC5463 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
0xE5975 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■
0xB5E75 :
■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■
0xF4C75 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■
■ ■ ■ ■ ■ ■
0xF5D75 :
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■
Aqui estão algumas explicações sobre como isso funciona:
0xFFFFF(16) = 1111 1111 1111 1111 1111(2)
Você aqui tem 20 bits, cada bit diz se um link existe ou não.
O índice do bit mais significativo (MSB) é 0 (referência à imagem) ou o bit menos significativo (LSB) é 19 (referência à imagem novamente).
Veja como ele funciona para a primeira forma, como exemplo:
0xE0C25(16) = 1110 0000 1100 0010 0101(2)
O que significa que você terá os seguintes links existentes: 0,1,2,8,9,14,17,19.
Se você destacar as linhas na imagem de referência com esses números, ele terá a seguinte forma:
■ ■ ■ ■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■ ■
■ ■
■ ■
■ ■
■ ■ ■ ■ ■
Aqui está uma implementação Python simples e simples, se você precisar de mais ajuda:
patterns = [
0xE0C25, 0xC1043, 0xE4F27, 0xF1957,
0xD0C67, 0x95E30, 0x95622, 0xC5463,
0xE5975, 0xB5E75, 0xF4C75, 0xF5D75
]
def printIfTrue(condition, text = "■ "):
if condition:
print(text, end="")
else:
print(" "*len(text), end="")
def orOnList(cube, indexes):
return (sum([cube[i] for i in indexes]) > 0)
def printPattern(pattern):
cube = [True if n == "1" else False for n in str(bin(pattern))[2::]]
for y in range(9):
if y == 0: printIfTrue(orOnList(cube, [0, 2, 3]))
if y == 4: printIfTrue(orOnList(cube, [2, 4, 9, 11, 12]))
if y == 8: printIfTrue(orOnList(cube, [11, 13, 18]))
if y in [0, 4, 8]:
printIfTrue(cube[int((y / 4) + (y * 2))], "■ ■ ■ ")
if y == 0: printIfTrue(orOnList(cube, [0, 1, 4, 5, 6]))
if y == 4: printIfTrue(orOnList(cube, [3, 5, 7, 9, 10, 13, 14, 15]))
if y == 8: printIfTrue(orOnList(cube, [12, 14, 16, 18, 19]))
printIfTrue(cube[int((y / 4) + (y * 2)) + 1], "■ ■ ■ ")
elif y in [1, 5]:
for i in range(7):
if i in [2, 5]:
print(" ", end=" ")
printIfTrue(cube[y * 2 + (1 - (y % 5)) + i])
elif y in [2, 6]:
for i in range(5):
if i in [1, 2, 3, 4]:
print(" ", end=" ")
if i in [1, 3]:
if i == 1 and y == 2:
printIfTrue(orOnList(cube, [3, 4]))
elif i == 3 and y == 2:
printIfTrue(orOnList(cube, [6, 7]))
if i == 1 and y == 6:
printIfTrue(orOnList(cube, [12, 13]))
elif i == 3 and y == 6:
printIfTrue(orOnList(cube, [15, 16]))
else:
printIfTrue(cube[(y * 2 - (1 if y == 6 else 2)) + i + int(i / 4 * 2)])
elif y in [3, 7]:
for i in range(7):
if i in [2, 5]:
print(" ", end="")
ri, swap = (y * 2 - 2) + (1 - (y % 5)) + i, [[3, 6, 12, 15], [4, 7, 13, 16]]
if ri in swap[0]: ri = swap[1][swap[0].index(ri)]
elif ri in swap[1]: ri = swap[0][swap[1].index(ri)]
printIfTrue(cube[ri])
if y == 0: printIfTrue(orOnList(cube, [1, 7, 8]))
if y == 4: printIfTrue(orOnList(cube, [6, 8, 10, 16, 17]))
if y == 8: printIfTrue(orOnList(cube, [15, 17, 19]))
print()
for pattern in patterns:
printPattern(pattern)
É claro que não é perfeito e é muito longo para o que deve fazer, e essa é a razão exata pela qual você está aqui!
Tornando este programa ridiculamente curto :)
Isso é código-golfe, então a resposta mais curta vence!