Помощь - Поиск - Пользователи - Календарь
Полная версия: Заполнение массива по спирали
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Alexdel
Всем привет! требуется написать прогу для заполнения прямоугольной таблицы размерами n*n по спирали числами от 1 до n*n. Я вот тут кое-что написал но работает не так, как надо... Мозги уже кипят... Помогите плиз кто чем может... Хотя бы намёк сделайте=)
Lapp
Цитата(Alexdel @ 10.02.2010 11:17) *
требуется написать прогу для заполнения прямоугольной таблицы размерами n*n по спирали числами от 1 до n*n. Я вот тут кое-что написал но работает не так, как надо...
По спирали - это от центра? тогда ПО часовой или против? Или скраю к центру? вопрос про направление остается..

А вообще, задача про спираль несколько раз была. Искать не пробовал?

И почему в алгоритмах? Тебе же код нужен или только словесное описание?

Последнее: код не надо прикреплять в файле. Надо вставлять в мессадж с тегами кода (меню CODE над окном ввода).
Lapp
Цитата(Alexdel @ 10.02.2010 11:17) *
Мозги уже кипят... Помогите плиз кто чем может... Хотя бы намёк сделайте=)
Вот, глянь.
Я тут изменил названия переменных. А то, ты в условии говоришь одно, а в решении - другое.. Зачем? Надо стараться сохранять буковки, как они есть.
program task4;
const
m= 20;
var
a: array[1..m, 1..m] of integer;
i,j, n, k: integer;
begin
k:=1;
write('vvedite razmer matricy (ot 1 do ',m,'): ');
ReadLn(n);

for i:=1 to (n+1) div 2 do begin {исправлено}
for j:=i to n-i+1 do begin
a[i,j]:=k;
Inc(k);
end;
for j:=i+1 to n-i+1 do begin
a[j,n-i+1]:=k;
Inc(k);
end;
for j:=n-i downto i do begin
a[n-i+1,j]:=k;
Inc(k);
end;
for j:=n-i downto i+1 do begin
a[j,i]:=k;
Inc(k);
end;
end;

for i:=1 to n do begin
for j:=1 to n do Write(a[i,j]:5);
WriteLn
end;
readln;
end.

М
Тему переношу в Задачи..



Добавлено через 2 мин.
Еще одно: тебе пришлось ставить два ReadLn в конце, потому что ты читал входные данные Read'ом, но вводил с энтером. Этот энтер сохранялся и съедал первый ReadLn. Если ввод заканчивается энтером - читай его ReadLn'ом.

Добавлено через 9 мин.
Упс!.. Моя прога не заполняет центральный элемент при нечетном n.
Сейчас исправим.. smile.gif

Добавлено через 2 мин.
Собственно, исправление совсем небольшое. Надо во внешнем цикле верхний предел изменить на (n+1) div 2.
Я это сейчас сделаю прямо в том коде..
RathaR
Забавно smile.gif
Буквально вчера, сидел в кабинете информатики, пересматривал задания старых олимпиад, и наткнулся на первую(!) олимпиаду по программированию, что проводились у нас, год точно не скажу, девяносто какой то, так это была первая задача в той олимпиаде))) Просто ради интереса сел, сделал её, за урок, правда там матрица прямоугольная была.
Вот, собственно, мое решение, особо долго не думал над ней(просто обходил матрицу определяя куда ставить след номер)...

const
max_size=10;

type
tMove=(up,down,left,right);
var
m,n:integer;
A:array[0..max_size+1,0..max_size] of integer;
I:integer;
K:integer;
x,y:integer;

procedure Input(var x,y:integer);
var
F1:text;
begin
assign(F1,'spiral.dat');
reset(F1);
read(F1,N,M);
close(F1);
end;

