(* 1996 Programming Contest Pascal Solution * * Filename: p1.p * * Authors: Andrew Lumsdaine * John Tran (translated to Pascal) * * * ---------------------------------------------------------------------- * DESCRIPTION: * See p1.c for complete description * * ---------------------------------------------------------------------- *) program main(input, output); (* Constant declarations *) const Time_block_size = 32; { maximum size for a time block } (* Aggregated datatype declarations *) type time_block = array[0..31] of char; day_block = record day_name : char; day_date : integer; times : time_block; end; month_block = array[0..31] of day_block; year_block = array[0..11] of month_block; date = record day_name : char; month, day : integer; end; time = record start : integer; stop : integer; end; function min(n1, n2 : integer): integer; begin if n1 <= n2 then min := n1 else min := n2; end; (* Variable declarations *) var buffer : array[0..79] of char; days_per_month : array[0..11] of integer; weekdays : array[0..6] of char; mo, dy, start,xmo : integer; i, j, k, len : integer; num_to_schedule : integer; length_to_schedule : integer; current_date : date; year : year_block; temp_day : array[0..99] of char; done_flag : boolean; var appt_date : date; appt_time : time; (* goto labels *) label branch_pt1, branch_pt2, branch_pt3, end_of_program; (* compute the index macro see the c solution for a more cryptic explanation *) function my_index(t : integer) : integer; begin my_index := trunc(( ((t - 900)/100)*4+(t-100*(t/100))/15 )); end; (* look ahead detects the 'done' keyword *) procedure look_ahead(var done : boolean; var day_name : char; var month : integer; var day : integer; var start : integer; var stop : integer); var Next : char; label local_bk; begin read(Next); if Next = 'd' then read(Next); if Next = 'o' then read(Next); if Next = 'n' then read(Next); if Next = 'e' then begin {if 'e'} done := true; day_name := ' '; month := 0; day := 0; start := 0; stop := 0; readln; (* eat up the carriage return *) goto local_bk; (* the word 'done' is matched *) end; {if 'e'} (* read the rest since 'done' is not matched *) done := false; day_name := Next; readln(month, day, start, stop); local_bk: end; {look_ahead} begin {main} (* number of days for each month initialization *) days_per_month[0] := 31; days_per_month[1] := 28; days_per_month[2] := 31; days_per_month[3] := 30; days_per_month[4] := 31; days_per_month[5] := 30; days_per_month[6] := 31; days_per_month[7] := 31; days_per_month[8] := 30; days_per_month[9] := 31; days_per_month[10] := 30; days_per_month[11] := 31; (* day of the week initialization *) weekdays[0] := 'M'; weekdays[1] := 'T'; weekdays[2] := 'W'; weekdays[3] := 'R'; weekdays[4] := 'F'; weekdays[5] := 'S'; weekdays[6] := 'S'; (* get current date *) readln(current_date.day_name, current_date.month, current_date.day); current_date.month := current_date.month - 1; current_date.day := current_date.day - 1; (* get desired meetings *) readln(num_to_schedule, length_to_schedule); while true do begin readln(buffer); (* read line *) if buffer = 'done' then goto branch_pt1; (* branch if done *) (* else must be name -- read appointments and store *) while true do begin look_ahead(done_flag, appt_date.day_name, appt_date.month, appt_date.day, appt_time.start, appt_time.stop); if done_flag then goto branch_pt2; { writeln(appt_date.day_name:2, appt_date.month:4, appt_date.day:4, appt_time.start:5, appt_time.stop:6); (* debug *) } i := appt_time.start; while i < appt_time.stop do begin year[appt_date.month-1][appt_date.day-1].times[my_index(i)] := 'x'; if trunc(( i - 100 * (i/100))) mod 60 = 45 then i := i + 45; i := i + 15; end; end; branch_pt2: end; branch_pt1: (* Initialize day names for year *) for start := 0 to 6 do begin if weekdays[start] = current_date.day_name then goto branch_pt3; end; {for start} writeln('error on the input: I should never get here'); branch_pt3: for i := 0 to 11 do begin {for} mo := (i + current_date.month) mod 12; for j := 0 to 30 do begin {for} dy := (j + current_date.day) mod 31; if (dy < current_date.day) then xmo := (mo + 1) mod 12 else xmo := mo mod 12; if (dy < days_per_month[mo]) then begin {if} year[xmo][dy].day_name := weekdays[(start mod 7)]; start := start + 1; end; {if} end; {for} end; {for} (* Find appointments by brute force *) len := 0; while num_to_schedule > 0 do begin {while} for i := 0 to 11 do begin mo := (i + current_date.month) mod 12; for j:= 0 to 30 do begin dy := (j + current_date.day) mod 31; if (dy < current_date.day) then xmo := (mo + 1) mod 12 else xmo := mo mod 12; if not (year[xmo][dy].day_name = 'S') and not(dy >= days_per_month[mo]) then begin {if} len := 0; start := 0; k := 900; while k < 1700 do begin {while} if not (year[xmo][dy].times[my_index(k)] = 'x') then begin if start = 0 then start := k; len := len + 1; end else begin len := 0; start := 0; end; if (len = length_to_schedule/15) then begin if (start < 1000) then writeln(year[xmo][dy].day_name, (xmo + 1):3, (dy + 1):3, ' 0', start:1) else writeln(year[xmo][dy].day_name, (xmo + 1):3, (dy + 1):3, ' ', start:1); len := 0; start := 0; num_to_schedule := num_to_schedule - 1; if (num_to_schedule = 0) then goto end_of_program; (* goto is a way of life *) end; if ((k - 100*trunc(1.0*k/100.0)) mod 60 = 45 ) then k := k + 40; k := k + 15; end {while} end; {if} end; end; end; {while} while (num_to_schedule > 0) do begin writeln("No more times available"); num_to_schedule := num_to_schedule - 1; end; end_of_program: end. {main}