Task: Matrix digital rain




Go: package main

import (
    gc "github.com/rthornton128/goncurses"
    "log"
    "math/rand"
    "time"
)



const rowDelay = 40000

func main() {
    start := time.Now()
    rand.Seed(time.Now().UnixNano())

    
    chars := []byte("0123456789")
    totalChars := len(chars)

    
    stdscr, err := gc.Init()
    if err != nil {
        log.Fatal("init", err)
    }
    defer gc.End()

    gc.Echo(false)
    gc.Cursor(0)

    if !gc.HasColors() {
        log.Fatal("Program requires a colour capable terminal")
    }

    if err := gc.StartColor(); err != nil {
        log.Fatal(err)
    }

    if err := gc.InitPair(1, gc.C_GREEN, gc.C_BLACK); err != nil {
        log.Fatal("InitPair failed: ", err)
    }
    stdscr.ColorOn(1)
    maxY, maxX := stdscr.MaxYX()

    

    
    columnsRow := make([]int, maxX)

    
    
    columnsActive := make([]int, maxX)

    
    for i := 0; i < maxX; i++ {
        columnsRow[i] = -1
        columnsActive[i] = 0
    }

    for {
        for i := 0; i < maxX; i++ {
            if columnsRow[i] == -1 {
                
                
                columnsRow[i] = rand.Intn(maxY + 1)
                columnsActive[i] = rand.Intn(2)
            }
        }

        
        for i := 0; i < maxX; i++ {
            if columnsActive[i] == 1 {
                
                charIndex := rand.Intn(totalChars)
                stdscr.MovePrintf(columnsRow[i], i, "%c", chars[charIndex])
            } else {
                
                stdscr.MovePrintf(columnsRow[i], i, "%c", ' ')
            }

            columnsRow[i]++

            
            if columnsRow[i] >= maxY {
                columnsRow[i] = -1
            }

            
            if rand.Intn(1001) == 0 {
                if columnsActive[i] == 0 {
                    columnsActive[i] = 1
                } else {
                    columnsActive[i] = 0
                }
            }
        }
        time.Sleep(rowDelay * time.Microsecond)
        stdscr.Refresh()
        elapsed := time.Since(start)
        
        if elapsed.Minutes() >= 1 {
            break
        }
    }
}








Ada: with Ada.Text_IO;
with Ada.Numerics.Discrete_Random;
with Ada.Strings.Fixed;

procedure Digital_Rain is
   type Column_Type     is range 0 .. 150;
   type Row_Type        is range 0 .. 25;
   type Character_Range is new Character range 'A' .. 'Z';
   subtype Delay_Range  is Integer range 2 .. 6;

   package Column_Random    is new Ada.Numerics.Discrete_Random (Column_Type);
   package Row_Random       is new Ada.Numerics.Discrete_Random (Row_Type);
   package Character_Random is new Ada.Numerics.Discrete_Random (Character_Range);
   package Delay_Random     is new Ada.Numerics.Discrete_Random (Delay_Range);

   Column_Generator    : Column_Random.Generator;
   Row_Generator       : Row_Random.Generator;
   Character_Generator : Character_Random.Generator;
   Delay_Generator     : Delay_Random.Generator;

   Esc     : constant Character := Character'Val (8#33#);
   Running : Boolean   := True;
   Char    : Character;
   use Ada.Text_IO;

   protected Text_Out is
      procedure Put_At (Row : Row_Type; Col : Column_Type;
                        Color : Integer; Item : Character);
   end Text_Out;

   protected body Text_Out is
      procedure Put_At (Row : Row_Type; Col : Column_Type;
                        Color : Integer; Item : Character)
      is
         use Ada.Strings;
      begin
         Put (Esc & "[" &
                Fixed.Trim (Row'Image, Left) & ";" &
                Fixed.Trim (Col'Image, Left) & "H");             
         Put (Esc & "[" & Fixed.Trim (Color'Image, Left) & "m"); 
         Put (Item);
      end Put_At;
   end Text_Out;

   task type Rainer;

   task body Rainer is
      Row : Row_Type;
      Col : Column_Type;
      Del : Delay_Range;
   begin
      Outer_Loop:
      loop
         Col := Column_Random.Random (Column_Generator);
         Row := Row_Random.Random (Row_Generator);
         for Rain in reverse Boolean loop
            Del := Delay_Random.Random (Delay_Generator);
            for R in 0 .. Row loop
               if Rain then
                  if R in 1 .. Row then
                     Text_Out.Put_At (R - 1, Col, Color => 32, Item => Char);
                  end if;
                  Char := Character (Character_Random.Random (Character_Generator));
                  if R in 0 .. Row - 1 then
                     Text_Out.Put_At (R, Col, Color => 97, Item => Char);
                  end if;
               else
                  Text_Out.Put_At (R, Col, Color => 30, Item => ' ');
               end if;
               delay 0.020 * Del;
               exit Outer_Loop when not Running;
            end loop;
         end loop;
      end loop Outer_Loop;
   end Rainer;

   Dummy   : Character;
   Rainers : array (1 .. 50) of Rainer;
begin
   Put (ESC & "[?25l");        
   Put (ESC & "[40m");         
   Put (ESC & "[2J");          

   Get_Immediate (Dummy);
   Running := False;
   delay 0.200;

   Put (ESC & "[?25h");        
   Put (ESC & "[0;0H");        
   Put (ESC & "[39m");         
   Put (ESC & "[49m");         
   Put (ESC & "[2J");          
end Digital_Rain;