procedure Output;
var
I,J:integer;
F2:text;
begin
assign(F2,'spiral.sol');
rewrite(F2);
for I:=0 to m+1 do
begin
for J:=0 to n+1 do
write(F2,A[I,J]:3);
writeln(F2);
end;
close(F2);
end;
function move(x,y:integer):tMove;
var
left_z,right_z,up_z,down_z:boolean;
begin
if A[x+1,y]=0 then right_z:=true else right_z:=false;
if A[x-1,y]=0 then left_z:=true else left_z:=false;
if A[x,y+1]=0 then down_z:=true else down_z:=false;
if A[x,y-1]=0 then up_z:=true else up_z:=false;
if right_z and not down_z then move:=right;
if left_z and not up_z then move:=left;
if up_z and not right_z then move:=up;
if down_z and not left_z then move:=down;
end;

begin
Input(m,n);
fillchar(A,sizeof(A),0);
for I:=0 to N+1 do
begin
A[0,I]:=-1;
A[M+1,I]:=-1;
end;
for I:=0 to M+1 do
begin
A[I,0]:=-1;
A[I,N+1]:=-1;
end;

K:=1;
x:=m;
y:=1;
A[x,y]:=K;
while K<>m*n do
begin
case move(x,y) of
right:begin
inc(K);
inc(x);
A[x,y]:=K;
end;
left:begin
inc(K);
dec(x);
A[x,y]:=K;
end;
up:begin
inc(K);
dec(y);
A[x,y]:=K;
end;
down:begin
inc(K);
inc(y);
A[x,y]:=K;
end; end;
end;
Output;
end.

Заядло я её не тестировал, но вроде работает, файлы прикрепляю.
Lapp
Цитата(RathaR @ 10.02.2010 15:29) *
сел, сделал её, за урок, правда там матрица прямоугольная была.

За урок такое сделать - респект!

Rathar, идея твоя интересная. Я ее реализовал тут.. Вот, что вышло:
const
max= 20;
var
a: array[1..max, 1..max] of integer;
m,n,i,j,di,dj,b,k: integer;
begin
FillChar(a,SizeOf(a),0); // инициализация, вставлено позже
k:=1;
write('введите количество строк (не больше ',max,'): ');
ReadLn(m);
write('введите количество столбцов (не больше ',max,'): ');
ReadLn(n);
k:=1;
i:=1;
j:=1;
di:=0;
dj:=1;
repeat
a[i,j]:=k;
Inc(k);
if (i+di>m)or(i+di<1)or(j+dj>n)or(j+dj<1)or(a[i+di,j+dj]>0) then begin
b:=dj;
dj:=-di;
di:=b
end;
i:=i+di;
j:=j+dj;
until a[i,j]>0;

for i:=1 to m do begin
for j:=1 to n do Write(a[i,j]:5);
WriteLn
end;
readln;
end.

Тут главное - что для смены направления не нужно знать направление. Формулы предельно просты:
di = dj
dj = -di
Проверь их.
smile.gif
Lapp
На свежую голову (после работы)) глянул на код и заметил, что так и забыл вставить инициализацию массива, которую почему-то откладывал на потом. Короче, сейчас вставлю..
RathaR
Мне эта задача выпала на лабораторную по проге, за тему матриц. Ну это судьба... lol.gif Совесть не выдержала, сразу показал преподу решение, взял другую лабу smile.gif
RathaR
Сегодня эта задача попалась на тренировке по спортивному програмированию... даж не знаю... задача классическая, никто не спорит, но я, перед окончанием, ради интереса отправил оба решения: Lapp твоя прога на 12 тесте дала неверный результат))) Моя - на шестом rolleyes.gif
Unconnected
Это уже правда судьба ))

А на каких тестах, не показывается там? Хотя, что я спрашиваю... это везде так, wrong answer on test 10, как будто номер теста чем то поможет)
TarasBer
> А на каких тестах, не показывается там?

Ну дык, чтобы программист в алгоритме ошибку искал, а не костыли для конкретного случая вбивал.

> как будто номер теста чем то поможет)

Поможет. Маленький номер - значит алгоритм сам по себе лажовый, большой - значит всё правильно, но не разобран какой-то корявый краевой случай.
Lapp
Цитата(RathaR @ 2.11.2010 22:31) *
задача классическая, никто не спорит
Я спорю. Ни разу еще в этой теме не появилось условие! Как вообще можно судить о верности рещения задачи без условия?? Ни автор темы, ни ты, RathaR, при повторном ее (двукратном) поднятии так и не потрудились привести нормальное условие. Поэтому, все, что я писал - это просто пример "на тему". Я не писал задачу для тестов. И НЕ СТАЛ БЫ писать, пока не получил бы нормального условия.

