Task: Abbreviations, automatic




Go: package main

import(
    "bufio"
    "fmt"
    "os"
    "strings"
)

func distinctStrings(strs []string) []string {
    len := len(strs)
    set := make(map[string]bool, len)
    distinct := make([]string, 0, len)
    for _, str := range strs {
        if !set[str] {
            distinct = append(distinct, str)
            set[str] = true
        }
    }
    return distinct
}

func takeRunes(s string, n int) string {
    i := 0
    for j := range s {
        if i == n {
            return s[:j]
        }
        i++
    }
    return s
}

func main() {
    file, err := os.Open("days_of_week.txt")
    if err != nil {
        fmt.Println("Unable to open file.")
        return
    }
    defer file.Close()
    reader := bufio.NewReader(file)
    lineCount := 0
    for {
        line, err := reader.ReadString('\n')
        if err != nil { 
            return
        }
        line = strings.TrimSpace(line)
        lineCount++
        if line == "" {
            fmt.Println()
            continue
        }
        days := strings.Fields(line)
        daysLen := len(days)
        if (len(days) != 7) {
            fmt.Println("There aren't 7 days in line", lineCount)
            return
        }
        if len(distinctStrings(days)) != 7 { 
            fmt.Println(" ∞ ", line)
            continue
        }
        for abbrevLen := 1; ; abbrevLen++ {
            abbrevs := make([]string, daysLen)
            for i := 0; i < daysLen; i++ {
                abbrevs[i] = takeRunes(days[i], abbrevLen)
            }
            if len(distinctStrings(abbrevs)) == 7 {
                fmt.Printf("%2d  %s\n", abbrevLen, line)
                break
            }
        }
    }
}








Ada: with Ada.Containers.Indefinite_Vectors;
with Ada.Strings.Fixed;
with Ada.Strings.Maps;
with Ada.Text_IO;

procedure Abbreviations is

   package String_Vectors is
     new Ada.Containers.Indefinite_Vectors (Index_Type   => Positive,
                                            Element_Type => String);
   use Ada.Text_IO, String_Vectors;

   function Split (Line : String) return Vector is
      Result : Vector;
      First  : Natural;
      Last   : Natural := Line'First - 1;
   begin
      while Last + 1 in Line'Range loop
         Ada.Strings.Fixed.Find_Token
           (Line, Ada.Strings.Maps.To_Set (" "), Last + 1,
            Ada.Strings.Outside, First, Last);
         exit when Last = 0;
         Append (Result, Line (First .. Last));
      end loop;
      return Result;
   end Split;

   function Abbrev_Length (Items : Vector) return Natural is
      use type Ada.Containers.Count_Type;
      Max     : Natural := 0;
      Abbrevs : Vector;
   begin
      for Item of Items loop
         Max := Natural'Max (Max, Item'Length);
      end loop;

      for Length in 1 .. Max loop
         Abbrevs := Empty_Vector;
         for Item of Items loop
            declare
               Last : constant Natural
                 := Natural'Min (Item'Last, Item'First + Length - 1);

               Abbrev : String renames Item (Item'First .. Last);
            begin
               exit when Abbrevs.Contains (Abbrev);
               Abbrevs.Append (Abbrev);
            end;
         end loop;
         if Abbrevs.Length = Items.Length then
            return Length;
         end if;
      end loop;
      return 0;
   end Abbrev_Length;

   procedure Process (Line : String) is
      package Natural_IO is new Ada.Text_IO.Integer_IO (Natural);
      Words  : constant Vector  := Split (Line);
      Length : constant Natural := Abbrev_Length (Words);
   begin
      Natural_IO.Put (Length, Width => 2);
      Put (" ");
      Put_Line (Line);
   end Process;

begin
   while not End_Of_File loop
      Process (Get_Line);
   end loop;
end Abbreviations;