library WordCount; uses SysUtils; type PTree = ^TTree; TTree = record word: string; num: integer; left: PTree; right: PTree; end; { prebere naslednjo besedo iz datoteke } function ReadNextWord(var f: TextFile; delimiter: word): string; var chr: char; word: string; ok: boolean; begin ok := true; word := ''; while ok and not eof(f) do begin read(f, chr); if delimiter > 0 then ok := (chr <= ' ') or (chr >= #127) else ok := not (chr in ['a'..'z', 'A'..'Z', '0'..'9']); if not ok then word := chr; end; if not eof(f) then begin ok := true; while ok and not eof(f) do begin read(f, chr); if delimiter > 0 then ok := (chr > ' ') and (chr < #127) else ok := chr in ['a'..'z', 'A'..'Z', '0'..'9']; if ok then word := word + chr; end; end; result := word; end; { besedo shrani v dvojisko drevo (urejeno po abecedi) } function Store(tree: PTree; word: string): Ptree; begin if tree = nil then begin New(tree); tree^.word := word; tree^.num := 1; tree^.left := nil; tree^.right := nil; end else begin if word = tree^.word then inc(tree^.num) else if word < tree^.word then tree^.left := Store(tree^.left, word) else tree^.right := Store(tree^.right, word); end; result := tree; end; { vozlisce dvojiskega drevesa prestavi v drugo (drugace urejeno) drevo } function InsertToTree(tree, node: PTree; sort: word): PTree; begin node^.left := nil; node^.right := nil; if tree = nil then tree := node else begin if (node^.num < tree^.num) or (node^.num = tree^.num) and ((sort = 1) and (node^.word < tree^.word) or (sort = 2) and (node^.word > tree^.word)) then tree^.left := InsertToTree(tree^.left, node, sort) else tree^.right := InsertToTree(tree^.right, node, sort); end; result := tree; end; { preuredi drevo na drugacen nacin } function SortTree(sorted, tree: PTree; sort: word): PTree; begin if tree <> nil then begin sorted := SortTree(sorted, tree^.left, sort); sorted := SortTree(sorted, tree^.right, sort); sorted := InsertToTree(sorted, tree, sort); end; result := sorted; end; { obrne vrstni red ureditve drevesa } procedure ReverseTree(tree: PTree); var temp: PTree; begin if tree <> nil then begin ReverseTree(tree^.left); ReverseTree(tree^.right); temp := tree^.left; tree^.left := tree^.right; tree^.right := temp; end; end; { obrne vrstni red znakov v nizu } procedure ReverseString(var str: string); var temp: char; i, j: integer; begin i := 1; j := Length(str); while i < j do begin temp := str[i]; str[i] := str[j]; str[j] := temp; inc(i); dec(j); end; end; { obrne vse besede v drevesu } procedure ReverseStrings(tree: PTree); begin if tree <> nil then begin ReverseStrings(tree^.left); ReverseStrings(tree^.right); ReverseString(tree^.word); end; end; { drevo zapise na datoteko } procedure WriteTree(tree: PTree; var f: TextFile); begin if tree <> nil then begin WriteTree(tree^.left, f); Writeln(f, tree^.num, ' ', tree^.word); WriteTree(tree^.right, f); end; end; { sprosti drevo } procedure DisposeTree(tree: PTree); begin if tree <> nil then begin DisposeTree(tree^.left); DisposeTree(tree^.right); Dispose(tree); end; end; { presteje pojavitve posameznih besed na dani datoteki } { rezultat zapise na drugo datoteko } procedure Count( inputFile, outputFile: PChar; sort, order, tail, delimiter, match, ignore: word ); stdcall; var f: TextFile; word: string; tree: PTree; begin tree := nil; AssignFile(f, inputFile); Reset(f); while not eof(f) do begin word := readNextWord(f, delimiter); if match = 0 then word := LowerCase(word); if tail > 0 then ReverseString(word); if Length(word) >= ignore then tree := Store(tree, word); end; CloseFile(f); if sort > 0 then tree := SortTree(nil, tree, sort); if order > 0 then ReverseTree(tree); if tail > 0 then ReverseStrings(tree); AssignFile(f, outputFile); Rewrite(f); WriteTree(tree, f); CloseFile(f); Dispose(tree); end; exports Count; begin end.