figbertmath

[RADIOACTIVE] miscellaneous math programs in website form
git clone git://git.figbert.com/figbertmath.git
Log | Files | Refs | README

simultaneousEquation.js (6847B)


      1 import React from 'react';
      2 import PropTypes from 'prop-types';
      3 import update from 'immutability-helper';
      4 import { CalcOut } from "../lowLevel/calcOut";
      5 import { Pad } from "../lowLevel/pad";
      6 
      7 export class SimultaneousEquation extends React.Component {
      8     constructor(props) {
      9         super(props);
     10         this.state = {
     11             output: [],
     12             dimension: 2,
     13             coefficients: [['', ''], ['', '']],
     14             sums: ['', '']
     15         };
     16         this.checkSolve = this.checkSolve.bind(this);
     17         this.modifyMatrix = this.modifyMatrix.bind(this);
     18         this.onChange = this.onChange.bind(this);
     19         this.solveMatrix = this.solveMatrix.bind(this);
     20     }
     21 
     22     checkSolve() {
     23         const coefficients = JSON.parse(JSON.stringify(this.state.coefficients)),
     24             sums = JSON.parse(JSON.stringify(this.state.sums));
     25         let truth = true;
     26         for (let i = 0; i < coefficients.length; i++) {
     27             for (let k = 0; k < coefficients[i].length; k ++) {
     28                 if (coefficients[i][k] === '') {
     29                     truth = false;
     30                 } else {
     31                     coefficients[i][k] = Number(coefficients[i][k]);
     32                 }
     33             }
     34         }
     35         if (truth) {
     36             for (let i = 0; i < sums.length; i++) {
     37                 if (sums[i] === '') {
     38                     truth = false;
     39                 } else {
     40                     sums[i] = Number(sums[i]);
     41                 }
     42             }
     43         }
     44         if (truth) {
     45             this.solveMatrix(coefficients, sums)
     46         }
     47     }
     48 
     49     modifyMatrix(object) {
     50         const value = object.target.value;
     51         let numOfVars = [],
     52             rows = [],
     53             sums = [],
     54             newDimension;
     55         if (value === 'raise') {
     56             newDimension = this.state.dimension + 1;
     57             if (newDimension > 5) {
     58                 newDimension = 5;
     59             }
     60         } else if (value === 'lower') {
     61             newDimension = this.state.dimension - 1;
     62             if (newDimension < 2) {
     63                 newDimension = 2;
     64             }
     65         }
     66         for (let i = 0; i < newDimension; i++) {
     67             numOfVars.push('');
     68             sums.push('');
     69         }
     70         for (let i = 0; i < newDimension; i++) {
     71             rows.push(numOfVars);
     72         }
     73         this.setState({
     74             output: [],
     75             dimension: newDimension,
     76             coefficients: rows,
     77             sums: sums
     78         });
     79     }
     80 
     81     onChange(object) {
     82         let name = object.target.name,
     83             i, k;
     84         const value = object.target.value;
     85         if (name.indexOf('c') > -1) {
     86             name = name.substr(1);
     87             i = Number(name.split('_')[0]);
     88             k = Number(name.split('_')[1]);
     89             this.setState({
     90                 coefficients: update(this.state.coefficients, {[i]: {[k]: {$set: value}}})
     91             }, () => {
     92                 this.checkSolve()
     93             });
     94         } else if (name.indexOf('s') > -1) {
     95             i = Number(name.substr(1));
     96             this.setState({
     97                 sums: update(this.state.sums, {[i]: {$set: value}})
     98             }, () => {
     99                 this.checkSolve()
    100             });
    101         } else {
    102             this.setState({
    103                 output: 'ERROR'
    104             });
    105         }
    106     }
    107 
    108     solveMatrix(equations, sums) {
    109         let abs = Math.abs;
    110         function array_fill(i, n, v) {
    111             let a = [];
    112             while (i < n) {
    113                 a.push(v);
    114                 i++;
    115             }
    116             return a;
    117         }
    118 
    119         // Adds the sums to the equations array
    120         for (let i = 0; i < equations.length; i++) {
    121             equations[i].push(sums[i]);
    122         }
    123         const numberOfEquations = equations.length;
    124 
    125         for (let i = 0; i < numberOfEquations; i++) {
    126             // Iterates over the first column of every row below the current one (i) and determines which row is the largest
    127             let maxEl = abs(equations[i][i]),
    128                 maxRow = i;
    129             for (let k = i + 1; k < numberOfEquations; k++) {
    130                 if (abs(equations[k][i]) > maxEl) {
    131                     maxEl = abs(equations[k][i]);
    132                     maxRow = k;
    133                 }
    134             }
    135             // Swaps the larger row and the current row, if a swap should be made
    136             if (maxRow !== i) {
    137                 for (let k = i; k < numberOfEquations + 1; k++) {
    138                     const tmp = equations[maxRow][k];
    139                     equations[maxRow][k] = equations[i][k];
    140                     equations[i][k] = tmp;
    141                 }
    142             }
    143             // Makes all lower numbers in the column zero
    144             for (let k = i + 1; k < numberOfEquations; k++) {
    145                 const c = -equations[k][i] / equations[i][i];
    146                 for (let j = i; j < numberOfEquations + 1; j++) {
    147                     if (i === j) {
    148                         equations[k][j] = 0;
    149                     } else {
    150                         equations[k][j] += c * equations[i][j];
    151                     }
    152                 }
    153             }
    154         }
    155 
    156         //Solve the simplified matrix
    157         sums = array_fill(0, numberOfEquations, 0);
    158         for (let i = numberOfEquations - 1; i > -1; i--) {
    159             sums[i] = equations[i][numberOfEquations] / equations[i][i];
    160             for (let k = i - 1; k > -1; k--) {
    161                 equations[k][numberOfEquations] -= equations[k][i] * sums[i];
    162             }
    163         }
    164 
    165         //Round each number to four decimal places
    166         const alphabet = (function(charA, charZ) {
    167             let a = [], i = charA.charCodeAt(0), j = charZ.charCodeAt(0);
    168             for (; i <= j; ++i) {
    169                 a.push(String.fromCharCode(i));
    170             }
    171             return a;
    172         }('a', 'z'));
    173         for (let i = 0; i < sums.length; i++) {
    174           if (sums[i] % 1 !== 0) {
    175             sums[i] = Math.round((sums[i] + 0.00001) * 100) / 100;
    176           }
    177           sums[i] = alphabet[i] + ' = ' + sums[i];
    178         }
    179 
    180         //Set the output to the array of values
    181         this.setState({
    182             output: sums
    183         });
    184     }
    185 
    186     render() {
    187         return (
    188             <div>
    189                 <CalcOut mode={this.props.mode} output={this.state.output} />
    190                 <Pad
    191                     buttonValues={['range', [this.state.coefficients, this.state.sums], 'select']}
    192                     displayValues={[this.state.dimension, undefined, '…']}
    193                     mode={this.props.mode}
    194                     onChange={this.onChange}
    195                     onClick={this.modifyMatrix}
    196                     onModeClick={this.props.onModeChange}
    197                     type={'large'}
    198                 />
    199             </div>
    200         );
    201     }
    202 }
    203 SimultaneousEquation.propTypes = {
    204     mode: PropTypes.string.isRequired,
    205     onModeChange: PropTypes.func.isRequired
    206 };