com.santhoshknn.sudoku.GridExtractor.java Source code

Java tutorial

Introduction

Here is the source code for com.santhoshknn.sudoku.GridExtractor.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Santhosh Kannan, santhoshknn@gmail.com
 *
 * This file is part of Sudoku Webapp.
 *
 * Sudoku Webapp is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Sudoku Webapp is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Sudoku Webapp.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package com.santhoshknn.sudoku;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.Scanner;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.santhoshknn.sudoku.model.GridResponse;

/**
 * <p>
 * Parses the supplied as-is input and creates a 9x9 grid for one of the sudoku
 * solvers to attempt a solution.
 * <p>
 * <p>
 * <strong>Note:</strong> The assumption is the supplied input is of the form
 * x,x,x,6,x,1,x,......x,x received by the RESTful resource via GET. Work on
 * other options as needed.
 * </p>
 *
 * @author santhoshk
 *
 */
public class GridExtractor {

    private static final int GRID_SIZE = 161;

    private final Logger log = LoggerFactory.getLogger(GridExtractor.class);

    private final String INPUT_LENGTH_INVALID = "Invalid input. Length of input is not 161";
    private final String INVALID_NUMBER_ERROR = "Invalid number encountered during sudoku grid extraction in supplied input";
    private final String INVALID_CHAR_ERROR = "Invalid character encountered during sudoku grid extraction in supplied input";
    private final String INVALID_CHARS_IN_FILE = "Invalid number of chars in row.Please fix input in row ";

    /**
     * Parses the supplied input to extract a 9x9 grid of integers substituting
     * the supplied x with a 0
     *
     * @param input
     * @return extracted gridresponse
     */
    public GridResponse parse(final String input) {

        int[][] grid = new int[9][9];
        String error = null;
        GridResponse response = new GridResponse();
        log.info("Parsing supplied input string to create sudoku grid");
        // Strip whitespaces if any
        String sanitized = StringUtils.deleteWhitespace(input);
        // Fail early. Check if the length is 161 (81 + 80 commas)
        if (StringUtils.isBlank(sanitized) || StringUtils.length(sanitized) != GRID_SIZE) {
            error = INPUT_LENGTH_INVALID;
        } else {
            String[] tokens = sanitized.split(",");
            int row = 0, col = 0;
            for (int k = 0; k < 81; k++) { // tokens = 81
                if (StringUtils.equals("x", tokens[k]))
                    grid[row][col] = 0;
                else if (StringUtils.isNumeric(tokens[k])) {
                    // What if the user enters a number > 9? However, accept 0
                    // since it could mean an empty cell
                    int number = Integer.parseInt(tokens[k]);
                    if (number > 9) {
                        error = INVALID_NUMBER_ERROR + ":" + number;
                        break;
                    }
                    grid[row][col] = number;
                } else {
                    // Invalid character. Fail
                    error = INVALID_CHAR_ERROR;
                    break;
                }
                col++;
                if ((k + 1) % 9 == 0) { // Update row & reset column
                    row++;
                    col = 0;
                }
            }
        }
        if (null == error)
            response.setGrid(grid);
        else {
            response.setError(error);
            log.error(error);
        }
        return response;
    }

    /**
     * <p>
     * Parses the supplied file to extract a 9x9 grid of integers substituting
     * the supplied x with a 0
     * </p>
     * <b>Note:</b>Used internally for testing with various data. REST API uses
     * the operation above
     *
     * @param input
     * @return extracted grid if valid input, null otherwise
     */
    public GridResponse parseFromFile(final String fileName) {
        int[][] grid = new int[9][9]; // default 0 vals
        GridResponse response = new GridResponse();
        Scanner scanner = null;
        String error = null;
        try {
            URL url = getClass().getResource(fileName);
            log.info("Reading input file [{}]", url.getFile());
            scanner = new Scanner(new File(url.getPath()));
            int row = 0;
            while (scanner.hasNext()) {
                int col = 0;
                String line = scanner.nextLine();
                // delete whitespaces added for cosmetic purpose
                line = StringUtils.deleteWhitespace(line);
                if (line.isEmpty())
                    continue; // Sanitize input. Remove line added for
                              // readability
                              // fail if line's length!=9
                if (line.length() != 9) {
                    error = INVALID_CHARS_IN_FILE + ":" + (row + 1);
                    break;
                }

                for (int i = 0; i < line.length(); i++) {
                    //log.info("Row [{}] Char is [{}]",row,line.charAt(i));
                    if (Character.isDigit(line.charAt(i))) {
                        int number = Character.getNumericValue(line.charAt(i));
                        grid[row][col] = number;
                    } else {
                        grid[row][col] = 0;
                    }
                    col++;
                }
                if (row == 9)
                    break;
                row++;
            }
        } catch (FileNotFoundException e) {
            log.error("Error reading file [{}]", fileName, e);
        } finally {
            if (scanner != null)
                scanner.close();
        }
        if (null == error) {
            response.setGrid(grid);
        } else {
            response.setError(error);
            log.error(error);
        }
        return response;
    }

}