Validar soluções Loopy

9

Este é um desafio adicional ao desafio de gerar quebra-cabeças Loopy . Você pode resolver esse desafio antes de tentar o desafio mais difícil no link anterior.

O objetivo deste desafio é validar a solução para um quebra-cabeça maluco. Por favor, pegue toda a documentação sobre o que é um quebra-cabeça maluco no link anterior. Um quebra-cabeça em loop resolvido é formatado de maneira muito semelhante à saída de um envio válido para o desafio "gerar quebra-cabeças em loop" e pode ser assim:

+-+-+ +-+ +-+ +
|   | | |2|3|  
+-+ + + + + +-+
 2| | | |2|  3|
+ + +-+ + + +-+
 2|  2 1|3| |  
+-+ +-+ +-+ +-+
|2  | |    1 2|
+ +-+ +-+ +-+ +
| |2 1 2|3|3| |
+ + +-+ +-+ +-+
| | |3|2   1   
+ +-+ +-+-+-+-+
|        2 2  |
+-+-+-+-+-+-+-+

O caminho que compõe a solução é marcado com |e -caracteres entre os +caracteres.

Especificação de entrada

Seu programa receberá um quebra-cabeça em loop com uma solução formatada como o exemplo acima como entrada. Seu programa deve inferir o tamanho do quebra-cabeça a partir da entrada. Você pode fazer as seguintes suposições sobre a entrada:

  • O quebra-cabeça tem nada menos que 2 e não mais que 99 células em qualquer direção
  • Assim, cada linha tem um comprimento máximo de 199 caracteres, sem incluir o (s) caractere (s) de nova linha
  • Assim, a entrada contém um máximo de 99 linhas
  • cada linha pode terminar após o último caractere imprimível ou ser preenchida com caracteres de espaço em branco, para ter um comprimento de até 2 · y + 1 caracteres, em que y é o número de células na direção horizontal
  • cada posição com as coordenadas x e y ainda contém um +caractere
  • as posições horizontal ou verticalmente adjacentes às posições que contêm +caracteres contêm um caractere de espaço em branco, estão atrás do final da linha ou contêm um -caractere se horizontalmente adjacente ou um |caractere se verticalmente adjacente
  • todas as outras posições são ou por trás da extremidade da linha ou conter um dos caracteres , 0, 1, 2, ou3
  • todas as linhas são finalizadas com o (s) caractere (s) de nova linha padrão da sua plataforma
  • existe exatamente uma nova linha à direita

A entrada deve ser recebida de uma das seguintes maneiras:

  • Da entrada padrão
  • Como o valor de um parâmetro nomeado pem uma solicitação HTTP POST
  • Como o conteúdo de um formulário HTML
  • Como o conteúdo de um arquivo nomeado pem um diretório definido pela implementação
  • De uma maneira definida por implementação em tempo de execução, se os quatro primeiros não estiverem disponíveis
  • Codificado se o seu idioma não fornecer meios de receber entrada

Especificação de saída

Seu programa será finalizado para todas as entradas correspondentes à especificação de entrada e calculará se a solução para o quebra-cabeça está correta. Seu programa deve gerar o resultado da computação como um valor booleano de uma das seguintes maneiras:

  • Como um status de saída igual a zero (a solução é válida) ou diferente de zero (a solução é inválida)
  • Como o caractere y(solução é válida) ou n(solução é inválida) seguido por zero ou mais caracteres arbitrários emitidos de uma maneira definida pela implementação

O comportamento do seu programa não é especificado ao encontrar entrada não formatada de acordo com a especificação de entrada.

Pontuação

A pontuação do seu programa é o número de caracteres em sua origem, exceto caracteres em branco omitíveis e comentários omitíveis. Você é incentivado a recuar seu envio, para que seja mais fácil ler para os outros e comentar sua solução, para que seja mais fácil seguir.

Os envios que não seguem a especificação de entrada ou saída ou geram resultados incorretos são inválidos.

FUZxxl
fonte
Como a entrada deve ser manipulada? Ler de um arquivo? STDIN? Posso escrever uma função?
Martin Ender
@ MartinBüttner "seu programa receberá ...". Não sabe por que você gostaria de ler um arquivo.
John Dvorak
@ MartinBüttner Você precisa escrever um programa completo. Eu acho que o idioma "seu programa", "deve terminar", "status de saída" é bastante claro.
FUZxxl
11
Observe também que na maioria dos quebra 0- cabeças também é um número válido para uma célula.
Howard
@ Howard Desculpe, perdi isso.
FUZxxl 17/08/14

Respostas:

2

GolfScript, 133 caracteres

