Fillomino Solver


20

Fillomino é um quebra-cabeça em que você preenche uma grade com poliamino . Cada poliomino é uma área de células contíguas. A representação em grade mostra qual tamanho o polyomino está cobrindo cada célula. Por exemplo, um pentomino (5) seria mostrado como 5em cada uma das cinco células contíguas (veja abaixo). Dois poliominoes do mesmo tamanho não podem compartilhar uma borda, mas podem bordar na diagonal.

Para cada quebra-cabeça, você começa com um número de dados e deve preencher as células restantes. Um exemplo fácil de quebra-cabeça e solução:

amostra puzzle puzzle

Sua tarefa: Dado um quebra-cabeça quadrado, resolva-o e dê a resposta. A entrada pode ser via stdin, um único argumento de linha de comando ou arquivo de texto. A entrada será fornecida como um número inteiro n, seguida por nlinhas de ndígitos cada. As células vazias serão fornecidas como pontos ( .). Para o exemplo de quebra-cabeça acima, seria:

5
3..66
5.4.6
.54.6
.1.6.
..312

Saída é o quebra-cabeça resolvido, fornecido em nlinhas de ndígitos, para console ou arquivo de texto:

33366
55446
55466
51462
33312

Se o quebra-cabeça não for válido, produza 0. Um quebra-cabeça pode ser inválido se a entrada estiver malformada ou se não houver solução. Se houver várias soluções, você poderá gerar uma ou todas elas.

Como cada célula é representada por um único dígito, todos os quebra-cabeças consistirão no tamanho 9e no tamanho de polioaminoes . Se não for possível resolver sem poliomatinos maiores, considere-o inválido.

Respostas válidas resolverão qualquer quebra-cabeça, não apenas soluções de saída para casos de teste. Nenhum recurso externo, seja online ou local. Se não acontece para ser uma linguagem com um built-in função fillomino problemas, você não pode usá-lo. Em suma, jogue limpo .

Caso de teste:

Entrada:

9
..21.3..5
.5...5..5
.1.44.334
...53.4..
2.3.3..5.
1.15.5.15
..45..1..
.24.53.53
....2....

Saída (uma solução possível):

322133315
355445555
315443334
235531444
233135551
141535515
344553155
324553553
321223133

Lembre-se de que alguns poliomatinos não têm números determinados e alguns têm mais de um. Há não uma relação de um-para-um entre o número de Givens e o número de poliominós.

Pontuação é código-golfe padrão, tamanho do programa em bytes.


Uma abordagem recursiva é uma resposta válida se funcionar para uma placa 9x9, mas ficar sem memória para uma placa de tamanho maior?
Trichoplax

1
Yes.I não esperam que você seja capaz de viabilizar executar um nada 31x31 ou. Apenas para que você possa realmente executar o 5x5 e o 9x9 acima (para fornecer saída para os casos de teste) e, teoricamente, funcionaria para um tamanho maior com o mesmo algoritmo (considerando uma tonelada de recursos).
Geobits

Respostas:


4

4882 caracteres - Java

Não é uma solução muito golfe (ou seja, 4800 caracteres é um lotttttttttttt). Poderia ser um pouco mais jogado porque 1 ou 2 linhas de impressão de depuração ainda estão lá. Acho que posso reduzir um pouco ainda em termos de código inútil / otimizado.

