На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Название темы должно быть информативным !
Прежде чем задать вопрос, воспользуйтесь Поиском. и проверьте в FAQ (ЧАВО) Паскаля
Чтобы получить вразумительный ответ, подробно опишите проблему: что надо сделать, что не получается и номер ошибки (если есть), которую выводит компилятор.
Для вставки кода ваших программ используйте, пожалуйста, кнопку СODE=pas или выпадающий список СODE для других языков (подсветка синтаксиса).
[!] Как правильно задавать вопросы | Руководство по языку B.Pascal 7 & Objects/LR | Borland Pascal. Руководство пользователя
Модераторы: volvo877
  
> Время и положение стрелок часов
    Please,people!!!


    Пусть даны целые числа h,m(часы,минуты),
    0<=h<=11, 0<=m<=59, определяющие время суток. Опредилить
    наименьшее время(число полных минут), к-е должно пройти
    до того момента,когда часовая и минутная стрелки
    на цферблате:
    а)совпадут;
    b)расположатся перпендикулярно друг другу;


                                              ВНИМАНИЕ!!!

    !!!МОЖНО ИСПОЛЬЗОВАТЬ ТОЛЬКО ОПЕРАТОР ПРИСВАИВАНИЯ И ВВОДА/ВЫВОДА!!!
    Сообщение отредактировано: vot -
      Теория такова:
      Представь себе циферблат с двумя стрелками.
      У каждой стрелки есть свой угол, в отношении с начальным положением (там где цифра 12).
      12    1
      |--/  
      |  /      2
      | /
      |/
      o

      И каждая стрелка с каждым тиком изменяют этот угол по разному:
      к примеру минутная стрелка изменяет угол с каждым движением на 360/60 градусов, а часовая на 360/12 градусов.
      В то-же время есть взаимоотношение, что каждый тик часовой стрелки, это 60 тиков минутной, тоесть в каждые 360/12 градусов часовой стрелки входит 360 градусов минутной (полный оборот или 60 тиков). Следовательно с каждым движением минутной стрелки на 360/60 градусов часовая стрелка делает движение на (360/12)/60 градусов.
      Посчитав всё это можно определить, что часовая стрелка изменяет своё положение на пол градуса в каждый тик минутной стрелки (за одну минуту).

      Рассмотрим теперь твою первую задачу:
      Пусть у нас даны исходный час - H и исходные минуты - M.
      Найдём такое количество минут - DeltaM, при добавлении которых исходному времени углы часовой и минутной стрелки совпали бы. Для этого составим следующее уравнение:
      0.5*(H*60+M+DeltaM)=6*(M+DeltaM)
      В этом уравнении нам неизвестна только искомая DeltaM. С левой стороны уравнения выражен угол часовой стрелки, посчитанный из общего количества минут умноженных на изменение угла часовой стрелки за каждую минуту. С правой стороны уравнения выражен угол минутной стрелки, без учёта часов, так как минутная стрелка совпадёт с часовой хотябы один раз за час (тоесть меньше чем за час).
      Теперь выразим из уравнения искомую DeltaM:
      Умножим обе стороны на 2:
      H*60+M+DeltaM=12*M+12*DeltaM
      Перенесём DeltaM в левую сторону уравнения, а всё остальное в правую:
      DeltaM-12*DeltaM=-H*60-M+12*M
      -11*DeltaM=-H*60+11*M
      Поменяем знаки уравнения:
      11*DeltaM=H*60-11*M
      Разделим обе части на 11:
      DeltaM=(H*60-11*M)/11
      DeltaM=H*60/11-M
      DeltaM и будет разницей между заданным временем, и временем, когда часовая и минутная стрелки совпадут.

      Рассмотрим теперь твою вторую задачу:
      В этой задаче у нас углы часовой и минутной стрелки должны отличаться на 90 градусов в любую сторону (минутная левее, или правее).
      Следовательно уравнение почти такое же, за исключением того, что надо учесть разницу в градусах в любую сторону:
      abs(6*(M+DeltaM)-0.5*(H*60+M+DeltaM))=90
      Здесь из угла минутной стрелки вычитается угол часовой, и разница по модулю должна быть равна 90 градусам.
      Как и в прошлый раз, умножим обе стороны на 2:
      abs(12*M+12*DeltaM-H*60-M-DeltaM)=180
      abs(11*DeltaM+11*M-H*60)=180
      Далее уравнение раскладывается на два пути:
      11*DeltaM+11*M-H*60=180  и  11*DeltaM+11*M-H*60=-180
      DeltaM=(180+H*60)/11-M  и  DeltaM=(H*60-180)/11-M
      Получится так, что решения должны совпасть, но быть различными в знаках (По моему, но я могу и ошибаться).
      Как эту задачу сделать без оператора условия я не знаю :)))
      Сообщение отредактировано: Some1 -
        А вот вариант как сделать задачку #2 без оперетора условия.
        Вникать, что там Some1 написал не охота, поэтому получаем код, на основе его рассуждений.
        ExpandedWrap disabled
          var result1,result2,result,m,h:longint;
          begin
          readln(h,m);
          result1:=(180+H*60)/11-M; {а может быть и так: result1:=abs((180+H*60)/11-M)};
          result2:=DeltaM=(H*60-180)/11-M; {аналогично}
          result:=result1*byte(result1<result2)+result2*byte(result2<=result1);
          writeln(result);
          end.

        Т.е. выражение byte(100<200) равно единице, а выражение byte(5<>5) равно нулю. Это и позволяет найти минимальное значение.
          Не, я так тоже делать умею, тока я не думаю, что у него препод такой зверь :)))
          Я как то своему в универе так "оптимизировал прогу" в 10 местах, он меня послал подальше с моими оптимизациями :)))) Пришлось переделывать.
          ИМХО - Должен быть другой способ, возможно я где-то ошибся или выбрал не тот метод :)))))
            Ну вы мужики понаписали!
            Что за байты у вас в выражениях? Ничего не понимаю!
            Объясните поподробнее что это за byte такой и с чем его едят!
              Byte -тип такой - целые числа от 0 до 255 - занимает 1 байт. А в данном случае используется приведение типа boolean к этому типу.
              Сообщение отредактировано: ozzy -
                Поясню полнее то, что сказал Ozzy:
                Вот смотри, когда ты пишешь
                if <чёнить> then <ченить ещё>
                то там, где <чёнить> ты всегда пишешь переменную типа boolean - тоесть условие.
                Любое условие в паскале рассматривается как переменная типа boolean.
                Этот тип может иметь только два значения -True или False.
                В первом случае условие - правда, а во втором случае - неправда.
                Вот пример:
                Если мы напишем (100<500) - то это правда. И следовательно паскаль воспримет всё это выражение как переменную типа boolean, равную true.
                Если мы теперь напишем if (100<500)=true then <Чёнить>, то наше условие выполнится, и выполнится <чёнить>
                А если написать if (100<500)=false then <Чёнить>, то мы получим расхождение, и условие не выполнится, и не выполнится наше <чёнить>.
                Теперь смотри дальше - внутренне в паскале тип Boolean занимает один байт в памяти, и является по сути байтом, у которого 0 - это неправда (False в паскале) и 1 - это правда (True в паскале).
                В паскале есть такое хорошее свойство - приведение типов, при помощи него можно узнать, чему равен байт переменной типа Boolean, если взять эту переменную в скобки и перед ней написать byte.
                byte(1<10) будет равен 1 так как 1 действительно меньше 10 и значит наш Boolean=True и в его байте содержится 1.
                byte(1>10) будет равен 0 так как 1>10 это неправда и значит наш Boolean=Falseи в его байте содержится 0.
                Если написать write(byte(100<500)) на экран выведется "1".
                Всё это удобно для использования условий прямо в операторах присваивания.
                Ведь если умножать на "0" то получится "0", а если умножать на "1" то получится то число, которое мы на "1" умножали :)))
                Смотри, тебе написали: result:=result1*byte(result1<result2)+result2*byte(result2<=result1);
                Если result1<result2 это правда, то первый byte будет равен 1, а второй 0, и тогда result1 будет умножен на 1, а result2 на 0, в результате чего он сократится, и result будет равен result1.
                Если же result1<result2 это неправда, то первый byte будет равен 0, а второй 1, и тогда result1 будет умножен на 0 и сократится, а result2 на 1 и result будет равен result2.
                Таким образом вся эта запись является аналогом такой:
                If (result1<result2)=true then result:=result1 else result:=result2;
                Сообщение отредактировано: Some1 -
                  Some1, большое тебе спасибо!
                  Теперь всё хорошо ясно!
                    Люди! Нашёл в задаче а ужасный баг( b пока не смотрел)!
                    В результате проги мы находим просто кол-во минут до времени ,
                    в к-е стрелки совпадут. Т.е. ответ в некоторых случаях получается отрицательным!
                    А нам надо найти кол-во минут до ближайшего момента когда стрелки совпадут, отсчитывая этот момент с заданного времени!
                    Люди у кого какие идеи? Может другой алгоритм предложите (хотя и этот хорош -
                    только где то, что-то нужно подправить)?
                      А почему ты в "Алгоритмы" не напишешь?

                      Текущее положение стрелок (будем считать по большим цифрам, т.е. значения = 0..12):
                      h = h mod 12
                      Hpos = h + m/60 - позиция часовой стрелки
                      Mpos = m/5 - позиция минутной стрелки

                      Теперь... если Mpos < Hpos, значит минутная стрелка находится раньше часовой (относительно 12 часов), и они совпадут в этом часе. Если же Mpos > Hpos, значит позже, и они совпадут в следующем часе.
                      [*] В первом случае:
                      h + m/60 = m/5
                      h = m*11/60

                      Msovpadut = h*60/11
                      Minterval = Msovpadut - m

                      [*] Во втором случае:
                      h = (h + 1) mod 12
                      h + m/60 = m/5
                      h = m*11/60

                      Msovpadut = h*60/11
                      Minterval = 60 + Msovpadut - m


                      Это теория... попробуй...
                      (то, что синим прогать не надо - это вывод формулы :))
                      Сообщение отредактировано: 7in -
                        Во! Вроде работает! ;D

                        ExpandedWrap disabled
                          Var
                             h, m: Integer;
                             Hpos, Mpos, Msovp, Mint: Real;
                           
                          Begin
                             Write('Введите Часы Минуты: ');
                             ReadLn(h, m);
                             h := h mod 12;
                             Hpos := h + m/60;
                             Mpos := m/5;
                             If Mpos < Hpos then
                             Begin
                                Msovp := h*60/11;
                                Mint := Msovp - m
                             End
                             else If Mpos > Hpos then
                             Begin
                                h := (h + 1) mod 12;
                                Msovp := h*60/11;
                                Mint := 60 + Msovp - m
                             End;
                             WriteLn('Через ', Trunc(Mint), ' минут ', Trunc(Frac(Mint)*60), ' секунд')
                          End.
                          To Jin-X: Жека, прочитай внимательно последнюю строку условия (первого поста) :)))
                          To .exe: Ты часом условие не подправлял ? :)) А то мне кажется, там писалось, что надо найти время (без "которое должно пройти") до совпадения стрелок, кажется автоматически подумал, что не важно, в какую сторону время считать :)))
                          Короче тогда делай, как сказал Jin-X :))
                          З.Ы. Жек, у тебя точно правильно ? А какой наименьший шаг у твоей часовой стрелки?? Не размером ли с пять минут ?... я что-то сегодня не очень соображаю :))) (ну в смысле у тебя не берётся за правило, что часовая стрелка делает одно движение в пять минут, и исходя из этого высчитывается угол ?) Я могу ошибаться :)
                            Нет, не в 5 минут... Если она на 13 минутах, то будет 2.6 :)
                            Ну если учесть последнюю строку условия, тогда так:

                            ExpandedWrap disabled
                              Var
                                 h, m: Integer;
                                 Hpos, Mpos, Msovp, Mint: Real;
                                 After: Boolean;
                               
                              Begin
                                 Write('Введите Часы Минуты: ');
                                 ReadLn(h, m);
                                 h := h mod 12;
                                 Hpos := h + m/60;
                                 Mpos := m/5;
                                 After := Mpos > Hpos;
                                 h := (h + Ord(After)) mod 12;
                                 Msovp := h*60/11;
                                 Mint := 60*Ord(After) + Msovp - m;
                                 WriteLn('Через ', Trunc(Mint), ' минут ', Trunc(Frac(Mint)*60), ' секунд')
                              End.

                            P.S. Что, собственно, однохренственно ;D
                              Мужики, я уж извиняюсь, но  как эту задачу можно сделать, если мало того, что оператор условия не дают использовать, так ещё и булевские переменные не разрешают?
                                Ужас.......
                                А промежуточные булевские можно ?
                                Ну без объявления самой переменной, ну как у меня выше..
                                я не объявлял булевскую, а только в присваиваниях писал булевское условие. Это тоже нельзя ?
                                  Ну хорошо!!!

                                  ExpandedWrap disabled
                                    Var
                                       h, m: Integer;
                                       Hpos, Mpos, Msovp, Mint: Real;
                                     
                                    Begin
                                       Write('Введите Часы Минуты: ');
                                       ReadLn(h, m);
                                       h := h mod 12;
                                       Hpos := h + m/60;
                                       Mpos := m/5;
                                       h := (h + Ord(Mpos > Hpos)) mod 12;
                                       Msovp := h*60/11;
                                       Mint := 60*Ord(Mpos > Hpos) + Msovp - m;
                                       WriteLn('Через ', Trunc(Mint), ' минут ', Trunc(Frac(Mint)*60), ' секунд')
                                    End.

                                  Булевских переменных нет!
                                  (есть только булевские выражения, но это же не переменные) ;D
                                    Сформулировал не полностью - булевские выражения тоже низззя !!!! ???
                                      Наверное, что-то вроде этого:
                                      ExpandedWrap disabled
                                        program clock1;
                                        var
                                         h,m,s,t:integer;
                                        begin
                                         readln(h,m);
                                         s:=((m-5*h-(m div 12)) div abs(m-5*h-(m div 12))+1) div 2;  (* s=0, если минутная стрелка
                                         позади часовой, иначе s=1 *)
                                         t:=(60-m)*s;
                                         h:=h+s;
                                         m:=m*(1-s);
                                         t:=t+5*h-m+(h-1) div 2;
                                         writeln(t);
                                        end.
                                        А лучше - вроде этого:
                                        ExpandedWrap disabled
                                          program clock2;
                                          var
                                           h,m,s,t:integer;
                                          begin
                                           readln(h,m);
                                           t:=5*h-m+(h-1) div 2;
                                           s:=((t div abs(t))+1) div 2;
                                           t:=t+65*(1-s);
                                           writeln(t);
                                          end.
                                          Кто-нибудь, пож-ста, поясните последнее решение!
                                            to exe смотри вроде так
                                            ExpandedWrap disabled
                                              programm cl;
                                              var
                                              z,j,h,m:integer;
                                              begin
                                              readln(h,m);
                                              j:=h*5 div m;
                                              if j=0 then
                                              writeln('Svpodaet');
                                              if m:=h*5+30 then
                                              writeln('perpendikylarni!');
                                              end.
                                              извини я условие мельком прочитал!!!
                                              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                              0 пользователей:


                                              Рейтинг@Mail.ru
                                              [ Script execution time: 0,0921 ]   [ 15 queries used ]   [ Generated: 9.12.24, 13:22 GMT ]