MatrixInverter

by Nathaniel Oshunniyi: Y12 Age ~17

Introduction

Nathaniel has had another great idea for an educational program and he makes it helpful to others with carefully designed output while improving his own command of advanced language features. This screenshot shows the menu and a matrix used for testing.

Program in action on a PC

Program in action on a PC

We recommend Option s to see the working as in these screenshots. This screenshot shows the program running on a Raspberry Pi.

MatrixInverter running on the Pi

MatrixInverter running on the Pi

The final screenshot shows a later output on a PC following the same input sequence:

MatrixInverter showing calculation of a minor

MatrixInverter showing calculation of a minor

Our test using the inverter with the worked example in the Engineering Maths First Aid Kit outputted this instructive text file:
Original Matrix:
|       1.0000       3.0000      -1.0000 |
|      -2.0000       1.0000       2.0000 |
|       0.0000       5.0000       3.0000 |


>>>>> Step one: Calculating the determinant <<<<<

  >>  Determinant = 21.0

>>>>> Step two: calculating the co-factor elements of the new matrix <<<<<
|      -7.0000      -6.0000     -10.0000 |
|      14.0000       3.0000       5.0000 |
|       7.0000       0.0000       7.0000 |

>>>>> Step three: Multiplying by the sign matrix to create the co-factors <<<<<
|      -7.0000       6.0000     -10.0000 |
|     -14.0000       3.0000      -5.0000 |
|       7.0000      -0.0000       7.0000 |

>>>>> Step four: Transposing the elements <<<<<
|      -7.0000       6.0000     -10.0000 |
|     -14.0000       3.0000      -5.0000 |
|       7.0000      -0.0000       7.0000 |

>>>>> Final Step: Dividing by the determinant <<<<<
|      -0.3333       0.2857      -0.4762 |
|      -0.6667       0.1429      -0.2381 |
|       0.3333      -0.0000       0.3333 |

The terminology can be confusing. Nathaniel refers to the cofactors before multiplication by the sign matrix as cofactor elements rather than the term minor used by Vitutor. For Option c to show the cofactors we added a line of code to call the procedure to apply the sign changes so that the program now gives the same result as WolframAlpha.

Technical Features

The program benefits from many technical features:

  • own procedures and functions with parameters;
  • use of inbuilt routines such as Val, Rewrite, Assign, CloseFile, Sleep and TextColor;
  • appropriate comments;
  • validation;
  • nested loops;
  • good use of case statement;
  • effective animation, with scrolling text used for most but not all of the output;
  • enumerated type;
  • file handling;
  • records;
  • pointers;
  • carefully formatted output.

Download

You can download the Pascal Source (instead of copying it from the page) and/or the executable MatrixInverter.exe for a PC.

Code

program MatrixInverter;

{
    Copyright (c) 2015 Nathaniel Oshunniyi

    Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); you may not
    use this file except in compliance with the License, as described at
    http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/
}

  {$mode objfpc}{$H+}

  {At the end of step by step inverse say if you would
   like to save this worked solution to a text file}

uses
  sysutils, strutils, crt;

type
  TElement = (a, b, c, d, e, f, g, h, i); // enumerated type for user matrix input
  REALpointer = ^real;
  TMatrix = record
    REALelements: array[1..9] of real;  // elements of matrix
    STRelements: array[1..9] of string; // string components of matrix elements (val)
  end;

  {I understand there is absolutely no need for a record here but
   I just want to get used to using them so I put one in.}

const
  MAX: integer = 9; // maximum size of matrix (a little bit of future proofing)

var
  matrix: TMatrix;
  fillMatrix: TElement;
  countr1, countr2, ValCheck: integer; // for loop integers
  answer, iteration : string;
  answerval: boolean;
  calcedDET: real;
  calc: array[1..9] of real;
  Pa, Pb, Pc, Pd, Pe, Pf, Pg, Ph, Pi: REALpointer;
  Ca, Cb, Cc, Cd, Ce, Cf, Cg, Ch, Ci: REALpointer;

procedure scroll(text: string; line: boolean); // scrolling text
var
  count: integer;
begin
  for count := 1 to length(text) do
    begin
      write(text[count]);
      sleep(10);  // change the speed of the scrolling text
    end;
  if line then
    writeln;      // true = writeline, false = write
end;

procedure error(text: string); // user input errors
begin
  textcolor(red);
  writeln(text);
  textcolor(white);
end;

