Ad
Code
Diff
  • import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.LinkedList;
    import java.util.regex.Pattern;
     
    public class CrossMath {
    	static class Operation {
    		ArrayList<String> parameters;
    		String result;
    		public Operation(ArrayList<String> parameters, String result) {
    			this.parameters = parameters;
    			this.result = result;
    		}
     
    		@Override
    		public String toString() {
    			return "Operation [" + parameters + ", =" + result + "]";
    		}
    		public int unknownAmmount(HashMap<String, Integer> solvedUnkowns) {
    			int ammount = 0;
    			final String REGEX = "^((-)?[0-9]+)|([-+x/])$";
    			for (String str : parameters) {
    				if (!str.matches(REGEX) && !solvedUnkowns.containsKey(str)) {
    					ammount++;
    				}
    			}
    			if (!result.matches(REGEX) && !solvedUnkowns.containsKey(result)) {
    				ammount++;
    			}
    			return ammount;
    		}
     
    		public void calculateUnkown(HashMap<String, Integer> solvedUnkowns) {
    			for(int position=0;position<this.parameters.size();position++) {
    				String param = this.parameters.get(position);
    				if (solvedUnkowns.containsKey(param)) {
    				    this.parameters.set(position, Integer.toString(solvedUnkowns.get(param)));
    				}
    			}
    
    			String resultVar = result;
    			if (solvedUnkowns.containsKey(resultVar)) {
    			    result = Integer.toString(solvedUnkowns.get(resultVar));
    			}
    			
    			if(result.matches("[A-Z]+")) {
    				int resultUnknown=0;
    					switch(this.parameters.get(1)) {
    						case "+":
    							resultUnknown = Integer.parseInt(this.parameters.get(0))+Integer.parseInt(this.parameters.get(2));
    							break;
    						case "-":
    							resultUnknown = Integer.parseInt(this.parameters.get(0))-Integer.parseInt(this.parameters.get(2));
    							break;
    						case "*":
    							resultUnknown = Integer.parseInt(this.parameters.get(0))*Integer.parseInt(this.parameters.get(2));
    							break;
    						case "/":
    							resultUnknown = Integer.parseInt(this.parameters.get(0))/Integer.parseInt(this.parameters.get(2));
    							break;
    						default: 
    							throw new IllegalArgumentException("Comando desconocido: ");
    				}
    				solvedUnkowns.put(result, resultUnknown);
    			}else if(this.parameters.get(0).matches("[A-Z]+")){
    				int resultUnknown=0;
    				switch(this.parameters.get(1)) {
    				case "+":
    					resultUnknown = Integer.parseInt(result)-Integer.parseInt(this.parameters.get(2));
    					break;
    				case "-":
    					resultUnknown = Integer.parseInt(this.parameters.get(2))+Integer.parseInt(result);
    					break;
    				case "*":
    					resultUnknown = Integer.parseInt(result)/Integer.parseInt(this.parameters.get(2));
    					break;
    				case "/":
    					resultUnknown = Integer.parseInt(result)*Integer.parseInt(this.parameters.get(2));
    					break;
    				default: 
    					throw new IllegalArgumentException("Comando desconocido: ");
    				}
    				solvedUnkowns.put(this.parameters.get(0), resultUnknown);
    			}else if(this.parameters.get(2).matches("[A-Z]+")){
    				int resultUnknown=0;
    				switch(this.parameters.get(1)) {
    				case "+":
    					resultUnknown = Integer.parseInt(result)-Integer.parseInt(this.parameters.get(0));
    					break;
    				case "-":
    					resultUnknown = Integer.parseInt(this.parameters.get(0))-Integer.parseInt(result);
    					break;
    				case "*":
    					resultUnknown = Integer.parseInt(result)/Integer.parseInt(this.parameters.get(0));
    					break;
    				case "/":
    					resultUnknown = Integer.parseInt(this.parameters.get(0))/Integer.parseInt(result);
    					break;
    				default: 
    					throw new IllegalArgumentException("Comando desconocido: ");
    				}
    				solvedUnkowns.put(this.parameters.get(2), resultUnknown);
    			}
    		}
    	
    	}
    	public static String[][] solve(String[][] board) {
    		HashMap<String, Integer> solvedUnkowns = new HashMap<String, Integer>();
    		LinkedList<Operation> operations = new LinkedList<CrossMath.Operation>();
    		for (int row = 0; row < board.length; row += 2) {
    			ArrayList<String> parameters = new ArrayList<String>();
    			for (int col = 0; col < board[row].length; col++) {
    				if ("=".equals(board[row][col])) {
    					operations.add(new Operation(parameters, board[row][col+1]));
    					parameters = new ArrayList<String>();
    				} else {
    					parameters.add(board[row][col]);
    				}
    			}
    		}
    		for (int col = 0; col < board[0].length; col += 2) {
    			ArrayList<String> parameters = new ArrayList<String>();
    			for (int row = 0; row < board.length; row++) {
    				if ("=".equals(board[row][col])) {
    					operations.add(new Operation(parameters, board[row+1][col]));
    					parameters = new ArrayList<String>();
    				} else {
    					parameters.add(board[row][col]);
    				}
    			}
    		}
    		int cont = 0;
    		while (0 < operations.size()) {
    			Operation op = operations.pollFirst();
    			switch (op.unknownAmmount(solvedUnkowns)) {
    			case 0:
    				cont = 0;
    				break;
    			case 1:
    				op.calculateUnkown(solvedUnkowns);
    				cont = 0;
    				break;
    			default:
    				operations.addLast(op);
    				cont++;
    				break;
    			}
    			if (operations.size() <= cont) {
    				String[][] res = new String[5][5];
    				for(int i = 0; i < board.length; i++) {
    					for(int k = 0; k < board[i].length; k++) {
    						if(board[i][k].matches("[A-Z]")) {
    							res[i][k] = String.valueOf(solvedUnkowns.get(board[i][k]));
    						}else {
    							res[i][k] = board[i][k];
    						}
    					}
    				}
    				
    				return res;
    			}
    		}
    		return null;
    	}
    }
    • package com.cruci.cruci;
    • import java.util.ArrayList;
    • import java.util.HashMap;
    • import java.util.LinkedList;
    • import java.util.regex.Pattern;
    • public class CrossMath {
    • static class Operation {
    • ArrayList<String> parameters;
    • String result;
    • public Operation(ArrayList<String> parameters, String result) {
    • this.parameters = parameters;
    • this.result = result;
    • }
    • @Override
    • public String toString() {
    • return "Operation [" + parameters + ", =" + result + "]";
    • }
    • public int unknownAmmount(HashMap<String, Integer> solvedUnkowns) {
    • int ammount = 0;
    • final String REGEX = "^((-)?[0-9]+)|([-+x/])$";
    • for (String str : parameters) {
    • if (!str.matches(REGEX) && !solvedUnkowns.containsKey(str)) {
    • ammount++;
    • }
    • }
    • if (!result.matches(REGEX) && !solvedUnkowns.containsKey(result)) {
    • ammount++;
    • }
    • return ammount;
    • }
    • public void calculateUnkown(HashMap<String, Integer> solvedUnkowns) {
    • for(int position=0;position<this.parameters.size();position++) {
    • String param = this.parameters.get(position);
    • if (solvedUnkowns.containsKey(param)) {
    • this.parameters.set(position, Integer.toString(solvedUnkowns.get(param)));
    • }
    • }
    • String resultVar = result;
    • if (solvedUnkowns.containsKey(resultVar)) {
    • result = Integer.toString(solvedUnkowns.get(resultVar));
    • }
    • if(result.matches("[A-Z]+")) {
    • int resultUnknown=0;
    • switch(this.parameters.get(1)) {
    • case "+":
    • resultUnknown = Integer.parseInt(this.parameters.get(0))+Integer.parseInt(this.parameters.get(2));
    • break;
    • case "-":
    • resultUnknown = Integer.parseInt(this.parameters.get(0))-Integer.parseInt(this.parameters.get(2));
    • break;
    • case "*":
    • resultUnknown = Integer.parseInt(this.parameters.get(0))*Integer.parseInt(this.parameters.get(2));
    • break;
    • case "/":
    • resultUnknown = Integer.parseInt(this.parameters.get(0))/Integer.parseInt(this.parameters.get(2));
    • break;
    • default:
    • throw new IllegalArgumentException("Comando desconocido: ");
    • }
    • solvedUnkowns.put(result, resultUnknown);
    • }else if(this.parameters.get(0).matches("[A-Z]+")){
    • int resultUnknown=0;
    • switch(this.parameters.get(1)) {
    • case "+":
    • resultUnknown = Integer.parseInt(result)-Integer.parseInt(this.parameters.get(2));
    • break;
    • case "-":
    • resultUnknown = Integer.parseInt(this.parameters.get(2))+Integer.parseInt(result);
    • break;
    • case "*":
    • resultUnknown = Integer.parseInt(result)/Integer.parseInt(this.parameters.get(2));
    • break;
    • case "/":
    • resultUnknown = Integer.parseInt(result)*Integer.parseInt(this.parameters.get(2));
    • break;
    • default:
    • throw new IllegalArgumentException("Comando desconocido: ");
    • }
    • solvedUnkowns.put(this.parameters.get(0), resultUnknown);
    • }else if(this.parameters.get(2).matches("[A-Z]+")){
    • int resultUnknown=0;
    • switch(this.parameters.get(1)) {
    • case "+":
    • resultUnknown = Integer.parseInt(result)-Integer.parseInt(this.parameters.get(0));
    • break;
    • case "-":
    • resultUnknown = Integer.parseInt(this.parameters.get(0))-Integer.parseInt(result);
    • break;
    • case "*":
    • resultUnknown = Integer.parseInt(result)/Integer.parseInt(this.parameters.get(0));
    • break;
    • case "/":
    • resultUnknown = Integer.parseInt(this.parameters.get(0))/Integer.parseInt(result);
    • break;
    • default:
    • throw new IllegalArgumentException("Comando desconocido: ");
    • }
    • solvedUnkowns.put(this.parameters.get(2), resultUnknown);
    • }
    • }
    • }
    • public static String[][] solve(String[][] board) {
    • HashMap<String, Integer> solvedUnkowns = new HashMap<String, Integer>();
    • LinkedList<Operation> operations = new LinkedList<CrossMath.Operation>();
    • for (int row = 0; row < board.length; row += 2) {
    • ArrayList<String> parameters = new ArrayList<String>();
    • for (int col = 0; col < board[row].length; col++) {
    • if ("=".equals(board[row][col])) {
    • operations.add(new Operation(parameters, board[row][col+1]));
    • parameters = new ArrayList<String>();
    • } else {
    • parameters.add(board[row][col]);
    • }
    • }
    • }
    • for (int col = 0; col < board[0].length; col += 2) {
    • ArrayList<String> parameters = new ArrayList<String>();
    • for (int row = 0; row < board.length; row++) {
    • if ("=".equals(board[row][col])) {
    • operations.add(new Operation(parameters, board[row+1][col]));
    • parameters = new ArrayList<String>();
    • } else {
    • parameters.add(board[row][col]);
    • }
    • }
    • }
    • int cont = 0;
    • while (0 < operations.size()) {
    • Operation op = operations.pollFirst();
    • switch (op.unknownAmmount(solvedUnkowns)) {
    • case 0:
    • cont = 0;
    • break;
    • case 1:
    • op.calculateUnkown(solvedUnkowns);
    • cont = 0;
    • break;
    • default:
    • operations.addLast(op);
    • cont++;
    • break;
    • }
    • if (operations.size() <= cont) {
    • String[][] res = new String[5][5];
    • for(int i = 0; i < board.length; i++) {
    • for(int k = 0; k < board[i].length; k++) {
    • if(board[i][k].matches("[A-Z]")) {
    • res[i][k] = String.valueOf(solvedUnkowns.get(board[i][k]));
    • }else {
    • res[i][k] = board[i][k];
    • }
    • }
    • }
    • return res;
    • }
    • }
    • return null;
    • }
    • }

