RosettaCodeData/Task/Word-frequency/Ada/word-frequency.ada

88 lines
3.0 KiB
Ada

with Ada.Command_Line;
with Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Strings.Maps;
with Ada.Strings.Fixed;
with Ada.Characters.Handling;
with Ada.Containers.Indefinite_Ordered_Maps;
with Ada.Containers.Indefinite_Ordered_Sets;
with Ada.Containers.Ordered_Maps;
procedure Word_Frequency is
package TIO renames Ada.Text_IO;
package String_Counters is new Ada.Containers.Indefinite_Ordered_Maps(String, Natural);
package String_Sets is new Ada.Containers.Indefinite_Ordered_Sets(String);
package Sorted_Counters is new Ada.Containers.Ordered_Maps
(Natural,
String_Sets.Set,
"=" => String_Sets."=",
"<" => ">");
-- for sorting by decreasing number of occurrences and ascending lexical order
procedure Increment(Key : in String; Element : in out Natural) is
begin
Element := Element + 1;
end Increment;
path : constant String := Ada.Command_Line.Argument(1);
how_many : Natural := 10;
set : constant Ada.Strings.Maps.Character_Set := Ada.Strings.Maps.To_Set(ranges => (('a', 'z'), ('0', '9')));
F : TIO.File_Type;
first : Positive;
last : Natural;
from : Positive;
counter : String_Counters.Map;
sorted_counts : Sorted_Counters.Map;
C1 : String_Counters.Cursor;
C2 : Sorted_Counters.Cursor;
tmp_set : String_Sets.Set;
begin
-- read file and count words
TIO.Open(F, name => path, mode => TIO.In_File);
while not TIO.End_Of_File(F) loop
declare
line : constant String := Ada.Characters.Handling.To_Lower(TIO.Get_Line(F));
begin
from := line'First;
loop
Ada.Strings.Fixed.Find_Token(line(from .. line'Last), set, Ada.Strings.Inside, first, last);
exit when last < First;
C1 := counter.Find(line(first .. last));
if String_Counters.Has_Element(C1) then
counter.Update_Element(C1, Increment'Access);
else
counter.Insert(line(first .. last), 1);
end if;
from := last + 1;
end loop;
end;
end loop;
TIO.Close(F);
-- fill Natural -> StringSet Map
C1 := counter.First;
while String_Counters.Has_Element(C1) loop
if sorted_counts.Contains(String_Counters.Element(C1)) then
tmp_set := sorted_counts.Element(String_Counters.Element(C1));
tmp_set.Include(String_Counters.Key(C1));
else
sorted_counts.Include(String_Counters.Element(C1), String_Sets.To_Set(String_Counters.Key(C1)));
end if;
String_Counters.Next(C1);
end loop;
-- output
C2 := sorted_counts.First;
while Sorted_Counters.Has_Element(C2) loop
for Item of Sorted_Counters.Element(C2) loop
Ada.Integer_Text_IO.Put(TIO.Standard_Output, Sorted_Counters.Key(C2), width => 9);
TIO.Put(TIO.Standard_Output, " ");
TIO.Put_Line(Item);
end loop;
Sorted_Counters.Next(C2);
how_many := how_many - 1;
exit when how_many = 0;
end loop;
end Word_Frequency;