procedure magic; // makes the elements simultaneously change
begin
  clrscr;
  textcolor(cyan);
  writeln;
  writeln('| ', Pa^ : 12 : 4, ' ' , Pb^ : 12 : 4, ' ' , Pc^ : 12 : 4, ' |');
  writeln('| ', Pd^ : 12 : 4, ' ' , Pe^ : 12 : 4, ' ' , Pf^ : 12 : 4, ' |');
  writeln('| ', Pg^ : 12 : 4, ' ' , Ph^ : 12 : 4, ' ' , Pi^ : 12 : 4, ' |');
  textcolor(white);
end;

procedure resetMatrix; // initialises the calculation variables
var
  i : integer;
begin
  for i := 1 to MAX do
    calc[i] := matrix.REALelements[i];
end;

procedure inputMatrix; // user input matrix prompt
begin
  scroll('Please enter your matrix:', true);
  writeln;
  textcolor(cyan);
  scroll('|a b c|', true);
  scroll('|d e f|', true);
  scroll('|g h i|', true);
  textcolor(white);

  //initialisation of variables
  with matrix do
    for countr2 := 1 to MAX do
      REALelements[countr2] := 0;

  Pa := @matrix.REALelements[1];
  Pb := @matrix.REALelements[2];
  Pc := @matrix.REALelements[3];
  Pd := @matrix.REALelements[4];
  Pe := @matrix.REALelements[5];
  Pf := @matrix.REALelements[6];
  Pg := @matrix.REALelements[7];
  Ph := @matrix.REALelements[8];
  Pi := @matrix.REALelements[9];

  Ca := @calc[1];
  Cb := @calc[2];
  Cc := @calc[3];
  Cd := @calc[4];
  Ce := @calc[5];
  Cf := @calc[6];
  Cg := @calc[7];
  Ch := @calc[8];
  Ci := @calc[9];

  //user input
  for fillMatrix := a to i do
    begin
      writeln;
      //user prompt
      repeat
        scroll('Element ', false);
        write(fillMatrix);
        scroll(': ', false);
        countr1 := ord(fillMatrix) + 1;
        readln(matrix.STRelements[countr1]);

        //validation
        val(matrix.STRelements[countr1], matrix.REALelements[countr1], ValCheck);
        if ValCheck <> 0 then
          error('ERROR: Please enter a number');
      until valCheck = 0;
      magic;
    end; // end for

  resetMatrix;
end; // end procedure

procedure display; //displays matrix
begin
  writeln;
  scroll('Your matrix is:', true);
  writeln;
  textcolor(cyan);
  writeln('| ', Ca^ : 12 : 4, ' ' , Cb^ : 12 : 4, ' ' , Cc^ : 12 : 4, ' |');
  writeln('| ', Cd^ : 12 : 4, ' ' , Ce^ : 12 : 4, ' ' , Cf^ : 12 : 4, ' |');
  writeln('| ', Cg^ : 12 : 4, ' ' , Ch^ : 12 : 4, ' ' , Ci^ : 12 : 4, ' |');
  textcolor(white);
end;

function determinant: real;  // calculates the 3 x 3 determinant
var
  firstcomponent, secondcomponent: real;
begin
  firstcomponent := (Pa^ * Pe^ * Pi^) + (Pb^ * Pf^ * Pg^) + (Pc^ * Pd^ * Ph^);
  secondcomponent := (Pg^ * Pe^ * Pc^) + (Ph^ * Pf^ * Pa^) + (Pi^ * Pd^ * Pb^);
  result := firstcomponent - secondcomponent;
end;

function  smallDet(a, b, c, d : real): real; // calculates the 2 x 2 determinants needed for the cofactors
begin
  { a b
    c d }
  result := a * d - b * c;
end;

procedure CoFactors; // calculates the cofactor elements (before sign matrix)
begin
  with matrix do
    begin
      calc[1] := smallDet(Pe^, Pf^, Ph^, Pi^);
      calc[2] := smallDet(Pd^, Pf^, Pg^, Pi^);
      calc[3] := smallDet(Pd^, Pe^, Pg^, Ph^);
      calc[4] := smallDet(Pb^, Pc^, Ph^, Pi^);
      calc[5] := smallDet(Pa^, Pc^, Pg^, Pi^);
      calc[6] := smallDet(Pa^, Pb^, Pg^, Ph^);
      calc[7] := smallDet(Pb^, Pc^, Pe^, Pf^);
      calc[8] := smallDet(Pa^, Pc^, Pd^, Pf^);
      calc[9] := smallDet(Pa^, Pb^, Pd^, Pe^);
    end;
  end;

procedure signMatrix; // multiplies sign matrix by cofactor elements (creating the cofactors)
begin
  with matrix do
    begin
      calc[2] := calc[2] * -1;
      calc[4] := calc[4] * -1;
      calc[6] := calc[6] * -1;
      calc[8] := calc[8] * -1;
    end;
end;

