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!
fonte
Respostas:
JavaScript (ES6),
202188187 bytesComo funciona
Trabalhamos em uma grade
g
de 9 linhas de 10 caracteres. A grade é inicialmente preenchida com espaços, com um LineFeed a cada 10 caracteres.Cada segmento é definido por uma posição inicial e uma direção.
As instruções são codificadas da seguinte forma:
Cada segmento é codificado como um número inteiro:
Por exemplo, o segmento 3 começa na posição 55 e usa a 3ª direção. Portanto, é codificado como
(55 << 2) | 3 == 223
.Abaixo está a lista resultante de números inteiros, do segmento 19 ao segmento 0:
Uma vez codificado em delta, começando em 356, ele se torna:
Finalmente codificado como:
fonte
Python 3, 289 bytes
Nada inteligente, apenas codificado.
fonte
"trq|t...a|eca".split("|")
tornar"tqr t...a eca".split()
?.split()
destrói||
.Ruby, 116 bytes
Isso se baseia em alguns padrões que observei. Primeiro, o padrão se repete a cada 9 linhas. Em segundo lugar, se os pontos de partida das linhas horizontais são escolhidos adequadamente, as direções x circulam continuamente pela direita, esquerda e reta.
Ungolfed in program program
Acredito que exista uma solução de 112 bytes usando uma cadeia de 20 caracteres e alguma decodificação para definir os parâmetros das 20 linhas. Vou tentar isso mais tarde se tiver tempo.
fonte
PHP,
142150149 bytesimprime a forma o quanto for necessário; isto é, se a parte inferior estiver vazia, será cortada.
Corra com
php -nr '<code>' <input>
. Não prefixe a entradaTeste on-line
Adicione 11 bytes para não cortar: Insira
,$r[80]=" "
depois$r=""
.codificação explicada
Cada linha pode ser descrita com um ponto de partida e uma das quatro direções.
Desenhando em uma grade 9x9, a posição inicial varia de
0,0
a8,4
; ou, combinado, de0
a8*9+4=76
. Felizmente, todos os pontos de partida[0,4,8,36,40,44,72,76]
são divisíveis por 4; então o código de direção[0..3]
pode ser espremido nos bits 0 e 1 -> nenhuma mudança necessária.Para um cálculo fácil do movimento do cursor,
0
é utilizado o leste (somente direção sem movimento vertical) e[1,2,3]
sudoeste, sul e sudeste, onde o deslocamento é9
(para o movimento vertical) mais[-1,0,1]
->[8,9,10]
->delta=code?code+7:1
.A direção da primeira e da última linha sendo leste, que resulta em códigos que variam de 0 a 76
[0+0,4+0,0+2,0+3,4+1,4+2,4+3,8+1,8+2,...,44+1,44+2,72+0,76+0]
; e bit a bit xor 96 em cada valor resulta em códigos ascii imprimíveis e sem problemas[96,100,98,99,101,102,103,105,106,68, 72,70,71,73,74,75,77,78,40,44]
->`dbcefgijDHFGIJKMN(,
. O código usa o LSB para o bit 0, enquanto a linha 0 corresponde ao MSB, portanto, a string deve ser revertida. Finito.demolir
algum golfe explicou
^96
não tem efeito nos dois bits inferiores, pode ser ignorado ao extrair a direção; portanto, não há necessidade de armazenar o valor em uma variável, que economiza 5 bytes no init do cursor.~3
vez de124
salva um byte e permite o próximo jogo de golfe:$k=3
dentro da$p
atribuição economiza dois bytese não prejudica a pré-condição (já que o valor superior ainda possui um dígito).
chunk_split
é a maneira mais curta de inserir as quebras de linha.Eu nem quero saber quanto mais qualquer coisa levaria.
7+($c&3?:-6)
é um byte menor que$c&3?$c%4+7:1
.hexdec()
(8 bytes) para satisfazer a restrição de entrada.fonte
JavaScript,
184183178168167 167 bytesEra originalmente de 206 bytes, mas a resposta da @ Arnauld me inspirou a investigar uma solução de matriz unidimensional. Editar: salvou 1 byte graças a @ edc65. Guardado
515 bytes graças a @Arnauld. Economizou mais um byte, aprimorando a escolha dos caracteres.fonte
[0,1,2,3,4]
é mais curto[67,65,52,36,51,50,34,49,48,35,33,20,4,19,18,2,17,16,3,1]
e[0,2,4,6,8].map(i=>a[(e&102)*4+(e&17||15)*i]='o')
[..."ecVFUTDSREC6&54$32%#"]
e[0,2,4,6,8].map(i=>a[(e&102)*4+(e&17||15)*i]='o',e=e.charCodeAt()-34)
salvar mais 10 bytes.~
vez de-34
(infelizmente, eu entro em \ \, e é por isso que não economizo 2 bytes).Lote, 491 bytes
Nota: A última linha termina com um espaço. Colocar uma
if
condicional com uma variável dentro de umfor
loop está além do lote, de modo que precisa de sua própria sub-rotina. Como não faz nada visível, caio nele para sair. Entre~
aspas as strings no loop externo, permitindo que o loop interno faça um loop sobre os números. Os números são simplesmente as máscaras de bits para todos os lugares ondeo
s devem ser desenhados.fonte
C,
267262260256 caracteresA contagem de escapes como 1 caractere
k é uma pesquisa que se refere a quais caixas colocar um 'o'.
Experimente online!
fonte
Anterior, 468 bytes
Experimente online!
A primeira linha lê uma string de stdin, avaliando-a como um número hexadecimal. O restante do código é essencialmente apenas um loop duplo sobre as coordenadas x / y da grade, com um cálculo booleano massivo que determina se um
o
deve ser gerado para cada local.Há basicamente uma condição separada para cada um dos 20 pontos da grade, por exemplo (os quatro primeiros):
E depois que calculamos todos os 20 deles, OR OU o lote juntos, e se esse resultado for verdadeiro, produzimos a
o
, caso contrário, produzimos um espaço.O Befunge não possui nada no caminho das operações de manipulação de bits; portanto, para extrair os bits da entrada, estamos apenas avaliando repetidamente
n%2
e, depoisn/=2
, avançando nos cálculos das 20 condições.fonte