Из упорядоченного массива случайный
Первое число упорядоченного массива меняем со случайным числом следующим за ним, т.е. от 2 до n-го, второе число меняем с числом из диапазона 3, n и т.д.
Входные данные: 1 2 3 4 5 6 7 8 9 10
Выходные данные: 2 4 1 10 7 3 9 6 8 5
Program RandomArray; Uses CRT; Const n=10; Type a_type=array [1..n] of integer; Var a:a_type; m,x,i:integer; Begin ClrScr; randomize; {исходный массив} for i:=1 to n do a[i]:=i; for i:=1 to n do write(a[i]:3); writeln; for i:=1 to n-1 do begin {случайное число из диапазона i+1,n} m:=random(n-i-1)+i+1; {обмен i и m числа массива } x:=a[i]; a[i]:=a[m]; a[m]:=x end; for i:=1 to n do write(a[i]:3); readln End.
Самая длинная подпоследовательность в последовательности
В последовательности 0 и 1 найти длину самой длинной подпоследовательности 0, индекс ее начала и индекс ее конца. Длина последовательности задана.
Входные данные: n=10. 0 1 0 0 0 0 1 0 0 0
Выходные данные: 4 3 6
Program Sequence; Uses CRT; Const n=10; Var x:array [1..n] of integer; i,max,k,s:integer; Begin ClrScr; for i:=1 to n do begin {ввод и проверка данных} repeat write(i,' '); readln(x[i]); until (x[i]=0) or (x[i]=1); end; {вывод исходной последовательности} for i:=1 to n do write(x[i]); writeln; s:=0; max:=0; for i:=1 to n do if x[i]=0 then inc(s) else if s>max then begin max:=s; k:=i-1; s:=0 end; {Если самая длинная одпоследовательность в конце последовательности} if s>max then begin max:=s; k:=n end; {вывод результата} writeln(max,' ',k-max+1,' ',k); readln End.
Несколько календарных задач
Високосный год
Продолжительность тропического года (время между двумя весенними равноденствиями) составляет 365 суток 5 часов 48 минут 46 секунд. Различие в продолжительности тропического года и среднего юлианского календарного года (365,25 суток) составляет 11 минут 14 секунд. Из этих 11 минут и 14 секунд приблизительно за 128 лет складываются одни сутки.
По истечении столетий было замечено смещение дня весеннего равноденствия, с которым связаны церковные праздники. К XVI веку весеннее равноденствие наступало примерно на 10 суток раньше 21 марта, используемого для определения дня Пасхи.
Чтобы компенсировать накопившуюся ошибку и избежать подобного смещения в будущем, в 1582 году римский папа Григорий XIII провёл реформу календаря. Чтобы средний календарный год лучше соответствовал солнечному, было решено изменить правило високосных лет. По-прежнему високосным оставался год, номер которого кратен четырём, но исключение делалось для тех, которые были кратны 100. Отныне такие годы были високосными только тогда, когда делились ещё и на 400.
Иными словами, год является високосным, если он кратен 4 и при этом не кратен 100, либо кратен 400. Год не является високосным, если он не кратен 4, либо кратен 4, но при этом кратен 100 и не кратен 40 [1].
Отсюда функция опредляющая является ли год високосным или обычным:
Function LeapYear(y:integer):boolean; Begin if y mod 400 =0 then if y mod 100=0 then LeapYear:=true else LeapYear:=false else if y mod 4 =0 then LeapYear:=true else LeapYear:=false End;
Количество дней от 1 января 1 года
Хотя григорианский календарь был введен 1582 г., а в некторых странах гораздо позднее, например в СССР в 1918 г., условно будем считать, что он действует с 1 января 1 года. Тогда число дней прошедших с этого дня до данной даты (D.M.Y) определяется так: меняем параметр i от 1 до Y-1, если i соответсвует обычному году, то в переменную s прибавляем 365, если - високосному, то в s прибавляем 366. Далее меняем параметр i от 1 до M-1, в s прибавляем число дней в месяцах (с учетом является ли Y високосным или обычным годом). Наконец в s прибавляем число D.
Program TaskCalendar; Uses CRT; Type date=record day,month,year:integer; end; Const dmm:array [1..12] of integer =(31,28,31,30,31,30,31,31,30, 31,30,31); Function NumberOfDays(yy:date):longint; Var y,i:integer; s:longint; Begin s:=0; for y:=1 to yy.year-1 do if (LeapYear(y)) then s:=s+366 else s:=s+365; for i:=1 to yy.month-1 do if (LeapYear(yy.year)) and (i=2) then s:=s+29 else s:=s+dmm[i]; s:=s+yy.day; NumberOfDays:=s End;
Олимпиадная задача
В сборнике олимпиадных задач, опубликованных А.С. Пономаренко в приложении к журналу «Информатика в школе», представлена следующая задача [2]:
Составить программу, которая определит все годы до 100 - летнего юбелея, когда вы будете праздновать день своего рождения в тот же день недели, когда родились.
Если бы не было вискосных лет, то календарь повторялся бы каждые 7 лет, так как остаток от деления 365 на 7 равен 1. Если в этом году некая дата приходится на среду, то в следующем году она придется на четверг, на среду огна придется через 7 лет. Наличие високосных лет приводит к тому, что календарь полностью повторяется через каждые 7*4=28 лет.
Используем тот факт, что 01.01.01 было воскресеньем. Для кадого дня 100 - летнего периода будем определять число дней прошедших с 01.01.01, далее будем определять остаток от деления прошедших числа дней на 7, если этот остаток 1- то данный день - воскресенье, если 2, то понедельник и т.д., если остаток 0 - то данный день - суббота. Применим введенные нами функции.
Program TaskCalendar1; Uses CRT; Type date=record day,month,year:integer; end; dw=array[0..6] of string[3]; Var d,d1:date; i,k,j:integer; Const dww:array [0..6] of string[3]= ('Sat','Sun','Mon','Tue','Wen', Thu','Fri'); dmm:array [1..12] of integer= (31,28,31,30,31,30,31,31,30, 31,30,31);
Function LeapYear(y:integer):boolean; Begin if y mod 400 =0 then if y mod 100=0 then LeapYear:=true else LeapYear:=false else if y mod 4 =0 then LeapYear:=true else LeapYear:=false End;
Function NumberOfDays(yy:date):longint; Var y,i:integer; s:longint; Begin s:=0; for y:=1 to yy.year-1 do if (LeapYear(y)) then s:=s+366 else s:=s+365; for i:=1 to yy.month-1 do if (LeapYear(yy.year)) and (i=2) then s:=s+29 else s:=s+dmm[i]; s:=s+yy.day; NumberOfDays:=s End;
Begin ClrScr; write('day ='); readln(d.day); write('month='); readln(d.month); write('year ='); readln(d.year); k:=NumberOfDays(d) mod 7; yy:=d.year; d1:=d; for i:=d.year to d.year+100 do begin d1.year:=i; j:=NumberOfDays(d1) mod 7; if k=j then writeln(i:6,' ',dww[j]); end; readln; End.
Определение даты по числу дней от 1 января 1 года
Задачу можно представить как введение функции обратной NumberOfDays. Однако, мы введем процедуру, которая по количесву дней с 1 января 1 г. вычисляет дату.
Сначала из числа дней y будем вычитать 365/366 дней и считать число лет d.year пока не получим отрицательное число, прибавим к нему последнее вычитаемое и число лет уменьшим на 1. Если оставшееся число дней y будет меньше 31, то сразу выводим month=1 и y. Если это не так, то начинаем счет месяцев, вычитая из y число дней в месяце. Если в процессе счета полцчим month=13, то присвоим month значение 1. Счет месяцев будем вести до тех пор пока y остается больше 0. Скорректируем y на число дней в последнем месяце, а число месяцев уменьшим на 1. Если при этом month примет значение 0, то назначим ему значение 12.
Procedure DateN(y:longint; var d:date); Var dy:integer; Begin with d do begin year:=1; {счет числа лет} repeat if (LeapYear(year)) then dy:=366 else dy:=365; y:=y-dy; year:=year+1 until (y<=0); {корректировка числа лет} y:=y+dy; year:=year-1; {счет числа месяцев} month:=1; if y>31 then begin repeat if (LeapYear(year)) and (month=2) then dy:=29 else dy:=dmm[month]; y:=y-dy; month:=month+1; if month>12 then month:=1; until (y<=0); {корректировка числа месяцев} y:=y+dy; month:=month-1; if month=0 then month:=12; end; d.day:=y end; End;
Пятницы 13
Для данного года определим пятницы 13. Применим введенные нами функции.
Program TaskCalendar2; Uses CRT; Type date=record day,month,year:integer; end; dw=array[0..6] of string[3]; Var d:date; yb,ye,i:longint; k:integer; ........................ Begin ClrScr; with d do begin write('year ='); readln(year); day:=1; month:=1; yb:=NumberOfDays(d); if (LeapYear(year)) then ye:=yb+366 else ye:=yb+365; for i:=yb to ye do begin DateN(i,d); {день недели } k:=i mod 7; {если этот остаток =6, то это Fri} if (k=6) and (day=13) then writeln(13,' ',month,' Fri'); end; end; readln; End.
Пасхалии
По заданному номеру года определить дату Пасхи по григорианскому календарю.
Пасхалия, сборник правил, на основании которых определяется день празднования пасхи. Поскольку эти правила требуют выполнения определённых условий, связанных с движением Земли вокруг Солнца (пасха должна быть вскоре после весеннего равноденствия), обращением Луны вокруг Земли (связь пасхи с полнолунием), с семидневной неделей (воскресенье), даты празднования пасхи непостоянны и перемещаются от года к году. Вследствие неидентичности правил П. разных религий, дни празднования пасхи у них не совпадают. Математическую теорию П. разработал К. Гаусс [3,4].
Program Easter; Uses CRT; Var g,y,i,j,l,month,day:integer; Begin ClrScr; write('год='); readln(y); g:=y mod 19; i:=(g*19+15) mod 30; j:=(y+y div 4+i) mod 7; l:=i-j; month:=3+(l+40) div 44; day:=l+28-31*(month div 4); day:=day+13; if day>31 then begin day:=day-31; month:=month+1; end; writeln('пасха ',day,' ',month); writeln('----------------------------------'); readln End.
Источники:
1. Википедия. Високосный год
2. Информатика в школе: Приложение к журналу «Информатика и образование. №1 - 2006. -M.: Образование и информатика, 2006. - 112 с.
3. БСЭ. Пасхалии.
4. Малаховскй В.С. Введение в математику. - Калининград: Янтарный сказ, 2006. - 439 с.
<