Validate Loopy Solutions This is an additional challenge to the generate Loopy puzzles challenge. You might want to solve this challenge before attempting the harder challenge in the previous link.

The goal of this challenge is to validate the solution to a loopy puzzle. Please take all documentation on what a loopy puzzle is from the previous link. A solved loopy puzzle is formatted in a very similar way to the output of a valid submission to the “generate loopy puzzles” challenge and may look like this:

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


The path that makes up the solution is marked with | and - characters between the + characters.

Input specification

Your program shall receive a loopy puzzle with a solution formatted like the example above as input. Your program shall infer the size of the puzzle from the input. You may make the following assumptions about the input:


The puzzle has no less than 2 and no more than 99 cells in either direction
Thus, each line has a maximum length of 199 characters not including the newline character(s)
Thus, the input contains a maximum of 99 lines
each line may end after the last printable character or may be padded with whitespace characters so it has a length of up to 2·y + 1 characters where y is the number of cells in horizontal direction
each position with both x and y coordinates even contains a + character
positions horizontally or vertically adjacent to positions containing + characters contain either a whitespace character, are behind the end of line or contain a - character if horizontally adjacent or a | character if vertically adjacent
all other positions are either behind the end of line or contain one of the characters , 0, 1, 2, or 3
all lines are terminated with your platforms default newline character(s)
there is exactly one trailing newline


Input shall be received in one of the following ways:


From standard input
As the value of a parameter named p in an HTTP POST request
As the content of an HTML form
As the content of a file named p in an implementation-defined directory
In an implementation defined way at runtime if the former four are not available
Hard coded if your language provides no mean of receiving input


Output specification

Your program shall terminate for all inputs matching the input specification and shall compute whether the solution to the puzzle is correct. Your program shall output the result of the computation as a boolean value in one of the following ways:


As an exit status of either zero (solution is valid) or non-zero (solution is invalid)
As the character y (solution is valid) or n (solution is invalid) followed by zero or more arbitrary characters output in an implementation defined way


The behaviour of your program is unspecified when encountering input not formatted according to the input specification.

Scoring

The score of your program is the number of characters in its source except for omittable whitespace characters and omittable comments. You are encouraged to indent your submission so it's easier to read for the others and to comment your solution so its easier to follow.

Submissions that fail to follow the input or output specification or generate incorrect results are invalid.
C# 803 579bytes

Complete program, reads from STDIN, should cope with any common new-line scheme as long as it has line feeds. Thanks to HackerCow for pointing out that I don't have to append a new line in a different question, prompting me to remove it here and save 4 bytes

Golfed code:

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++&lt;w-2;)for(j=0;j&lt;h-2;B[i,j]=c)if((c=(D[j++][i-1]-8)%10)&gt;5){c=5;T++;S[0]=i+j*w;}for(i=0;++i&lt;w-1;)for(j=0;++j&lt;h-1;)R=(i%2+j%2&gt;1&amp;(o=B[i,j-1]%2+B[i-1,j]%2+B[i+1,j]%2+B[i,j+1]%2)&gt;0&amp;o!=2)|((c=B[i,j])&lt;4&amp;c!=o)?7:R;for(o=h=0;o&lt;O;B[i,j]=0)if(B[i=(c=S[o++])%w,j=c/w]&gt;4){h++;S[O++]=(S[O++]=c-w-1)+2;S[O++]=(S[O++]=c+w-1)+2;z=j%2&lt;1?w*2:2;S[O++]=c-z;S[O++]=c+z;}C.Write(h-R&lt;T?"n":"y");}}


The code performs 3 checks, first checking the number of lines around each number and that each junction has 0 or 2 lines leading from it, then that all the lines are joined together.

Formatted code:

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

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

        for(o=h=0;o&lt;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]&gt;4)
            {
                h++; // increment "seen" counter
                S[O++]=(S[O++]=c-w-1)+2;
                S[O++]=(S[O++]=c+w-1)+2;
                z=j%2&lt;1?w*2:2; // special for | and -
                S[O++]=c-z;
                S[O++]=c+z;
            }

        C.Write(h-R&lt;T?"n":"y"); // check if R is greater than 0 or h is less than T and output appropriately
    }
}