Para obter mais informações, assista a este vídeo e acesse A276523 para obter uma sequência relacionada.
O quebra-cabeça Mondrian (para um número inteiro n
) é o seguinte:
Coloque retângulos não congruentes em uma n*n
grade quadrada. Qual é a menor diferença possível entre o maior e o menor retângulo?
Pois 6
, a diferença ideal para M(6)
é 5
e pode ser demonstrada da seguinte maneira:
___________
| |S|_______|
| | | L |
| |_|_______|
| | | |
| |_____|___|
|_|_________| (fig. I)
O maior retângulo (L) tem uma área de 2 * 4 = 8
, e o menor retângulo (S) tem uma área de 1 * 3 = 3
. Portanto, a diferença é 8 - 3 = 5
.
Lembre-se de que, atualmente, nenhuma solução ideal n > 44
foi encontrada.
Sua tarefa é criar um programa que gere uma grade Mondrian que contenha uma solução (não ótima), dado um número inteiro n
.
Você será testado nos números de 100 a 150. Sua pontuação para cada teste será a diferença entre o maior e o menor retângulo. Sua pontuação total é a soma das suas pontuações em todos os testes de 100 a 150.
Você deve apresentar sua saída da seguinte forma:
{number}
{grid}
Onde number
está a pontuação (a diferença entre maior e menor) e grid
é:
- Uma cadeia de linhas múltiplas ou
- Uma lista bidimensional.
A grade DEVE mostrar claramente onde um retângulo começa e termina.
Regras:
- Seu programa deve se encaixar na sua resposta.
- Seu programa deve gerar um valor para qualquer número entre 100 e 150 dentro de 1 hora em um laptop moderno.
- Seu programa deve gerar a mesma solução para um número inteiro
n
toda vez que o programa for executado. - Você deve fornecer um link para as saídas de todas as 51 soluções (usando Pastebin, Github Gist ... qualquer coisa, realmente).
- Você deve ter pelo menos dois retângulos na grade quadrada para sua solução.
fonte
Respostas:
Piet, 9625
(Finalmente funciona!)
As pessoas exigiram, então aqui está. Essa é uma solução extremamente ingênua (essencialmente a mesma que os limites superiores soltos na página OEIS): divide cada quadrado em apenas dois retângulos.
Esta essência contém os detalhes em dois arquivos:
?
é o prompt de entrada, seguido imediatamente pela pontuação de saída e depois pela grade.Explicação
Este programa aceita um único número
N
como entrada. Se o número for ímpar, a pontuação é o número; se for par, a pontuação é o dobro do número.Após a saída da pontuação, o restante do lado esquerdo do programa é gasto preenchendo a pilha com cinco lotes das seguintes informações:
N
)_
espaço ou)|
)O lado direito do programa pega cada conjunto de quatro valores e imprime essa parte da grade.
fonte
C 6108
Isso usa uma versão recursiva (realmente iterativa) da solução mínima. Em vez de dividir o quadrado em dois retângulos, onde um é um pouco maior que a metade da área, ele o divide em N retângulos. Portanto, o primeiro retângulo é um pouco maior que
1/N
a área total. Depois, pegando o restante, o programa divide um retângulo um pouco maior que1/(N-1)
o restante e assim sucessivamente, até que o restante seja o último retângulo. Os retângulos são cortados do restante em espiral no sentido horário, primeiro na parte superior, depois à direita etc.Como esse é um método muito direto, em vez de procurar um espaço amplo, ele é executado rapidamente - levando cerca de 25 segundos (em um Raspberry Pi) para analisar 74 soluções cada um para o conjunto de problemas fornecido.
Minha intenção é usar esses resultados para informar melhor um algoritmo de pesquisa para uma abordagem mais sofisticada.
A saída fornece a pontuação e um desenho (ascii) e as coordenadas para os vértices dos retângulos. Os vértices estão no sentido horário, começando no canto superior esquerdo do retângulo em questão.
Desenvolvido usando o gcc 4.9.2-10.
Resultados em https://github.com/JaySpencerAnderson/mondrian
Código:
fonte
C - 2982
Este programa implementa uma pesquisa através de um amplo conjunto de resultados. A parte importante de tornar essa pesquisa prática foi falhar cedo e / ou não seguir caminhos ruins.
Isso gera um conjunto de retângulos a serem considerados para a solução. O conjunto de retângulos gerados evita aqueles com dimensões que não seriam úteis. Por exemplo, se o programa estiver tentando encontrar a solução para um quadrado de 128x128, dividido em 8 retângulos, ele gerará um retângulo de 128x16. Não será gerado 120 x 17, porque não há perspectiva de um retângulo de geração com 8 de largura para preencher a lacuna no final de 120.
A estratégia inicial para colocar retângulos é colocá-los no interior do perímetro do quadrado (função de construção). Dessa forma, o algoritmo obtém um feedback muito rápido em cada canto, sobre se há um problema com a sequência escolhida. Ao colocar retângulos, a lógica continua observando para ver se há brechas no espaço muito estreitas para qualquer retângulo. Depois que o perímetro foi preenchido com sucesso, a estratégia muda para tentar corresponder o espaço restante com os retângulos restantes (função de correspondência).
Outra coisa que pode ser interessante é que isso implementa transações com reversão para as pilhas de retângulos.
Este programa não tenta encontrar o melhor ajuste possível. Ele recebe um orçamento (64) e sai quando encontra a primeira solução. Se ele nunca encontrar uma solução, aumentamos o orçamento (em 16) e tentamos novamente. O tempo necessário (em um laptop Dell com um processador I7) variou de bem menos de um minuto a 48 minutos para 150 de um lado (149 de um lado levaram menos de 2 minutos). Todas as 51 soluções usaram 11 retângulos. As pontuações das 51 soluções variaram de 41 a 78. As razões pelas quais usei 11 retângulos foram que a pontuação era menor do que com menos retângulos e parecia que 12 retângulos levariam muito mais do que a hora prevista.
As soluções e o código podem ser encontrados em https://github.com/JaySpencerAnderson/mondrian . Eles são os dois arquivos my4 *.
BTW, se você compilar isso em "my4" e executá-lo da seguinte forma: "./my4 -h", ele lhe dará uso. Se você quiser vê-lo em ação, tente algo como "./my4 -l 50 -n 8". Se você alterar o "#if 0" para "#if 1", ele renderizará o espaço restante na tela. Se você quiser alterar isso para renderizar os retângulos, procure o ponto em que o código executa "gráfico (espaço, lado)" e mude para "gráfico (pilha de chamadas, lado)". Eu também sugeriria alterar o orçamento inicial de 64 para 32 se você quiser brincar com soluções para quadrados com cerca de 50 de largura. A solução para quadrados menores terá uma pontuação melhor com um orçamento menor.
O programa abaixo é funcional. Verifique o github para o código completo (com uso, comentários, etc).
fonte