Hashiwokakero ("construir pontes" em japonês) é um quebra-cabeça em que você é encarregado de conectar um grupo de ilhas a pontes. As regras são:
- As pontes devem ser executadas vertical ou horizontalmente entre duas ilhas.
- Pontes não podem se cruzar.
- Um par de ilhas pode ser conectado por no máximo duas pontes paralelas.
- Cada ilha é marcada com um número entre 1 e 8, inclusive. O número de pontes conectadas a uma ilha deve corresponder ao número nessa ilha.
- As pontes devem conectar as ilhas em um único grupo conectado.
Sua tarefa é escrever um programa que resolva quebra-cabeças Hashiwokakero.
Você pode assumir que qualquer quebra-cabeça é solucionável e que existe apenas uma solução.
O programa deve ser razoavelmente eficiente. Por exemplo, resolver o quebra-cabeça 25x25 abaixo não deve demorar mais de 10 minutos em um PC comum e não deve usar mais do que um gigabyte de memória. Resolver quebra-cabeças menores como o 7x7 deve levar alguns segundos.
Entrada:
O quebra-cabeça será dado como um mapa 2D de caracteres, com os dígitos 1
para 8
representar as ilhas e os espaços representando a água. As linhas serão preenchidas com espaços, se necessário, para torná-las todas do mesmo comprimento.
As ilhas sempre serão separadas horizontal e verticalmente por pelo menos um quadrado de água, para que haja espaço para colocar a ponte potencial entre elas. Sempre haverá pelo menos duas ilhas em um quebra-cabeça.
Seu programa deve ler, de preferência, o mapa do quebra-cabeça a partir da entrada padrão, mas você pode especificar um método de entrada alternativo se a sua linguagem de programação exigir.
Resultado:
A saída deve ser como a entrada, exceto com espaços substituídos por pontes, conforme necessário. As pontes devem ser desenhadas usando caracteres de desenho de caixa Unicode ─
(U + 2500), │
(U + 2502), ═
(U + 2550) e ║
(U + 2551) para representar pontes simples e duplas horizontais e verticais.
Se os caracteres Unicode são um problema, você pode usar os caracteres ASCII -
, |
, =
e H
em vez disso.
Critérios de vitória:
Isso é código de golfe. A menor solução correta e razoavelmente eficiente vence.
Exemplos:
Quebra-cabeça (7x7):
2 2 1
1 4 3
3 2
4
3 2 3
1
3 4 2
Solução:
2─2──1
│1──4─3
3──2║ ║
│ │4 ║
│3─2║ 3
1║ ║ │
3──4─2
Quebra-cabeça (25x25):
2 2 2 2 1 1 2 2 2 2 2
1 3 5 4 4 2
2 2 4 5 5 4 2 2 1 3
2 1 1 3 3 2 2
3 4 4 4 4 5 4 3 2 3
2 4 5 4 2 3
2 1 4 2 4 3 1 1 2
2 1 3 1 1 6 4 2
3 2 4 3 6 3 2
2 2 3 3 2 5 2 4 3
2 1 1 2
1 3 3 3 3 5 8 7 6 5 4
2 3 1 1 2
1 1 5 1 4 5 6 3 1 2
1 1 2 2 3 4
3 5 4 4 3 3 8 7 5 1 2
2 3 1 2 2 1 1
2 2 2 2 5 7 6 3 3
3 3 6 3 5 3 2 2 2 3
2 1 2 3 2 2
3 4 6 4 5 5 3 3 5 1
2 1 2 2 1 1 3
2 1 1 2 3 6 5 2 2
2 3 4 4 4 2 1
2 2 2 2 2 2 2 1 1 3 2
Solução:
2─2─2──2 1 1─2─2──2──2─2
│ │ │1─3═5══4══4─2│
2 2─4─5══5═4═2│2──1 │ │3
│ 2│ ║1│ 1─3═3─2│ │ 2║
│ ║3═4│4══4─4═5─4─3──2 │3
2 4═5─4│ │ │ ║ │ │2───3│
│2─1║ ║4─2│ 4─3 │ 1│ 1 │2
2│1─3 ║║ │1 ║1──6══4 │ 2│
│3─2──4║ 3══6─3 ║ │ │ │2
2│2═3 │3──2 │ ║ 5─2│ 4─3│
│2─1│ │ │ │ ║ ║ │1 ║ │2
│ 1─3─3─3─3─5═8═7═6──5═4│
2──3───1│1─2│ ║ │ ║ ││
1 │ 1──5─1││ 4─5─6─3─1│2
1│ │1──2║ │2 │ ║ ║ │3═4│
│3─5═4 │4──3│ 3═8═7═5│1│2
2│ │ ║ 3│ 1│2──2║ │ ║1│1│
│2 │ ║ ║2 │2──2│5═7═6─3─3
3│ 3─6─3│ 5═3 │2│ ║2│2─3│
║2 │ ║ │ ║ │ 1│2─3║2│ ║2
3│ 4═6──4─5─5──3─3─5││1║│
│2 │ │1 │ │2║2──1│ ║1││3│
2│ │ 1│ │ 1║2│3══6═5─2││2
│2─3──4═4──4─2│ │ │1│
2─2──2─2──2─2─2 1 1─3─2
1 1
entrada?1 1
, que é válido e deve ser manuseado corretamente.Respostas:
Haskell, 1074 caracteres
Originalmente, eu o tinha ainda mais puramente japonês, implementando também as funções primitivas em termos de simples correspondência de padrões e combinações de listas:
Haskell, 1192
roda em ≈3 minutos no meu i5 .
Versão comentada:
fonte
Python, 1079 caracteres
O código faz uma pesquisa exaustiva bastante direta
S
, usando alguma propagação de restrição para executá-lo em um tempo razoável.E
representa o conjunto atual de arestas, no formato [de, para, delta, pesos possíveis] . de e para são identificadores de ilha e delta é 1 para arestas horizontais ou W (= largura das linhas) para arestas verticais. pesos possíveis é uma sub-lista de [0,1,2] que codifica o estado atual conhecido dessa aresta (0 = sem ponte, 1 = ponte única, 2 = ponte dupla).S
faz três coisas. Primeiro, ele propaga informações, como se uma aresta não tem mais um peso 0 como uma possibilidade, então todas as arestas que a atravessam são eliminadas (seus possíveis pesos são definidos para [0]). Da mesma forma, se a soma do peso mínimo para as arestas incidentes em uma ilha for igual ao peso da ilha, todas essas arestas serão definidas no mínimo.Segundo,
S
verifica se o gráfico ainda está conectado usando arestas não [0] (oQ
cálculo).Por fim,
S
escolhe uma aresta que ainda não está totalmente determinada e se chama recursivamente, definindo essa aresta para uma de suas possibilidades restantes.Demora cerca de 2 minutos para o maior exemplo.
fonte
print(B);sys.exit(0)
C # -
660156612225Não é particularmente bem-golfe. Usa a biblioteca de programação de restrições do google or-tools. Constrói restrições para contagens totais de arestas e para eliminar pontes cruzadas, mas é um pouco mais difícil definir restrições para garantir que todas elas estejam conectadas. Eu adicionei lógica para remover os componentes 2 = 2 e 1-1, mas ainda tenho que passar pela lista final (39 na grande) e eliminar aqueles que não estão totalmente conectados. Funciona muito rápido. Leva apenas alguns segundos no maior exemplo. Ungolfed:
fonte