Java tutorial
/******************************************************************************* * 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; } }