Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Минимум среди максимумов матрицы

Автор: Айра 9.12.2007 2:27

Привет!
В общем нужно было найти минумум среди максимумов каждой строки матрицы и вывести его вместе с его координатами.. Использовать процедуры, либо функции.. (делала через процедуры)
Задача конечно очень "сложная" и редкая)), аж самой противно unsure.gif , но не могли бы проверить, представляя себя очень строгим и дотошным преподом smile.gif


const n=5;
m=4;
type matr = array[1..n,1..m] of integer;
var arr: matr;
str,stl,min: integer;

procedure vvod(var a: matr);
var i,j: integer;
begin
for i:=1 to n do
for j:=1 to m do a[i,j]:=random(11);
end;

procedure vuvod(a: matr);
var i,j: integer;
begin
for i:=1 to n do
begin
for j:=1 to m do write(a[i,j]:4);
writeln;
end;
end;

procedure poisk_min(a: matr; var mn,st,sl: integer);
var i,w,mx: integer;

procedure poisk_max(b: matr; l: integer; var t,v: integer);
var j: integer;
begin
for j:=1 to m do
if b[l,j]>t then
begin
t:=b[l,j];
v:=j;
end;
end;

begin
for i:=1 to n do
begin
mx:=0;
poisk_max(a,i,mx,w);
if mx<mn then
begin
mn:=mx;
st:=i;
sl:=w;
end;
end;
end;

begin
randomize;
str:=0;
stl:=0;
min:=1000;
vvod(arr);
vuvod(arr);
poisk_min(arr,min,str,stl);
writeln('искомый элемент: ',min,' в ',str,'-й строке ',stl,'-го столбца');
end.


еще.. мне кажется, чет я намудрила там с переменными.. с их глобальностью и локальностью.. Мне это не кажется?

Заранее спасибо)))

Автор: Michael_Rybak 9.12.2007 4:11

Вообще все хорошо. У меня было бы два таких небольших замечания.

Первое - матрицу как параметр лучше передавать всегда по ссылке, а не по значению (т.е. через var-параметр), т.к. иначе при каждом вызове создается дополнительная копия матрицы в стеке, и при больших размерах матрицы это существенно влияет на производительность.

И второе - лучше инициализацию выходных параметров инкапсулировать внутри процедур. Ты заполняешь min, str и stl, и передаешь их функции, которая при этом расчитывает на то, str и stl обнулены, а min - достаточно большое. Пусть лучше процедура внутря себя обеспечит эти условия, а снаружи ты ее только вызываешь, полагаясь, что параметры будут заполнены правильно. То же самое и для mx, передаваемой в poisk_max - пусть сам poisk_max ее и обнуляет.

Автор: Айра 9.12.2007 4:39

Спасибо!))
Все поняла, исправила.
Только один вопрос.. "инкапсулировать" - значит "производить/проводить"? (буду пополнять свой словарный запас wink.gif)

Автор: Michael_Rybak 9.12.2007 4:49

Инкапсулировать - это значит собирать в капсулу, дословно smile.gif То есть вбирать в себя то, что другим знать необязательно.

Допустим, ты этой функцией хочешь поделиться со мной. Ты мне эту функцию даешь, и говоришь - параметр min нужно сделать очень большим, а параметры str и stl - обнулить, и тогда функция вычислит минимум максимумов и запишет в min.

А на самом деле гораздо удобнее для меня как для пользователя твоего кода, чтобы я знал только, что надо ее вызвать, и что при этом получится минимум максимумов. А обнуление пусть за меня выполнит сама функция.

Таким образом ты прячешь часть зависимостей внутрь функции, по возможности изолируешь детали реализации от внешнего мира. Это есть инкапсуляция.

Хотя чаще это слово используется в отношении классов (а не функций). Но это уже совсем другая история smile.gif

Автор: volvo 9.12.2007 4:53

Цитата
"инкапсулировать" - значит "производить/проводить"?
Инкапсулировать - от слова "капсула" - скрывать, закрывать оболочкой...