A crossword (also called cruciverbalist) is a puzzle in which given a clue, white spaces and black spaces you need to fill the white spaces with letters. Usually, words fill a letter of another word, giving you another clue.

This type of crossword works moreless like that.
Given some mathematical expresions you need to find out the value of the incognita with the values you know.

Some expresions have more than one incognita, making you figure one of the unknown values via another expresion that can be resolved.

You will be given a bidimensional array of Strings which will have the following format:

String[][] cross = {
			{"1","+","A","=","6"},
			{"+"," ","-"," ","+"},
			{"B","-","3","=","4"},
			{"="," ","="," ","="},
			{"8","+","C","=","D"}};

Which will return:

String[][] cross = {
			{"1","+","5","=","6"},
			{"+"," ","-"," ","+"},
			{"7","-","3","=","4"},
			{"="," ","="," ","="},
			{"8","+","2","=","10"}};

To make it simple, you will follow some rules:

  • All numbers will be positive Integers.
  • The results of the operations will be positive Integers.
  • The array will always have the same number of lines and columns.
  • The incognita could be in any position of the operation.
  • The function will always receive at least a correctly filled 5x5 array, not a null, an empty or an incorrect array.
  • The size of the array could be bigger than 5x5, but always odd.
  • The jerachy will be from left to right and from up to down. Sums and substractions at left will be before mutiplications and divisions at right.
  • The corners of the array will never be all incognitas.
class Crossword{
  
}