procedure transpositionalDisplay; // transposes the cofactors
begin
  Cb := @calc[4];
  Cd := @calc[2];
  Cc := @calc[7];
  Cg := @calc[3];
  Cf := @calc[8];
  Ch := @calc[6];
end;

procedure save; //saves the SLOWinverse procedure to a file
var
  count: integer;
  det: real;
  savefile: text;
begin
  assign(savefile, 'MatrixCalculation.txt');
  rewrite(savefile);

  resetMatrix;
  det := determinant;

  writeln(savefile, 'Original Matrix:');
  writeln(savefile, '| ', Ca^ : 12 : 4, ' ' , Cb^ : 12 : 4, ' ' , Cc^ : 12 : 4, ' |');
  writeln(savefile, '| ', Cd^ : 12 : 4, ' ' , Ce^ : 12 : 4, ' ' , Cf^ : 12 : 4, ' |');
  writeln(savefile, '| ', Cg^ : 12 : 4, ' ' , Ch^ : 12 : 4, ' ' , Ci^ : 12 : 4, ' |');
  writeln(savefile);
  writeln(savefile);

  //step one (determinant)
  writeln(savefile, '>>>>> Step one: Calculating the determinant <<<<<');
  writeln(savefile);

  if det = 0 then
    writeln(savefile, 'The determinant is 0 so there is no inverse')
  else
    begin
      writeln(savefile, '  >>  Determinant = ', det : 0 : 1);
      //step two (cofactors)
      writeln(savefile);
      writeln(savefile, '>>>>> Step two: calculating the co-factor elements of the new matrix <<<<<');
      CoFactors;
      writeln(savefile, '| ', Ca^ : 12 : 4, ' ' , Cb^ : 12 : 4, ' ' , Cc^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cd^ : 12 : 4, ' ' , Ce^ : 12 : 4, ' ' , Cf^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cg^ : 12 : 4, ' ' , Ch^ : 12 : 4, ' ' , Ci^ : 12 : 4, ' |');
      // step three
      writeln(savefile);
      writeln(savefile, '>>>>> Step three: Multiplying by the sign matrix to create the co-factors <<<<<');
      signMatrix;
      writeln(savefile, '| ', Ca^ : 12 : 4, ' ' , Cb^ : 12 : 4, ' ' , Cc^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cd^ : 12 : 4, ' ' , Ce^ : 12 : 4, ' ' , Cf^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cg^ : 12 : 4, ' ' , Ch^ : 12 : 4, ' ' , Ci^ : 12 : 4, ' |');
      // step four
      writeln(savefile);
      writeln(savefile, '>>>>> Step four: Transposing the elements <<<<<');
      transpositionalDisplay;
      writeln(savefile, '| ', Ca^ : 12 : 4, ' ' , Cb^ : 12 : 4, ' ' , Cc^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cd^ : 12 : 4, ' ' , Ce^ : 12 : 4, ' ' , Cf^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cg^ : 12 : 4, ' ' , Ch^ : 12 : 4, ' ' , Ci^ : 12 : 4, ' |');
      //final step
      writeln(savefile);
      writeln(savefile, '>>>>> Final Step: Dividing by the determinant <<<<<');
      for count := 1 to MAX do
        calc[count] := calc[count] / det;
      writeln(savefile, '| ', Ca^ : 12 : 4, ' ' , Cb^ : 12 : 4, ' ' , Cc^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cd^ : 12 : 4, ' ' , Ce^ : 12 : 4, ' ' , Cf^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cg^ : 12 : 4, ' ' , Ch^ : 12 : 4, ' ' , Ci^ : 12 : 4, ' |');
      writeln(savefile);
      // end final
    end;
  textcolor(lightgreen);
  scroll('    Saved to file!', true);
  textcolor(white);
  closeFile(savefile);
end;

procedure inverse; //calculates the inverse
var
  count: integer;
  det: real;
begin
  det := determinant;
  if det = 0 then
    scroll('There is no inverse because the determinant is 0.', true)
  else
    begin
      CoFactors;
      for count := 1 to MAX do
        calc[count] := calc[count] / det;
      signMatrix;
      transpositionalDisplay;
      display;
    end;
    { The order in which you do the calculation does not matter
      as long as you start by calculating the new matrix elements }
  end;

procedure SLOWinverse; //calculates the inverse
var
  count: integer;
  det: real;
  answer: string;
  explanationDET: real;
