Глава 19. Решение локальных задач.

Глава 19
Решение локальных задач

  Расписание занятий

Предположим, что занятия в некотором учебном заведении начинаются по мере комплектования групп. В анкете заполняется дата начала и конца работы группы. Для проведения занятий по определенной дисциплине выбирается день недели. Требуется написать сценарий, который формирует расписание занятий.

После того как пользователь заполнил поля формы (рис. 19.1), указав дату начала и окончания занятий группы и день недели для проведения занятий по некоторой дисциплине, определяется дата первого занятия.

Рис 19.1. Расписание занятий

Предположим, группа начинает работу 15 февраля 2001 года (четверг), а занятия по заданной дисциплине должны проводиться по средам. Дата первого занятия — 21 февраля. Далее формируется дата следующего занятия и проверяется, попадает ли сформированная дата в интервал времени, определенный для занятий, т. е. предшествует ли текущая дата дате окончания курсов. Далее формируется очередная строка таблицы расписания. Расписание представляется в виде таблицы. Сначала в строковой переменной si формируется заголовок таблицы. Дата очередного занятия представляет строку таблицы. В таблице будет столько строк, сколько занятий требуется провести с данной группой. Дата очередного занятия формируется в строке scur. После анализа дат построение таблицы завершается. В сценарии используются массивы ident для хранения названий месяцев и iday для хранения названий дней. В строке s формируется таблица с расписанием. HTML-код, содержащий сценарий построения расписания, приведен в листинге 19.1.

Листинг 19.1. Формирование расписания занятий

<HTML>

<HEAD>

<TITLE>Расписание занятий</TITLE>

<script language="JavaScript"> 

<!-- //

// Формирование по номеру названия месяца

var ident=new Array ("январь ", "февраль ", "март ",

"апрель", "май", "июнь", "июль", "август", 

"сентябрь", "октябрь", "ноябрь", "декабрь")

var iday =new Array ("воскресенье", "понедельник", "вторник", 

"среда", "четверг", "пятница", "суббота") 

// Формирование расписания занятий 

function rasp(obj) 

{ // Дата начала занятий

var d= new Date (obj.begy.value, obj.begm.value, obj.begd.value) 

// Дата окончания занятий

var w= new Date (obj.endy.value, obj.endm.value, obj.endd.value) 

// дата текущего занятия

var t= new Date (obj.begy.value, obj.begm.value, obj.begd.value)

var s=""

var n=obj.dt.value // Выбранный для занятия день недели

var k=d.getDate()+Number(n)- Number(d.getDay())

if (n < d.getDayO )

k += 7

// Определения даты первого занятия

t.setDate(k)

// Формирование заголовка таблицы

var si = "<h4 align=center>Расписание занятий</h4>"

s1+="предмет <i><b>"+obj.predmet.value+" </b></i><br>"

s1+="<i>день занятий <b>" +iday [Number (n) ]+"</b></i>"

var sHEAD="<TABLE align=center border=3 bgcolor='#FFFFCC' 

cellpadding=3 cellspacing=5>"+ "<TR><th>число </th><th>месяц 

</th><th>год </th></TR>"

document.write(sHEAD)

var scur

var s=s1

// Поиск дат занятий

while (t.getYear () <=w.getYear ())

{ // Формирование текущей строки таблицы расписания

scur="<TR align=center><TD>"+ t.getDate ()+"</TDXTD>"+ 

ident[ t.getMonth ()]+ 

"</TD><TD>"+t.getYear () +"</TD></TR>" 

if (t.getYear () < w.getYear ())

{ s+= scur }

else

{ if (t.getMonth() < w. getMonth ())

{ s +=scur }

else

{ if (t.getMonth() == w. getMonth ())

{ if (t.getDate()<w.getDate())

{ s+=scur }

else

( if (t.getDate()==w.getDate())

{ s+= scur; break }

}

}

}

}

k=t.getDate()+7

t.setDate(k)

}

if (s==s1)

alert ("Проверьте даты начала и конца занятий")

else

document.write(s+"</TABLE>")

}

