/// <summary> /// Creates new SupremeComander and reades input file to commander's database. /// </summary> /// <param name="Reader">TextReader object, pointing to input file.</param> /// <returns>New SupremeCommander object.</returns> public static SupremeCommander Initialize(TextReader Reader, TextWriter Writer) { SupremeCommander thor = new SupremeCommander(Writer); string line = default(string); int numberOfRows = 0; while ((line = Reader.ReadLine()) != null) { string[] cells = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); Cell[] row = new Cell[cells.Length]; for (int column = 0; column < cells.Length; column++) { row[column] = default(Cell); if (Cell.TryParse(cells[column], out row[column])) { continue; } Equation Equation = default(Equation); CellType Error = default(CellType); if (Equation.TryParse(cells[column], out Equation, out Error)) { thor.Equations.Add(new Coords(numberOfRows, column), Equation); row[column] = new Cell(CellType.Equation); } else { row[column] = new Cell(Error); } } thor.Data.AddRow(row); numberOfRows++; } return(thor); }
/// <summary> /// Tries to parse data given to valid equation. /// </summary> /// <param name="EquationData">String: Data to work with.</param> /// <param name="Equation">Equation: Contains valid Equation or null.</param> /// <param name="Error">CellType: Contains Equation or errorType found during parsing.</param> /// <returns>On succes valid new Equation and corrsponding CellType. Empty Equation and corresponding error as CellType.</returns> public static bool TryParse(string EquationData, out Equation Equation, out CellType Error) { Equation = default(Equation); Error = default(CellType); const int alphabetLength = 26; char[] Operators = { '=', '+', '-', '*', '/' }; if (EquationData[0] != '=') { Error = CellType.Invalid; return(false); } string[] splitedData = EquationData.Split(Operators); if (splitedData.Length < 3) { // Missing operation Error = CellType.MissingOperation; return(false); } if (splitedData.Length > 3) { // Too many operations Error = CellType.Formula; return(false); } if (splitedData[1].Length == 0 || splitedData[2].Length == 0) { // Operator length = 0 Error = CellType.Formula; } Coords[] Operand = new Coords[2]; for (int i = 1; i < 3; i++) { int rowCoord = -1; int columnCoord = 0; for (int j = 0; j < splitedData[i].Length; j++) { if (splitedData[i][j] >= (int)'A' && splitedData[i][j] <= (int)'Z') { columnCoord *= alphabetLength; columnCoord += (int)splitedData[i][j] - 64; } else if (splitedData[i][j] >= (int)'0' && splitedData[i][j] <= (int)'9') { if (int.TryParse(splitedData[i].Substring(j), out rowCoord)) { Operand[i - 1] = new Coords(rowCoord - 1, columnCoord - 1); break; } else { Error = CellType.Formula; return(false); } } else { Error = CellType.Formula; return(false); } } if (rowCoord < 0) { Error = CellType.Formula; return(false); } } Equation.FirstOperand = Operand[0]; Equation.SecondOperand = Operand[1]; Equation.Operation = (Operation)EquationData[splitedData[1].Length + 1]; return(true); }
/// <summary> /// Solves given equation and saves correct value and type to cell, holding named equation. /// </summary> /// <param name="Equation">KeyValuePair[Coords, Equation] containing coordinates to cell and equation itself.</param> private void SolveEquation(KeyValuePair <Coords, Equation> Equation) { Stack <KeyValuePair <Coords, Equation> > solveStack = new Stack <KeyValuePair <Coords, Equation> >(); HashSet <Coords> locks = new HashSet <Coords>(); solveStack.Push(Equation); while (solveStack.Count > 0) { KeyValuePair <Coords, Equation> peek = solveStack.Peek(); Coords currentKey = peek.Key; Equation currentEquation = peek.Value; Cell firstOperand = default(Cell); Cell secondOperand = default(Cell); Coords firstOperandCoords = currentEquation.FirstOperand; Coords secondOperandCoords = currentEquation.SecondOperand; if (this.Data.AreCoordsValid(firstOperandCoords)) { firstOperand = this.Data[currentEquation.FirstOperand]; } if (this.Data.AreCoordsValid(secondOperandCoords)) { secondOperand = this.Data[currentEquation.SecondOperand]; } if (locks.Contains(currentKey)) { RemoveCycle(solveStack, locks, currentKey); RemoveError(solveStack, locks); continue; } locks.Add(currentKey); if (firstOperand.IsError || secondOperand.IsError) { this.Data[currentKey] = new Cell(CellType.Error); locks.Remove(currentKey); return; } if (firstOperand.IsEquation) { Coords operandCoords = currentEquation.FirstOperand; Equation operandEquation = this.Equations[operandCoords]; solveStack.Push(new KeyValuePair <Coords, Equation>(operandCoords, operandEquation)); continue; } if (secondOperand.IsEquation) { Coords operandCoords = currentEquation.SecondOperand; Equation operandEquation = this.Equations[operandCoords]; solveStack.Push(new KeyValuePair <Coords, Equation>(operandCoords, operandEquation)); continue; } this.Data[currentKey] = TryCompute(firstOperand.Value, secondOperand.Value, currentEquation.Operation); solveStack.Pop(); locks.Remove(currentKey); if (locks.Count > 0) { locks.Remove(solveStack.Peek().Key); } } }