Консультация № 176426
01.02.2010, 00:31
0.00 руб.
0 11 4
Добрый вечер!Помогите пожалуйста вот с такой задачей:
дан двумерный массив,определить к-количество различных элементов массива (повторяющиеся элементы считать один раз)

Обсуждение

Неизвестный
01.02.2010, 02:03
общий
это ответ
Здравствуйте, angel.nero.
Я предлагаю такой вот способ. Хотя может с точки зрения экономии ресурсов памяти и времени он и не очень хорош, но решает поставленную задачу. Метод:
Создается массив (описываем в разделе переменных или создаем динамически) такой же размерностью, что и заданный (если не знаешь как создать массив динамически, то просто опиши массив заранее достаточного размера). После, организуем два вложенных цикла, которые пробегают по всем элементам исходной матрицы:
//mas - исходный массив
//mas_ij - созданный массив для подсчета различных эллементов (массив отметок)
//N - количество строк в массиве
//K - количество стлбцов в массиве
//kol - количество различных элементов
//--------------------------------------

//заполнение массива отметок числом отличным от чисел, испоьзуемых для
//подсчета разных элементов
for i:=1 to N do
for j:=1 to K do mas_ij[i,j]:=-1;

//заполнение массива отметок....
//берем очередной элемент исходного массива
for i:=1 to N do
for j:=1 to K do begin
//если данный элемент i,j отличается от предыдуших (в масссиве отметок
//соответствующий элемент равен -1), то ставим в массив отметок 1, иначе
//переходим к следующей итерации continue (если не знаешь , то можно
//убрать его, всё-равно алгоритм будет работать)
if mas_ij[i,j]=-1 then mas_ij[i,j]:=1;
else continue;
m:=j+1;
//сравниваем элемент i,j с последующими элементами
for l:=i to N do begin
while m<=K do begin
//если они равны, записываем в массив отметок 0;
if mas[i,j]=mas[l,m] then mas_ij[l,m]:=0;
inc(m);
end;
m:=1;
end;
end;

//подсчет различных элементов. сумма элементов массива отметок и будет
//количеством различных элементов
kol:=0;
for i:=1 to N do
for j:=1 to K do kol:=kol+mas_ij[i,j];
//конец
Неизвестный
01.02.2010, 02:47
общий
03.02.2010, 00:39
это ответ
Здравствуйте, angel.nero.
Делается просто. В одномерный массив записываем те элементы заданного двумерного массива, которые еще не встречались. По ходу, смотрим, встречалось ли уже такое значение, если нет, то увеличиваем счетчик. Изначальный массив генерируется случайно.
Решение с комментариями в приложении.

Приложение:
cconst
n=3; m=3; c=9;
var i,j,ii,k,jj:integer;
povtor: boolean;
a: array [1..n,1..m] of integer; {матрица NxM}
b: array [1..c] of integer; {в этой матрице будем хранить встретившиеся цифры, очевидно с не д.б. меньше n*m}

begin
randomize;
ii:=1; k:=0;
b[ii]:=-1000;
for i:=1 to n do
begin
for j:=1 to m do
begin
a[i,j]:=random(10); {заполняем матрицу случайными значениями}
for jj:=1 to ii do
begin
if b[jj]=a[i,j] then {смотрим, если такой элемент уже встречался, выход из цикла}
begin
povtor:=true;
break; end;
end;
if povtor=false then
begin
k:=k+1; {если не встречался, прибавляем к счетчику}
ii:=ii+1;
b[ii]:=a[i,j]; {если такого элемента еще не было, добавляем в вектор b}
end;
povtor:=false;
write(a[i,j]:4); {выводим матрицу}
end;
writeln;
end;
writeln('Count of different elements ',k);
writeln('Vector b:');
for i:=2 to k+1 do
write(b[i]:4);
writeln;
readln;
end.
Неизвестный
01.02.2010, 02:51
общий
angel.nero:
Также советую книгу Культина "Турбо Паскаль в примерах и задачах" на случай, если захотите научиться самостоятельно писать программы. Успехов
Неизвестный
01.02.2010, 09:29
общий
Лейла:
Добрый день! Вы создаете элемент [1,1] матрицы дважды.
Код:
a[1,1]:=random(100); {заносим в первую ячейку матрицы случайное значение}
b[ii]:=a[1,1];
k:=k+1; {есть первый встреченный элемент}


