Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] Помогите с задачей /Pascal/ (http://forum.oszone.net/showthread.php?t=153867)

Habetdin 21-10-2009 14:08 1248727

Помогите с задачей /Pascal/
 
Собственно, задача:
Цитата:

В центре городского парка, имеющего форму круга радиуса R2, находится круглый фонтан радиусом R1. Деревья в парке растут в узлах координатной сетки, начало которой находится в центре фонтана. Шаг координатной сетки равен 1. На границах парка и фонтана деревья не растут. Посчитайте количество деревьев в парке.

Вводятся два целых числа R1 и R2. Вывести количество деревьев.
Вопрос в том, как найти кол-во деревьев (по какой формуле?) :(

lxa85 21-10-2009 22:29 1249083

Цитата:

Цитата Habetdin
Вопрос в том, как найти кол-во деревьев (по какой формуле?) »

Для каждого дерева узнать длину вектора Ri(O,Ti) где Ti - i'тое дерево парка O - центр парка.
В формуле получается сумма от 1 до n при условии R1<Ri<R2 .
Для уменьшения кол-ва расчетов можно взять 1/8 круга, скорректировав конечный результат.

Habetdin 22-10-2009 00:04 1249151

Код:

program Park;
var
r1,r2,rez: integer;
i,o: text;
begin
assign(i,'input.txt');
assign(o,'output.txt');
reset(i);
read(i,r1,r2);
close(i);
// Как дальше?
rez:=Ri(0,


lxa85 22-10-2009 01:31 1249182

Habetdin,
Цитата:

Цитата Habetdin
// Как дальше? »

А дальше я своих студентов заставляю писать математическую модель :)
И тогда введя все нужные обозначения, у них не должно возникнуть вопроса, а "что писать"?
Все это будет четко привязано к формулам. Только за абстракцией, к примеру, R=... будет стоять либо функция, либо простая арифметика, массив, и пр.
Цитата:

Цитата Habetdin
assign(i,'input.txt');
assign(o,'output.txt'); »

asignfile !

" rez:=Ri(0, " - вот это надо переделать в отдельную функцию. И больше ничего подсказывать не буду :)


P.S. Я как-то говорил, что не буду заниматься написанием программ. Мне больше интересен процесс понимания человеком того, что он пишет. Т.е. семантика языка это одно, внутренняя логика и структура программы - другое. Вот меня интересует то самое другое. :)

pva 22-10-2009 07:17 1249243

Для экономии времени ещё можно ходить не по всему кругу, а только по его границе, потом вычести компоненту y "нижнего" круга из "верхнего". Получится имитация вычисления площади как интеграла (f2(x) - f1(x))dx

detrin 22-10-2009 10:39 1249366

В школьные годы на олимпиаде была подобная задача, но с треугольником. По трем заданным точка рисуется треугольник и нужно проверить попадает ли четвертая точка в него или нет. Одноклассник очень оригинально ее решил, что мне сильно врезалось в память.
Он решил ее графически. Если сделать аналогию, то нужно нарисовать 2 окружности и залить внутреннее пространство каким-либо цветом. Ну а после нужно перебирать точки и считывать их цвет. Решение данной задачи было сделано на Бейсике, но ведь наверняка в Паскале есть подобные функции.

emTPy 26-10-2009 02:46 1252485

Код:

program Park;
var
r1,r2,rez,i,j: integer;
in: text;
begin
assign(in,'input.txt');
assign(o,'output.txt');
reset(in);
read(in,r1,r2);
close(i);
rez:=0;
for i:=-r2 to r2 do
  for j:=-r2 to r2 do
    if ((i*i+j*j<r2) and(i*i+j*j>r1)) then rez:=rez+1;
writeln(rez);
end.


Habetdin 26-10-2009 20:40 1253177

Вот что имеется на данный момент:
Код:

program Park;
var
r1,r2,k,x,y: integer;
begin
assign(input,'input.txt');
assign(output,'output.txt');
reset(input);
read(input,r1,r2);
close(input);
k:=0;
for x:=r1+1 to r2-1 do
begin
y:=sqrt(sqr(r2)-sqr(x));
if sqr(x)+sqr(y)=sqr(r2) then dack(y);
k:=k+y;
for x:=0 to r1-1 do
begin
if sqr(x)+sqr(y)=sqr(r1) then k:=k-y;
end;
end;
k:=k*4;
rewrite(output);
writeln(output,k);
close(output);
end.

