Faça uma foto em um quebra-cabeça deslizante

14

Sumário

O objetivo desse desafio é criar uma versão desfeita da imagem de um quebra-cabeça de 15 quebra-cabeças / deslizante, também chamado de taquin em francês.

Detalhes:

Dada uma entrada composta de:

  • uma imagem,
  • um número inteiro n,
  • um outro inteiro r,

seu programa, função ou qualquer outra coisa que se ajuste, deve gerar a mesma imagem ( ou seja, o mesmo tamanho e formato) da entrada, mas que passou pelo seguinte processo:

  1. divida a imagem em retângulos,
  2. remova um desses retângulos aleatoriamente,
  3. mova um número aleatório de retângulos contíguos da linha / coluna afetada pelo ponto (2.) para que o buraco criado seja preenchido e outro seja gerado nessa linha / coluna. Esse número pode ser 0se o espaço em branco estiver em um canto ou em uma aresta.

Repita (3) rvezes.

Esclarecimentos:

  • Se você moveu retângulos da linha na etapa (3.), você deve mover retângulos da coluna na próxima repetição,
  • se você moveu retângulos da esquerda para a direita em uma etapa da linha, eles devem ser movidos da direita para a esquerda na próxima etapa da linha, o mesmo para as colunas de cima para baixo e de baixo para cima,
  • você pode assumir que nserá escolhido para dividir os comprimentos dos lados da imagem.

Um último ponto:

Uma animação .gifmostrando todo o processo é muito bem-vinda.

Proponho usar a figura a seguir (que é 1024x768), com n=16e r=100como modelo, você pode usar qualquer outra figura (desde que seja relevante e cumpra as regras da SE, é claro).

Observe que as políticas de lacunas nos padrões se aplicam.

Isso é , então a submissão mais curta vence!

Os amantes de cães, gatos e patos devem ficar satisfeitos!

Como um exemplo foi solicitado, aqui está um, feito "à mão", com n=4er=1

Passos 1 e 2

insira a descrição da imagem aqui

Etapa 3 : em linha, 2 retângulos à esquerda

insira a descrição da imagem aqui

Frédéric
fonte
O exemplo sugere que os retângulos não precisam ter o mesmo tamanho, não precisam cobrir a imagem inteira e devem incluir linhas desenhadas sobre a imagem original. Você poderia esclarecer isso, alterando a especificação ou o exemplo?
Trichoplax
@ tricoplax: o exemplo foi desenhado à mão com tinta e rapidez. Vou refazê-lo corretamente.
Frédéric
@trichoplax: Devo admitir que não entendi completamente o seu ponto, mas essa linha de abertura não é necessária para entender o desafio, então acho que é inútil mantê-lo.
Frédéric
move a random number of contiguous rectanglespode ser 0 retângulos? (isto seria uma dor para fazer o comportamento de mudança de programa quando o branco aparece sobre uma borda / canto)
JungHwan min
@JungHwanMin: sim, pode. Boa observação, obrigado!
Frédéric

Respostas:

10

Mathematica, 246 bytes

ImageAssemble@(n=Nest)[k=RandomInteger;q=Reverse;({t,r}=1~k~2;q[o=n[q/@#&,#,r]&@*(n[#&,#,t]&)])[o@#/.{a___,b:_~RepeatedNull~k[Position[o@#,i][[1,2]]-1],i,c___}:>{a,i,b,c}]&,MapAt[(i=#~ImageAdd~1)&,#~ImagePartition~Scaled[1/#2],{1,#2}~k~2],#3]&

Função anônima. Contém U + F3C7, correspondente ao Transposeoperador do Mathematica . Esta função pega um Imageobjeto e retorna um Imageobjeto.

Animação de exemplo, com n=16er=100

Após 5000 iterações:

insira a descrição da imagem aqui(Clique na imagem para uma versão maior)

Explicação

Inicialização

n=Nest

Armazene a Nestfunção (operação repetida) em n.

k=RandomInteger;q=Reverse;

Armazene a RandomIntegerfunção em ke Reversefuncione em q.

Dividindo a imagem

#~ImagePartition~Scaled[1/#2]

Particione a imagem de entrada em (segunda entrada) ^ 2 blocos.

{1,#2}~k~2

Gere dois RandomIntegers entre 1 e a segunda entrada. Isso seleciona um bloco aleatório.

MapAt[(i=#~ImageAdd~1)&, ..., {1,#2}~k~2]

Faça esse azulejo branco. Guarde-o i.

Moving Tiles

{t,r}=1~k~2

Gere dois números inteiros aleatórios de 0 a 1 e armazene-os em te r, respectivamente. Isso seleciona aleatoriamente a direção.

o=n[q/@#&,#,r]&@*(n[#&,#,t]&)

Definir função o: a composição de

  1. uma função que transpõe os ttempos de entrada .
  2. uma função que inverte cada linha rvezes.
o @ #

Aplique oà entrada.

Position[o@#,i][[1,2]]

Encontre a coluna de i(imagem em branco).

k[ ... -1]

Subtraia um e encontre um número inteiro aleatório entre 0 e esse número. Isso escolhe aleatoriamente quantas peças mover.

o@#/.{a___,b:_~RepeatedNull~ ... ,i,c___}:>{a,i,b,c}

Quando o referido número de peças ocorrer antes de uma i(imagem em branco), troque de lugar.

(... q[o= ... ])[ ... ]

Inverta a ofunção e aplique-a ao resultado da operação acima. Isso inverte e não transpõe a imagem.

Loop e montagem de imagem

(n=Nest)[ ... ,#3]

Repita o processo acima (terceira entrada) vezes.

ImageAssemble@

Coloque as imagens juntas.

JungHwan Min
fonte
1
Boa resposta ! Obrigado pelos detalhes!
Frédéric