Welcome to collectivesolver - Programming & Software Q&A with code examples. A website with trusted programming answers. All programs are tested and work.

Contact: aviboots(AT)netvision.net.il

Semrush - keyword research tool

Create your online store today with Shopify

Turn ChatGPT, Claude, Gemini, And CoPilot Into Your Personal Assistant, Business Coach, Content Creator, And More

AFFILIATE MARKETING Your all-in-one performance engine Manage affiliates, creators, and customer referrals in one unified platform—turning every partnership into measurable growth

Secure & Reliable Web Hosting, Free Domain, Free SSL, 1-Click WordPress Install, Expert 24/7 Support

Disclosure: My content contains affiliate links.

43,227 questions

56,129 answers

573 users

How to find the N most frequent non‑stopwords in a text in Pascal

1 Answer

0 votes
program TopWordsPascal;

{$mode objfpc}{$H+}

uses
  SysUtils, StrUtils;

(*
    This program finds the N most frequently appearing words in a text
    after removing stopwords. It demonstrates clean structure, clear
    comments, and efficient use of Free Pascal arrays and sorting.
*)

type
  // Dynamic array of strings used for word tokens and stopwords
  TStringArray = array of string;

  // Structure holding a unique word and its frequency counter
  TWordFreq = record
    Word: string;
    Count: Integer;
  end;

  // Dynamic array of word frequency records
  TWordFreqArray = array of TWordFreq;

(* ---------------------------------------------------------------
   Helper: check if a character is a punctuation symbol
   --------------------------------------------------------------- *)
function IsPunct(c: Char): Boolean;
begin
  Result := c in ['.', ',', ';', ':', '!', '?', '"', '''', '(', ')', '[', ']', '{', '}'];
end;

(* ---------------------------------------------------------------
   Tokenize text into words (simple whitespace split)
   --------------------------------------------------------------- *)
function Tokenize(const Text: string): TStringArray;
var
  Parts: TStringArray;
  W: string;
  I: Integer;
begin
  // Initialize dynamic array pointer to nil to eliminate compiler warnings
  Result := nil;

  Parts := SplitString(Text, ' ');

  for I := 0 to High(Parts) do
  begin
    W := Parts[I];

    (* Remove leading punctuation *)
    while (Length(W) > 0) and IsPunct(W[1]) do
      Delete(W, 1, 1);

    (* Remove trailing punctuation *)
    while (Length(W) > 0) and IsPunct(W[Length(W)]) do
      Delete(W, Length(W), 1);

    if W <> '' then
    begin
      W := LowerCase(W);
      // Grow the dynamic array to store the valid word
      SetLength(Result, Length(Result) + 1);
      Result[High(Result)] := W;
    end;
  end;
end;

(* ---------------------------------------------------------------
   Check if a word is present in the list of stopwords
   --------------------------------------------------------------- *)
function IsStopword(const W: string; const Stopwords: TStringArray): Boolean;
var
  I: Integer;
begin
  Result := False;
  for I := 0 to High(Stopwords) do
    if W = Stopwords[I] then
      Exit(True);
end;

(* ---------------------------------------------------------------
   Count word frequencies, skipping stopwords
   --------------------------------------------------------------- *)
function CountWordFrequencies(const Words: TStringArray;
                              const Stopwords: TStringArray): TWordFreqArray;
var
  I, J: Integer;
  Found: Boolean;
begin
  // Initialize result array pointer to nil to silence compiler warnings
  Result := nil;

  for I := 0 to High(Words) do
  begin
    // Skip words present in the stopword array
    if IsStopword(Words[I], Stopwords) then
      Continue;

    Found := False;

    // Check if word has already been recorded
    for J := 0 to High(Result) do
      if Result[J].Word = Words[I] then
      begin
        Inc(Result[J].Count);
        Found := True;
        Break;
      end;

    // Append new word record if not previously found
    if not Found then
    begin
      SetLength(Result, Length(Result) + 1);
      Result[High(Result)].Word := Words[I];
      Result[High(Result)].Count := 1;
    end;
  end;
end;

(* ---------------------------------------------------------------
   Sort frequency array in descending order by count,
   using alphabetical order as a secondary tie-breaker
   --------------------------------------------------------------- *)
procedure SortFreq(var Arr: TWordFreqArray);
var
  I, J: Integer;
  Temp: TWordFreq;
begin
  for I := 0 to High(Arr) do
    for J := I + 1 to High(Arr) do
      if (Arr[J].Count > Arr[I].Count) or
         ((Arr[J].Count = Arr[I].Count) and (Arr[J].Word < Arr[I].Word)) then
      begin
        Temp := Arr[I];
        Arr[I] := Arr[J];
        Arr[J] := Temp;
      end;
end;

(* ---------------------------------------------------------------
   Sort and extract top N most frequent words
   --------------------------------------------------------------- *)
function TopN(Freq: TWordFreqArray; N: Integer): TWordFreqArray;
var
  Count, I: Integer;
begin
  // Initialize result array pointer to nil
  Result := nil;

  Count := Length(Freq);
  SortFreq(Freq);

  if Count > N then
    Count := N;

  SetLength(Result, Count);

  // Copy top elements into result array
  for I := 0 to Count - 1 do
  begin
    Result[I].Word := Freq[I].Word;
    Result[I].Count := Freq[I].Count;
  end;
end;

(* ---------------------------------------------------------------
   Main program execution
   --------------------------------------------------------------- *)
var
  Text: string;
  Stopwords: TStringArray;
  Words: TStringArray;
  Freq: TWordFreqArray;
  TopNWords: TWordFreqArray;
  I, N: Integer;

begin
  // Source text corpus
  Text :=
    'C is a general-purpose programming language created in 1972 by ' +
    'Dennis Ritchie. C gives programmers direct access to the features ' +
    'of CPU. It has been and continues to be used to implement ' +
    'operating systems (especially kernels) and device ' +
    'drivers. C programming language used on computers ranging from ' +
    'supercomputers to microcontrollers and embedded systems.';

  // Defined stopwords to ignore
  Stopwords := TStringArray.Create(
    'the','is','a','to','how','after','but','this','for','by','in',
    'and','can','content','be','you','yes','no','next','about','used',
    'access','been','continues'
  );

  // Run pipeline
  Words := Tokenize(Text);
  Freq := CountWordFrequencies(Words, Stopwords);

  N := 7;
  TopNWords := TopN(Freq, N);

  // Output top results
  WriteLn('Top ', N, ' most frequent non-stopwords:');
  for I := 0 to High(TopNWords) do
    WriteLn(TopNWords[I].Word, ' : ', TopNWords[I].Count);
end.



{
run:

Top 7 most frequent non-stopwords:
c : 3
language : 2
programming : 2
systems : 2
1972 : 1
computers : 1
cpu : 1

}

 



answered Aug 30 by avibootz
edited Aug 30 by avibootz
...