begin
  det :=  determinant;
  //step one (determinant)
  scroll('Step one: Calculating the determinant', true);
  scroll('Would you like to see how this is done? (PRESS ''y'' for yes)', true);
  write('  >>  ');
  readln(answer);
  writeln;
  textcolor(green);
  if (answer = 'y') or (answer = 'Y') then
    begin
      scroll('Write out the matrix like this: ', true);
      textcolor(white);
      writeln('| a b c | a b ');
      writeln('| d e f | d e ');
      writeln('| g h i | g h ');
      textcolor(green);
      scroll('This makes it easier to visualise', true);
      writeln;
      scroll('The determinant is (aei + bfg + cdh) - (ceg + afh + bdi)', true);
      scroll('(look at the diagonals)', true);
      writeln;
    end;

  if det = 0 then
    begin
      textcolor(cyan);
      scroll('The determinant is 0 so there is no inverse', true);
    end
  else
    begin
      textcolor(cyan);
      writeln('     Determinant = ', det : 0 : 1);
      textcolor(white);
      //step two (cofactors)
      writeln;
      scroll('Step two: calculating the co-factors of the new matrix', true);
      scroll('Would you like to see how this is done? (PRESS ''y'' for yes)', true);
      write('  >>  ');
      readln(answer);
      writeln;
      textcolor(green);
      if (answer = 'y') or (answer = 'Y') then
        begin
          scroll('Select an element, let us say a', true);
          writeln;
          textcolor(white);
          write('| ');
          textcolor(red);
          write('a ');
          textcolor(white);
          writeln('b c |');
          writeln('| d e f |');
          writeln('| g h i |');
          writeln;
          readln;

          textcolor(green);
          scroll('Replace that element by:', true);
          scroll(' - Deleting the elements in its row and column', true);
          scroll(' - calculate the determinant of the 2x2 left', true);
          scroll(' - replace the element (in this case a) with the answer', true);
          writeln;
          readln;

          textcolor(red);
          writeln('| a b c |');
          write('| d ');
          textcolor(white);
          writeln('e f |');
          textcolor(red);
          write('| g ');
          textcolor(white);
          writeln('h i |');
          writeln;

          scroll('The determinant of a 2x2 | a b |', true);
          writeln('                         | c d | is: ad - bc');
          writeln;
          scroll('So the determinant of | e f |', true);
          write('                      | h i | is: ');
          explanationDET := smallDet(Pe^, Pf^, Ph^, Pi^);
          writeln(explanationDET : 0 : 1);
          writeln;
          textcolor(green);
          writeln;
          writeln('Element a is replaced with ', explanationDET : 0 : 1);

          textcolor(white);
          scroll('You do the same for each element', true);
          writeln;
          readln;
        end;

      CoFactors;
      display;
      // step three
      readln;
      scroll('Step three: Multiplying by the sign matrix to create the co-factors', true);
      scroll('sign matrix: | +1 -1 +1 |', true);
      writeln('             | -1 +1 -1 |');
      writeln('             | +1 -1 +1 |');
      signMatrix;
      display;
      // step four
      readln;
      scroll('Step four: Transposing the elements', true);
      scroll('(this is flipping along the leading diagonal)', true);
      transpositionalDisplay;
      display;
      // final step
      readln;
      scroll('Final Step: Dividing by the determinant', true);
      for count := 1 to MAX do
        calc[count] := calc[count] / det;
      display;
      writeln;
    end;

  scroll('Would you like to save this solution to a file? (PRESS ''y'' for yes)', true);
  scroll('  >>  ', false);
  readln(answer);

  if (answer = 'y') or (answer = 'Y') then
    save;
end;

procedure EndProgram;
begin
  writeln;
  writeln('Thanks for using the program!');
  writeln('       - Nathaniel, the Don');
  sleep(1222);
  exit;
end;