Код:
for i:=1 to n do
begin
for j:=1 to m do
begin
a[i,j]:=random(100); {заполняем матрицу случайными значениями}
..............

Ваш алгоритм выглядит так.
1. Создать a[1,1]
2. Добавить a[1,1] в вектор неповторяющихся элементов
3. Создать a[1,1]
4. Если он не совпадает с имеющимся в векторе, добавить его и увеличить счетчик на 1
Таким образом, если первое значение a[1,1] не совпадает ни с каким из вновь созданных значений матрицы, ответ будет на 1 больше, чем на самом деле.

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

Неизвестный
01.02.2010, 13:04
общий
lamed:
Спасибо, исправила.
Код:
const
n=3; m=3; c=9;
var i,j,ii,k,jj:integer;
povtor: boolean;
a: array [1..n,1..m] of integer; {матрица NxM}
b: array [1..c] of integer; {в этой матрице будем хранить встретившиеся цифры, очевидно с не д.б. меньше n*m}

begin
randomize;
ii:=1; k:=0;
b[ii]:=-1000;
for i:=1 to n do
begin
for j:=1 to m do
begin
a[i,j]:=random(10); {заполняем матрицу случайными значениями}
for jj:=1 to ii do
begin
if b[jj]=a[i,j] then {смотрим, если такой элемент уже встречался, выход из цикла}
begin
povtor:=true;
break; end;
end;
if povtor=false then
begin
k:=k+1; {если не встречался, прибавляем к счетчику}
ii:=ii+1;
b[ii]:=a[i,j]; {если такого элемента еще не было, добавляем в вектор b}
end;
povtor:=false;
write(a[i,j]:4); {выводим матрицу}
end;
writeln;
end;
writeln('Count of different elements ',k);
writeln('Vector b:');
for i:=2 to k+1 do
write(b[i]:4);
writeln;
readln;
end.
Неизвестный
01.02.2010, 14:01
общий
это ответ
Здравствуйте, angel.nero.
Для учебных задач вместо вектора (одномерного массива) достаточно использовать строку с разделителями.

Приложение:
Uses
Crt;
Const
Rows = 5;
Columns = 5;
Var
Ar: Array[1..Rows, 1..Columns] of Integer;
St, s: String;
count, r, c: Byte;
begin
ClrScr;
Randomize;

{initialize varialble}
St := ',';
count := 0;
for r:=1 to Rows do
begin
for c:=1 to Columns do
begin
Ar[r, c] := Random(30);
Write(Ar[r, c]:5);
end;
WriteLn;
end;

{solving}
for r:=1 to Rows do
for c:=1 to Columns do
begin
Str(Ar[r, c], s);
if (Pos(','+s+',', St) = 0) then
begin
St := St + s + ',';
Inc(count);
end;
end;

{Debug info}
{
writeln(St);
}

{Type result}
write('Found ', count, ' different numbers.');
repeat until keypressed;
end.
Неизвестный
01.02.2010, 14:25
общий
это ответ
Здравствуйте, angel.nero.

