(* 1996 Programming Contest Pascal Solution * * Filename: p7.p * * Authors: Andrew Lumsdaine * John Tran (translated to Pascal) * * ---------------------------------------------------------------------- * DESCRIPTION: * See p7.c for complete description * *) program main(input, output); (* Constant declarations *) const TABLE_SIZE = 4000; MAX_SIZE = 100; WORD_SIZE = 7; type Buffer = packed array[0..MAX_SIZE - 1] of char; Word = Buffer; Word_array = array[0..TABLE_SIZE - 1] of Word; key_type = array[0..7] of char; salt_type = array[0..2] of char; encrypt_type = array[0..31] of char; check_type = array[0..12] of char; var twos : Word_array; threes : Word_array; fours : Word_array; fives : Word_array; arr : array[0..3] of char; procedure pcrypt( key : key_type; salt : salt_type; var result : encrypt_type); external C; (* zero out the buffers *) procedure zero_buffer(var A : Buffer; size:integer) ; var i : integer; begin for i := 0 to size - 1 do A[i] := ' '; end; {zero_buffer} (* compute the length of the word *) function Length_word(A : Word): integer; const Blank = ' '; var Count : integer; begin Count := WORD_SIZE - 1; while (A[Count] = Blank) do Count := Count - 1; Length_word := Count; end; {Length_word} (* compute the length of a string *) function Length(var A : Buffer): integer; const Blank = ' '; var Count : integer; begin Count := MAX_SIZE; while (A[Count] = Blank) do Count := Count - 1; Length := Count; end; {Length} (* check to see if a character is a valid char *) function isalpha(a : char): boolean; begin if ( ( (ord(a) >= 65) and (ord(a) <= 90) ) or ( (ord(a) >= 97) and (ord(a) <= 122) )) then isalpha:= true else isalpha := false; end; { isalnum } (* is Word a word *) function isword(word : Word): integer; var i, n, status: integer; label bk1; begin {isword} n := Length_word(word); status := 1; for i := 0 to n - 1 do if not isalpha(word[i]) then begin {if} status := 0; goto bk1; end; {if} bk1: isword := status; end; {isword} procedure uniq_insert(var buf : Word_array; cptr : Word); var i, j : integer; buffer : Word; begin {uniq_insert} i := 0; buffer := cptr; (* convert to lower case *) for j := 0 to 6 do if (buffer[j] <> ' ') and (ord(buffer[j]) < 91) then buffer[j] := chr(ord(buffer[j]) + 32); for j := 7 to MAX_SIZE-1 do buffer[j] := ' '; while (buf[i][0] <> chr(0)) do begin {while} if buf[i] = buffer then return; i := i + 1; end; {while} buf[i] := buffer; buf[i+1][0] := chr(0); end; {uniq_insert} function try(first : Word_array; size1 : integer; second : Word_array; size2 : integer; crypted : encrypt_type): integer; var i, j, k, n : integer; position : integer; salt : salt_type; buffer : key_type; result : encrypt_type; ck_res : check_type; ck_cry : check_type; label bk_1; begin {try} salt[0] := crypted[0]; salt[1] := crypted[1]; salt[2] := chr(0); i := 0; while first[i][0] <> chr(0) do begin j := 0; while second[j][0] <> chr(0) do begin {while} for n := 0 to 4 - 1 do begin {for} (* stuff the first half *) position := 0; for k := 0 to size1 - 1 do begin {for} buffer[position] := first[i][k]; position := position + 1; end; {for} (* stuff the numbber *) buffer[position] := arr[n]; position := position + 1; (* stuff the second half in passwd *) for k := 0 to size2 - 1 do begin {for} buffer[position] := second[j][k]; position := position + 1; end; {for} buffer[position] := chr(0); (* call pcrypt *) pcrypt(buffer, salt, result); for k := 0 to 12 do begin ck_res[k] := result[k]; ck_cry[k] := crypted[k]; end; if ck_res = ck_cry then begin {if} writeln(buffer); try := 1; goto bk_1; end; {if} end; {for} j := j + 1; end; {while} i := i + 1; end; {while} try := 0; bk_1: end; {try} function read_next_word(var word_out : Word; var first : integer; word_in : Buffer): integer; var i : integer; chr1 : char; label bk1; begin {read_next_word} chr1 := word_in[first]; for i := 0 to WORD_SIZE -1 do word_out[i] := ' '; i := 0; while isalpha(chr1) do begin {begin} word_out[i] := chr1; i := i + 1; first := first + 1; chr1 := word_in[first]; end; {while} bk1: first := first + 1; read_next_word := i; end; {read_next_word} var i, j : integer; first, last : integer; word_size : integer; buffer : Buffer; word : Word; crypted : encrypt_type; result : integer; label the_end; begin {main} (* initializations *) arr[0] := '0'; arr[1] := '2'; arr[2] := '4'; arr[3] := '8'; for i := 0 to TABLE_SIZE -1 do begin {for} twos[i][0] := chr(0); threes[i][0] := chr(0); fours[i][0] := chr(0); fives[i][0] := chr(0); end; {for} (* get the crypted password *) readln(crypted); (* Filter out all words into appropriate arrays *) while not eof do begin {while} readln(buffer); first := 0; last := Length(buffer); while (first < last) do begin {while} word_size := read_next_word(word, first, buffer); if word_size = 2 then uniq_insert(twos, word) else if word_size = 3 then uniq_insert(threes, word) else if word_size = 4 then uniq_insert(fours, word) else if word_size = 5 then uniq_insert(fives, word); end; {while} end; {while} (* Start trying out combinations *) result := try(twos, 2, threes, 3, crypted); if result = 1 then goto the_end; result := try(twos, 2, fours, 4, crypted); if result = 1 then goto the_end; result := try(twos, 2, fives, 5, crypted); if result = 1 then goto the_end; result := try(threes, 3, threes, 3, crypted); if result = 1 then goto the_end; result := try(threes, 3, fours, 4, crypted); if result = 1 then goto the_end; result := try(fours, 4, twos, 2, crypted); if result = 1 then goto the_end; result := try(fours, 4, threes, 3, crypted); if result = 1 then goto the_end; result := try(fives, 5, twos, 2, crypted); if result = 1 then goto the_end; result := try(threes, 3, fours, 4, crypted); if result = 1 then goto the_end; the_end: end. {main}