Цитата
, но я, перед окончанием, ради интереса отправил оба решения: Lapp твоя прога на 12 тесте дала неверный результат))) Моя - на шестом rolleyes.gif
Я не буду даже смотреть в код. Это неуважение - взять учебный набросок (написанный по высосанному из пальца условию) и начать его тестировать.. norespect.gif Лень приводить условие - мне лень тебе отвечать..
Unconnected
Цитата
Это неуважение - взять учебный набросок (написанный по высосанному из пальца условию) и начать его тестировать.. norespect.gif


Оой ну прям такое неуважение, набросок тестировать..
Lapp
Цитата(Unconnected @ 3.11.2010 0:55) *
Оой ну прям такое неуважение, набросок тестировать..
Ты сколотишь табурет, чтоб просто сидеть, а кто-то подаст его на конкурс кроватей. И потом терпи, когда будут показывать на тебя пальцами и говорить: а, это тот, чья кровать заняла последнее место на конкурсе..

Пока не будет точного условия, я в эту тему не отвечаю.
Гость
Цитата(Alexdel @ 10.02.2010 15:17) *

Всем привет! требуется написать прогу для заполнения прямоугольной таблицы размерами n*n по спирали числами от 1 до n*n. Я вот тут кое-что написал но работает не так, как надо... Мозги уже кипят... Помогите плиз кто чем может... Хотя бы намёк сделайте=)

//на PascalABC.net
//Матрица по спирали из любого угла или из центра, по часовой или против часовой
begin
var n:= 3;
var ИзЦентра := 0; // 0 - из угла 1 - из Центра

Var Центр := Ceil(n / 2) - 1; //Координата центра матрицы
var (i, j, Направление, nEven) := (0, 0, 1, n.IsEven ? 1 : 0); // с левого верхнего
if ИзЦентра = 1 then (i, j, Направление, nEven) := (Центр, Центр, 1, 0); // из центра
var Матрица := new integer[n,n];
for var Элемент := 1 to n*n do
begin
Матрица[i,j]:= Элемент; {
[i,j] - с левого верхнего по часовой; из Центра вправо по часовой
[j,i] - с левого верхнего против часовой; из Центра вниз против часовой
[n-1-i,j] - с левого нижнего против часовой; из Центра вправо против часовой
[n-1-j,i] - с левого нижнего по часовой; из центра вверх по часовой
[j,n-1-i] - с правго верхнего по часовой; из Центра вниз по часовой
[i,n-1-j] - c правго верхнего против часовой; из Центра влево против часовой
[n-1-i,n-1-j] - c правого нижнего по часовой; из Центра влево по часовой
[n-1-j,n-1-i] - c правого нижнего против часовой; из центра вверх по часовой
}
case Направление of
1:begin {вправо}
inc(j);
if (Центр - i + ИзЦентра ) = (j - Центр - nEven) then Направление := 2;
end;
2:begin {вниз}
inc(i);
if i = j then Направление := 3;
end;
3:begin {влево}
dec(j);
if (i - Центр) = (Центр - j + nEven) then Направление := 4;
end;
4:begin {вверх}
dec(i);
if (i - 1) = (j - ИзЦентра) then Направление := 1;
end
end;
end;
Матрица.Println;
end.
Гость
 
begin //PascalABC.net
var n := 5; // от 2 (2 на 2) и более
var a := new integer[n, n];
var (i, j, c) := (0, -1, 1);
repeat
loop n do begin inc(j); a[i, j] := c; inc© end;
loop n - 1 do begin inc(i); a[i, j] := c; inc© end;
loop n - 1 do begin dec(j); a[i, j] := c; inc© end;
loop n - 2 do begin dec(i); a[i, j] := c; inc© end;
dec(n, 2);
until n < 1;
a.Println
end.

Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.