import java.util.*;import java.awt.Point;public class G{public static void main(String[]args){new G();}Scanner z=new Scanner(System.in);public G(){s=z.nextInt();z.nextLine();int g[][]=new int[s][s];for(int i=0;i<s;i++)Arrays.fill(g[i],-1);for(int i=0;i<s;i++){String line=z.nextLine();for(int j=0;j<s;j++)if(line.charAt(j)!='.')g[i][j]=Integer.parseInt(Character.toString(line.charAt(j)));}System.out.println();if(y(g)){for(int i=0;i<s;i++)for(int j=0;j<s;j++)System.out.print(g[i][j]);System.out.println();}else System.out.println(0);}private boolean x(Collection<Point>c,int[][]d){if(c.size()==0)return true;int j=0;for(Iterator<Point>k=c.iterator();k.hasNext();k.next(),j++){for(int sol=9;sol>=0;sol--){int[][]a=new int[s][s];for(int i=0;i<s;i++)a[i]=Arrays.copyOf(d[i],s);List<Point>b=new ArrayList<Point>();for(Point p:c)if(!b.contains(p))b.add(new Point(p));a[b.get(j).x][b.get(j).y]=sol;if(w(a,b.get(j))){if(x(b,a)){for(int i=0;i<s;i++)d[i]=Arrays.copyOf(a[i],s);c.clear();c.addAll(b);return true;}}}}return false;}int s;private boolean y(int[][]d){int[][] a=new int[s][s];for (int i = 0; i<s;i++)a[i]=Arrays.copyOf(d[i],s);List<Point> incomplete=new ArrayList<Point>();if(r(a)&&s(a)){a(a);System.exit(0);}else if(!r(a)){q("INVALID FROM MAIN, ",12);return false;}for(int i=0;i<s;i++)for(int j=0;j<s;j++){if(a[i][j]!=-1)if(t(new Point(i,j),a,null,a[i][j]).size()!=a[i][j]){if(w(a,new Point(i,j))){a(a);if(y(a)){for(int i=0;i<s;i++)d[i]=Arrays.copyOf(a[i],s);return true;}else return false;}else return false;}}for(int i=0;i<s;i++)for(int j=0;j<s;j++)if(a[i][j]==-1){Set<Point>c=t(new Point(i,j),a,null,-1);if(x(c,a)){if(y(a)){for(int i=0;i<s;i++)d[i] = Arrays.copyOf(a[i], s);return true;}else return false;}else return false;}q("How did you get here",1);return false;}private boolean w(int[][]d,Point b){List<Point>c;Set<Point>a;a=t(b,d,null,d[b.x][b.y]);c=new ArrayList<Point>(u(b,d,null,d[b.x][b.y]));int h=d[b.x][b.y];int g=h-a.size();if(c.size()<g){return false;}else if(v(c,h,h,new ArrayList<Point>(a),0,d))return true;else return false;}private boolean v(List<Point>c,int h,int g,List<Point>e,int f,int[][]d){if(e==null)e=new ArrayList<Point>();int[][]a=new int[s][s];for(int i=0;i<s;i++)for(int k=0;k<s;k++)a[i][k]=d[i][k];if(f<g&&e.size()<g){for(int i=0;i<c.size();i++){if(!e.contains(c.get(i))){if(d[c.get(i).x][c.get(i).y]==h){for(Point c:e){a[c.x][c.y]=h;}Set<Point> u=t(e.get(0),a,null,h);Set<Point>v=t(c.get(i),a,null,h);if(!Collections.disjoint(u,v)){u.addAll(v);List<Point>uList=new ArrayList<Point>(u);if(v(c,h,g,uList,f+1,a)){q("this e sucess",2);if(y(d)){e.addAll(uList);return true;}}else;}for(int l=0;l<s;l++)for(int k=0;k<s;k++)a[l][k]=d[l][k];}else if(e.add(c.get(i))){if(v(c,h,g,e,f+1,d)){q("this e sucess",2);if(y(d))return true;}}if(e.contains(c.get(i)))e.remove(c.get(i));}}return false;}else if(f>g||e.size()>g){if(f>g){q("Your over the g. ");return false;}else return false;}else{for(Point c:e){a[c.x][c.y]=h;}if(r(a)){if(y(a)){for(int i=0;i<s;i++)d[i]=Arrays.copyOf(a[i],s);q("complete(a) is true, ",4);return true;}else{return false;}}else{return false;}}}private void q(String out,int i){System.err.println(out+". exit code: "+i);System.exit(i);}private void q(String a){q(a,0);}private boolean r(int[][] d){for(int i=0;i<s;i++)for(int j=0;j<s;j++)if(d[i][j]!=-1){Set<Point>same=t(new Point(i,j),d,null,d[i][j]);if(same.size()>d[i][j]){return false;}Set<Point>fae=u(new Point(i,j),d,null,d[i][j]);if(u(new Point(i,j),d,null,d[i][j]).size()<d[i][j]){return false;}}return true;}private Set<Point> u(Point p,int[][]d,Set<Point>u,int i){u=(u==null)?new HashSet<Point>():u;if(d[p.x][p.y]==i||d[p.x][p.y]==-1)u.add(p);int x=p.x,y=p.y;Point t=new Point();if(x+1<s&&(d[x+1][y]==i||d[x+1][y]==-1)){if(u.add(new Point(x+1,y)))u=u(new Point(x+1,y),d,u,i);}if(y+1<s&&(d[x][y+1]==i||d[x][y+1]==-1)){if(u.add(new Point(x,y+1)))u=u(new Point(x,y+1),d,u,i);}if(x-1>=0&&(d[x-1][y]==i||d[x-1][y]==-1)){if(u.add(new Point(x-1,y)))u=u(new Point(x-1,y),d,u,i);}if(y-1>=0&&(d[x][y-1]==i||d[x][y-1]==-1)){if(u.add(new Point(x,y-1)))u=u(new Point(x,y-1),d,u,i);}return u;}private Set<Point> t(Point p,int[][]d,Set<Point>u,int i){u=(u==null)?new HashSet<Point>():u;if(d[p.x][p.y]==i)u.add(p);int x=p.x,y=p.y;Point t=new Point(p);if(x+1<s&&d[x+1][y]==i){if(u.add(new Point(x+1,y)))u=t(new Point(x+1,y),d,u,i);}if(y+1<s&&d[x][y+1]==i){if(u.add(new Point(x,y+1)))u=t(new Point(x,y+1),d,u,i);}if(x-1>=0&&d[x-1][y]==i){if(u.add(new Point(x-1,y)))u=t(new Point(x-1,y),d,u,i);}if(y-1>=0&&d[x][y-1]==i){if(u.add(new Point(x,y-1)))u=t(new Point(x,y-1),d,u,i);}return u;}private boolean s(int[][]d){for(int i=0;i<s;i++)for(int j=0;j<s;j++)if(t(new Point(i,j),d,null,d[i][j]).size()!=d[i][j])return false;return true;}private void a(int[][]d){for(int i=0;i<s;i++){for(int j=0;j<s;j++){System.out.printf("%1s",d[i][j]==-1?".":Integer.toString(d[i][j]));}System.out.println("");}}}

Como nunca vi Polyominoes antes disso, li o que são e, sem olhar para resolver os alrogitmos, acabei inventando os meus (bem devagar).

Basicamente, usa muito a recursão ... Encontra um Polyomino incompleto, tenta concluí-lo. Encontra um espaço vazio, dá laços de 1 a 9 por todos os quadrados no bolso e define esse bolso para esse valor. Se o bolso estiver completo, ele tenta encontrar outro bolso e depois repete até terminar. Não consegui fazê-lo funcionar para uma grade de tamanho 9 ... Tenho pelo menos uma otimização em mente que poderia fazê-lo funcionar dentro de um tempo razoável para 9. Talvez tente colocar isso em breve.


1
Como você está compilando isso? Estou recebendo erros variáveis ​​duplicados em alguns lugares.
Geobits 13/03/2015
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.