Task: Dutch national flag problem




Go: package main

import (
    "fmt"
    "math/rand"
    "time"
)


const (
    red = iota
    white
    blue
    nColors
)


type ball struct {
    color int
}


func (b1 ball) lt(b2 ball) bool {
    return b1.color < b2.color
}


type ordering []ball


func (o ordering) ordered() bool {
    var b0 ball
    for _, b := range o {
        if b.lt(b0) {
            return false
        }
        b0 = b
    }
    return true
}

func init() {
    rand.Seed(time.Now().Unix())
}



func outOfOrder(n int) ordering {
    if n < 2 {
        panic(fmt.Sprintf("%d invalid", n))
    }
    r := make(ordering, n)
    for {
        for i, _ := range r {
            r[i].color = rand.Intn(nColors)
        }
        if !r.ordered() {
            break
        }
    }
    return r
}



func (a ordering) sort3() {
    lo, mid, hi := 0, 0, len(a)-1
    for mid <= hi {
        switch a[mid].color {
        case red:
            a[lo], a[mid] = a[mid], a[lo]
            lo++
            mid++
        case white:
            mid++
        default:
            a[mid], a[hi] = a[hi], a[mid]
            hi--
        }
    }
}

func main() {
    f := outOfOrder(12)
    fmt.Println(f)
    f.sort3()
    fmt.Println(f)
}








Ada: with Ada.Text_IO, Ada.Numerics.Discrete_Random, Ada.Command_Line;

procedure Dutch_National_Flag is

   type Colour_Type is (Red, White, Blue);

   Number: Positive range 2 .. Positive'Last :=
     Positive'Value(Ada.Command_Line.Argument(1));
   

   type Balls is array(1 .. Number) of Colour_Type;

   function Is_Sorted(B: Balls) return Boolean is
      
   begin
      for I in Balls'First .. Balls'Last-1 loop
         if B(I) > B(I+1) then
            return False;
         end if;
      end loop;
      return True;
   end Is_Sorted;

   function Random_Balls return Balls is
      
      package Random_Colour is new Ada.Numerics.Discrete_Random(Colour_Type);
      Gen: Random_Colour.Generator;
      B: Balls;
   begin
      Random_Colour.Reset(Gen);
      loop
         for I in Balls'Range loop
            B(I) := Random_Colour.Random(Gen);
         end loop;
         exit when (not Is_Sorted(B));
         
      end loop;
      return B;
   end Random_Balls;

   procedure Print(Message: String; B: Balls) is
   begin
      Ada.Text_IO.Put(Message);
      for I in B'Range loop
         Ada.Text_IO.Put(Colour_Type'Image(B(I)));
         if I < B'Last then
            Ada.Text_IO.Put(", ");
         else
            Ada.Text_IO.New_Line;
         end if;
      end loop;
   end Print;

   procedure Sort(Bls: in out Balls) is
      

      Cnt: array(Colour_Type) of Natural := (Red => 0, White => 0, Blue => 0);
      Col: Colour_Type;

      procedure Move_Colour_To_Top(Bls: in out Balls;
                                   Colour: Colour_Type;
                                   Start: Positive;
                                   Count: Natural) is
         This: Positive := Start;
         Tmp: Colour_Type;
      begin
         for N in Start .. Start+Count-1 loop
            while Bls(This) /= Colour loop
               This := This + 1;
            end loop; 
            Tmp := Bls(N); Bls(N) := Bls(This); Bls(This) := Tmp; 
            This := This + 1;
         end loop;
      end  Move_Colour_To_Top;

   begin
      for Ball in Balls'Range loop
         
         Col := Bls(Ball);
         Cnt(Col) := Cnt(Col) + 1;
      end loop;
      Move_Colour_To_Top(Bls, Red,   Start => 1,          Count => Cnt(Red));
      Move_Colour_To_Top(Bls, White, Start => 1+Cnt(Red), Count => Cnt(White));
      
   end Sort;

   A: Balls := Random_Balls;

begin
   Print("Original Order: ", A);

   pragma Assert(not Is_Sorted(A));   

   Sort(A); 

   pragma Assert(Is_Sorted(A));   

   Print("After Sorting:  ", A);
end Dutch_National_Flag;