| Массивы и матрицы | |
| Произведение сцепленных матриц / Определитель матрицы | |
| Макс. последовательности в массиве: одинаковые / возрастающие элементы | |
| Как задать матрицу, чтобы быстро поменять местами ее строки / столбцы | |
| Вычисление заданного многочлена от матрицы | Вычисление квадратного корня из матрицы |
| Как заполнить матрицу "по спирали" | |
Произведение сцепленных матриц
const
nRowFirst = 3; { Количество строк первой матрицы }
nCommon = 2; { Количество столбцов первой и строк второй матрицы }
nColSecond = 5; { Количество столбцов второй матрицы }
type
TType = Integer;
TFirst = { Тип данных для хранения первой матрицы }
array[1 .. nRowFirst, 1 .. nCommon] of TType;
TSecond = { Тип данных для хранения второй матрицы }
array[1 .. nCommon, 1 .. nColSecond] of TType;
TResult = { Тип данных для хранения результата }
array[1 .. nRowFirst, 1 .. nColSecond] of TType;
{ Собственно процедура перемножения матриц: (res) = (a) X (B) }
procedure matrixMult(var res: TResult;
a: TFirst; b: TSecond);
var i, j, k: integer;
begin
for i := 1 to nRowFirst do
for j := 1 to nColSecond do begin
res[i, j] := 0;
for k := 1 to nCommon do
res[i, j] := res[i, j] + a[i, k] * b[k, j];
end
end;
var
iRow, iCol: Integer;
m1: TFirst; m2: TSecond;
mr: TResult;
begin
WriteLn('Ввод первой матрицы: (', nRowFirst, 'x', nCommon, ')');
for iRow := 1 to nRowFirst do
for iCol := 1 to nCommon do begin
write('m1[', iRow, ',', iCol,'] : '); ReadLn(m1[iRow, iCol])
end;
writeln('Ввод второй матрицы: (', nCommon, 'x', nColSecond, ')');
for iRow := 1 to nCommon do
for iCol := 1 to nColSecond do begin
write('m2[', iRow, ',', iCol,'] : '); ReadLn(m2[iRow, iCol])
end;
matrixMult(mr, m1, m2); { Вызов процедуры перемножения }
writeln('Результирующая матрица: (', nRowFirst, 'x', nColSecond, ')');
for iRow := 1 to nRowFirst do begin
for iCol := 1 to nColSecond do
write(mr[iRow, iCol]:4);
writeln
end;
end.
Определитель матрицы (рекурсивное определение)
const
max_n = 4;
type
matrix = array[1 .. max_n, 1 .. max_n] of real;
{ Матрица, для которой будет вычисляться определитель }
const
a: matrix = (
(2, 9, 9, 4),
(2, -3, 12, 8),
(4, 8, 3, -5),
(1, 2, 6, 4)
);
function minusOne(n: integer): integer;
begin
minusOne := (1 - 2*Byte(Odd(n)));
end;
function get_addr(i, j: integer; const n: integer): integer;
begin
get_addr := pred(i) * n + j
end;
{ Рекурсивное определение определителя }
function det(var p; const n: integer): real;
type
matrix = array[1 .. max_n * max_n] of real;
var
my_p: matrix absolute p;
pp: ^matrix;
s: real;
i, j, curr: integer;
begin
s := 0.0;
if n = 2 then begin
det := my_p[1]*my_p[4] - my_p[2]*my_p[3]; exit
end;
for i := 1 to n do begin
GetMem(pp, Sqr(Pred(n)) * sizeof(real));
curr := 1;
for j := 1 to n do
if j <> i then begin
move(my_p[get_addr(j, 2, n)],
pp^[get_addr(curr, 1, Pred(n))], pred(n) * sizeof(real));
inc(curr);
end;
s := s + minusOne(Succ(i)) * my_p[get_addr(i, 1, n)] * det(pp^, Pred(n));
FreeMem(pp, Sqr(Pred(n)) * sizeof(real))
end;
det := s
end;
begin
writeln( det(a, 4):0:0 );
end.
Как найти в массиве максимальную последовательность одинаковых символов?
type TType = integer;
const
n = 10;
a: array[1 .. n] of TType = (1, 2, 2, 3, 4, 5, 5, 5, 26, 6);
function get_chain(var arr: array of TType;
const n: integer; var Len: integer): integer;
var
i, start, count: integer;
T: TType;
begin
Len := 0; i := 0;
while i <= pred(n) do begin
count := 1; T := arr[i];
while arr[i] = T do begin
inc(count); inc(i)
end;
if Len < count then begin
start := i - count;
Len := count
end;
inc(i)
end;
get_chain := start
end;
{ Пример использования: }
var _start, _max: Integer;
begin
_start := get_chain(a, n, _max);
writeln('start = ', _start, ' len = ', _max)
end.
Как найти в массиве максимальную возрастающую последовательность символов?
type TType = integer;
const
n = 15;
a: array[1 .. n] of TType = (1, 2, 5, 6, 3, 7, 8, 9, 8, 11, 23, 33, 45{0}, 56, 90);
function find_ascend(var arr: array of ttype;
const n: integer; var max: integer): integer;
var curr, start: integer;
function check_max(i: integer): integer;
begin
if max < curr then begin
max := curr;
check_max := i - curr + byte(i = pred(n))
end
else check_max := start
end;
var i: integer;
begin
max := 0; curr := 1;
start := 1;
for i := 1 to pred(n) do begin
if arr[i - 1] < arr[i] then inc(curr)
else begin
start := check_max(i);
curr := 1
end;
end;
start := check_max(i);
find_ascend := start
end;
{ Пример использования: }
var _start, _max: integer;
begin
_start := find_ascend(a, n, _max);
writeln('start = ', _start, ' len = ', _max)
end.
Как задать матрицу, чтобы быстро поменять местами ее строки ?
const
size_row = 10; { число строк }
size_col = 10; { число столбцов }
type
tvector = array[1 .. size_col] of integer;
tmatrix = array[1 .. size_row] of tvector;
При таком определении для того, чтобы поменять местами строки матрицы, достаточно сделать следующее:procedure swap_rows(var mx: tmatrix; const i, j: integer);
var T: tvector;
begin
T := mx[i]; mx[i] := mx[j]; mx[j] := T
end;
procedure print(var mx: tmatrix);
var i, j: integer;
begin
for i := 1 to size_row do begin
for j := 1 to size_col do
write(mx[i][j]:4);
writeln
end;
end;
var
mx: tmatrix;
i, j: integer;
begin
{ Заполнение матрицы }
for i := 1 to size_row do
for j := 1 to size_col do
mx[i][j] := random(100);
{ Матрица до обмена }
writeln('before:'); print(mx);
{ Обмен строк }
swap_rows(mx, 1, 5);
{ Матрица после обмена }
writeln('after:'); print(mx);
end.
Как задать матрицу, чтобы быстро поменять местами ее столбцы ?
const
size_row = 10; { число строк }
size_col = 10; { число столбцов }
type
trow = array[1 .. size_row] of integer;
tmatrix = array[1 .. size_col] of trow;
При таком определении для того, чтобы поменять местами столбцы матрицы, достаточно сделать следующее:procedure swap_cols(var mx: tmatrix; const i, j: integer);
var T: trow;
begin
T := mx[i]; mx[i] := mx[j]; mx[j] := T
end;
procedure print(var mx: tmatrix);
var i, j: integer;
begin
for i := 1 to size_row do begin
for j := 1 to size_col do
write(mx[j][i]:4); { <<< Обратите внимание на индексы !!! }
writeln
end;
end;
var
mx: tmatrix;
i, j: integer;
begin
{ Заполнение матрицы }
for i := 1 to size_row do
for j := 1 to size_col do
mx[i][j] := random(100);
{ Матрица до обмена }
writeln('before:'); print(mx);
{ Обмен столбцов }
swap_cols(mx, 1, 5);
{ Матрица после обмена }
writeln('after:'); print(mx);
end.
Как вычислить заданный многочлен от матрицы A
{ Порядок матрицы }
const size = 4;
type
TMatrix = array[1 .. size, 1 .. size] of real;
(* Умножение матриц *)
procedure matrixMult(Var m: TMatrix; a, b: TMatrix);
var i, j, k: Integer;
begin
for i := 1 to size do
for j := 1 to size do begin
m[i, j] := 0;
for k := 1 to size do
m[i, j] := m[i, j] + a[i, k] * b[k, j]
end;
end;
(* Возведение матрицы в степень *)
procedure matrixPower(var m: TMatrix; a: TMatrix; pow: integer);
var
i, j: Integer;
T: TMatrix;
begin
if pow = 0 then begin
for i := 1 to size do
for j := 1 to size do m[i, j] := Byte(i = j);
exit
end;
move(a, T, sizeof(T));
for i := 1 To Pred(pow) do
matrixMult(T, T, a);
move(T, m, sizeof(T))
end;
(* Сложение матриц *)
procedure matrixAdd(var m: TMatrix; a, b: TMatrix);
var
i, j: Integer;
begin
for i := 1 to size do
for j := 1 to size do
m[i, j] := a[i, j] + b[i, j]
end;
(* Умножение матрицы на число *)
procedure matrixScale(var m: TMatrix; a: TMatrix; f: real);
var
i, j: Integer;
begin
for i := 1 to size do
for j := 1 to size do
m[i, j] := f * a[i, j]
end;
(* Печать матрицы *)
procedure matrixPrint(a: TMatrix);
var
i, j: Integer;
begin
for i := 1 to size do begin
for j := 1 to size do
write(a[i, j]:9:2);
writeln
end
end;
const
n = 3; { Порядок многочлена }
p: array[1 .. n] of real = { Коэффициенты многочлена }
(1.0, -2.0, 3.0);
var
a: TMatrix;
T, Res: TMatrix;
i, j: Integer;
begin
for i := 1 to size do
for j := 1 to size do
a[i, j] := Random(20);
matrixPrint(a);
for i := 1 to n do begin
matrixPower(T, a, n - i);
matrixScale(T, T, p[i]);
matrixAdd(Res, Res, T)
end;
matrixPrint(Res)
end.
Пример вычисления этого же задания с использованием Free Pascal Compiler-а и перегрузки функций приведен здесь:
Вычисление квадратного корня из матрицы
{$mode objfpc}
const
size = 3;
eps = 0.001;
type
TMatrix = array[1 .. size, 1 .. size] of double;
const
E: TMatrix = (
(1, 0, 0),
(0, 1, 0),
(0, 0, 1)
);
operator * (const a, b: TMatrix) m: TMatrix;
var i, j, k: integer;
begin
for i := 1 to size do
for j := 1 to size do begin
m[i, j] := 0;
for k := 1 to size do
m[i, j] := m[i, j] + a[i, k] * b[k, j]
end;
end;
operator * (const a: TMatrix; const f: double) m: TMatrix;
var i, j: integer;
begin
for i := 1 to size do
for j := 1 to size do
m[i, j] := f * a[i, j]
end;
operator + (const a, b: TMatrix) m: TMatrix;
var i, j: integer;
begin
for i := 1 to size do
for j := 1 to size do
m[i, j] := a[i, j] + b[i, j]
end;
operator ** (const a: TMatrix; const pow: integer) m: TMatrix;
var i, j: Integer;
begin
if pow = 0 then begin
for i := 1 to size do
for j := 1 to size do
m[i, j] := Byte(i = j);
exit
end;
m := a;
for i := 1 to pred(pow) do
m := m * a;
end;
procedure matrixPrint(a: TMatrix);
var i, j: integer;
begin
for i := 1 to size do begin
for j := 1 to size do
write(a[i, j]:9:2);
writeln
end
end;
function matrixInvert(a: TMatrix): TMatrix;
function sign(r: double): shortint;
begin
if r >= 0 then sign := 1 else sign := -1;
end;
procedure AddStrings(var a, b: TMatrix;
i1, i2: integer; r: double);
var j: integer;
begin
for j := 1 to size do begin
a[i1,j] := a[i1,j] + r*a[i2,j];
b[i1,j] := b[i1,j] + r*b[i2,j];
end;
end;
procedure MultString(var a, b: TMatrix;
i1: integer; r: double);
var j: integer;
begin
for j := 1 to size do begin
a[i1,j] := a[i1,j]*r;
b[i1,j] := b[i1,j]*r;
end;
end;
var
i, j: integer;
b: TMatrix;
begin
b := E;
for i :=1 to size do begin
for j := i + 1 to size do
AddStrings(a, b, i, j,sign(a[i,i])*sign(a[j,i]));
if abs(a[i,i]) > Eps then begin
multString(a, b, i, 1 / a[i,i]);
for j := i+1 to size do
AddStrings(a, b, j, i, -a[j,i]);
end
else begin
writeln('error inverting matrix.'); halt(100);
end
end;
if (a[size, size]>eps) then begin
for i := size downto 1 do
for j := 1 to i-1 do begin
AddStrings(a, b, j, i, -a[j,i]);
end;
end
else begin
writeln('error inverting matrix.'); halt(100);
end;
result := b;
end;
const
a: TMatrix = (
(3, 2, 1),
(1, 0, 2),
(4, 1, 3)
);
var
Ypred, Y, Zpred, Z: TMatrix;
i: integer;
begin
Ypred := a; Zpred := E;
for i := 1 to 4 do begin
Y := (Ypred + matrixInvert(Zpred)) * 0.5;
Z := (Zpred + matrixInvert(Ypred)) * 0.5;
Ypred := Y; Zpred := Z;
writeln('iteration #', i);
matrixPrint(Ypred ** 2); { <--- для проверки печатаем возведенную в квадрат Ypred }
end;
writeln('result:');
matrixPrint(Ypred);
end.После запуска программы получаем вот такой результат:
iteration #1
5.50 2.75 3.00
3.25 1.25 2.75
8.25 3.25 5.50
iteration #2
3.37 2.26 1.15
1.15 -0.01 2.26
4.55 1.15 3.37
iteration #3
3.01 2.01 1.00
1.01 -0.00 2.01
4.02 1.01 3.01
iteration #4
3.00 2.00 1.00
1.00 0.00 2.00
4.00 1.00 3.00
result:
1.74 0.97 0.02
-0.05 0.32 0.97
1.15 -0.05 1.74, то есть, за 4 итерации был найден квадратный корень из матрицы...
Как заполнить матрицу "по спирали"
const
m = 5; { Количество строк }
n = 8; { Количество столбцов }
type
TMx = array[1 .. m, 1 .. n] of integer;
procedure Print(mx : TMx);
var i, j: byte;
begin
writeln;
for i := 1 to m do begin
writeln;
for j := 1 to n do write(mx[i,j]:3);
end;
writeln;
end;
procedure Spiral(var mx : TMx);
var
i, j, c: byte;
A: integer;
begin
i := 1; j := 1; c := 0; A := 1;
repeat
while (A <= m*n) and (j <= n - c) do begin mx[i,j] := A; inc(j); inc(A); end;
inc(i); dec(j);
while (A <= m*n) and (i <= m - c) do begin mx[i,j] := A; inc(i); inc(A); end;
dec(j); dec(i);
while (A <= m*n) and (j >= 1 + c) do begin mx[i,j] := A; dec(j); inc(A); end;
inc(c); inc(j); dec(i);
while (A <= m*n) and (i >= 1 + c) do begin mx[i,j] := A; dec(i); inc(A); end;
inc(j); inc(i);
until A > m * n;
end;
var
mx : TMx;
begin
Spiral(mx);
print(mx);
end.