#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <cctype>
#include <cstdlib>

using namespace std;

void error(const string& msg) {
    cerr << "Validation Error: " << msg << endl;
    exit(1);
}

int main() {
    string line;
    bool ended = false;
    
    while (getline(cin, line)) {
        // Strip trailing CR
        if (!line.empty() && line.back() == '\r') {
            line.pop_back();
        }
        
        // Skip completely empty lines between cases
        if (line.empty()) continue;
        
        stringstream ss(line);
        int w = -1, h = -1;
        if (!(ss >> w >> h)) {
            error("Could not read width and height from line: '" + line + "'");
        }
        
        string extra;
        if (ss >> extra) {
            error("Extra characters after width and height: '" + extra + "'");
        }
        
        if (w == 0 && h == 0) {
            ended = true;
            break;
        }
        
        if (w < 1 || w > 40 || h < 1 || h > 40) {
            error("Width or height out of bounds (1-40): w=" + to_string(w) + ", h=" + to_string(h));
        }
        
        vector<string> grid(h);
        vector<int> chk_count(10, 0);
        
        for (int i = 0; i < h; i++) {
            if (!getline(cin, grid[i])) {
                error("Unexpected EOF while reading grid row " + to_string(i) + " of " + to_string(h));
            }
            if (!grid[i].empty() && grid[i].back() == '\r') {
                grid[i].pop_back();
            }
            
            if ((int)grid[i].length() != w) {
                error("Row " + to_string(i) + " has length " + to_string(grid[i].length()) + " instead of expected width " + to_string(w));
            }
            
            for (int j = 0; j < w; j++) {
                char c = grid[i][j];
                if (c == 'x' || c == 'X' || c == ' ') {
                    // Valid
                } else if (c >= '0' && c <= '9') {
                    chk_count[c - '0']++;
                } else {
                    error("Invalid character '" + string(1, c) + "' at row " + to_string(i) + ", col " + to_string(j));
                }
            }
        }
        
        // Validate checkpoints
        if (chk_count[0] != 1) {
            error("Must have exactly one start checkpoint '0'. Found: " + to_string(chk_count[0]));
        }
        if (chk_count[1] != 1) {
            error("Must have exactly one checkpoint '1'. Found: " + to_string(chk_count[1]));
        }
        
        int highest = 1;
        for (int k = 2; k <= 9; k++) {
            if (chk_count[k] > 0) {
                if (chk_count[k] != 1) {
                    error("Multiple occurrences of checkpoint '" + to_string(k) + "' found: " + to_string(chk_count[k]));
                }
                if (highest != k - 1) {
                    error("Gap in checkpoints! Found '" + to_string(k) + "' but previous was '" + to_string(highest) + "'");
                }
                highest = k;
            }
        }
    }
    
    if (!ended) {
        error("Input did not end with '0 0'");
    }
    
    // Check if there is trailing non-whitespace data at EOF
    char extra_char;
    while (cin >> extra_char) {
        error("Extra trailing non-whitespace character after '0 0': '" + string(1, extra_char) + "'");
    }
    
    cout << "Validation successful! All constraints met." << endl;
    return 0;
}