Теперь о программе... Если быть
Цитата
очень строгим и дотошным преподом
- то я бы порекомендовал:

1. Все переменные, описанные в самом начале перенести так, чтоб они были описаны прямо перед началом основной программы (это к тому, что "меньше знаешь - лучше спишь", чем меньше процедур/функций "знают" о существовании глобальных переменных - есть меньше возможностей получить побочные эффекты)...

2. То же самое касается и вложенной процедуры - секция Var должна быть не ДО нее, а после...

3. Еще нечто, что у тебя во вложенной процедуре не совсем понятно:
procedure poisk_max(b: matr; l: integer; var t,v: integer);
Зачем ты еще раз передаешь матрицу? У тебя же сама матрица "А", переданная в процедуру poisk_min, доступна...

(передавай матрицу по константной ссылке, если не будешь запускать программу на TP ниже 7 версии:
procedure poisk_min(const a: matr; var mn,st,sl: integer);
- это даст тебе дополнительную гарантию безопасности данных)

Автор: Айра 9.12.2007 4:55

to Michael_Rybak Понятно. Еще раз спасибо за подробное объяснение! give_rose.gif

Автор: Michael_Rybak 9.12.2007 4:59

Цитата(volvo @ 8.12.2007 23:53) *

(передавай матрицу по константной ссылке, если не будешь запускать программу на TP ниже 7 версии:


Опа smile.gif А про константные ссылки-то я и не знал. Как их в паскале реализовать в смысле.

Автор: мисс_граффити 9.12.2007 5:01

может, я сейчас скажу не совсем правильные вещи...
это скорее на уровне не "правильно/неправильно", а "мне так удобнее".
если что - надеюсь, меня поправят smile.gif)

0) я бы минимизировала работу с глобальными константами.
размерность матрицы - передавала процедурам.
имхо, это несколько упрощает отладку.

1) названия переменных... l,v,w... хотелось бы побольше информативности

2) зачем хранить и значение элемента, и его индексы? по индексу всегда можно обратиться к элементу...

Автор: Michael_Rybak 9.12.2007 5:02

Цитата(Айра @ 8.12.2007 23:55) *

to Michael_Rybak Понятно. Еще раз спасибо за подробное объяснение! give_rose.gif

smile.gif

Автор: Айра 9.12.2007 5:20

to volvo: тоже разобралась, спасибо!
to мисс_граффити:

0) я тоже об этом думала.. (вспоминается одна из лекций по информатике) наверно так и сделаю..
1) тоже согласна, что запутанно, скорее всего и препод придерется.. придется выдумавать понятные обозначения..
2) получается можно было сделать процедуру поиска минимума без передачи туда переменной min? а просто потом по индексам выводить элемент массива.. но раз я там уже нахожу минимальное, так пусть оно потом и поработает smile.gif

Автор: мисс_граффити 9.12.2007 6:09

нумерация пунктов та же smile.gif
1) комментарии напиши...
добавлять их к программкам - вообще хорошая привычка. хотя обычно лень... особенно если что-то совсем простенькое пишешь.

2) ну, по сути, да.
то есть, грубо говоря, существует 2 банально-примитивно-классически-рассматривающихся везде способа поиска минимума:
а)

min:=очень_большое_число;
for i:=1 to n do
if ar[i]<min then
min:=ar[i];

б)
min:=ar[1];
for i:=2 to n do
if ar[i]<min then
min:=ar[i];

поскольку тебе все равно нужны индексы, я бы опиралась на второй вариант. то есть:
min_ind:=1;
for i:=2 to n do
if ar[i]<ar[min_ind] then
min_ind:=i;

насколько я понимаю, здесь даже нет вопроса быстродействие vs экономия памяти.... доступ к элементам массива прямой.

это, кстати, позволит тебе переделать poisk_max из процедуры в функцию.
что, на мой взгляд, с учетом учебной, а не практической направленности данной задачи будет плюсом - ты покажешь преподу, что умеешь работать с обоими видами подпрограмм.