Вот только ошибка в 13 строке (error 26: type mismatch) - наверное из-за типа данных integer? :(

lxa85 26-10-2009 21:23 1253215

Цитата:

Цитата Drongo
Habetdin, Небольшой совет, делайте отступы в блоках\условиях, так будет легче читать код. Иначе многие специалисты, просто не утрудят себя "ломанием" глаз чтобы прочитать не читабельный код. Понимаете? »

Позволю себе процитировать Drongo, т.к. у меня та же мысль звучит в более жестких формах.
Habetdin,
Цитата:

Цитата Habetdin
наверное из-за типа данных integer? »

Разумеется.
y - определен как целое, а ему хотят назначить результат с плавающей запятой. результат работы функции sqrt.
Цитата:

if sqr(x)+sqr(y)=sqr(r2) then dack(y);
dack(y) - вот это что такое?
Цитата:

Цитата Habetdin
begin
y:=sqrt(sqr(r2)-sqr(x));
if sqr(x)+sqr(y)=sqr(r2) then dack(y);
k:=k+y;
for x:=0 to r1-1 do
begin
if sqr(x)+sqr(y)=sqr(r1) then k:=k-y;
end;
end; »

Ошибку не вижу, но чую она есть. Код какой-то неправильный. Не складный.
На будущее операцию возведения в квадрат проще и читабельнее писать как x*x
Всем переменным либо дать более полные и нормальные названия, либо в var прокомментировать их и дать словесное обозначение.
Что такое k - ?
К циклу так же дать комментарии. Т.к. непонятно что делаешь, и что надо проверять.

Habetdin 27-10-2009 21:43 1254174

lxa85, r1,r2 - см. условие задачи; k - кол-во деревьев; x,y - оси абцисс, ординат
dack(y); - то же самое, что и y:=y-1
Код:

program Park;
var
r1,r2,k: integer;
x,y: real;
begin
assign(input,'input.txt');
assign(output,'output.txt');
reset(input);
read(input,r1,r2);
close(input);
k:=0;
for x:=r1+1 to r2-1 do
begin
y:=sqrt(r2*r2-x*x);
if x*x+y*y=r2*r2 then dack(y);
k:=k+y;
for x:=0 to r1-1 do
begin
if x*x+y*y=r1*r1 then k:=k-y;
end;
end;
k:=k*4;
rewrite(output);
writeln(output,k);
close(output);
end.

Теперь ошибка в 12 строке:
Цитата:

Error 97: Invalid FOR Control variable - Ошибочен тип переменной параметра цикла оператора FOR.

emTPy 27-10-2009 22:06 1254203

for x:=r1+1 to r2-1 do
Должен быть целочисленным

Код:

var
r1,r2,k,x,y,rez: integer;
begin
assign(input,'input.txt');
assign(output,'output.txt');
reset(input);
read(input,r1,r2);
close(input);
rez:=0;
{*Делаем перебор всех точек начиная от [-r2,r2](верхнийй левый угол) и
заканчивая [r2,-r2](нижний правый угол)*}
for x:=-r2 to r2 do
  for y:=-r2 to r2 do
{*Для каждой точки проверяем *}
    if ((x*x+y*y<r2){*Лежит ли она внутри окружность радиуса r2 И*}
and (x*x+y*y>r1){*вне окружности радиуса r1*}) then rez:=rez+1;{*если да прибавляем 1 к количесву деревьев*}
writeln(output,rez);
close(output);
end.


detrin 27-10-2009 22:20 1254225

Цитата:

Цитата Habetdin
Теперь ошибка в 12 строке:
Цитата:
Error 97: Invalid FOR Control variable - Ошибочен тип переменной параметра цикла оператора FOR. »

Имхо, скобки нужны: "for x:=(r1+1) to (r2-1) do"

Habetdin 27-10-2009 23:08 1254264

Код:

program Park;
var
r1,r2,k,x,y: integer;
begin
assign(input,'input.txt');
assign(output,'output.txt');
reset(input);
read(input,r1,r2);
close(input);
k:=0;
for x:=-r2 to r2 do
for y:=-r2 to r2 do
if ((x*x+y*y<r2) and (x*x+y*y>r1)) then k:=k+1;
rewrite(output);
writeln(output,k);
close(output);
end.

Выходной файл не создается, да и простой вывод на экран k не работает :o

lxa85 28-10-2009 09:19 1254470

Habetdin,
Цитата:

Цитата Habetdin
if ((x*x+y*y<r2) and (x*x+y*y>r1)) then k:=k+1; »

найди 2 ошибки.
Цитата:

Цитата Habetdin
да и простой вывод на экран k не работает »

это как?
readln; в конце программы поставь, чтобы вывод k посмотреть.
переменными r1, r2 тоже можно для начала задаться в ручную.

Отладчик что говорит по ходу выполнения программы?
Какая вообще среда программирования?

Habetdin 28-10-2009 17:53 1254941

lxa85, Turbo Pascal
Вот что сейчас:
Код:

program Park;
var
r1,r2,k,x,y: integer;
begin
assign(input,'C:\input.txt');
reset(input);
read(input,r1,r2);
close(input);
k:=0;
for x:=-r2 to r2 do
for y:=-r2 to r2 do
if (x*x+y*y<r2) and (x*x+y*y>r1) then
k:=k+1;
assign(output,'C:\output.txt');
rewrite(output);
writeln(output,k);
close(output);
end.

Но результат почему-то неверный, при r1=1 и r2=3 k должно быть 20, а получается 4

lxa85 28-10-2009 20:10 1255057

Habetdin,
Цитата:

Цитата lxa85
Habetdin,
Цитата Habetdin:if ((x*x+y*y<r2) and (x*x+y*y>r1)) then k:=k+1; »
найди 2 ошибки. »

Вся твоя программа, по сути, состоит из этого условия. Все что выше и ниже, не более чем обрамление, и ничего интересного не представляет. Т.е. про это вообще сейчас можно забыть, и не смотреть.

Habetdin 28-10-2009 20:47 1255093

lxa85,
Цитата:

Цитата Habetdin
if (x*x+y*y<r2) and (x*x+y*y>r1) then k:=k+1; »

Как я понял, 1 ошибка устранена (в синтаксисе команды?)? :)