'|':^4,{48+.(}%+^*1>.^/'-'*+2/:F;4{{~@@/*}2F//n%zip-1%n*}:X*.'+-'?.3+@/(-2<' 9'+\+'9-+  99|+  9'3/:F;.,4*{X}*.9`?@=\' +09
'-!&'ny'1/=

Espera a entrada do STDIN e imprime ypara uma solução válida e npara uma inválida. Executa a tarefa usando principalmente substituição de cadeia na grade ou com versões rotacionadas da grade.

Código anotado:

# construct the string "|0|/|1|0|2|1|3|2-0-/-1-0-2-1-3-2"
# split into pieces of two and save to variable F
'|':^4,{48+.(}%+^*1>.^/'-'*+
2/:F;

# run the code block X 4 times
# with X: string-replace 1st item in F with 2nd, 3rd with 4th, ...
# i.e. '|0' with '|/', '|1' with '|0'
# and then rotate grid by 90 degrees
4{{~@@/*}2F//n%zip-1%n*}:X*

# for a valid grid all digits are now reduced to exactly '0'
# (i.e. no '1' or '2' or '3' or '/')

# now follow the loop along and remove it
# start: find the first occurence of '+-+' and replace with '+ 9'
# note: '9' is the marker for the current position
.'+-'?
.3+@/(-2<' 9'+\+

# string-replace '9-+' or '9|+' by '  9' (i.e. go one step along the loop)
# using block X enough times
'9-+  99|+  9'3/:F;
.,4*{X}*

# look for the marker '9' in the result and check if it is at the original
# position again
.9`?
@=

# the remaining grid must not contain any digits besides 0 and 9
# esp. no '|' or '-' may remain
\' +09
'-!

# check if both conditions are fulfilled and output corresponding character
&'ny'1/=
Howard
fonte
2

C # 803 579bytes

O programa completo, leituras do STDIN, deve lidar com qualquer esquema de nova linha comum, desde que tenha feeds de linha. Agradecemos ao HackerCow por apontar que não preciso anexar uma nova linha em uma pergunta diferente, solicitando que eu a remova aqui e economize 4 bytes

Código de golfe:

using C=System.Console;class P{static void Main(){var D=C.In.ReadToEnd().Replace("\r","").Split('\n');int w=D[0].Length+2,h=D.Length+1,i=0,j,c,T=0,O=1,o,z,R=0;var B=new int[w,h];var S=new int[w*h*9];for(;i++<w-2;)for(j=0;j<h-2;B[i,j]=c)if((c=(D[j++][i-1]-8)%10)>5){c=5;T++;S[0]=i+j*w;}for(i=0;++i<w-1;)for(j=0;++j<h-1;)R=(i%2+j%2>1&(o=B[i,j-1]%2+B[i-1,j]%2+B[i+1,j]%2+B[i,j+1]%2)>0&o!=2)|((c=B[i,j])<4&c!=o)?7:R;for(o=h=0;o<O;B[i,j]=0)if(B[i=(c=S[o++])%w,j=c/w]>4){h++;S[O++]=(S[O++]=c-w-1)+2;S[O++]=(S[O++]=c+w-1)+2;z=j%2<1?w*2:2;S[O++]=c-z;S[O++]=c+z;}C.Write(h-R<T?"n":"y");}}

O código executa 3 verificações, primeiro verificando o número de linhas ao redor de cada número e se cada junção tem 0 ou 2 linhas à frente, e depois todas as linhas são unidas.

Código formatado:

using C=System.Console;

class P
{
    static void Main()
    {
        var D=C.In.ReadToEnd().Replace("\r","").Split('\n');
        int w=D[0].Length+2,h=D.Length+1,i=0,j,c,T=0,O=1,o,z,R=0;
        var B=new int[w,h]; // this is the grid
        var S=new int[w*h*9]; // this is a list of joined up lines (stored as x+y*w)

        for(;i++<w-2;)
            for(j=0;j<h-2;B[i,j]=c)
                if((c=(D[j++][i-1]-8)%10)>5)
                { // we are a line
                    c=5;
                    T++; // increment line counter
                    S[0]=i+j*w; // set start of loop
                }

        for(i=0;++i<w-1;) // this loop checks the numbers and that every + has 0 or 2 lines leading from it
            for(j=0;++j<h-1;)
                R=(i%2+j%2>1&(o=B[i,j-1]%2+B[i-1,j]%2+B[i+1,j]%2+B[i,j+1]%2)>0&o!=2)|((c=B[i,j])<4&c!=o)?7:R; // set R to 7 (no significance) if check fails

        for(o=h=0;o<O;B[i,j]=0) // this loops through the list of joined lines adding more until the whole loop has been seen
            if(B[i=(c=S[o++])%w,j=c/w]>4)
            {
                h++; // increment "seen" counter
                S[O++]=(S[O++]=c-w-1)+2;
                S[O++]=(S[O++]=c+w-1)+2;
                z=j%2<1?w*2:2; // special for | and -
                S[O++]=c-z;
                S[O++]=c+z;
            }

        C.Write(h-R<T?"n":"y"); // check if R is greater than 0 or h is less than T and output appropriately
    }
}
VisualMelon
fonte
Obrigado @ edc65, não faço ideia de como eu perdi isso!
VisualMelon
1

Cobra - 514

class P
    def main
        t,m,g=[[1]][:0],nil,File.readAllLines('p')
        u,i=g[0].length,1
        for l in g.length,for c in u,if g[l][c]in'0123'
            n=0
            for j in-1:2:2,for r in[g[l+j][c],g[l][c+j]],if r in'-|',n+=1
            if'[n]'<>g[l][c],m?='n'
        else if g[l][c]in'-|',x,y,t,d=c,l,t+[[c,l]],g[l][c]
        while i
            i=z=6
            for f,b in[[-1,1],[1,1],[0,2],[-1,-1],[+1,-1],[0,-2]]
                if'-'==d,f,b=b,f
                for w in t.count,if z and t[w]==[x+f,y+b],t,x,y,d,z=t[:w]+t[w+1:],x+=f,y+=b,g[y][x],0
                i-=z//6
        print if(t.count,'n',m?'y')

Verifica se todos os números têm o número certo de linhas ao lado e, em seguida, percorre um caminho ao redor das linhas e verifica se houve algum erro.

Furioso
fonte