begin
  // first intro
  scroll('Welcome to the Matrix calculator', true);
  inputMatrix;

  //matrix calculations
  writeln;
  repeat
    scroll('What would you like to calculate:', true);
    writeln;
    scroll('Inverse (PRESS ''i'')', true);
    scroll('Inverse step-by-step (PRESS ''s'')', true);
    scroll('Save inverse calculation to file (PRESS ''q'')', true);
    writeln;
    scroll('Determinant (PRESS ''d'')', true);
    scroll('Co-factors (PRESS ''c'')', true);
    writeln;
    scroll('Show original matrix (PRESS ''o'')', true);
    scroll('Input new matrix (PRESS ''n'')', true);
    scroll('Exit (PRESS ''e'')', true);
    writeln;
    write('  >> ');
    readln(answer);
    answerval := true;

    //matrix operations
    case answer of
      'i', 'I': inverse;
      'd', 'D': begin
                  textcolor(cyan);
                  writeln;
                  calcedDET :=  determinant;
                  writeln('Determinant = ', calcedDET:0:2);
                  textcolor(white);
                end;
      'e', 'E': break;
      's', 'S': begin
                  textcolor(green);
                  scroll('(Press ENTER to continue between each step)', true);
                  readln;
                  textcolor(white);
                  SLOWinverse;
                end;
      'n', 'N': begin
                  inputMatrix;
                  answerval := false;
                  writeln;
                end;
      'c', 'C': begin
                  cofactors;
                  signMatrix; // added by PPS
                  display;
                end;
      'o', 'O': begin
                  scroll('Your matrix is:', true);
                  writeln;
                  textcolor(cyan);
                  writeln('| ', Pa^:12:4, ' ' , Pb^:12:4, ' ' , Pc^:12:4, ' |');
                  writeln('| ', Pd^:12:4, ' ' , Pe^:12:4, ' ' , Pf^:12:4, ' |');
                  writeln('| ', Pg^:12:4, ' ' , Ph^:12:4, ' ' , Pi^:12:4, ' |');
                  textcolor(white);
                end;
      'q', 'Q': save;
    else
      answerval := false;
      error('ERROR: Command not recognised');
    end;

    if answerval = false then
      continue
    else
      begin
        writeln;
        scroll('Would you like to do something else? (PRESS ''y'' for yes)', true);
        readln(iteration);
        writeln;
        writeln;
        if (iteration = 'y') or (iteration = 'Y') then
          answerval := false;
      end; //end else

  until answerval = true;
  EndProgram;
end.program MatrixInverter;

{
    Copyright (c) 2015 Nathaniel Oshunniyi

    Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); you may not
    use this file except in compliance with the License, as described at
    http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/
}

{$apptype console}


{At the end of step by step inverse say if you would
like to save this worked solution to a text file}

uses
  sysutils, strutils, crt;

type
  TElement = (a, b, c, d, e, f, g, h, i); // enumerated type for user matrix input
  REALpointer = ^real;
  TMatrix = record
    REALelements: array[1..9] of real;  // elements of matrix
    STRelements: array[1..9] of string; // string components of matrix elements (val)
  end;

  {I understand there is absolutely no need for a record here but
  i just want to get used to using them so I put one in.}

const
  MAX: integer = 9; // maximum size of matrix (a little bit of future proofing)

var
  matrix: TMatrix;
  fillMatrix: TElement;
  countr1, countr2, ValCheck: integer; // for loop integers
  answer, iteration : string;
  answerval: boolean;
  calcedDET: real;
  calc: array[1..9] of real;
  Pa, Pb, Pc, Pd, Pe, Pf, Pg, Ph, Pi: REALpointer;
  Ca, Cb, Cc, Cd, Ce, Cf, Cg, Ch, Ci: REALpointer;

procedure scroll(text: string; line: boolean); // scrolling text
var count: integer;
  begin
    for count := 1 to length(text) do
      begin
        write(text[count]);
        sleep(10);  // change the speed of the scrolling text
      end;
    if line then
      writeln;    // true = writeline, false = write
  end;

procedure error(text: string); // user input errors
begin
  textcolor(red);
  writeln(text);
  textcolor(white);
end;

procedure magic; // makes the elements simultaneously change
begin
  clrscr;
  textcolor(cyan);
  writeln;
  writeln('| ', Pa^ : 12 : 4, ' ' , Pb^ : 12 : 4, ' ' , Pc^ : 12 : 4, ' |');
  writeln('| ', Pd^ : 12 : 4, ' ' , Pe^ : 12 : 4, ' ' , Pf^ : 12 : 4, ' |');
  writeln('| ', Pg^ : 12 : 4, ' ' , Ph^ : 12 : 4, ' ' , Pi^ : 12 : 4, ' |');
  textcolor(white);
end;

procedure resetMatrix; // initilises the calculation variables
var
  i : integer;
begin
  for i := 1 to MAX do
    calc[i] := matrix.REALelements[i];
end;

procedure inputMatrix; // user input matrix prompt
begin
  scroll('Please enter your matrix:', true);
  writeln;
  textcolor(cyan);
  scroll('|a b c|', true);
  scroll('|d e f|', true);
  scroll('|g h i|', true);
  textcolor(white);

  //initialisation of variables
  with matrix do
    for countr2 := 1 to MAX do
      REALelements[countr2] := 0;

  Pa := @matrix.REALelements[1];
  Pb := @matrix.REALelements[2];
  Pc := @matrix.REALelements[3];
  Pd := @matrix.REALelements[4];
  Pe := @matrix.REALelements[5];
  Pf := @matrix.REALelements[6];
  Pg := @matrix.REALelements[7];
  Ph := @matrix.REALelements[8];
  Pi := @matrix.REALelements[9];

  Ca := @calc[1];
  Cb := @calc[2];
  Cc := @calc[3];
  Cd := @calc[4];
  Ce := @calc[5];
  Cf := @calc[6];
  Cg := @calc[7];
  Ch := @calc[8];
  Ci := @calc[9];

  //user input
  for fillMatrix := a to i do
    begin
      writeln;
      //user prompt
      repeat
        scroll('Element ', false);
        write(fillMatrix);
        scroll(': ', false);
        countr1 := ord(fillMatrix) + 1;
        readln(matrix.STRelements[countr1]);

        //validation
        val(matrix.STRelements[countr1], matrix.REALelements[countr1], ValCheck);
        if ValCheck <> 0 then
          error('ERROR: Please enter a number');
      until valCheck = 0;
      magic;
    end; // end for

  resetMatrix;