Предлагаю свой вариант. Предназначен для целых чисел, имеющих размер 1 или 2 байта (т.е. типы Byte, Word или Integer).
Т.к. нас интересует только признак "число уже встречалось", то идеальная структура языка Паскаль для этого - множество.
Множества очень эффективно реализованы (для вставки, удаления и проверки выполняется одна-две машинные команды), но
у них есть ограничение: они могут быть реализованы только на ограниченных типах с количеством элементов не более 256.
А мы хотим работать с 65536 числами. Заметим, что 65536 = 256 * 256, т.е. если мы заведем массив из 256 множеств, то мы
сможем охватить весь диапазон 0..256.
Индексом для выбора нужного множества будет служить старший байт числа, а элементом множества будет младший байт.
Получение старшего байта - это арифметический сдвиг вправо на 8 разрядов (целочисленное деление на 256), получение
младшего байта - логическое И с числом 255.
Функция notYet проверяет, что указанное число еще не встречалось и устанавливает признак.
Для установки используется процедура Include, существующая в Borland Pascal 7.0. Если в вашей версии такой процедуры нет,
используйте вместо нее команду:
Код:

flg [b] := flg [b] + [n];



Приложение:
{
дан двумерный массив,
определить к - количество различных элементов массива
(повторяющиеся элементы считать один раз)
}
Program DifCount;

Const
N = 10;
M = 10;
cMax = 10;

Type
TArray = array [1..M, 1..N] of Word;

TByteSet = set of Byte;
TWordSet = array [0..255] of TByteSet;

Var
arr : TArray;
flg : TWordSet;

i : 1..M;
j : 1..N;

k : Word;

Function notYet (a : Word) : Boolean;
var
b : Byte;
n : Byte;

begin
b := a shr 8;
n := a and 255;

if n in flg [b] then notYet := false
else begin
Include (flg [b], n);
notYet := true;
end;
end;

Begin
Randomize;

{ Заполняем массив случайными числами }
for j := 1 to N do
for i := 1 to M do
arr [i, j] := Random (cMax);

{ Печатаем массив на экране }
for j := 1 to N do
begin
for i := 1 to M do
write (arr [i, j]:5, ' ');
writeln;
end;

{ Инициализируем признаки для повторения элементов }
for k := 0 to 255 do flg [k] := [];

{ Считаем количество различных элементов }
k := 0;
for j := 1 to N do
for i := 1 to M do
if notYet (arr [i, j]) then Inc (k);

write ('Количество различных элементов массива равно ', k);
readln;
End.

Неизвестный
02.02.2010, 22:46
общий
Модераторы:
Обновите, пожалуйста, прогу в моем ответе, а то в рассылку уйдет не совсем корректный вариант(
Код:
const
n=3; m=3; c=9;
var i,j,ii,k,jj:integer;
povtor: boolean;
a: array [1..n,1..m] of integer; {матрица NxM}
b: array [1..c] of integer; {в этой матрице будем хранить встретившиеся цифры, очевидно с не д.б. меньше n*m}

begin
randomize;
ii:=1; k:=0;
b[ii]:=-1000;
for i:=1 to n do
begin
for j:=1 to m do
begin
a[i,j]:=random(10); {заполняем матрицу случайными значениями}
for jj:=1 to ii do
begin
if b[jj]=a[i,j] then {смотрим, если такой элемент уже встречался, выход из цикла}
begin
povtor:=true;
break; end;
end;
if povtor=false then
begin
k:=k+1; {если не встречался, прибавляем к счетчику}
ii:=ii+1;
b[ii]:=a[i,j]; {если такого элемента еще не было, добавляем в вектор b}
end;
povtor:=false;
write(a[i,j]:4); {выводим матрицу}
end;
writeln;
end;
writeln('Count of different elements ',k);
writeln('Vector b:');
for i:=2 to k+1 do
write(b[i]:4);
writeln;
readln;
end.
давно
Мастер-Эксперт
23033
1095
02.02.2010, 23:11
общий
Лейла:
Так?
Неизвестный
02.02.2010, 23:41
общий
Федоров Михаил/ Error00:
Спасибо! Можно еще вместо фразы "В одномерный массив записываем все элементы заданного двумерного массива." написать "В одномерный массив записываем те элементы заданного двумерного массива, которые еще не встречались". А то в программе одно, а в описании противоположное
давно
Мастер-Эксперт
23033
1095
03.02.2010, 00:39
общий
Лейла:
Сделано.
Форма ответа