З.Ы. Если бы преподы ТАК принимали лабораторные shok.gif

Автор: Айра 9.12.2007 6:55

Т.е. получится что-то типа такого:

  
const n=5;
m=4;
type matr = array[1..n,1..m] of integer;

procedure vvod(var a: matr; const n,m: integer);
var i,j: integer;
begin
for i:=1 to n do
for j:=1 to m do a[i,j]:=random(11);
end;

procedure vuvod(var a: matr; const n,m: integer);
var i,j: integer;
begin
for i:=1 to n do
begin
for j:=1 to m do write(a[i,j]:4);
writeln;
end;
end;

procedure poisk_min(const a: matr; var mn,st,sl: integer; const n,m: integer);
function poisk_max(const a: matr; l,max_ind: integer; const m: integer): integer;
var j: integer;
begin
max_ind:=1;
for j:=1 to m do
if a[l,j]>a[l,max_ind] then
begin
max_ind:=j;
end;
poisk_max:=max_ind;
end;
var i,w,mx: integer;
begin
st:=0;
sl:=0;
mn:=1000;
for i:=1 to n do
begin
if a[i,poisk_max(a,i,mx,m)]<mn then
begin
mn:=a[i,poisk_max(a,i,mx,m)]; //комментарий smile.gif очень смущает этот кусок, точнее неоднократное вычисление одной и той же функции.. или я уже что-то не то делаю..
st:=i;
sl:=poisk_max(a,i,mx,m);
end;
end;
end;

var arr: matr;
str,stl,min: integer;

begin
randomize;
vvod(arr,n,m);
vuvod(arr,n,m);
poisk_min(arr,min,str,stl,n,m);
writeln('искомый элемент: ',min,' в ',str,'-й строке ',stl,'-го столбца');
end.


А реализовать поиск_мин через индекс чет у меня не получается.. поздно наверно уже..

Автор: volvo 9.12.2007 7:24

Оля, смотри, что можно сделать:

const
n = 5;
m = 4;
type
vector = array[1 .. m] of integer;
matrix = array[1 .. n] of vector;

procedure vvod(var a: matrix; const n,m: integer);
var i, j: integer;
begin
for i:=1 to n do
for j:=1 to m do a[i,j]:=random(11);
end;

procedure vuvod(var a: matrix; const n,m: integer);
var i,j: integer;
begin
for i:=1 to n do
begin
for j:=1 to m do write(a[i,j]:4);
writeln;
end;
end;

procedure get_min(const mx: matrix; var row, col: integer;
const n, m: integer);

function get_max_index(const v: vector; const m: integer): integer;
var max_index, i: integer;
begin
max_index := 1;
for i := 1 to m do
if v[i] > v[max_index] then max_index := i;
get_max_index := max_index;
end;

var i, max_col: integer;
begin
col := 0; row := 0;

for i := 1 to n do begin

max_col := get_max_index(mx[i], m);
if (i = 1) or (mx[i, col] < mx[row, col]) then begin
col := max_col; row := i
end;

end;
end;

var
arr: matrix;
min_row, min_col: integer;

begin
randomize;
vvod(arr, n, m);
vuvod(arr, n, m);
get_min(arr, min_row, min_col, n, m);

writeln('искомый элемент: ',arr[min_row, min_col],' в ',min_row,'-й строке ',min_col,'-го столбца');
end.

smile.gif

Автор: Айра 10.12.2007 4:28

volvo, спасибо! give_rose.gif
У меня были мысли про массив векторов, но реализовать не удалось(( Кстати, он ведь по идее считается одномерным, или как?

Автор: volvo 10.12.2007 4:36

Вектор - одномерный, массив векторов - уже двумерный... У тебя же не возникает вопроса: массив
array[1 .. n, 1 .. n] of integer - двумерный или нет? А согласно синтаксису Паскаля это объявление аналогично
array[1 .. n] of array[1 .. n] of integer, ну а я ввел промежуточный тип (для удобства)...

Автор: Айра 10.12.2007 4:40

Точно!
Еще раз пасибо))