end; // end procedure

procedure display; //displays matrix
begin
  writeln;
  scroll('Your matrix is:', true);
  writeln;
  textcolor(cyan);
  writeln('| ', Ca^ : 12 : 4, ' ' , Cb^ : 12 : 4, ' ' , Cc^ : 12 : 4, ' |');
  writeln('| ', Cd^ : 12 : 4, ' ' , Ce^ : 12 : 4, ' ' , Cf^ : 12 : 4, ' |');
  writeln('| ', Cg^ : 12 : 4, ' ' , Ch^ : 12 : 4, ' ' , Ci^ : 12 : 4, ' |');
  textcolor(white);
end;

function determinant: real;  // calculates the 3 x 3 determinant
var
  firstcomponent, secondcomponent: real;
begin
  firstcomponent := (Pa^ * Pe^ * Pi^) + (Pb^ * Pf^ * Pg^) + (Pc^ * Pd^ * Ph^);
  secondcomponent := (Pg^ * Pe^ * Pc^) + (Ph^ * Pf^ * Pa^) + (Pi^ * Pd^ * Pb^);
  result := firstcomponent - secondcomponent;
end;

function  smallDet(a, b, c, d : real): real; // calculates the 2 x 2 determinants needed for the cofactors
begin
  { a b
    c d }
  result := a * d - b * c;
end;

procedure CoFactors; // calculates the cofactor elements (before sign matrix)
begin
  with matrix do
    begin
      calc[1] := smallDet(Pe^, Pf^, Ph^, Pi^);
      calc[2] := smallDet(Pd^, Pf^, Pg^, Pi^);
      calc[3] := smallDet(Pd^, Pe^, Pg^, Ph^);
      calc[4] := smallDet(Pb^, Pc^, Ph^, Pi^);
      calc[5] := smallDet(Pa^, Pc^, Pg^, Pi^);
      calc[6] := smallDet(Pa^, Pb^, Pg^, Ph^);
      calc[7] := smallDet(Pb^, Pc^, Pe^, Pf^);
      calc[8] := smallDet(Pa^, Pc^, Pd^, Pf^);
      calc[9] := smallDet(Pa^, Pb^, Pd^, Pe^);
    end;
  end;

procedure signMatrix; // multiplies by sign matrix to the cofactor elements (creating the cofactors)
begin
  with matrix do
    begin
      calc[2] := calc[2] * -1;
      calc[4] := calc[4] * -1;
      calc[6] := calc[6] * -1;
      calc[8] := calc[8] * -1;
    end;
end;

procedure transpositionalDisplay; // transposes the cofactors
begin
  Cb := @calc[4];
  Cd := @calc[2];
  Cc := @calc[7];
  Cg := @calc[3];
  Cf := @calc[8];
  Ch := @calc[6];
end;

procedure save; //saves the SLOWinverse procedure to a file
var
  count: integer;
  det: real;
  savefile: text;