//-—>

</script>

</HEAD>

<BODY>

<H4 align=center>Фopмиpoвaниe расписания занятий</Н4>

<FORM name="form1">

<TABLE border=3 align=center cellpadding=3 cellspacing=5>

<TR><th>Haчало курсов</th><th>Конец курсов</th></TR>

<TR><TD>

<pre>

число <input type="text" name="begd" size=10>

месяц <select name="begm" size=l>

<option value=0>январь

<option value=l>фeвpaль

<option value=2>март

<option value=3>апрель

<option value=4>май

<option value=5>июнь

<option value=6>июль

<option value=7>август

<option value=8>сентябрь

<option value=9>октябрь

<option value=10>ноябрь

<option value=ll>декабрь

</select>

год <input type="text" name="begy" size=10 value=2001> 

</pre></TD>

<TD>

<pre>

число <input type="text" name="endd" size=10>

месяц <select name="endm" size=1>

<option value=0>январь

<option value=1>фквраль

<option value=2>март

<option value=3>aпpeль

<option value=4>май

<option value=5>июнь

<option value=6>июль

<option value=7>август

<option value=8>сентябрь

<option value=9>октябрь

<option value=10>ноябрь

<option value=ll>декабрь

</select>

год <input type="text" name="endy" size=10 value=2001> 

</pre></TD></TR>

<ТR><TD>предмет</TD>

<TD align=right>

<input type="text" name="predmet" size=14

value=инфopмaтикa></TD></TR>

<TR><TD>день занятий</TD>

<TD align=right>

<select name= dt size=l>

<option value=0>воскресенье

<option value=l selected>понедельник

<option value=2>вторник

<option value=3>среда

<option value=4>четверг

<option value=5>пятница

<option value=6>суббота

</select>

</TD></TR>

<TR><TD align=left>

<input type="button" value="Сформировать"

onClick="rasp (form1)"><br>

</TD>

<TD align=right>

<input type="reset" value=" Отменить "> 

</TD>

</TR>

</TABLE>

</FORM>

</BODY>

</HTML>

Для исходных данных, представленных в анкете (рис. 19.1), в результате выполнения сценария будет сформирована таблица (рис. 19.2).

Рис 19.2. Пример сформированного расписания занятий

  

Ведомость проведения занятий

Напишем сценарий, в результате работы которого формируется ведомость проведения занятий. Пользователь в анкете задает дату начала и окончания семестра, выбирает день проведения занятий, может указать дисциплину, количество студентов в группе и номер группы. Ведомость представляет собой таблицу, в заголовке которой предусмотрены поля: номер записи, фамилия студента, даты проведения занятий, отметка о зачете.

В этой задаче в отличие от предыдущей динамически формируются сначала столбцы таблицы в зависимости от продолжительности семестра. Далее будут сформированы строки таблицы. В каждой строке должна располагаться информация об одном студенте.

Вычисление даты очередного занятия происходит так, как и в предыдущей задаче.

Анкета для заполнения представлена на рис. 19.3.

Приведем только сценарий решения задачи, необходимые пояснения содержаться в тексте (листинг 19.2).

Рис 19.3. Формирование ведомости

Листинг 19.2. Формирование ведомости проведения занятий

<script language="JavaScript">

<!—- //

var iday =new Array("воскресенье", "понедельник", "вторник", "среда", 

"четверг", "пятница", "суббота")

// Формирование ведомости проведения занятий

function rasp(obj)

