Fillomino Solver

20

Fillomino es un rompecabezas en el que rellenas una cuadrícula con poliominós . Cada poliomino es un área de células contiguas. La representación de la cuadrícula muestra qué tamaño de poliomino cubre cada celda. Por ejemplo, un pentomino (5) se mostraría como 5en cada una de las cinco celdas contiguas (ver más abajo). Dos poliominós del mismo tamaño no pueden compartir un borde, pero pueden hacerlo en diagonal.

Para cada juego, que está comenzado con una serie de Givens y debe rellenar las celdas restantes. Un ejemplo sencillo de rompecabezas y solución:

muestra de rompecabezas de Fillomino

Su tarea: dado un rompecabezas cuadrado, resuélvalo y envíe la respuesta. La entrada puede ser a través de stdin, un argumento de línea de comando único o un archivo de texto. La entrada se dará como un número entero n, seguido de nlíneas de ndígitos cada uno. Las celdas vacías se darán como puntos ( .). Para el ejemplo de rompecabezas anterior, sería:

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

La salida es el rompecabezas resuelto, dado en nlíneas de ndígitos, a la consola o al archivo de texto:

33366
55446
55466
51462
33312

Si el rompecabezas no es válido, salida 0. Un rompecabezas podría no ser válido si la entrada está mal formada o no hay solución. Si hay varias soluciones, puede generar una o todas ellas.

Dado que cada celda está representada por un solo dígito, todos los rompecabezas consistirán en tamaño de poliominós 9y solo debajo. Si no es posible resolver sin poliominós más grandes, considérelo inválido.

Las respuestas válidas resolverán cualquier rompecabezas dado, no simplemente soluciones de salida para probar casos. Sin recursos externos, ya sea en línea o local. Si resulta que hay un idioma con una función incorporada de resolución de fillomino, no puede usarlo. En resumen, juega limpio .

Caso de prueba:

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....

Salida (una posible solución):

322133315
355445555
315443334
235531444
233135551
141535515
344553155
324553553
321223133

Recuerde que algunos poliominós no tienen números dados, y algunos tienen más de uno. Hay no una relación de uno a uno entre el número de Givens y el número de poliominós.

El puntaje es el código de golf estándar, el tamaño del programa en bytes.

Geobits
fuente
¿Es un enfoque recursivo una respuesta válida si funciona para una placa de 9x9 pero se queda sin memoria para una placa de mayor tamaño?
trichoplax
1
Yes.I no esperan que seas capaz de factible ejecutar un 31x31 o nada. Sólo para que pueda realmente funcionar tanto el 5x5 y 9x9 anteriormente (para dar salida a los casos de prueba), y sería teóricamente trabajo para más grande con el mismo algoritmo (dado una porquería toneladas de recursos).
Geobits

Respuestas:

4

4882 caracteres - Java

No es una solución muy desarrollada (es decir, 4800 caracteres es mucho más) Podría jugarse un poco más de golf ya que todavía hay 1 o 2 líneas de impresión de depuración. Creo que todavía puedo reducir bastante en términos de código inútil / optimizado.

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 había visto Polyominoes antes de esto, leí lo que son y, sin mirar a resolver los alrogitmos, acabo de inventar el mío (bastante lento).

Básicamente, usa mucho la recursividad ... Encuentra un Polyomino que está incompleto, intenta completarlo. Encuentra un espacio vacío, recorre 1-9 a través de todos los cuadrados en el bolsillo, establece ese bolsillo en ese valor. Si el bolsillo está completo, intenta encontrar otro bolsillo, luego se repite hasta terminar. No pude hacer que funcione para una cuadrícula de tamaño 9 ... Tengo al menos una optimización en mente que podría hacer que funcione dentro de un tiempo razonable para 9. Podría intentar ponerlo en práctica pronto.

Will_61
fuente
1
¿Cómo estás compilando esto? Recibo errores de variables duplicadas en algunos lugares.
Geobits