begin
  assign(savefile, 'MatrixCalculation.txt');
  rewrite(savefile);

  resetMatrix;
  det := determinant;

  writeln(savefile, 'Original Matrix:');
  writeln(savefile, '| ', Ca^ : 12 : 4, ' ' , Cb^ : 12 : 4, ' ' , Cc^ : 12 : 4, ' |');
  writeln(savefile, '| ', Cd^ : 12 : 4, ' ' , Ce^ : 12 : 4, ' ' , Cf^ : 12 : 4, ' |');
  writeln(savefile, '| ', Cg^ : 12 : 4, ' ' , Ch^ : 12 : 4, ' ' , Ci^ : 12 : 4, ' |');
  writeln(savefile);
  writeln(savefile);

  //step one (determinant)
  writeln(savefile, '>>>>> Step one: Calculating the determinant <<<<<');
  writeln(savefile);

  if det = 0 then
    writeln(savefile, 'The determinant is 0 so there is no inverse')
  else
    begin
      writeln(savefile, '  >>  Determinant = ', det : 0 : 1);
      //step two (cofactors)
      writeln(savefile);
      writeln(savefile, '>>>>> Step two: calculating the co-factors of the new matrix <<<<<');
      CoFactors;
      writeln(savefile, '| ', Ca^ : 12 : 4, ' ' , Cb^ : 12 : 4, ' ' , Cc^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cd^ : 12 : 4, ' ' , Ce^ : 12 : 4, ' ' , Cf^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cg^ : 12 : 4, ' ' , Ch^ : 12 : 4, ' ' , Ci^ : 12 : 4, ' |');
      // step three
      writeln(savefile);
      writeln(savefile, '>>>>> Step three: Multiplying by the sign matrix to create the co-factors <<<<<');
      signMatrix;
      writeln(savefile, '| ', Ca^ : 12 : 4, ' ' , Cb^ : 12 : 4, ' ' , Cc^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cd^ : 12 : 4, ' ' , Ce^ : 12 : 4, ' ' , Cf^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cg^ : 12 : 4, ' ' , Ch^ : 12 : 4, ' ' , Ci^ : 12 : 4, ' |');
      // step four
      writeln(savefile);
      writeln(savefile, '>>>>> Step four: Transposing the elements <<<<<');
      transpositionalDisplay;
      writeln(savefile, '| ', Ca^ : 12 : 4, ' ' , Cb^ : 12 : 4, ' ' , Cc^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cd^ : 12 : 4, ' ' , Ce^ : 12 : 4, ' ' , Cf^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cg^ : 12 : 4, ' ' , Ch^ : 12 : 4, ' ' , Ci^ : 12 : 4, ' |');
      //final step
      writeln(savefile);
      writeln(savefile, '>>>>> Final Step: Dividing by the determinant <<<<<');
      for count := 1 to MAX do
        calc[count] := calc[count] / det;
      writeln(savefile, '| ', Ca^ : 12 : 4, ' ' , Cb^ : 12 : 4, ' ' , Cc^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cd^ : 12 : 4, ' ' , Ce^ : 12 : 4, ' ' , Cf^ : 12 : 4, ' |');
      writeln(savefile, '| ', Cg^ : 12 : 4, ' ' , Ch^ : 12 : 4, ' ' , Ci^ : 12 : 4, ' |');
      writeln(savefile);
      // end final
    end;
  textcolor(lightgreen);
  scroll('    Saved to file!', true);
  textcolor(white);
  closeFile(savefile);
end;

procedure inverse; //calculates the inverse
var
  count: integer;
  det: real;
begin
  det := determinant;
  if det = 0 then
    scroll('There is no inverse', true)
  else
    begin
      CoFactors;
      for count := 1 to MAX do
        calc[count] := calc[count] / det;
      signMatrix;
      transpositionalDisplay;
      display;
    end;
    {The order in which you do the calculation does not matter
    as long as you start by calculating the new matrix elements}
  end;

procedure SLOWinverse; //calculates the inverse
var
  count: integer;
  det: real;
  answer: string;
  explanationDET: real;