lxa85 28-10-2009 20:54 1255101

Цитата:

Цитата Habetdin
Как я понял, 1 ошибка устранена? »

Нет!
Конструкции
Код:

if (x*x+y*y<r2) and (x*x+y*y>r1) then
    k:=k+1;

и
Код:

if (x*x+y*y<r2) and (x*x+y*y>r1) then k:=k+1;
совершенно идентичны.
if <условие> then <оператор, действие> ;
Ищи ошибку дальше.
Если не найдешь, утром буду сильно ругаться.
( С приведением наглядного материала и разносом по всем статьям. )
Я предупредил.

Habetdin 28-10-2009 21:25 1255122

lxa85, э... я скобки лишние убрал :)
Цитата:

Цитата lxa85
С приведением наглядного материала и разносом по всем статьям. »

Паскаль неделю назад начал изучать по очень старой книжке :not-me:

Drongo 28-10-2009 21:36 1255126

Цитата:

Цитата Habetdin
э... я скобки лишние убрал »

Вряд ли там скобки, так как скобки могут быть управляющими, например, ((a + b) + (c + d )) + (e + f) Сначала выполнится сложение в скобках ((a + b) + (c + d )), потом в (e + f).

lxa85, Я думаю ты строг сильно, одно дело понимать что ищем, а другое дело, не знать и при этом искать ошибку. :)

lxa85 28-10-2009 22:02 1255148

Drongo, Habetdin, Ошибка логическая, поэтому я так сильно ругаюсь. Мы до Паскаля еще не дошли.
Скобки в данном случае не причем. Ну причем конечно, но не в них дело.
Кстати я бы их оставил, они погоды не сделают, но и не помешают.
В ниже написанное углубляться не следует :)

(Паскаль есть выражение мысли в семантике языка.
Мысль -> Математика, логика -> Семантический перевод в язык программирования -> код Pascal)
Мысль - ясна
Мат., логика - присутствует ошибка. Ошибка. Однотипная 1ая и 2ая.
Семантический перевод в язык программирования - проблем нет.
код Pascal - ошибочен в силу ошибки в логике, но не в силу семантического перевода.

lxa85 29-10-2009 22:56 1256063

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

Из теоремы имеем:
A^2+B^2=C^2; (1)
sqrt(A^2+B^2) = C; (2)
Что имеем :
x*x+y*y < r2; -> X^2 + Y^2 = R2 (3)
Проводим аналогию формулы 3 и 1, разницу видишь? Вот она ошибка. У тебя была правильная попытка ввести квадратный корень, но затем он потерялся.
Самым элегантным, по моему, решением является возведение R2 в квадрат.
if ((x*x+y*y< r2*r2 ) and (x*x+y*y> r1*r1)) then k:=k+1;

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

Неверное условие началось с 7ого сообщения от участника emTPy.
Цитата:

Цитата emTPy
for i:=-r2 to r2 do
for j:=-r2 to r2 do
if ((i*i+j*j<r2) and(i*i+j*j>r1)) then rez:=rez+1; »

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

Habetdin, не в обиду, но на будущее. Внимательно смотри, что ты копируешь!
Успехов! :)

P.S. emTPy, простите, если задел.

Habetdin 10-11-2009 11:04 1266446

Вот что получилось, работает:
Код:

program Park;
var r1,r2,x,y,n: integer;
l:real;
begin
assign(input,'input.txt');
reset(input);
read(input,r1,r2);
close(input);
n:=0;
for x:=-r2 to r2 do begin
for y:=-r2 to r2 do begin
l:=sqrt(x*x+y*y);
if (l>r1) and (l<r2) then
n:=n+1;
end;
end;
assign(output,'output.txt');
rewrite(output);
write(output,n);
close(output);
end.

Вопрос: возможна ли оптимизация этого кода? :)

Upd: судя по незамеченному посту #23, оптимизация возможна..
:closed-to

emTPy 11-11-2009 22:46 1267944

оптимизация возможно если рассмотреть одну четверть полученный результат умножить на 4
и положительные части осей умножив результат осей на 2


Время: 16:02.

Время: 16:02.
© OSzone.net 2001-