Разбор решения. Урок 15 Задача 13 - Сдвиг массива с помощью готовой процедуры

Разбор решения. Урок 15 Задача 13

Условие:

Пусть есть процедура, которая умеет сдвигать массив влево на 1 элемент, начиная с указанного символа (устанавливая последний элемент равным нулю):

type newArr = array [1..5] of integer;
 
procedure shiftArr(var promArr: newArr; k:integer);
var j:integer;
begin
  for j:=k to 4 do
    promArr[j]:=promArr[j+1];
  promArr[high(promArr)]:=0;
end;

Задача: У вас есть исходный массив случайных целых чисел из 5 элементов. Пользователь вводит три числа целых числа, сохраните их во второй массив и затем проведите сдвиг элементов исходного массива, для каждого случая их совпадения с элементами из второго массива, для сдвига используйте процедуру shiftArr().

Пример 1:

Исходный массив: 1 5 6 8 9
Числа пользователя:
2
4
5
Ответ:
1 6 8 9 0

Пример 2:

Исходный массив: 1 5 6 8 9
Числа пользователя:
8
4
6
Ответ:
1 5 9 0 0

Пример 3:

Исходный массив: 1 5 6 5 9
Числа пользователя:
5
4
6
Ответ:
1 9 0 0 0

Пример 4:

Исходный массив: 1 5 5 5 9
Числа пользователя:
5
4
6
Ответ:
1 9 0 0 0

Пример 5:

Исходный массив: 1 5 0 5 9
Числа пользователя:
3
4
0
Ответ:
1 5 5 9 0

Разбор решение

1) Объявим переменные. Объявим тип - массив из пяти чисел.

Примечание: Если указать отдельно тип array в секции var и в процедуре, то в процедуре элементы будут считаться с нуля, а не с единицы (подробнее про "потерю индекса" см. в уроке 15).

Заполним исходный массив случайными числами:

type Arr= array[1..5] of integer;
 
var a: Arr; b: array[1..3] of integer; i,l, min,max: integer;
 
procedure shiftArr(var promArr: Arr; k:integer);
var j:integer;
begin
  for j:=k to 4 do
    promArr[j]:=promArr[j+1];
  promArr[high(promArr)]:=0;
end;

begin
  randomize();
  min:=1;
  max:=8;
  for i:=low(a) to high(a) do
  begin
    a[i] := min + random(max - min + 1);
    write (a[i],' ');
  end;
  writeln();
  
  b[1]:=3;
  b[2]:=4;
  b[3]:=6;

2) Вложенный цикл: проверка соответствия элемента исходного массива элементу массива пользователя. В случае совпадения - процедура shiftArr и разрыв вложенного цикла:

  
for i:=low(a) to high(a) do // обычный вложенный перебор в прямом порядке
  for l:=low(b) to high(b) do
    if a[i]= b[l] then
    begin
      shiftArr (a, i); // сдвиг
      break;
    end; 

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

Самый простой способ решить эту проблему - перебирать исходный массив с конца. Тогда в случае сдвига порядковый номер изменится только у перебранных элементов:

for i:=high(a) downto low(a) do // перебор основного в обратную строну
  for l:=low(b) to high(b) do // массив сдвигов, как и раньше перебираем в прямом направлении
    if a[i]= b[l] then
    begin
      // ........

Чтобы не выйти за пределы исходного массива, добавляем проверку:

  if i=high(a) then
    a[i]:=0
  else
    shiftArr (a, i);
  break; 
end; // убрать, если нет открывающего, или пояснить

3) Выводим на экран, что получилось:

  for i:=low(a) to high(a) do
    write(a[i],' ');
  readln();
end. // конец программы

Видео-материалы

  1. Комментарии к написанию разборов задач на примере данного:
vedro-compota's picture

> Чтобы не выйти за пределы исходного массива,

Разве можно выйти при таком переборе за пределы?

_____________
матфак вгу и остальная классика =)