{ // Дата начала занятий

var d= new Date.(obj.begy.value, obj.begm.value, obj.begd.value)

// Дата окончания занятий

var w= new Date(obj.endy.value, obj.endm.value, obj.endd.value)

// Дата текущего занятия

var t= new Date(obj.begy.value, obj.begm.value, obj.begd.value) 

var s=""

var n=Number(obj.dt.value) // Выбранньй для занятия день недели

var nn=Number(obj.numst.value)

var k=d.getDate()+Number(n)- Number(d.getDay())

if (n < d.getDay())

k += 7

// Определения даты первого занятия 

t.setDate(k)

// Формирование заголовка таблицы

var s1 = "<h4 align=center>Ведомость проведения занятий</h4>" 

s1+="<р>дисциплина<i><b> "+obj .predmet .value+"</b></i></p>" 

s1+="<р><i>номер группы </i><b> "+obj .numgr .value+"</b></p>" 

s1+="<i>день занятий "+"<b>"+iday[Number(n)]+"</b></i>" 

var sHEAD="<TABLE align=center border=3 bgcolor='#FFFFCC'"+ 

" cellpadding=3 cellspacing=0>"+ 

"<TR><th>нoмep</th><th>фaмилия</th>" 

document.write(sHEAD) 

var scur 

var s=s1 

var num=0

// Поиск дат занятий 

while (t.getYear() <= w.getYear()) 

{ // Формирование текущей даты проведения занятий 

var mon= t.getMonth ()+1 

var temp=((mon<10) ? ".0" :".")+mon 

scur="<th>"+ t.getDate ()+temp+"</th>" 

if (t.getYear() < w. getYear (}}

{ s+= scur -r num+=l} 

else 

{ if (t.getMonth() < w.getMonth(})

{s +=scur; num+=l} 

else

(if (t.getMonth() == w. getMonth ()) 

{ if (t.getDate()<w.getDate())

(s +=scur; num+=l) 

else

{if (t.getDate()==w.getDate())

{s+= scur; num+=l; break } 

}

k=t.getDate()+7 

t.setDate(k) 

}

if (s==s1)

alert ("Проверьте даты начала и конца занятий") 

else

{ s+="<th>отметка о зачете</th></TR>" 

var sn=""

for (var i=l; i<=nn; i++)

{sn="<TRXTD>"+i+"</TD>"+"<TD> &nbsp </TD>" 

for (var j=l; j<=num+l; j++)

{sn+="<TD> &nbsp</TD>"} 

sn+="</TR>" 

s+=sn

}

s+="</TABLE>" 

document.write(s)

document.write("<p align=center>4ncno занятий в семестpe

<b>"+num+"</b></p>")

}

//-—>

</script>

Рис 19.4. Пример сформированной ведомости

По тем данным, которые представлены в анкете на рис. 19.3, будет сформирована ведомость, вид которой представлен на рис. 19.4. После формирования таблицы будет указано число занятий в заданном семестре.

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

  Ближайший праздник

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

На рис. 19.5 приведен пример работы сценария.

Рис 19.5. Формирование календаря событий

Кроме сообщения о праздничных датах выводится календарь, в календаре день, в который запускается сценарий, выделен цветом.

HTML-код приведен в листинге 19.3.

Листинг 19.3. Количество дней до ближайшего праздника: формирование календаря 

<HTML>

<НЕАD>

<TITLE>Календать событий. Raskin A.</TITLE>

</HEAD> 

<BODY bgcolor="#F8F8FF" text="#000000"> 

<CENTER>

<IMG align=center SRC="buket.gif" width=164 height=164> 

<Script Language="JavaScript"> 

<!-—

// Переменные для хранения цвета различных элементов таблицы 

var cToday="bgcolor='#BBEEFF'" 

var cEmpty="bgcolor='#OOCCFF'" 

var cDay="bgcolor= '#OOCCFF'" 

var cCap="bgcolor= '#FFAOAO'" 

var cTABLE="bgcolor='#DODODO'" 

// Празничный день 

var HolidayDay 

var HolidayMonth 

var HolidayName 

var Left 

// Приветствие 

var Congrate 

// Текущая дата 

var today=new Date() 

var Mon=today.getMonth()+1 

var Day=today.getDate() 

var currDay=today.getDate() 

var currMonth=today.getMonth() 

var currYear=today.getYear() 

var i

function array(mO,ml,m2,m3,m4,m5,m6,m7,m8,m9,ml0,ml1) 

{this[0]=m0; this[l]=ml; this[2]=m2; this[3]=m3; 

this[4]=m4; this[5]=m5; this[6]=m6; this[7]=m7; 

this[8]=m8; this[9]=m9; this[10]=mlO; this[ll]=mll; 

var monames=new array("Январь","Февраль","Март","Апрель","Май",

"Июнь","Июль","Август","Сентябрь", 

"Октябрь","Ноябрь","Декабрь") 

// Количество дней в каждом месяце

var days=new array(31,28,31,30,31,30,31,31,30,31,30,31); 

function rDay(ptoday) 

( var vDay=ptoday,getDay(); 

vDay=vDay-l; 

if (vDay==-l) vDay=6 

return vDay 

}

//Формирование приветствия 

function GetHol()

{ var HolMonth=new Array(1,1 ,2 ,3 , 4, 5, 5, 6,6, 9,11,12); 

var HolDays= new Array(7,13,23,8 , 1, 1, 9, 1,12, 1, 7,31); 

var HolNames= new Array("Рождества","Старого Нового Года",

"23 Февраля",

"8 Марта","! Апреля — Дня Смеха", 

"1 Мая — Праздника Весны и Труда", 

"9 Мая - Дня Победы", 

"1 Июня — Дня Зашиты Детей", 

"12 Июня — Дня Независимости", 

"1 Сентября — Дня Знаний", 

"7 Ноября — Дня Примирения", 

"Нового Года"); 

var HolNow= new Array(" с Рождеством! ",

" с праздником <br>Старого Нового Года! ", 

" защитников Отечества <br>с праздником 23 Февраля!", 

" женщин <br>с праздником 8 Марта!", 

" с 1 Апреля <br> — Днем Смеха!", 

" с 1 Мая <br> — Праздником Весны и Труда!", 

" с 9 Мая <Ьг> — Днем Победы!", 

" с 1 Июня <br> — Днем Защиты Детей!", 

" с 12 Июня <br> — Днем Независимости России! ", 

" учащихся с 1 Сентября <br> — Днем Знаний! ", 

" с 7 Ноября <br> — Днем Примирения! ", 

" с Новым Годом! "); 

for(i=0; i<=HolMonth.length; i++) 

{ if (Mon<=HolMonth[i]) 

{ if (Mon==HolMonth[i])

{ if (Day<=HolDays[i])

{ HolidayDay=HolDays[i] 

HoiidayMonth=HolMonth[i] 

HolidayName=HolNames[i] 

Congrate=HolNow[i] 

Left=Ho1idayDay-Day break; 

}

else

{ HolidayDay=HolDays[i] 

HolidayMonth=HolMonth[i] 

HolidayName=HolNames[i] 

Congrate=HolNow[i] 

var HolDate=new Date(today.getYear(),

HolidayMonth-1,HolidayDay()

Left = Math. round ((HolDate. getTime()- 

today. getTime () ) / (24000 * 3600))

break; }

} } if (Left==0)

document.write("<пЗх!>Поздравляем всех "+Congrate+"</Ix/h3>") else document.write("<h3><I>flo "+HolidayName+"<br> осталось дней: "+

Left+" !</I></h3>") 

}

// Построение календаря 

function showCalendar(Month,Year)

{ document.write ("<B><I>"+monames [Month] +" "+Year+"</B><I>") 

firstDay=new Date(Year,Month,1) 

startDay=rDay(firstDay) 

if(((Year%4==0)&&(Year%100!=0))||(Year%400==0))

days[l]=29; 

else

days[1]=28; document.write("<TABLE "+CTABLE+

" CallSpacing=l CellPadding=l Border=l>");

document.write("<TR"+cCap+

"><th>Пн</th><th>Bт</th><th>Cp</th>"+"

<th>Чт</th><th>Пт</th><th>Сб</th><th>Bc</th></TR>") 

document.write("<TR align=Right>"); 

var column=0

for (1=0; i<startDay; i++) 

{ document.write("<TD ",cEmpty,">&nbsp</TD>");

column++; 

}

for (i=1; i<=days[Month]; i++) 

{ if((i==currDay)&&(Month=currMonth)&&(Year==currYear))

{ document.write("<TD ",cToday,">",i,"</TD>")} 

else 

{ document.write("<TD ",cDay,">","<b>"+i+"</B>","</TD>")

}

column++; 

if (column==7) 

{ document.write("</TR><TR align=Right>");

column=0; 

document, write ("</TR></TABLE>") 

}

//Today=new Date() 

GetHol();

showCalendar(today.getMonth(),today.getYear(}); 

//-—> 

</Script>

В календарь занесены основные праздники и поздравления к ним 

</BODY> 

</HTML>

  Латинский квадрат

Напишем сценарий построения латинского квадрата. В квадрате размером N х N в каждой из клеток требуется поставить одно из чисел 1, 2, ..., N так, чтобы сумма чисел, стоящих в каждом вертикальном, горизонтальном ряду и по диагонали, равнялась одному и тому же числу 1 + 2 + 3 +... + N.

Разобьем окно документа на две горизонтальные области с помощью фреймов. В верхней части поместим условие задачи и форму для ввода размера таблицы. При нажатии кнопки ОК в нижнем фрейме будет помещен документ, содержащий таблицу, представляющую собой латинский квадрат (рис. 19.6).

Рис 19.6. Латинский квадрат для N = 11

Для разбиения окна на две области требуется создать документ, описывающий фреймовую структуру. В данном случае документ имеет простую структуру и может быть задан, например, как в листинге 19.4.

Листинг 19.4. Фреймовая структура для задачи ; "Построение латинского квадрата"

<HTML> 

<HEAD>

<TITLE>Построение латинского квадрата</TITLE>

</HEAD>

<frameset ROWS="35%, *">

<frame name="lattab" SRC="formtab.html">

<frame name="bottom"> 

</frameset> 

</HTML>

Таблица формируется по строкам. Элемент, который заносится в таблицу с /-ым номером строки и у-ым номером столбца, определяется по формуле Math.round(Number{(j+k-i+3*n-i)%n+1)), причем значение k зависит от того, четное или нечетное заданное значение п. При переходе к формированию следующей строки происходит как бы циклический сдвиг предыдущей. Переменная out предназначена для работы с документом, который загружается в нижний фрейм, это обеспечивается выполнением присваивания out = top.frames['bottom'].document. Применением к out Метода close () закрывается поток вывода в документ. Метод open () открывает поток вывода в документ. Далее в сценарии формируются элементы таблицы с помощью методов write () и writeln (), например, так

out.writeln('<BODY bgcolor=silver><CENTER>')

Полностью HTML- код документа приведен в листинге 19.5.

Листинг 19.5. Построение латинского квадрата

<HTML> 

<HEAD>

<TITLE>Латинский квадрат</TITLE> 

<script language="Javascript"> 

<!--//

function solvetab()

{ var n = Number(document.forms['form1'].num.value); 

var k 

if (n%2==0)

k= Number(n/2) 

else

k= Number((n+1)/2);

var out = top.frames['bottom'].document; 

out. close()

out.open()

out.writeln('<BODY bgcolor=silver><CENTER>'); 

out.writeln('<TABLE bgcolor=white COLS='+n+' ROWS='+n+

' border=3>'); 

for (i=0; i<n; i++) 

{ out.writeln('<TR>'); 

for (j=0; j<n; j++) 

{ out.writeln('<TD> '+Math.round(Number((j+k-i+3*n-l)%n+l))+

 ' ')}

out.writeln('</TR>'); 

}

out.write('</TABLE>'); 

out.writeln('</CENTER><BODY>') ; 

}

—->

</script> 

</HEAD> 

<BODY>

<i>3адание на построение латинского квадрата</i><br> 

В квадрате размером NxN в каждой из клеток требуется поставить 

одно из чисел 1, 2, ..., N так, чтобы сумма чисел в любой строке, 

столбце и диагонали равнялась одному и тому же числу 1+2+...+N.<br> 

<FORM name="form1">

Введите N: <input name="num" TYPE="text" size=4> 

<input TYPE="button'\value=" OK " onclick="solvetab()"> 

</FORM> 

</BODY> 

</HTML>

  Упражнения

1. Задаются две литеры — латинская буква (от а до К) и цифра (от 1 до 8). Рассматривая их как координаты поля шахматной доски, на которой находится выбранная пользователем фигура, напишите сценарий построения шахматной доски с выбранной фигурой. Требуется указать все поля, которые "бьет" данная фигура.

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

Пользователь должен иметь возможность переставлять фигуры на доске, указывая координаты начала и конца хода.

3. Пользователь на шахматной доске расставляет два ферзя. Укажите поля, на которые может пойти белый ферзь, чтобы не попасть под удар черного. В сценарии предусмотрите случай, когда пользователь может произвольно выбрать две фигуры и расставить их на шахматной доске.

4. У белых на доске только король, у черных — король, конь, слон. Напишите сценарий, который осуществляет расстановку фигур на доске и при анализе ситуации характеризует положение белых с помощью слов "мат", "шах", "пат", "обычная позиция".

5. Напишите сценарий, который расставляет на шахматной доске 8 ладей так, чтобы ни одна из них не угрожала другой.

6. Напишите сценарий, который расставляет на шахматной доске 8 ферзей так, чтобы ни один из них не угрожал цругому.

7. Напишите сценарий, который по заданному расположению одного ферзя расставит еще 7 так, чтобы ни один из них не угрожал другому. Если пользователь первого ферзя поставил на поле A3, то следующие фигуры будут расставлены.

8. Напишите сценарий, который выводит изображение шахматной доски с указанием порядка ходов, которые необходимо сделать коню для того, чтобы обойти все клетки доски, побывав в каждой из них только один раз. Пользователь может задать начальную позицию коня.

9. Напишите сценарий, который расставляет на шахматной доске 12 коней, таким образом, что каждое поле шахматной доски находится под ударом одного из коней.

10. Напишите сценарий, определяющий такую расстановку 5 ферзей, при которой каждое поле будет находиться под ударом одного из них.

11. Напишите сценарий, определяющий такую расстановку 8 слонов, при которой каждое поле будет находиться под ударом одного из них.

12. Напишите сценарий, при работе которого устанавливается начальная комбинация при игре в шашки, либо подготавливается собственная. При этом пользователю предоставляется возможность выбрать шашки и установить их на соответствующее поле доски. Доска должна иметь стандартную нумерацию и раскраску.

13. Лабиринт задается прямоугольной матрицей с целыми значениями. Разрешается сделать ход только вниз или вправо на клетку с большим значением. Определите, существует ли путь в лабиринте от клетки левого верхнего конца к правому нижнему. Напишите сценарий, который рисует лабиринт и найденный путь.

14. Лабиринт задается прямоугольной матрицей с целыми значениями. Разрешается сделать ход только вниз или вправо на клетку с большим значением. Определите, существует ли путь в лабиринте от заданного пользователем входа до заданного выхода. Напишите сценарий, который рисует лабиринт и найденный путь.

15. Лабиринт задается прямоугольной матрицей с целыми значениями. Разрешается сделать ход по любому из 4-х направлений на клетку с большим значением. Напишите сценарий, определяющий, существует ли путь в лабиринте. Требуется нарисовать лабиринт и путь, найденный в нем.

16. Магическим квадратом порядка п называется квадратная таблица размера п х п, составленная из чисел 1, 2, ..., п2 так, что суммы по каждому столбцу, каждой строке и каждой из двух диагоналей равны между собой. Задается порядок п. Постройте магический квадрат порядка п.

17. Задача о рюкзаке. Имеется т различных предметов, известен вес каждого и стоимость. Определите, какие предметы надо положить в рюкзак, чтобы общий вес не превышал заданного значения, а общая стоимость была максимальной.



Опубликовал admin
13 Авг, Пятница 2004г.



Программирование для чайников.