begin
  det :=  determinant;
  //step one (determinant)
  scroll('Step one: Calculating the determinant', true);
  scroll('Would you like to see how this is done? (PRESS ''y'' for yes)', true);
  write('  >>  ');
  readln(answer);
  writeln;
  textcolor(green);
  if (answer = 'y') or (answer = 'Y') then
    begin
      scroll('Write out the matrix like this: ', true);
      textcolor(white);
      writeln('| a b c | a b ');
      writeln('| d e f | d e ');
      writeln('| g h i | g h ');
      textcolor(green);
      scroll('This makes it easier to visualise', true);
      writeln;
      scroll('The determinant is (aei + bfg + cdh) - (ceg + afh + bdi)', true);
      scroll('(look at the diagonals)', true);
      writeln;
    end;


  if det = 0 then
    begin
      textcolor(cyan);
      scroll('The determinant is 0 so there is no inverse', true);
    end
  else
    begin
      textcolor(cyan);
      writeln('     Determinant = ', det : 0 : 1);
      textcolor(white);
      //step two (cofactors)
      writeln;
      scroll('Step two: calculating the co-factors of the new matrix', true);
      scroll('Would you like to see how this is done? (PRESS ''y'' for yes)', true);
      write('  >>  ');
      readln(answer);
      writeln;
      textcolor(green);
      if (answer = 'y') or (answer = 'Y') then
        begin
          scroll('Select an element, let us say a', true);
          writeln;
          textcolor(white);
          write('| ');
          textcolor(red);
          write('a ');
          textcolor(white);
          writeln('b c |');
          writeln('| d e f |');
          writeln('| g h i |');
          writeln;
          readln;

          textcolor(green);
          scroll('Replace that element by:', true);
          scroll(' - Deleting the elements in its row and column', true);
          scroll(' - calculate the determinant of the 2x2 left', true);
          scroll(' - replace the element (in this case a) with the answer', true);
          writeln;
          readln;

          textcolor(red);
          writeln('| a b c |');
          write('| d ');
          textcolor(white);
          writeln('e f |');
          textcolor(red);
          write('| g ');
          textcolor(white);
          writeln('h i |');
          writeln;

          scroll('The determinant of a 2x2 | a b |', true);
          writeln('                         | c d | is: ad - bc');
          writeln;
          scroll('So the determinant of | e f |', true);
          write('                      | h i | is: ');
          explanationDET := smallDet(Pe^, Pf^, Ph^, Pi^);
          writeln(explanationDET : 0 : 1);
          writeln;
          textcolor(green);
          writeln;
          writeln('Element a is replaced with ', explanationDET : 0 : 1);

          textcolor(white);
          scroll('You do the same for each element', true);
          writeln;
          readln;
        end;

      CoFactors;
      display;
      // step three
      readln;
      scroll('Step three: Multiplying by the sign matrix to create the co-factors', true);
      scroll('sign matrix: | +1 -1 +1 |', true);
      writeln('             | -1 +1 -1 |');
      writeln('             | +1 -1 +1 |');
      signMatrix;
      display;
      // step four
      readln;
      scroll('Step four: Transposing the elements', true);
      scroll('(this is flipping along the leading diagonal)', true);
      transpositionalDisplay;
      display;
      // final step
      readln;
      scroll('Final Step: Dividing by the determinant', true);
      for count := 1 to MAX do
        calc[count] := calc[count] / det;
      display;
      writeln;
    end;

  scroll('Would you like to save this solution to a file? (PRESS ''y'' for yes)', true);
  scroll('  >>  ', false);
  readln(answer);

  if (answer = 'y') or (answer = 'Y') then
    save;
end;

procedure EndProgram;
begin
  writeln;
  writeln('Thanks for using the program!');
  writeln('       - Nathaniel, the Don');
  sleep(1222);
  exit;
end;

begin
  // first intro
  scroll('Welcome to the Matrix calculator', true);
  inputMatrix;

  //matrix calculations
  writeln;
  repeat
    scroll('What would you like to calculate:', true);
    writeln;
    scroll('Inverse (PRESS ''i'')', true);
    scroll('Inverse step-by-step (PRESS ''s'')', true);
    scroll('Save inverse calculation to file (PRESS ''q'')', true);
    writeln;
    scroll('Determinant (PRESS ''d'')', true);
    scroll('Co-factors (PRESS ''c'')', true);
    writeln;
    scroll('Show original matrix (PRESS ''o'')', true);
    scroll('Input new matrix (PRESS ''n'')', true);
    scroll('Exit (PRESS ''e'')', true);
    writeln;
    write('  >> ');
    readln(answer);
    answerval := true;

    //matrix operations
    case answer of
      'i', 'I': inverse;
      'd', 'D': begin
                textcolor(cyan);
                writeln;
                   calcedDET :=  determinant;
                   writeln('Determinant = ', calcedDET:0:2);
                   textcolor(white);
              end;
      'e', 'E': break;
      's', 'S': begin
                  textcolor(green);
                  scroll('(Press ENTER to continue between each step)', true);
                  readln;
                  textcolor(white);
                  SLOWinverse;
                end;
      'n', 'N': begin
                  inputMatrix;
                  answerval := false;
                  writeln;
                end;
      'c', 'C': begin
                  cofactors;
                  display;
                end;
      'o', 'O': begin
                  scroll('Your matrix is:', true);
                  writeln;
                  textcolor(cyan);
                  writeln('| ', Pa^:12:4, ' ' , Pb^:12:4, ' ' , Pc^:12:4, ' |');
                  writeln('| ', Pd^:12:4, ' ' , Pe^:12:4, ' ' , Pf^:12:4, ' |');
                  writeln('| ', Pg^:12:4, ' ' , Ph^:12:4, ' ' , Pi^:12:4, ' |');
                  textcolor(white);
                end;
      'q', 'Q': save;
    else
      answerval := false;
      error('ERROR: Command not recognised');
    end;

    if answerval = false then
      continue
    else
      begin
        writeln;
        scroll('Would you like to do something else? (PRESS ''y'' for yes)', true);
        readln(iteration);
        writeln;
        writeln;
        if (iteration = 'y') or (iteration = 'Y') then
          answerval := false;
      end; //end else

  until answerval = true;
  EndProgram;
end.

Programming - a skill for life!

Student programs to inspire you!