#!/user/bin/perl

use strict;
use warnings;
use Tk;

my $delay      = 50;                            # milliseconds
my $fade       = 8;                             # number of characters to "fade"
my $base_color = '#004000';                     # dark green
my $fontname   = 'Times';                       # Whatever
my $fontsize   = 12;                            # point size
my $font       = "{$fontname} $fontsize bold";
my @objects;

my ( $xv, $yv ) = ( 0, 0 );

my $top = MainWindow->new();

$top->geometry('800x600');

my $run = 1;

$top->protocol( 'WM_DELETE_WINDOW' => sub { $run = 0; } );

my @letters = ( 'A' .. 'Z', 'a' .. 'z', '0' .. '9' );

my $canvas = $top->Canvas(
    -background => 'black'
)->pack(
    -fill   => 'both',
    -expand => 'y'
);

my $testch = $canvas->createText(
    100, 100,
    -text => 'o',
    -fill => 'black',
    -font => $font
);

$top->update;

my @coords = $canvas->bbox($testch);

$canvas->delete($testch);

my $lwidth  = $coords[2] - $coords[0];
my $lheight = ( $coords[3] - $coords[1] ) * .8;
my $cols    = int $canvas->width / $lwidth;
my $rows    = int $canvas->height / $lheight;

for my $y ( 0 .. $rows ) {
    for my $x ( 0 .. $cols ) {
        $objects[$x][$y] = $canvas->createText(
            $x * $lwidth, $y * $lheight,
            -text => $letters[ int rand @letters ],
            -fill => $base_color,
            -font => $font
        );
    }
}

my $neo_image = $top->Photo( -data => neo() );

my $neo = $canvas->createImage(
    $canvas->width / 2,
    $canvas->height / 2,
    -image => $neo_image
);

while ($run) {
    drop('Nothing Like The Matrix');
}
exit;

MainLoop;

sub drop {
    my @phrase = split //, reverse shift;
    my $x = int rand $cols;
    my @orig;
    for my $y ( 0 .. $rows ) {
        $orig[$y] = $canvas->itemcget( $objects[$x][$y], '-text' );
    }
    for my $y ( 0 .. $rows + @phrase + $fade ) {
        for my $letter ( 0 .. @phrase ) {
            last if ( $y - $letter < 0 );
            $canvas->itemconfigure(
                $objects[$x][ $y - $letter ],
                -text => $phrase[$letter],
                -fill => "#00FF00"
            );
        }
        if ( $y > @phrase ) {
            $canvas->itemconfigure(
                $objects[$x][ $y - @phrase ],
                -text => $orig[ $y - @phrase ],
                -fill => "#009000"
            );
        }
        if ( $y > @phrase + 2 ) {
            $canvas->itemconfigure( $objects[$x][ $y - @phrase - int ($fade / 2) ],
                -fill => "#006000" );
            $canvas->itemconfigure( $objects[$x][ $y - @phrase - $fade + 1 ],
                -fill => $base_color );
        }
        last unless $run;
        $top->after($delay);
        neo_move();
        $top->update;
    }
}

sub neo_move {
    $xv += ( ( rand 2 ) - 1 > 0 ) ? 1 : -1;
    $yv += ( ( rand 2 ) - 1 > 0 ) ? 1 : -1;
    my ( $x, $y ) = $canvas->coords($neo);
    $xv = -$xv if ( ( $x < 0 ) or ( $x > $canvas->width ) );
    $yv = -$yv if ( ( $y < 0 ) or ( $y > $canvas->height ) );
    $canvas->move( $neo, $xv, $yv );
}

sub neo {
return '
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
8SLGjBo3cuzo8SPIkCJHkixp8iTKiQEBADs=
';
}


/*REXX program  creates a  directory (folder)  and all its  parent paths  as necessary. */
trace off                                              /*suppress possible warning msgs.*/

dPath = 'path\to\dir'                                  /*define directory (folder) path.*/

'MKDIR'  dPath  "2>nul"                                /*alias could be used:  MD dPath */
                                                       /*stick a fork in it, we're done.*/


System("mkdir C:\Ring\docs")
isdir("C:\Ring\docs")

see isdir("C:\Ring\docs") + nl
func isdir cDir
     try
        dir(cDir)
        return true
     catch
        return false
     done


files #f, "c:\myDocs"		' check for directory
if #f hasanswer() then
   if #f isDir() then		' is it a file or a directory
    print "A directory exist"
    else
    print "A file exist"
   end if
 else
  shell$("mkdir c:\myDocs"    ' if not exist make a directory
end if


use std::fs;

fn main() {
    fs::create_dir_all("./path/to/dir").expect("An Error Occured!")
}


$ include "seed7_05.s7i";
  include "cli_cmds.s7i";

const proc: main is func
  begin
    doMkdirCmd(argv(PROGRAM), TRUE);
  end func;


       IDENTIFICATION DIVISION.
       PROGRAM-ID. demo-map-range.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  i                       USAGE FLOAT-LONG.

       01  mapped-num              USAGE FLOAT-LONG.

       01  a-begin                 USAGE FLOAT-LONG VALUE 0.
       01  a-end                   USAGE FLOAT-LONG VALUE 10.

       01  b-begin                 USAGE FLOAT-LONG VALUE -1.
       01  b-end                   USAGE FLOAT-LONG VALUE 0.

       01  i-display               PIC --9.9.
       01  mapped-display          PIC --9.9.

       PROCEDURE DIVISION.
           PERFORM VARYING i FROM 0 BY 1 UNTIL i > 10
               CALL "map-range" USING CONTENT a-begin, a-end, b-begin,
                   b-end, i, REFERENCE mapped-num
               COMPUTE i-display ROUNDED = i
               COMPUTE mapped-display ROUNDED = mapped-num
               DISPLAY FUNCTION TRIM(i-display) " maps to "
                   FUNCTION TRIM(mapped-display)
           END-PERFORM
           .
       END PROGRAM demo-map-range.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. map-range.

       DATA DIVISION.
       LINKAGE SECTION.
       01  a-begin                 USAGE FLOAT-LONG.
       01  a-end                   USAGE FLOAT-LONG.

       01  b-begin                 USAGE FLOAT-LONG.
       01  b-end                   USAGE FLOAT-LONG.

       01  val-to-map              USAGE FLOAT-LONG.

       01  ret                     USAGE FLOAT-LONG.

       PROCEDURE DIVISION USING a-begin, a-end, b-begin, b-end,
               val-to-map, ret.
           COMPUTE ret =
               b-begin + ((val-to-map - a-begin) * (b-end - b-begin)
                   / (a-end - a-begin))
           .
       END PROGRAM map-range.


let rnd : int -> int =
  let gen = new System.Random()
  fun max -> gen.Next(max)

// randomly choose an element of a list
let choose (xs:_ list) = xs.[rnd xs.Length]

type Maze(width, height) =
  // (x,y) -> have we been here before?
  let visited = Array2D.create width height false
  // (x,y) -> is there a wall between (x,y) and (x+1,y)?
  let horizWalls = Array2D.create width height true
  // (x,y) -> is there a wall between (x,y) and (x,y+1)?
  let vertWalls = Array2D.create width height  true

  let isLegalPoint (x,y) =
    x >= 0 && x < width && y >= 0 && y < height

  let neighbours (x,y) =
    [(x-1,y);(x+1,y);(x,y-1);(x,y+1)] |> List.filter isLegalPoint

  let removeWallBetween (x1,y1) (x2,y2) =
    if x1 <> x2 then
      horizWalls.[min x1 x2, y1] <- false
    else
      vertWalls.[x1, min y1 y2] <- false

  let rec visit (x,y as p) =
    let rec loop ns =
      let (nx,ny) as n = choose ns
      if not visited.[nx,ny] then
        removeWallBetween p n
        visit n
      match List.filter ((<>) n) ns with
      | [] -> ()
      | others -> loop others

    visited.[x,y] <- true
    loop (neighbours p)

  do visit (rnd width, rnd height)

  member x.Print() =
    ("+" + (String.replicate width "-+")) ::
    [for y in 0..(height-1) do
       yield "\n|"
       for x in 0..(width-1) do
         yield if horizWalls.[x,y] then " |" else "  "
       yield "\n+"
       for x in 0..(width-1) do
         yield if vertWalls.[x,y] then "-+" else " +"
    ]
    |> String.concat ""
    |> printfn "%s"

let m = new Maze(10,10)
m.Print()


--
-- demo\rosetta\Matrix_Digital_Rain.exw
--
with javascript_semantics
sequence sushii = {},   -- w x h of unicode char strings
         colours,       --  """  of their fading colours
         droplets       -- w column droplets, or zeroes

include pGUI.e

Ihandle dlg, canvas, timer
cdCanvas cddbuffer, cdcanvas

procedure rain(integer w,h)
    for x=1 to w do
        integer y = droplets[x]
        if y or rand(40)=1 then
            if y<h then
                droplets[x] = y+1
                sushii[y+1][x] = utf32_to_utf8({0x30A0 + rand(96)})
                colours[y+1][x] = CD_WHITE
            end if
            if y then
                bool clear_droplet = true
                if colours[y][x]=CD_WHITE then
                    colours[y][x] = #00F800 -- (CD_GREEN to nearest #800)
                    clear_droplet = false
                    y -= 1
                end if
                while y>=1 do
                    integer cy = colours[y][x]
                    if cy=0 then exit end if
                    clear_droplet = false
                    cy -= #000800
                    colours[y][x] = cy
                    y -= 1
                end while
                if clear_droplet then
                    droplets[x] = 0
                end if
            end if
        end if
    end for
end procedure

function redraw_cb(Ihandle /*ih*/, integer /*posx*/, /*posy*/)
    integer {w,h} = IupGetIntInt(canvas, "DRAWSIZE"),
            {dx,dy} = cdCanvasGetTextSize(cddbuffer, "W")
    w = max(1,floor(w/dx))
    h = max(1,floor(h/dy))
    if length(sushii)!=h
    or length(sushii[1])!=w then
        sushii = repeat(repeat(" ",w),h)
        colours = repeat(repeat(CD_BLACK,w),h)
        droplets = repeat(0,w)
    end if
    cdCanvasActivate(cddbuffer)
    cdCanvasClear(cddbuffer)
    rain(w,h)
    for x=1 to w do
        for y=1 to h do
            if colours[y][x] then
                cdCanvasSetForeground(cddbuffer, colours[y][x])
                cdCanvasText(cddbuffer,x*dx, (h-y)*dy, sushii[y][x])
            end if
        end for
    end for
    cdCanvasFlush(cddbuffer)
    return IUP_DEFAULT
end function

function timer_cb(Ihandle /*ih*/)
    IupUpdate(canvas)
    return IUP_IGNORE
end function

function map_cb(Ihandle ih)
    cdcanvas = cdCreateCanvas(CD_IUP, ih)
    cddbuffer = cdCreateCanvas(CD_DBUFFER, cdcanvas)
    cdCanvasSetBackground(cddbuffer, CD_BLACK)
    return IUP_DEFAULT
end function

procedure main()
    IupOpen()
    IupSetGlobal("UTF8MODE","YES")

    canvas = IupCanvas("RASTERSIZE=640x480")
    IupSetCallbacks(canvas, {"MAP_CB", Icallback("map_cb"),
                             "ACTION", Icallback("redraw_cb")})

    timer = IupTimer(Icallback("timer_cb"), 50)

    dlg = IupDialog(canvas,`TITLE="Matrix Digital Rain"`)

    IupShow(dlg)
    IupSetAttribute(canvas, "RASTERSIZE", NULL)
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure

main()


Dir.new(Dir.cwd, "path", "to", "dir").make_path;   # works cross-platform


Module Module1

    Sub Main()
        System.IO.Directory.CreateDirectory("some/where")
    End Sub

End Module


import "io" for FileSystem

class Main {
    construct new() {}

    init() {
        FileSystem.createDirectory("path/to/dir")
    }

    update() {}

    draw(alpha) {}
}

var Game = Main.new()


(defun map-range (a1 a2 b1 b2 s)
  (+ b1
     (/ (* (- s a1)
	   (- b2 b1))
	(- a2 a1))))

(loop
   for i from 0 to 10
   do (format t "~F maps to ~F~C" i
	      (map-range 0 10 -1 0 i)
	      #\Newline))


double mapRange(in double[] a, in double[] b, in double s)
pure nothrow @nogc {
    return b[0] + ((s - a[0]) * (b[1] - b[0]) / (a[1] - a[0]));
}

void main() {
    import std.stdio;

    immutable r1 = [0.0, 10.0];
    immutable r2 = [-1.0, 0.0];
    foreach (immutable s; 0 .. 11)
        writefln("%2d maps to %5.2f", s, mapRange(r1, r2, s));
}


\ Bit Arrays

: to-bits ( c -- f f f f f f f f )
    8 0 ?do
        2 /mod
        swap negate swap
    loop
    drop ;

: from-bits ( f f f f f f f f -- )
    8 0 ?do
        if [char] 1 emit else [char] 0 emit then
    loop ;

: byte-bin. ( c -- )
    to-bits from-bits space ;

: byte. ( c -- )
    dup byte-bin.
    dup 2 ['] u.r 16 base-execute space
    3 u.r space ;

: bytes-for-bits ( u1 -- u2 )
    8 /mod swap
    0> if 1+ then ;

: bits ( u -- bits )
    dup bytes-for-bits cell +  \ u-bits u-bytes
    dup allocate throw         \ u-bits u-bytes addr
    2dup swap erase nip        \ u-bits addr
    swap over ! ;              \ addr

: free-bits ( bits -- )
    free throw ;

: bits. ( bits -- )
    dup @ bytes-for-bits \ addr bytes
    swap cell+ swap      \ addr+cell bytes
    bounds ?do
        i cr 20 ['] u.r 16 base-execute space
        i [email protected] byte.
    loop
    cr ;

: bit-position ( u -- u-bit u-byte )
    8 /mod ;

: assert-bit ( bits u -- bits u )
    assert( 2dup swap @ < ) ;

: find-bit ( bits u1 -- addr u2 )
    assert-bit
    bit-position       \ addr bit byte
    rot                \ bit byte addr
    cell+ + swap ;     \ addr' bit

: set-true ( addr u -- )
    1 swap lshift over \ addr mask addr
    [email protected] or swap c! ;

: set-false ( addr u -- )
    1 swap lshift invert over \ addr mask addr
    [email protected] and swap c! ;

: set ( addr u f -- )
    if set-true else set-false then ;

: set-bit ( bits u f -- )
    { f }
    find-bit f set ;

: set-bits-at-addr ( addr u-start u-stop f -- )
    { f }
    1+ swap u+do
        dup i f set
    loop
    drop ;

: byte-from-flag ( f -- c )
    if 255 else 0 then ;

: set-bits { bits u-start u-stop f -- }

    u-start u-stop > if exit then

    bits u-start find-bit { addr-start bit-start }
    bits u-stop  find-bit { addr-stop  bit-stop  }

    addr-start addr-stop = if
        addr-start bit-start bit-stop f set-bits-at-addr
    else
        addr-start bit-start 7 f set-bits-at-addr
        addr-start 1+ addr-stop addr-start - 1- f byte-from-flag fill
        addr-stop 0 bit-stop f set-bits-at-addr
    then ;

: check-bit ( addr u -- f )
    find-bit           \ addr bit
    1 swap lshift swap \ mask addr
    [email protected] and 0> ;

: resize-bits ( bits u -- bits )
    over @ { old-size }
    tuck bytes-for-bits cell + resize throw \ u-bits bits
    2dup ! swap                             \ bits u-bits
    dup old-size > if
        over swap                           \ bits bits u-bits
        1- old-size swap false set-bits
    else
        drop
    then ;


import curses
import random
import time

"""

Based on C ncurses version

http://rosettacode.org/wiki/Matrix_Digital_Rain#NCURSES_version

"""

"""
Time between row updates in seconds
Controls the speed of the digital rain effect.
"""

ROW_DELAY=.0001

def get_rand_in_range(min, max):
    return random.randrange(min,max+1)

try:
    # Characters to randomly appear in the rain sequence.
    chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

    total_chars = len(chars)

    stdscr = curses.initscr()
    curses.noecho()
    curses.curs_set(False)

    curses.start_color()
    curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK)
    stdscr.attron(curses.color_pair(1))

    max_x = curses.COLS - 1
    max_y = curses.LINES - 1

    # Create arrays of columns based on screen width.

    # Array containing the current row of each column.

    columns_row = []

    # Array containing the active status of each column.
    # A column draws characters on a row when active.

    columns_active = []

    for i in range(max_x+1):
        columns_row.append(-1)
        columns_active.append(0)

    while(True):
        for i in range(max_x):
            if columns_row[i] == -1:
                # If a column is at the top row, pick a
                # random starting row and active status.
                columns_row[i] = get_rand_in_range(0, max_y)
                columns_active[i] = get_rand_in_range(0, 1)

        # Loop through columns and draw characters on rows

        for i in range(max_x):
            if columns_active[i] == 1:
                # Draw a random character at this column's current row.
                char_index = get_rand_in_range(0, total_chars-1)
                #mvprintw(columns_row[i], i, "%c", chars[char_index])
                stdscr.addstr(columns_row[i], i, chars[char_index])
            else:
                # Draw an empty character if the column is inactive.
                #mvprintw(columns_row[i], i, " ");
                stdscr.addstr(columns_row[i], i, " ");

            columns_row[i]+=1

            # When a column reaches the bottom row, reset to top.
            if columns_row[i] >= max_y:
                columns_row[i] = -1

            # Randomly alternate the column's active status.
            if get_rand_in_range(0, 1000) == 0:
                if columns_active[i] == 0:
                    columns_active[i] = 1
                else:
                    columns_active[i] = 0

            time.sleep(ROW_DELAY)
            stdscr.refresh()

except KeyboardInterrupt as err:
    curses.endwin()


(lib 'plot) ;; interpolation functions
(lib 'compile)

;; rational version
(define (q-map-range x xmin xmax ymin ymax) (+ ymin (/ ( * (- x xmin) (- ymax ymin)) (- xmax xmin))))

;; float version
(define (map-range x xmin xmax ymin ymax) (+ ymin (// ( * (- x xmin) (- ymax ymin)) (- xmax xmin))))
; accelerate it
(compile 'map-range "-vf")

(q-map-range 4 0 10 -1 0)
    → -3/5
(map-range 4 0 10 -1 0)
    → -0.6
(linear 4 0 10 -1 0) ;; native
    → -0.6

(for [(x (in-range 0 10))] (writeln x (q-map-range x 0 10 -1 0) (map-range x 0 10 -1 0)))

0     -1     -1
1     -9/10     -0.9
2     -4/5     -0.8
3     -7/10     -0.7
4     -3/5     -0.6
5     -1/2     -0.5
6     -2/5     -0.4
7     -3/10     -0.3
8     -1/5     -0.2
9     -1/10     -0.1


' version 04-12-2016
' compile with: fbc -s console
' when generating a big maze it's possible to run out of stack space
' increase stack with the -t xxxx (xxxx is the amount you want in Kbytes)

ReDim Shared As String d() ' directions
ReDim Shared As ULong c()  ' cell's

Sub cell(x As ULong, y As ULong, s As ULong)

    Dim As ULong x1, y1, di_n
    c(x,y) = 1 ' mark as visited

    Do
        Dim As String di = d(x, y)
        Dim As Long l = Len(di) -1
        If l < 0 Then Exit Sub ' no directions left then exit
        di_n = di[l] ' get direction
        If l = 0 Then
            d(x,y) = ""
        Else
            d(x,y) = Left(di,l)
        End If

        Select Case di_n ' 0,0 is upper left corner
            Case Asc("N")
                x1 = x    : y1 = y -1
            Case Asc("E")
                x1 = x +1 : y1 = y
            Case Asc("S")
                x1 = x    : y1 = y +1
            Case Asc("W")
                x1 = x -1 : y1 = y
        End Select

        If c(x1,y1) <> 0 Then Continue Do

        Select Case di_n ' 0,0 is upper left corner
            Case Asc("N")
                Line (x * s +1 , y * s) - ((x +1) * s -1, y * s),0
            Case Asc("E")
                Line (x1 * s, y * s +1) - (x1 * s, (y +1) * s -1),0
            Case Asc("S")
                Line (x * s +1, y1 * s) - ((x +1) * s -1, y1 * s),0
            Case Asc("W")
                Line (x * s , y * s +1) - (x * s, (y +1) * s -1),0
        End Select

        cell(x1, y1, s)
    Loop

End Sub

Sub gen_maze(w As ULong, h As ULong, s As ULong)

    ReDim d(w, h)
    ReDim c(w, h)
    Dim As ULong x, y, r, i
    Dim As String di

    d(0, 0) = "SE"       ' cornes
    d(0, h -1) ="NE"
    d(w -1, 0) ="SW"
    d(w -1, h -1) ="NW"

    For x = 1 To w -2  ' sides
        d(x,0) = "EWS"
        d(x,h -1) = "NEW"
    Next

    For y = 1 To h -2
        d(0, y) = "NSE"
        d(w -1, y) ="NSW"
    Next

    For x = 0 To w -1     ' shuffle directions
        For y = 0 To h -1
            di = d(x,y)
            If di = "" Then di = "NEWS"
            i = Len(di)
            Do
                r = Fix(Rnd * i)
                i = i - 1
                Swap di[r], di[i]
            Loop Until i = 0
            d(x,y) = di
        Next
    Next

    ScreenRes w * s +1, h * s +1, 8
    ' draw the grid
    For x = 0 To w
        Line (x * s, 0) - (x * s, h * s), 2 ' green color
    Next

    For y = 0 To h
        Line(0, y * s) - (w* s, y * s),2
    Next
    ' choice the start cell
    x = Fix(Rnd * w)
    y = Fix(Rnd * h)

    cell(x, y, s)

End Sub

' ------=< MAIN >=------

Randomize Timer

Dim As ULong t

Do
    ' gen_maxe(width, height, cell size)
    gen_maze(30, 30, 20)
    WindowTitle " S to save, N for next maze, other key to stop"
    Do
    Var key = Inkey
    key = UCase(key)
    If key = "S" Then
        t = t +1
        BSave("maze" + Str(t) + ".bmp"), 0
        key = ""
    End If
    If key = "N" Then Continue Do, Do
    If key <> "" Then Exit Do, Do
    Loop
Loop

End


#lang racket

(define codes '((Α Π) (Ѐ ѵ) (Ҋ ԯ) (Ϣ ϯ) (ｦ ﾝ) (Ⲁ ⳩) (∀ ∗) (℀ ℺) (⨀ ⫿)))

(define (symbol->integer s) (char->integer (string-ref (symbol->string s) 0)))
(define (pick xs) (list-ref xs (random (length xs))))

(define glyphs
  (map
   integer->char
   (append*
    (for/list ([c (in-list codes)])
      (range (symbol->integer (first c)) (add1 (symbol->integer (second c))))))))

(define palette (vector-append (vector "\e[38;2;255;255;255m")
                               (for/vector ([n (in-range 245 29 -10)])
                                 (format "\e[38;2;0;~a;0m" n))
                               (make-vector 75 "\e[38;2;0;25;0m")))

(match-define (list (app (compose1 sub1 string->number) rows)
                    (app string->number cols))
  (string-split (with-output-to-string (thunk (system "stty size")))))

(define screen (for/vector ([_ (in-range (* rows cols))]) (pick glyphs)))
(define offsets (for/vector ([col cols]) (random (vector-length palette))))

(display "\e[?25l\e[48;5;232m") ; hide the cursor, set the background color

(define (main)
  (for ([iter (in-naturals)])
    (sleep 0.1)
    (display "\e[1;1H") ; reset cursor to top left
    (for ([i (in-range 30)]) (vector-set! screen (random (* rows cols)) (pick glyphs)))
    (for ([i (in-range rows)])
      (for ([j (in-range cols)])
        (display (vector-ref palette (modulo (+ (- i) iter (vector-ref offsets j))
                                             (vector-length palette))))
        (display (vector-ref screen (+ (* cols i) j))))
      (display "\n"))))

(with-handlers ([exn:break? (thunk*
                             ; reset ANSI codes, reshow cursor, clear screen
                             (display "\e[0m")
                             (display "\e[H\e[J\e[?25h"))])
  (main))


# clean up on exit, reset ANSI codes, scroll, re-show the cursor & clear screen
signal(SIGINT).tap: { print "\e[0m", "\n" xx 50, "\e[H\e[J\e[?25h"; exit(0) }

# a list of glyphs to use
my @codes = flat 'Α' .. 'Π', 'Ѐ' .. 'ѵ', 'Ҋ' .. 'ԯ', 'Ϣ' .. 'ϯ', 'ｦ'.. 'ﾝ',
                 'Ⲁ' .. '⳩', '∀' .. '∗', '℀' .. '℺', '⨀' .. '⫿';

# palette of gradient ANSI foreground colors
my @palette = flat  "\e[38;2;255;255;255m", (255,245 … 30).map({"\e[38;2;0;$_;0m"}),
              "\e[38;2;0;25;0m" xx 75;

my @screen; # buffer to hold glyphs
my @rotate; # palette rotation position buffer

my ($rows, $cols) = qx/stty size/.words; # get the terminal size
init($rows, $cols); # set up the screen buffer and palette offsets

my $size-check;

print "\e[?25l\e[48;5;232m"; # hide the cursor, set the background color

loop {
     if ++$size-check %% 20 {                         # periodically check for
         my ($r, $c) = qx/stty size/.words;           # resized terminal and
         init($r, $c) if $r != $rows or $c != $cols;  # re-initialize screen buffer
         $size-check = 0
     }
     print "\e[1;1H";                                 # set cursor to top left
     print join '', (^@screen).map: {
         @rotate[$_] = (@rotate[$_] + 1) % +@palette; # rotate the palettes
         flat @palette[@rotate[$_]], @screen[$_]      # and print foreground, glyph
     }
     @screen[(^@screen).pick] = @codes.roll for ^30;  # replace some random glyphs
}

sub init ($r, $c) {
    @screen = @codes.roll($r * $c);
    ($rows, $cols) = $r, $c;
    my @offset = (^@palette).pick xx $cols;
    for ^$rows -> $row {
        @rotate[$row * $cols ..^ $row * $cols + $cols] = @offset;
        # for no "lightning" effect, add   '1 + '  ↓ here: (1 + $_ % 3)
        @offset = (^@offset).map: {(@offset[$_] - ($_ % 3)) % +@palette};
    }
}


package main

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

type maze struct {
    c  []byte   // cell contents
    h  []byte   // horizontal walls above cells
    v  []byte   // vertical walls to the left of cells
    c2 [][]byte // cells by row
    h2 [][]byte // horizontal walls by row (ignore first row)
    v2 [][]byte // vertical walls by row (ignore first of each column)
}

func newMaze(rows, cols int) *maze {
    c := make([]byte, rows*cols)              // all cells
    h := bytes.Repeat([]byte{'-'}, rows*cols) // all horizontal walls
    v := bytes.Repeat([]byte{'|'}, rows*cols) // all vertical walls
    c2 := make([][]byte, rows)                // cells by row
    h2 := make([][]byte, rows)                // horizontal walls by row
    v2 := make([][]byte, rows)                // vertical walls by row
    for i := range h2 {
        c2[i] = c[i*cols : (i+1)*cols]
        h2[i] = h[i*cols : (i+1)*cols]
        v2[i] = v[i*cols : (i+1)*cols]
    }
    return &maze{c, h, v, c2, h2, v2}
}

func (m *maze) String() string {
    hWall := []byte("+---")
    hOpen := []byte("+   ")
    vWall := []byte("|   ")
    vOpen := []byte("    ")
    rightCorner := []byte("+\n")
    rightWall := []byte("|\n")
    var b []byte
    // for all rows
    for r, hw := range m.h2 {
        // draw h walls
        for _, h := range hw {
            if h == '-' || r == 0 {
                b = append(b, hWall...)
            } else {
                b = append(b, hOpen...)
            }
        }
        b = append(b, rightCorner...)
        // draw v walls
        for c, vw := range m.v2[r] {
            if vw == '|' || c == 0 {
                b = append(b, vWall...)
            } else {
                b = append(b, vOpen...)
            }
            // draw cell contents
            if m.c2[r][c] != 0 {
                b[len(b)-2] = m.c2[r][c]
            }
        }
        b = append(b, rightWall...)
    }
    // draw bottom edge of maze
    for _ = range m.h2[0] {
        b = append(b, hWall...)
    }
    b = append(b, rightCorner...)
    return string(b)
}

func (m *maze) gen() {
    m.g2(rand.Intn(len(m.c2)), rand.Intn(len(m.c2[0])))
}

const (
    up = iota
    dn
    rt
    lf
)

func (m *maze) g2(r, c int) {
    m.c2[r][c] = ' '
    for _, dir := range rand.Perm(4) {
        switch dir {
        case up:
            if r > 0 && m.c2[r-1][c] == 0 {
                m.h2[r][c] = 0
                m.g2(r-1, c)
            }
        case lf:
            if c > 0 && m.c2[r][c-1] == 0 {
                m.v2[r][c] = 0
                m.g2(r, c-1)
            }
        case dn:
            if r < len(m.c2)-1 && m.c2[r+1][c] == 0 {
                m.h2[r+1][c] = 0
                m.g2(r+1, c)
            }
        case rt:
            if c < len(m.c2[0])-1 && m.c2[r][c+1] == 0 {
                m.v2[r][c+1] = 0
                m.g2(r, c+1)
            }
        }
    }
}

func main() {
    rand.Seed(time.Now().UnixNano())
    m := newMaze(4, 6)
    m.gen()
    fmt.Print(m)
}


/*REXX program creates/displays Matrix (the movie) digital rain; favors non-Latin chars.*/
signal on halt                                   /*allow the user to halt/stop this pgm.*/
parse arg pc seed .                              /*obtain optional arguments from the CL*/
if pc=='' | pc==","     then pc= 20              /*Not specified?  Then use the default.*/
if datatype(seed, 'W')  then call random ,,seed  /*Numeric?  Use seed for repeatability.*/
parse value  scrsize()  with  sd  sw  .          /*obtain the dimensions of the screen. */
if sd==0  then sd= 54;  sd= sd - 2 + 1           /*Not defined? Then use default; adjust*/
if sw==0  then sw= 80;  sw= sw - 1               /* "      "      "   "     "        "  */
lowC= c2d(' ')  +  1                             /*don't use any characters  ≤  a blank.*/
@.= ' '                                          /*PC  is the % new Matric rain streams.*/
cloud= copies(@., sw)                            /*the cloud, where matrix rain is born.*/
cls= 'CLS'                                       /*DOS command used to clear the screen.*/
                  do  forever;   call nimbus     /*define bottom of cloud  (the drops). */
                                 call rain       /*generate rain, display the raindrops.*/
                  end   /*j*/
halt:  exit                                      /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
rain:   do a=sd  by -1  for sd-1;   _= a-1;   @.a= @._;   end;      call fogger;    return
show:   cls;  @.1= cloud;    do r=1  for sd;  say strip(@.r, 'T');  end  /*r*/;     return
/*──────────────────────────────────────────────────────────────────────────────────────*/
nimbus: if random(, 100)<pc  then call mist      /*should this be a new rain stream ?   */
                             else call unmist    /*should any of the rain streams cease?*/
        return                                   /*note: this subroutine may pass──►MIST*/
        if random(, 100)<pc         then return  /*should this be a new rain stream ?   */
        ?= random(1, sw)                         /*pick a random rain cloud position.   */
        if substr(cloud,?,1)\==' '  then return  /*Is cloud position not a blank? Return*/
/*───── ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ────────────────────────────────────────────────────*/
mist:   ?= random(1, sw)                         /*obtain a random column in cloud.     */
        if substr(cloud,?,1)\==' '  then return  /*if this stream is active, return.    */
        if random(, 100)<pc         then return  /*should this be a new rain stream ?   */
        cloud= overlay(drop(), cloud, ?)         /*seed cloud with new matrix rain drop.*/
        return
/*──────────────────────────────────────────────────────────────────────────────────────*/
unmist: ?= random(1, sw)                         /*obtain a random column in cloud.     */
        if substr(cloud,?,1) ==' '  then return  /*if this stream is dry,  return.      */
        if random(, 100)>pc         then return  /*should this be a new dry stream ?    */
        cloud= overlay(' ', cloud, ?);   return  /*seed cloud with new matrix rain drop.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
drop:   Lat= random(1, 4)                        /*Now, chose a matrix rain stream char.*/
        tChr= 254;    if Lat==1  then tChr= 127  /*choose the  type of rain stream char.*/
        return d2c( random(lowC, tChr) )         /*Lat = 1?   This favors Latin letters.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
fogger: do f=1  for sw                           /*display a screen full of rain streams*/
        if substr(cloud, f, 1) \== ' '   then cloud= overlay( drop(), cloud, f)
        end   /*f*/;        call show;   return  /* [↑]  if raindrop, then change drop. */


defmodule RC do
  def map_range(a1 .. a2, b1 .. b2, s) do
    b1 + (s - a1) * (b2 - b1) / (a2 - a1)
  end
end

Enum.each(0..10, fn s ->
  :io.format "~2w map to ~7.3f~n", [s, RC.map_range(0..10, -1..0, s)]
end)


import "dome" for Window
import "graphics" for Canvas, Color, Font
import "random" for Random

var Rand = Random.new()

class MatrixDigitalRain {
    construct new(width, height) {
        Window.resize(width, height)
        Canvas.resize(width, height)
        Window.title = "Matrix digital rain"
        Font.load("Mem12", "memory.ttf", 24)
        Canvas.font = "Mem12"
    }

    letter(x, y, r, g, b) {
        if (y < 0 || y >= _my) return
        var col = Color.rgb(r, g, b)
        var c = String.fromByte(_scr[x][y])
        Canvas.print(c, x * 12.8 , y * 12.8 , col)
    }

    init() {
        _mx = 50
        _my = 42
        _scr = List.filled(_mx, null)
        for (x in 0..._mx) {
            _scr[x] = List.filled(_my, 0)
            for (y in 0..._my) _scr[x][y] = Rand.int(33, 128)
        }
        _ms = 50
        _sx = List.filled(_ms, 0)
        _sy = List.filled(_ms, 0)
    }

    update() {
        for (a in 0..._ms) {
            _sx[a] = Rand.int(_mx)
            _sy[a] = Rand.int(_my)
        }
    }

    draw(alpha) {
        for (s in 0..._ms) {
            var x = _sx[s]
            var y = _sy[s]
            letter(x, y, 0, 255, 0)
            y = y - 1
            letter(x, y, 0, 200, 0)
            y = y - 1
            letter(x, y, 0, 150, 0)
            y = y - 1
            if (y*12.8 + 3 < 0) y = 0
            var c = Color.rgb(0, 0, 0)
            Canvas.rectfill(x*12.8, y*12.8 + 3, 13, 14, c)
            letter(x, y, 0, 70, 0)
            y = y - 24
            if (y*12.8 + 3 < 0) y = 0
            Canvas.rectfill(x*12.8, y*12.8  + 3, 13, 14, c)
        }
        for (s in 0..._ms) {
            if (Rand.int(1, 6) == 1) _sy[s] = _sy[s] + 1
            if (_sy[s] > _my + 25) {
                _sy[s] = 0
                _sx[s] = Rand.int(_mx)
            }
        }
    }
}

var Game = MatrixDigitalRain.new(640, 550)


PROGRAM RANGE

BEGIN
      AL=0   AH=10
      BL=-1  BH=0
      FOR N=0 TO 10 DO
        RANGE=BL+(N-AL)*(BH-BL)/(AH-AL)
        WRITE("### maps to ##.##";N;RANGE)
!        PRINT(N;" maps to ";RANGE)
      END FOR
END PROGRAM


function map_range(sequence a, sequence b, atom s)
    return b[1]+(s-a[1])*(b[2]-b[1])/(a[2]-a[1])
end function

for i = 0 to 10 do
    printf(1, "%2g maps to %4g\n", {i, map_range({0,10},{-1,0},i)})
end for


{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}

import Data.Array.ST
       (STArray, freeze, newArray, readArray, writeArray)
import Data.STRef (STRef, newSTRef, readSTRef, writeSTRef)
import System.Random (Random(..), getStdGen, StdGen)
import Control.Monad (forM_, unless)
import Control.Monad.ST (ST, stToIO)
import Data.Array (Array, (!), bounds)
import Data.Bool (bool)

rand
  :: Random a
  => (a, a) -> STRef s StdGen -> ST s a
rand range gen = do
  (a, g) <- randomR range <$> readSTRef gen
  gen `writeSTRef` g
  return a

data Maze = Maze
  { rightWalls, belowWalls :: Array (Int, Int) Bool
  }

maze :: Int -> Int -> StdGen -> ST s Maze
maze width height gen = do
  visited <- mazeArray False
  rWalls <- mazeArray True
  bWalls <- mazeArray True
  gen <- newSTRef gen
  (,) <$> rand (0, maxX) gen <*> rand (0, maxY) gen >>=
    visit gen visited rWalls bWalls
  Maze <$> freeze rWalls <*> freeze bWalls
  where
    visit gen visited rWalls bWalls here = do
      writeArray visited here True
      let ns = neighbors here
      i <- rand (0, length ns - 1) gen
      forM_ (ns !! i : take i ns ++ drop (i + 1) ns) $
        \there -> do
          seen <- readArray visited there
          unless seen $
            do removeWall here there
               visit gen visited rWalls bWalls there
      where
        removeWall (x1, y1) (x2, y2) =
          writeArray (bool rWalls bWalls (x1 == x2)) (min x1 x2, min y1 y2) False
    neighbors (x, y) =
      bool [(x - 1, y)] [] (0 == x) ++
      bool [(x + 1, y)] [] (maxX == x) ++
      bool [(x, y - 1)] [] (0 == y) ++ bool [(x, y + 1)] [] (maxY == y)
    maxX = width - 1
    maxY = height - 1
    mazeArray =
      newArray ((0, 0), (maxX, maxY)) :: Bool -> ST s (STArray s (Int, Int) Bool)

printMaze :: Maze -> IO ()
printMaze (Maze rWalls bWalls) = do
  putStrLn $ '+' : concat (replicate (maxX + 1) "---+")
  forM_ [0 .. maxY] $
    \y -> do
      putStr "|"
      forM_ [0 .. maxX] $
        \x -> do
          putStr "   "
          putStr $ bool " " "|" (rWalls ! (x, y))
      putStrLn ""
      forM_ [0 .. maxX] $
        \x -> do
          putStr "+"
          putStr $ bool "   " "---" (bWalls ! (x, y))
      putStrLn "+"
  where
    maxX = fst (snd $ bounds rWalls)
    maxY = snd (snd $ bounds rWalls)

main :: IO ()
main = getStdGen >>= stToIO . maze 11 8 >>= printMaze


open window 640,512,"swiss12"
backcolor 0,0,0
clear window
mx=50
my=42
dim scr(mx,my)
for y=0 to my
    for x=0 to mx
        scr(x,y)=int(ran(96)+33)
    next x
next y
ms=50
dim sx(ms)
dim sy(ms)
for a=1 to ms
    sx(a)=int(ran(mx))
    sy(a)=int(ran(my))
next a
do
    for s=1 to ms
        x=sx(s)
        y=sy(s)

        letter(0,255,0)
        y=y-1

        letter(0,200,0)
        y=y-1

        letter(0,150,0)
        y=y-1

        color 0,0,0
        fill rect x*12.8-1,y*12.8+4 to x*12.8+12,y*12.8-10
        letter(0,70,0)
        y=y-24

        color 0,0,0
        fill rect x*12.8-1,y*12.8+4 to x*12.8+12,y*12.8-10
    next s
    for s=1 to ms
        if int(ran(5)+1)=1 sy(s)=sy(s)+1
        if sy(s)>my+25 then
            sy(s)=0
            sx(s)=int(ran(mx))
        end if
    next s
loop

sub letter(r,g,b)
    if y<0 or y>my return
    c=scr(x,y)
    color r,g,b
    text x*12.8,y*12.8,chr$(c)
end sub


var [const] codes=Walker.chain(  // a bunch of UTF non ascii chars
         [0x0391..0x03a0], [0x03a3..0x0475], [0x0400..0x0475],
         [0x048a..0x052f], [0x03e2..0x03ef], [0x2c80..0x2ce9],
         [0x2200..0x2217], [0x2100..0x213a], [0x2a00..0x2aff])
	 .apply(fcn(utf){ utf.toString(-8) }),  // jeez this is lame
    codeSz=codes.len(),	// 970
    c=L("\e[38;2;255;255;255m",[255..30,-15].apply("\e[38;2;0;%d;0m".fmt),
        (250).pump(List,T(Void,"\e[38;2;0;25;0m"))).flatten(),
    csz=c.len(); // 267, c is ANSI escape code fg colors: 38;2;<r;g;b>m

// query the ANSI terminal
rows,cols := System.popen("stty size","r").readln().split().apply("toInt");

o,s,fg := buildScreen(rows,cols);
ssz:=s.len();

print("\e[?25l\e[48;5;232m");  // hide the cursor, set background color to dark
while(1){		       // ignore screen resizes
   print("\e[1;1H");	       // move cursor to 1,1
   foreach n in (ssz){	       // print a screen full
      print( c[fg[n]], s[n] ); // forground color, character
      fg[n]=(fg[n] + 1)%csz;   // fade to black
   }
   do(100){ s[(0).random(ssz)]=codes[(0).random(codeSz)] }  // some new chars
   Atomic.sleep(0.1);	       // frame rate for my system, up to 200x41 terminal
}

fcn buildScreen(rows,cols){    // build a row major array as list
   // s --> screen full of characters
   s:=(rows*cols).pump(List(), fcn{ codes[(0).random(codeSz)]});
   // array fb-->( fg color, fg ..) where fg is an ANSI term 48;5;<n>m color
   fg:=List.createLong(s.len(),0);
   o:=csz.pump(List()).shuffle()[0,cols];  // cols random #s
   foreach row in (rows){		   // set fg indices
      foreach col in (cols){ fg[row*cols + col] = o[col] }
      o=o.apply(fcn(n){ n-=1; if(n<0) n=csz-1; n%csz });  // fade out
   }
   return(o,s,fg);
}


10 CLEAR 61999
20 BORDER 0: POKE 23624,4: POKE 23693,0: CLS: REM easier than "bright 0: flash 0: ink 0: paper 0"
30 PRINT INK 4; FLASH 1;"Initialising": GO SUB 9000: LET m=USR 62000: CLS: REM set up and run machine code; USR is the call function
40 DIM s(32,2): REM current top and bottom of character sequence for each of the 32 spaces across the screen

50 FOR x=1 TO 32: REM main loop
60 IF s(x,1)=0 AND RND>.95 THEN LET s(x,1)=1: LET s(x,2)=2: GO SUB 4000: GO SUB 3000: GO TO 80: REM start a new column; decrease the .95 modifier for a busier - but slower - screen
70 IF s(x,2)>0 THEN GO SUB 1000
80 NEXT x
90 FOR l=1 TO 10: REM matrix code switches existing glyphs occasionally
100 LET x=INT (RND*22): LET y=INT (RND*32)
110 IF PEEK (22528+32*x+y)=0 THEN GO TO 140: REM no point updating a blank space
120 GO SUB 4000
130 PRINT AT x,y; INK 8; BRIGHT 8;CHR$ (33+RND*95): REM ink 8 and bright 8 tells it to keep the cell's existing ink and bright values
140 NEXT l
150 GO TO 50

999 REM continue an existing column
1000 LET s(x,2)=s(x,2)+1
1010 IF s(x,2)<21 THEN GO SUB 3000
1020 IF s(x,2)>12 THEN LET s(x,1)=s(x,1)+1
1030 LET k=2
1040 GO SUB 2000
1050 LET k=6
1060 GO SUB 2000
1070 LET k=12
1080 GO SUB 2000
1090 IF s(x,1)=22 THEN LET s(x,1)=0: LET s(x,2)=0
1100 RETURN

1999 REM update colour
2000 LET a=22527+x+32*(s(x,2)-k)
2010 LET c=PEEK a
2020 IF c=4 THEN POKE a,0
2030 IF c=68 THEN POKE a,4
2040 IF c=71 THEN POKE a,68: REM this poke could be done with 'print at s(x,2)-k-1,x-1; ink 4; bright 1; over 1; " " ' but poking is FAR easier, especially considering the above pokes would be similar
2050 RETURN

2999 REM new character at bottom of column
3000 PRINT AT s(x,2)-1,x-1; INK 7; BRIGHT 1;CHR$ (33+RND*95)
3010 RETURN

3999 REM select character set
4000 POKE 23607,242+3*INT (RND*4): REM the spectrum character set is pointed to by the two-byte system value CHARS at 23606 and 23607, so repoking this selects a new character set - the machine code below has created four copies of the character set at suitable locations
4010 RETURN

8999 REM machine code routine to create multiple character sets
9000 RESTORE 9800
9010 LET h$="0123456789ABCDEF"
9020 LET o=62000
9030 IF PEEK o=33 AND PEEK 62121=201 THEN RETURN: REM saves storing it all again if the machine code is already there
9040 READ a$
9050 IF a$="eof" THEN RETURN
9060 FOR x=1 TO 8
9070 LET n=0
9080 LET s=(x*2)-1
9090 LET t=s+1
9100 FOR m=1 TO 16
9110 IF h$(m)=a$(s) THEN LET n=n+16*(m-1)
9120 IF h$(m)=a$(t) THEN LET n=n+m-1
9130 NEXT m
9140 POKE o,n
9150 LET o=o+1
9160 NEXT x
9170 GO TO 9040

9800 DATA "21003D1100F30100"
9810 DATA "03EDB02100F31100"
9820 DATA "F6010009EDB01100"
9830 DATA "F901FF051A6F0707"
9840 DATA "ADE6AAAD6F070707"
9850 DATA "CB0DADE666AD1213"
9860 DATA "0B78B120E721FFF5"
9870 DATA "010000E5CD8BF2E1"
9880 DATA "E5CD8BF2E1E5CD8B"
9890 DATA "F2E1CD8BF2232323"
9900 DATA "23AF470C79FEC0C2"
9910 DATA "6BF2C9E5D1043E09"
9920 DATA "90835F8A93577885"
9930 DATA "6F8C95671AE521AA"
9940 DATA "F277E17E123AAAF2"
9950 DATA "77C9000000000000"
9960 DATA "eof"

9999 POKE 23606,0: POKE 23607,60: INK 4: REM reset to default character set and colour if you get lost


*        Matrix multiplication     06/08/2015
MATRIXRC CSECT                     Matrix multiplication
         USING  MATRIXRC,R13
SAVEARA  B      STM-SAVEARA(R15)
         DC     17F'0'
STM      STM    R14,R12,12(R13)
         ST     R13,4(R15)
         ST     R15,8(R13)
         LR     R13,R15
         LA     R7,1               i=1
LOOPI1   CH     R7,M               do i=1 to m (R7)
         BH     ELOOPI1
         LA     R8,1               j=1
LOOPJ1   CH     R8,P               do j=1 to p (R8)
         BH     ELOOPJ1
         LR     R1,R7              i
         BCTR   R1,0
         MH     R1,P
         LR     R6,R8              j
         BCTR   R6,0
         AR     R1,R6
         SLA    R1,2
         LA     R6,0
         ST     R6,C(R1)           c(i,j)=0
         LA     R9,1               k=1
LOOPK1   CH     R9,N               do k=1 to n (R9)
         BH     ELOOPK1
         LR     R1,R7              i
         BCTR   R1,0
         MH     R1,P
         LR     R6,R8              j
         BCTR   R6,0
         AR     R1,R6
         SLA    R1,2
         L      R2,C(R1)           R2=c(i,j)
         LR     R10,R1             R10=offset(i,j)
         LR     R1,R7              i
         BCTR   R1,0
         MH     R1,N
         LR     R6,R9              k
         BCTR   R6,0
         AR     R1,R6
         SLA    R1,2
         L      R3,A(R1)           R3=a(i,k)
         LR     R1,R9              k
         BCTR   R1,0
         MH     R1,P
         LR     R6,R8              j
         BCTR   R6,0
         AR     R1,R6
         SLA    R1,2
         L      R4,B(R1)           R4=b(k,j)
         LR     R15,R3             a(i,k)
         MR     R14,R4             a(i,k)*b(k,j)
         LR     R3,R15
         AR     R2,R3              R2=R2+a(i,k)*b(k,j)
         ST     R2,C(R10)          c(i,j)=c(i,j)+a(i,k)*b(k,j)
         LA     R9,1(R9)           k=k+1
         B      LOOPK1
ELOOPK1  LA     R8,1(R8)           j=j+1
         B      LOOPJ1
ELOOPJ1  LA     R7,1(R7)           i=i+1
         B      LOOPI1
ELOOPI1  MVC    Z,=CL80' '         clear buffer
         LA     R7,1
LOOPI2   CH     R7,M               do i=1 to m
         BH     ELOOPI2
         LA     R8,1
LOOPJ2   CH     R8,P               do j=1 to p
         BH     ELOOPJ2
         LR     R1,R7              i
         BCTR   R1,0
         MH     R1,P
         LR     R6,R8              j
         BCTR   R6,0
         AR     R1,R6
         SLA    R1,2
         L      R6,C(R1)           c(i,j)
         LA     R3,Z
         AH     R3,IZ
         XDECO  R6,W
         MVC    0(5,R3),W+7        output c(i,j)
         LH     R3,IZ
         LA     R3,5(R3)
         STH    R3,IZ
         LA     R8,1(R8)           j=j+1
         B      LOOPJ2
ELOOPJ2  XPRNT  Z,80               print buffer
         MVC    IZ,=H'0'
         LA     R7,1(R7)           i=i+1
         B      LOOPI2
ELOOPI2  L      R13,4(0,R13)
         LM     R14,R12,12(R13)
         XR     R15,R15
         BR     R14
A        DC     F'1',F'2',F'3',F'4',F'5',F'6',F'7',F'8'  a(4,2)
B        DC     F'1',F'2',F'3',F'4',F'5',F'6'            b(2,3)
C        DS     12F                                      c(4,3)
N        DC     H'2'               dim(a,2)=dim(b,1)
M        DC     H'4'               dim(a,1)
P        DC     H'3'               dim(b,2)
Z        DS     CL80
IZ       DC     H'0'
W        DS     CL16
         YREGS
         END    MATRIXRC


INCLUDE "D2:PRINTF.ACT" ;from the Action! Tool Kit

DEFINE PTR="CARD"

TYPE Matrix=[
  BYTE width,height
  PTR data] ;INT ARRAY

PROC PrintMatrix(Matrix POINTER m)
  BYTE i,j
  INT ARRAY d
  CHAR ARRAY s(10)

  d=m.data
  FOR j=0 TO m.height-1
  DO
    FOR i=0 TO m.width-1
    DO
      StrI(d(j*m.width+i),s)
      PrintF("%2S ",s)
    OD
    PutE()
  OD
RETURN

PROC Create(MATRIX POINTER m BYTE w,h INT ARRAY a)
  m.width=w
  m.height=h
  m.data=a
RETURN

PROC MatrixMul(Matrix POINTER m1,m2,res)
  BYTE i,j,k
  INT ARRAY d1,d2,dres,sum

  IF m1.width#m2.height THEN
    Print("Invalid size of matrices for multiplication!")
    Break()
  FI
  d1=m1.data
  d2=m2.data
  dres=res.data

  res.width=m2.width
  res.height=m1.height

  FOR j=0 TO res.height-1
  DO
    FOR i=0 TO res.width-1
    DO
      sum=0
      FOR k=0 TO m1.width-1
      DO
        sum==+d1(k+j*m1.width)*d2(i+k*m2.width)
      OD
      dres(j*res.width+i)=sum
    OD
  OD
RETURN

PROC Main()
  MATRIX m1,m2,res
  INT ARRAY
    d1=[2 1 4 0 1 1],
    d2=[6 3 65535 0 1 1 0 4 65534 5 0 2],
    dres(8)

  Put(125) PutE() ;clear the screen

  Create(m1,3,2,d1)
  Create(m2,4,3,d2)
  Create(res,0,0,dres)
  MatrixMul(m1,m2,res)

  PrintMatrix(m1)
  PutE() PrintE("multiplied by") PutE()
  PrintMatrix(m2)
  PutE() PrintE("equals") PutE()
  PrintMatrix(res)
RETURN


let map (a1: float) (a2: float) (b1: float) (b2: float) (s: float): float =
    b1 + (s - a1) * (b2 - b1) / (a2 - a1)

let xs = [| for i in 0..10 -> map 0.0 10.0 -1.0 0.0 (float i) |]

for x in xs do printfn "%f" x


USE: locals
:: map-range ( a1 a2 b1 b2 x -- y )
   x a1 - b2 b1 - * a2 a1 - / b1 + ;


class FRange
{
  const Float low
  const Float high
  // in constructing a range, ensure the low value is smaller than high
  new make (Float low, Float high)
  {
    this.low = ( low <= high ? low : high )
    this.high = ( low <= high ? high : low )
  }

  // return range as a string
  override Str toStr () { "[$low,$high]" }

  // return a point in given range interpolated into this range
  Float remap (Float point, FRange given)
  {
    this.low + (point - given.low) * (this.high - this.low) / (given.high - given.low)
  }
}

class Main
{
  public static Void main ()
  {
    range1 := FRange (0f, 10f)
    range2 := FRange (-1f, 0f)
    11.times |Int n|
    {
      m := range2.remap (n.toFloat, range1)
      echo ("Value $n in ${range1} maps to $m in ${range2}")
    }
  }
}


import Algorithms as algo;
import Mathematics as math;
import Terminal as term;

class Maze {
	_rows = none;
	_cols = none;
	_data = none;
	constructor( rows_, cols_ ) {
		_rows = ( rows_ / 2 ) * 2 - 1;
		_cols = ( cols_ / 2 ) * 2 - 1;
		_data = [].resize( _rows + 2, [].resize( _cols + 2, false ) );
		x = 0;
		y = 0;
		path = [];
		rng = math.Randomizer( math.Randomizer.DISTRIBUTION.DISCRETE, 0, integer( $2 ^ $63 - $1 ) );
		for ( _ : algo.range( _rows * _cols / 3 ) ) {
			_data[y + 1][x + 1] = true;
			while ( true ) {
				n = neighbours( y, x );
				ns = size( n );
				if ( ns == 0 ) {
					if ( size( path ) == 0 ) {
						break;
					}
					y, x = path[-1];
					path.pop();
					continue;
				}
				oy, ox = ( y, x );
				y, x = n[rng.next() % ns];
				_data[(y + oy) / 2 + 1][(x + ox) / 2 + 1] = true;
				path.push( ( y, x ) );
				break;
			}
		}
		_data[0][1] = true;
		_data[-1][-2] = true;
	}
	neighbours( y_, x_ ) {
		n = [];
		if ( ( x_ > 1 ) && ! _data[y_ + 1][x_ - 1] ) {
			n.push( ( y_, x_ - 2 ) );
		}
		if ( ( y_ > 1 ) && ! _data[y_ - 1][x_ + 1] ) {
			n.push( ( y_ - 2, x_ ) );
		}
		if ( ( x_ < ( _cols - 2 ) ) && ! _data[y_ + 1][x_ + 3] ) {
			n.push( ( y_, x_ + 2 ) );
		}
		if ( ( y_ < ( _rows - 2 ) ) && ! _data[y_ + 3][x_ + 1] ) {
			n.push( ( y_ + 2, x_ ) );
		}
		return ( n );
	}
	to_string() {
		s = "";
		for ( r : _data ) {
			s += ∑( algo.map( r, @( b ) { b ? " " : "#"; } ) );
			s += "\n";
		}
		return ( s );
	}
}

main() {
	rows = term.lines() - 2;
	cols = term.columns() - 1;
	maze = Maze( rows, cols );
	print( "{}".format( maze ) );
}


link printf

procedure main(A)                               # generate rows x col maze
   /mh := \A[1] | 12                            # or take defaults 12 x 16
   /mw := \A[2] | 16
   mz := DisplayMaze(GenerateMaze(mh,mw))
   WriteImage(mz.filename)                      # save file
   WAttrib(mz.window,"canvas=normal")           # show maze in hidden window
   until Event() == &lpress                     # wait for left mouse press
   close(mz.window)
end

$define FINISH 64 # exit
$define START  32 # entrance
$define PATH  128
$define SEEN   16 # bread crumbs for generator
$define NORTH   8 # sides ...
$define EAST    4
$define SOUTH   2
$define WEST    1
$define EMPTY   0 # like new

procedure GenerateMaze(r,c)                     #: Depth First Maze Generation
static maze,h,w,rd
   if /maze then {                              # BEGING - No maze yet
      /h := integer(1 < r) | runerr(r,205)      # valid size 2x2 or better
      /w := integer(1 < c) | runerr(r,205)
      every !(maze := list(h)) := list(w,EMPTY) # shinny new empty maze
      start  := [?h,?w,?4-1,START]              # random [r,c] start & finish
      finish := [?h,?w,(start[3]+2)%4,FINISH]   # w/ opposite side exponent
      every x := start | finish do {
         case x[3] := 2 ^ x[3] of {             # get side from exponent and
            NORTH : x[1] := 1                   # project r,c to selected edge
            EAST  : x[2] := w
            SOUTH : x[1] := h
            WEST  : x[2] := 1
            }
         maze[x[1],x[2]] +:= x[3] + x[4]        # transcribe s/f to maze
         }
      rd := [NORTH, EAST, SOUTH, WEST]          # initial list of directions
      GenerateMaze(start[1],start[2])           # recurse through maze
      return 1(.maze,maze := &null)             # return maze, reset for next
   }
   else {         # ----------------------- recursed to clear insize of maze
      if iand(maze[r,c],SEEN) = 0 then {        # in bounds and not SEEN yet?
         maze[r,c] +:= SEEN                     # Mark current cell as visited
         every !rd :=: ?rd                      # randomize list of directions
         every d := !rd do
            case d of {                         # try all, succeed & clear wall
               NORTH :  maze[r,c] +:= ( GenerateMaze(r-1,c), NORTH)
               EAST  :  maze[r,c] +:= ( GenerateMaze(r,c+1),  EAST)
               SOUTH :  maze[r,c] +:= ( GenerateMaze(r+1,c), SOUTH)
               WEST  :  maze[r,c] +:= ( GenerateMaze(r,c-1),  WEST)
               }
         return                                 # signal success to caller
         }
   }
end

$define CELL   20                                   # cell size in pixels
$define BORDER 30                                   # border size in pixels

record mazeinfo(window,maze,filename)               # keepers

procedure DisplayMaze(maze)                         #: show it off
if CELL < 8 then runerr(205,CELL)                   # too small

wh := (ch := (mh := *maze  ) * CELL) + 2 * BORDER   # win, cell, maze height
ww := (cw := (mw := *maze[1]) * CELL) + 2 * BORDER  # win, cell, maze width

wparms := [ sprintf("Maze %dx%d",*maze,*maze[1]),   # window parameters
            "g","bg=white","canvas=hidden",
            sprintf("size=%d,%d",ww,wh),
            sprintf("dx=%d",BORDER),
            sprintf("dy=%d",BORDER)]

&window := open!wparms | stop("Unable to open Window")

Fg("black")                                         # Draw full grid
every DrawLine(x := 0 to cw by CELL,0,x,ch+1)       # . verticals
every DrawLine(0,y := 0 to ch by CELL,cw+1,y)       # . horizontals

Fg("white")                                         # Set to erase lines
every y := CELL*((r := 1 to mh)-1) & x := CELL*((c := 1 to mw)-1) do {
   WAttrib("dx="||x+BORDER,"dy="||y+BORDER)         # position @ cell r,c
   if iand(maze[r,c],NORTH) > 0 then DrawLine(2,0,CELL-1,0)
   if iand(maze[r,c],EAST)  > 0 then DrawLine(CELL,2,CELL,CELL-1)
   if iand(maze[r,c],SOUTH) > 0 then DrawLine(2,CELL,CELL-1,CELL)
   if iand(maze[r,c],WEST)  > 0 then DrawLine(0,2,0,CELL-1)
   }

return mazeinfo(&window,maze,sprintf("maze-%dx%d-%d.gif",r,c,&now))
end


with Ada.Text_IO;               use Ada.Text_IO;
with Ada.Numerics.Real_Arrays;  use Ada.Numerics.Real_Arrays;

procedure Matrix_Product is

   procedure Put (X : Real_Matrix) is
      type Fixed is delta 0.01 range -100.0..100.0;
   begin
      for I in X'Range (1) loop
         for J in X'Range (2) loop
            Put (Fixed'Image (Fixed (X (I, J))));
         end loop;
         New_Line;
      end loop;
   end Put;

   A : constant Real_Matrix :=
         (  ( 1.0,  1.0,  1.0,   1.0),
            ( 2.0,  4.0,  8.0,  16.0),
            ( 3.0,  9.0, 27.0,  81.0),
            ( 4.0, 16.0, 64.0, 256.0)
         );
   B : constant Real_Matrix :=
         (  (  4.0,     -3.0,      4.0/3.0,  -1.0/4.0 ),
            (-13.0/3.0, 19.0/4.0, -7.0/3.0,  11.0/24.0),
            (  3.0/2.0, -2.0,      7.0/6.0,  -1.0/4.0 ),
            ( -1.0/6.0,  1.0/4.0, -1.0/6.0,   1.0/24.0)
         );
begin
   Put (A * B);
end Matrix_Product;


\ linear interpolation

: lerp ( b2 b1 a2 a1 s -- t )
  fover f-
  frot frot f- f/
  frot frot fswap fover f- frot f*
  f+ ;

: test   11 0 do  0e -1e 10e 0e i s>f lerp f.  loop ;


program Map
  implicit none

  real :: t
  integer :: i

  do i = 0, 10
    t = Maprange((/0.0, 10.0/), (/-1.0, 0.0/), real(i))
    write(*,*) i, " maps to ", t
  end do

contains

function Maprange(a, b, s)
  real :: Maprange
  real, intent(in) :: a(2), b(2), s

  Maprange = (s-a(1)) * (b(2)-b(1)) / (a(2)-a(1)) + b(1)

end function Maprange
end program Map


Function MapRange(s As Integer, a1 As Integer, a2 As Integer, b1 As Integer, b2 As Integer) As Double
    Return b1+(s-a1)*(b2-b1)/(a2-a1)
End Function

For i As Integer = 0 To 10
    Print Using "## maps to ##.#"; i; MapRange(i,0,10,-1,0)
Next i
Sleep


maze=:4 :0
  assert.0<:n=.<:x*y
  horiz=. 0$~x,y-1
  verti=. 0$~(x-1),y
  path=.,:here=. ?x,y
  unvisited=.0 (<here+1)} 0,0,~|:0,0,~1$~y,x
  while.n do.
    neighbors=. here+"1 (,-)=0 1
    neighbors=. neighbors #~ (<"1 neighbors+1) {unvisited
    if.#neighbors do.
      n=.n-1
      next=. ({~ [email protected]#) neighbors
      unvisited=.0 (<next+1)} unvisited
      if.{.next=here
      do. horiz=.1 (<-:here+next-0 1)} horiz
      else. verti=. 1 (<-:here+next-1 0)} verti end.
      path=.path,here=.next
    else.
      here=.{:path
      path=.}:path
    end.
  end.
  horiz;verti
)

display=:3 :0
  size=. >.&$&>/y
  text=. (}:1 3$~2*1+{:size)#"1":size$<' '
  'hdoor vdoor'=. 2 4&*&.>&.> (#&,{@;&i./@$)&.> y
  ' ' (a:-.~0 1;0 2; 0 3;(2 1-~$text);(1 4&+&.> hdoor),,vdoor+&.>"0/2 1;2 2;2 3)} text
)


MODE FIELD = LONG REAL; # field type is LONG REAL #
INT default upb:=3;
MODE VECTOR = [default upb]FIELD;
MODE MATRIX = [default upb,default upb]FIELD;

# crude exception handling #
PROC VOID raise index error := VOID: GOTO exception index error;

# define the vector/matrix operators #
OP * = (VECTOR a,b)FIELD: ( # basically the dot product #
    FIELD result:=0;
    IF LWB a/=LWB b OR UPB a/=UPB b THEN raise index error FI;
    FOR i FROM LWB a TO UPB a DO result+:= a[i]*b[i] OD;
    result
  );

 OP * = (VECTOR a, MATRIX b)VECTOR: ( # overload vector times matrix #
    [2 LWB b:2 UPB b]FIELD result;
    IF LWB a/=LWB b OR UPB a/=UPB b THEN raise index error FI;
    FOR j FROM 2 LWB b TO 2 UPB b DO result[j]:=a*b[,j] OD;
    result
  );
# this is the task portion #
OP * = (MATRIX a, b)MATRIX: ( # overload matrix times matrix #
    [LWB a:UPB a, 2 LWB b:2 UPB b]FIELD result;
    IF 2 LWB a/=LWB b OR 2 UPB a/=UPB b THEN raise index error FI;
    FOR k FROM LWB result TO UPB result DO result[k,]:=a[k,]*b OD;
    result
  );

 # Some sample matrices to test #
test:(
  MATRIX a=((1,  1,  1,   1), # matrix A #
            (2,  4,  8,  16),
            (3,  9, 27,  81),
            (4, 16, 64, 256));

  MATRIX b=((  4  , -3  ,  4/3,  -1/4 ), # matrix B #
            (-13/3, 19/4, -7/3,  11/24),
            (  3/2, -2  ,  7/6,  -1/4 ),
            ( -1/6,  1/4, -1/6,   1/24));

  MATRIX prod = a * b; # actual multiplication example of A x B #

  FORMAT real fmt = $g(-6,2)$; # width of 6, with no '+' sign, 2 decimals #
  PROC real matrix printf= (FORMAT real fmt, MATRIX m)VOID:(
    FORMAT vector fmt = $"("n(2 UPB m-1)(f(real fmt)",")f(real fmt)")"$;
    FORMAT matrix fmt = $x"("n(UPB m-1)(f(vector fmt)","lxx)f(vector fmt)");"$;
    # finally print the result #
    printf((matrix fmt,m))
  );

  # finally print the result #
  print(("Product of a and b: ",new line));
  real matrix printf(real fmt, prod)
  EXIT

  exception index error:
    putf(stand error, $x"Exception: index error."l$)
)


include "NSLog.incl"

local fn MapRange( s as double, a1 as double, a2 as double, b1 as double, b2 as double ) as double
end fn = b1+(s-a1)*(b2-b1)/(a2-a1)

NSInteger i

for i = 0 to 10
NSLog( @"%2d maps to %5.1f", i, fn MapRange( i, 0, 10, -1, 0 ) )
next

HandleEvents


func mapRange(s:float, a1:float, a2:float, b1:float, b2:float) -> float :
  return b1 + ((b2-b1)/(a2-a1))*(s-a1)

for i in 11 :
  print( "%2d %+.1f" % [i,mapRange(i,0.0,10.0,-1.0,0.0)] )


package org.rosettacode;

import java.util.Collections;
import java.util.Arrays;

/*
 * recursive backtracking algorithm
 * shamelessly borrowed from the ruby at
 * http://weblog.jamisbuck.org/2010/12/27/maze-generation-recursive-backtracking
 */
public class MazeGenerator {
	private final int x;
	private final int y;
	private final int[][] maze;

	public MazeGenerator(int x, int y) {
		this.x = x;
		this.y = y;
		maze = new int[this.x][this.y];
		generateMaze(0, 0);
	}

	public void display() {
		for (int i = 0; i < y; i++) {
			// draw the north edge
			for (int j = 0; j < x; j++) {
				System.out.print((maze[j][i] & 1) == 0 ? "+---" : "+   ");
			}
			System.out.println("+");
			// draw the west edge
			for (int j = 0; j < x; j++) {
				System.out.print((maze[j][i] & 8) == 0 ? "|   " : "    ");
			}
			System.out.println("|");
		}
		// draw the bottom line
		for (int j = 0; j < x; j++) {
			System.out.print("+---");
		}
		System.out.println("+");
	}

	private void generateMaze(int cx, int cy) {
		DIR[] dirs = DIR.values();
		Collections.shuffle(Arrays.asList(dirs));
		for (DIR dir : dirs) {
			int nx = cx + dir.dx;
			int ny = cy + dir.dy;
			if (between(nx, x) && between(ny, y)
					&& (maze[nx][ny] == 0)) {
				maze[cx][cy] |= dir.bit;
				maze[nx][ny] |= dir.opposite.bit;
				generateMaze(nx, ny);
			}
		}
	}

	private static boolean between(int v, int upper) {
		return (v >= 0) && (v < upper);
	}

	private enum DIR {
		N(1, 0, -1), S(2, 0, 1), E(4, 1, 0), W(8, -1, 0);
		private final int bit;
		private final int dx;
		private final int dy;
		private DIR opposite;

		// use the static initializer to resolve forward references
		static {
			N.opposite = S;
			S.opposite = N;
			E.opposite = W;
			W.opposite = E;
		}

		private DIR(int bit, int dx, int dy) {
			this.bit = bit;
			this.dx = dx;
			this.dy = dy;
		}
	};

	public static void main(String[] args) {
		int x = args.length >= 1 ? (Integer.parseInt(args[0])) : 8;
		int y = args.length == 2 ? (Integer.parseInt(args[1])) : 8;
		MazeGenerator maze = new MazeGenerator(x, y);
		maze.display();
	}

}


#include <hopper.h>
main:
   first matrix=0, second matrix=0,a=-1
   {5,2},rand array(a),mulby(10),ceil, cpy(first matrix), puts,{"\n"},puts
   {2,3},rand array(a),mulby(10),ceil, cpy(second matrix), puts,{"\n"},puts
   {first matrix,second matrix},mat mul, println
exit(0)


package main

import "fmt"

type rangeBounds struct {
    b1, b2 float64
}

func mapRange(x, y rangeBounds, n float64) float64 {
    return y.b1 + (n - x.b1) * (y.b2 - y.b1) / (x.b2 - x.b1)
}

func main() {
    r1 := rangeBounds{0, 10}
    r2 := rangeBounds{-1, 0}
    for n := float64(0); n <= 10; n += 2 {
        fmt.Println(n, "maps to", mapRange(r1, r2, n))
    }
}


function maze(x,y) {
	var n=x*y-1;
	if (n<0) {alert("illegal maze dimensions");return;}
	var horiz =[]; for (var j= 0; j<x+1; j++) horiz[j]= [],
	    verti =[]; for (var j= 0; j<x+1; j++) verti[j]= [],
	    here = [Math.floor(Math.random()*x), Math.floor(Math.random()*y)],
	    path = [here],
	    unvisited = [];
	for (var j = 0; j<x+2; j++) {
		unvisited[j] = [];
		for (var k= 0; k<y+1; k++)
			unvisited[j].push(j>0 && j<x+1 && k>0 && (j != here[0]+1 || k != here[1]+1));
	}
	while (0<n) {
		var potential = [[here[0]+1, here[1]], [here[0],here[1]+1],
		    [here[0]-1, here[1]], [here[0],here[1]-1]];
		var neighbors = [];
		for (var j = 0; j < 4; j++)
			if (unvisited[potential[j][0]+1][potential[j][1]+1])
				neighbors.push(potential[j]);
		if (neighbors.length) {
			n = n-1;
			next= neighbors[Math.floor(Math.random()*neighbors.length)];
			unvisited[next[0]+1][next[1]+1]= false;
			if (next[0] == here[0])
				horiz[next[0]][(next[1]+here[1]-1)/2]= true;
			else
				verti[(next[0]+here[0]-1)/2][next[1]]= true;
			path.push(here = next);
		} else
			here = path.pop();
	}
	return {x: x, y: y, horiz: horiz, verti: verti};
}

function display(m) {
	var text= [];
	for (var j= 0; j<m.x*2+1; j++) {
		var line= [];
		if (0 == j%2)
			for (var k=0; k<m.y*4+1; k++)
				if (0 == k%4)
					line[k]= '+';
				else
					if (j>0 && m.verti[j/2-1][Math.floor(k/4)])
						line[k]= ' ';
					else
						line[k]= '-';
		else
			for (var k=0; k<m.y*4+1; k++)
				if (0 == k%4)
					if (k>0 && m.horiz[(j-1)/2][k/4-1])
						line[k]= ' ';
					else
						line[k]= '|';
				else
					line[k]= ' ';
		if (0 == j) line[1]= line[2]= line[3]= ' ';
		if (m.x*2-1 == j) line[4*m.y]= ' ';
		text.push(line.join('')+'\r\n');
	}
	return text.join('');
}


--------------------- MATRIX MULTIPLY --------------------

-- matrixMultiply :: Num a => [[a]] -> [[a]] -> [[a]]
to matrixMultiply(a, b)
    script rows
        property xs : transpose(b)

        on |λ|(row)
            script columns
                on |λ|(col)
                    my dotProduct(row, col)
                end |λ|
            end script

            map(columns, xs)
        end |λ|
    end script

    map(rows, a)
end matrixMultiply

--------------------------- TEST -------------------------
on run
    matrixMultiply({¬
        {-1, 1, 4}, ¬
        {6, -4, 2}, ¬
        {-3, 5, 0}, ¬
        {3, 7, -2} ¬
            }, {¬
        {-1, 1, 4, 8}, ¬
        {6, 9, 10, 2}, ¬
        {11, -4, 5, -3}})

    --> {{51, -8, 26, -18}, {-8, -38, -6, 34},
    --     {33, 42, 38, -14}, {17, 74, 72, 44}}
end run

-------------------- GENERIC FUNCTIONS -------------------

-- dotProduct :: [n] -> [n] -> Maybe n
on dotProduct(xs, ys)
    script mult
        on |λ|(a, b)
            a * b
        end |λ|
    end script

    if length of xs is not length of ys then
        missing value
    else
        sum(zipWith(mult, xs, ys))
    end if
end dotProduct

-- foldr :: (a -> b -> a) -> a -> [b] -> a
on foldr(f, startValue, xs)
    tell mReturn(f)
        set v to startValue
        set lng to length of xs
        repeat with i from lng to 1 by -1
            set v to |λ|(v, item i of xs, i, xs)
        end repeat
        return v
    end tell
end foldr

-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map

-- min :: Ord a => a -> a -> a
on min(x, y)
    if y < x then
        y
    else
        x
    end if
end min

-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
    if class of f is script then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn

-- product :: Num a => [a] -> a
on product(xs)
    script mult
        on |λ|(a, b)
            a * b
        end |λ|
    end script

    foldr(mult, 1, xs)
end product

-- sum :: Num a => [a] -> a
on sum(xs)
    script add
        on |λ|(a, b)
            a + b
        end |λ|
    end script

    foldr(add, 0, xs)
end sum

-- transpose :: [[a]] -> [[a]]
on transpose(xss)
    script column
        on |λ|(_, iCol)
            script row
                on |λ|(xs)
                    item iCol of xs
                end |λ|
            end script

            map(row, xss)
        end |λ|
    end script

    map(column, item 1 of xss)
end transpose

-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
on zipWith(f, xs, ys)
    set lng to min(length of xs, length of ys)
    set lst to {}
    tell mReturn(f)
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, item i of ys)
        end repeat
        return lst
    end tell
end zipWith


import Data.Ratio
import Text.Printf (PrintfType, printf)

-- Map a value from the range [a1,a2] to the range [b1,b2].  We don't check
-- for empty ranges.
mapRange
  :: Fractional a
  => (a, a) -> (a, a) -> a -> a
mapRange (a1, a2) (b1, b2) s = b1 + (s - a1) * (b2 - b1) / (a2 - a1)

main :: IO ()
main
-- Perform the mapping over floating point numbers.
 = do
  putStrLn "---------- Floating point ----------"
  mapM_ (\n -> prtD n . mapRange (0, 10) (-1, 0) $ fromIntegral n) [0 .. 10]
  -- Perform the same mapping over exact rationals.
  putStrLn "---------- Rationals ----------"
  mapM_ (\n -> prtR n . mapRange (0, 10) (-1, 0) $ n % 1) [0 .. 10]
  where
    prtD
      :: PrintfType r
      => Integer -> Double -> r
    prtD = printf "%2d -> %6.3f\n"
    prtR
      :: PrintfType r
      => Integer -> Rational -> r
    prtR n x = printf "%2d -> %s\n" n (show x)


record Range(a, b)

# note, we force 'n' to be real, which means recalculation will
# be using real numbers, not integers
procedure remap (range1, range2, n : real)
  if n < range2.a | n > range2.b then fail # n out of given range
  return range1.a + (n - range2.a) * (range1.b - range1.a) / (range2.b - range2.a)
end

procedure range_string (range)
  return "[" || range.a || ", " || range.b || "]"
end

procedure main ()
  range1 := Range (0, 10)
  range2 := Range (-1, 0)
  # if i is out of range1, then 'remap' fails, so only valid changes are written
  every i := -2 to 12 do {
    if m := remap (range2, range1, i)
      then write ("Value " || i || " in " || range_string (range1) ||
                  " maps to " || m || " in " || range_string (range2))
  }
end


using Random
check(bound::Vector) = cell -> all([1, 1] .≤ cell .≤ bound)
neighbors(cell::Vector, bound::Vector, step::Int=2) =
    filter(check(bound), map(dir -> cell + step * dir, [[0, 1], [-1, 0], [0, -1], [1, 0]]))

function walk(maze::Matrix, nxtcell::Vector, visited::Vector=[])
    push!(visited, nxtcell)
    for neigh in shuffle(neighbors(nxtcell, collect(size(maze))))
        if neigh ∉ visited
            maze[round.(Int, (nxtcell + neigh) / 2)...] = 0
            walk(maze, neigh, visited)
        end
    end
    maze
end
function maze(w::Int, h::Int)
    maze = collect(i % 2 | j % 2 for i in 1:2w+1, j in 1:2h+1)
    firstcell = 2 * [rand(1:w), rand(1:h)]
    return walk(maze, firstcell)
end


import java.util.*

class MazeGenerator(val x: Int, val y: Int) {
    private val maze = Array(x) { IntArray(y) }

    fun generate(cx: Int, cy: Int) {
        Direction.values().shuffle().forEach {
            val nx = cx + it.dx
            val ny = cy + it.dy
            if (between(nx, x) && between(ny, y) && maze[nx][ny] == 0) {
                maze[cx][cy] = maze[cx][cy] or it.bit
                maze[nx][ny] = maze[nx][ny] or it.opposite!!.bit
                generate(nx, ny)
            }
        }
    }

    fun display() {
        for (i in 0..y - 1) {
            // draw the north edge
            for (j in 0..x - 1)
                print(if (maze[j][i] and 1 == 0) "+---" else "+   ")
            println('+')

            // draw the west edge
            for (j in 0..x - 1)
                print(if (maze[j][i] and 8 == 0) "|   " else "    ")
            println('|')
        }

        // draw the bottom line
        for (j in 0..x - 1) print("+---")
        println('+')
    }

    inline private fun <reified T> Array<T>.shuffle(): Array<T> {
        val list = toMutableList()
        Collections.shuffle(list)
        return list.toTypedArray()
    }

    private enum class Direction(val bit: Int, val dx: Int, val dy: Int) {
        N(1, 0, -1), S(2, 0, 1), E(4, 1, 0),W(8, -1, 0);

        var opposite: Direction? = null

        companion object {
            init {
                N.opposite = S
                S.opposite = N
                E.opposite = W
                W.opposite = E
            }
        }
    }

    private fun between(v: Int, upper: Int) = v >= 0 && v < upper
}

fun main(args: Array<String>) {
    val x = if (args.size >= 1) args[0].toInt() else 8
    val y = if (args.size == 2) args[1].toInt() else 8
    with(MazeGenerator(x, y)) {
        generate(0, 0)
        display()
    }
}


maprange=:2 :0
  'a1 a2'=.m
  'b1 b2'=.n
  b1+((y-a1)*b2-b1)%a2-a1
)
NB. this version defers all calculations to runtime, but mirrors exactly the task formulation


public class Range {
	public static void main(String[] args){
		for(float s = 0;s <= 10; s++){
			System.out.println(s + " in [0, 10] maps to "+
					mapRange(0, 10, -1, 0, s)+" in [-1, 0].");
		}
	}

	public static double mapRange(double a1, double a2, double b1, double b2, double s){
		return b1 + ((s - a1)*(b2 - b1))/(a2 - a1);
	}
}


// Javascript doesn't have built-in support for ranges
// Insted we use arrays of two elements to represent ranges
var mapRange = function(from, to, s) {
  return to[0] + (s - from[0]) * (to[1] - to[0]) / (from[1] - from[0]);
};

var range = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (var i = 0; i < range.length; i++) {
  range[i] = mapRange([0, 10], [-1, 0], range[i]);
}

console.log(range);


math.randomseed( os.time() )

-- Fisher-Yates shuffle from http://santos.nfshost.com/shuffling.html
function shuffle(t)
  for i = 1, #t - 1 do
    local r = math.random(i, #t)
    t[i], t[r] = t[r], t[i]
  end
end

-- builds a width-by-height grid of trues
function initialize_grid(w, h)
  local a = {}
  for i = 1, h do
    table.insert(a, {})
    for j = 1, w do
      table.insert(a[i], true)
    end
  end
  return a
end

-- average of a and b
function avg(a, b)
  return (a + b) / 2
end

dirs = {
  {x = 0, y = -2}, -- north
  {x = 2, y = 0}, -- east
  {x = -2, y = 0}, -- west
  {x = 0, y = 2}, -- south
}

function make_maze(w, h)
  w = w or 16
  h = h or 8

  local map = initialize_grid(w*2+1, h*2+1)

  function walk(x, y)
    map[y][x] = false

    local d = { 1, 2, 3, 4 }
    shuffle(d)
    for i, dirnum in ipairs(d) do
      local xx = x + dirs[dirnum].x
      local yy = y + dirs[dirnum].y
      if map[yy] and map[yy][xx] then
        map[avg(y, yy)][avg(x, xx)] = false
        walk(xx, yy)
      end
    end
  end

  walk(math.random(1, w)*2, math.random(1, h)*2)

  local s = {}
  for i = 1, h*2+1 do
    for j = 1, w*2+1 do
      if map[i][j] then
        table.insert(s, '#')
      else
        table.insert(s, ' ')
      end
    end
    table.insert(s, '\n')
  end
  return table.concat(s)
end

print(make_maze())


Matrix("b","  ; rows separated by ","
, 1   2       ; entries separated by space or tab
, 2   3
, 3   0")
MsgBox % "B`n`n" MatrixPrint(b)
Matrix("c","
, 1 2 3
, 3 2 1")
MsgBox % "C`n`n" MatrixPrint(c)

MatrixMul("a",b,c)
MsgBox % "B * C`n`n" MatrixPrint(a)

MsgBox % MatrixMul("x",b,b)

Matrix(_a,_v) { ; Matrix structure: m_0_0 = #rows, m_0_1 = #columns, m_i_j = element[i,j], i,j > 0
   Local _i, _j = 0
   Loop Parse, _v, `,
      If (A_LoopField != "") {
         _i := 0, _j ++
         Loop Parse, A_LoopField, %A_Space%%A_Tab%
            If (A_LoopField != "")
               _i++, %_a%_%_i%_%_j% := A_LoopField
      }
   %_a% := _a, %_a%_0_0 := _j, %_a%_0_1 := _i
}
MatrixPrint(_a) {
   Local _i = 0, _t
   Loop % %_a%_0_0 {
      _i++
      Loop % %_a%_0_1
         _t .= %_a%_%A_Index%_%_i% "`t"
      _t .= "`n"
   }
   Return _t
}
MatrixMul(_a,_b,_c) {
   Local _i = 0, _j, _k, _s
   If (%_b%_0_0 != %_c%_0_1)
      Return "ERROR: inner dimensions " %_b%_0_0 " != " %_c%_0_1
   %_a% := _a, %_a%_0_0 := %_b%_0_0, %_a%_0_1 := %_c%_0_1
   Loop % %_c%_0_1 {
      _i++, _j := 0
      Loop % %_b%_0_0 {
         _j++, _k := _s := 0
         Loop % %_b%_0_1
            _k++, _s += %_b%_%_k%_%_j% * %_c%_%_i%_%_k%
         %_a%_%_i%_%_j% := _s
      }
   }
}


# The input is the value to be mapped.
# The ranges, a and b, should each be an array defining the
# left-most and right-most points of the range.
def maprange(a; b):
  b[0] + (((. - a[0]) * (b[1] - b[0])) / (a[1] - a[0])) ;


function maprange(s, a, b)
    a₁, a₂ = minimum(a), maximum(a)
    b₁, b₂ = minimum(b), maximum(b)
    return b₁ + (s - a₁) * (b₂ - b₁) / (a₂ - a₁)
end

@show maprange(6, 1:10, -1:0)
@show maprange(0:10, 0:10, -1:0)


// version 1.0.6

class FloatRange(override val start: Float, override val endInclusive: Float) : ClosedRange<Float>

fun mapRange(range1: FloatRange, range2: FloatRange, value: Float): Float {
    if (value !in range1) throw IllegalArgumentException("value is not within the first range")
    if (range1.endInclusive == range1.start) throw IllegalArgumentException("first range cannot be single-valued")
    return range2.start + (value - range1.start) * (range2.endInclusive - range2.start) / (range1.endInclusive - range1.start)
}

fun main(args: Array<String>) {
    for (i in 0..10) {
        val mappedValue = mapRange(FloatRange(0.0f, 10.0f), FloatRange(-1.0f, 0.0f), i.toFloat())
        println(String.format("%2d  maps to %+4.2f", i, mappedValue))
    }
}


Module Maze {
      width% = 40
      height% = 20
      \\ we can use DIM maze$(0 to width%,0 to  height%)="#"
      \\ so we can delete the two For loops
      DIM maze$(0 to width%,0 to  height%)
      FOR x% = 0 TO width%
          FOR y% = 0 TO height%
              maze$(x%, y%) = "#"
          NEXT y%
      NEXT x%

      currentx% = INT(RND * (width% - 1))
      currenty% = INT(RND * (height% - 1))

      IF currentx% MOD 2 = 0 THEN currentx%++
      IF currenty% MOD 2 = 0 THEN currenty%++
      maze$(currentx%, currenty%) = " "

      done% = 0
      WHILE done% = 0 {
          FOR i% = 0 TO 99
              oldx% = currentx%
              oldy% = currenty%
              SELECT CASE INT(RND * 4)
                  CASE 0
                      IF currentx% + 2 < width% THEN currentx%+=2
                  CASE 1
                      IF currenty% + 2 < height% THEN currenty%+=2
                  CASE 2
                      IF currentx% - 2 > 0 THEN currentx%-=2
                  CASE 3
                      IF currenty% - 2 > 0 THEN currenty%-=2
              END SELECT
              IF maze$(currentx%, currenty%) = "#"  Then {
                  maze$(currentx%, currenty%) = " "
                  maze$(INT((currentx% + oldx%) / 2), ((currenty% + oldy%) / 2)) = " "
             }
          NEXT i%
          done% = 1
          FOR x% = 1 TO width% - 1 STEP 2
              FOR y% = 1 TO height% - 1 STEP 2
                  IF maze$(x%, y%) = "#" THEN done% = 0
              NEXT y%
          NEXT x%
      }

      FOR y% = 0 TO height%
          FOR x% = 0 TO width%
              PRINT maze$(x%, y%);
          NEXT x%
          PRINT
      NEXT y%
}
Maze


MazeGraphics[m_, n_] :=
 Block[{$RecursionLimit = Infinity,
   unvisited = Tuples[Range /@ {m, n}], maze},
  maze = Graphics[{Line[{{#, # - {0, 1}}, {#, # - {1, 0}}}] & /@
      unvisited,
     Line[{{0, n}, {0, 0}, {m, 0}}]}]; {unvisited =
      DeleteCases[unvisited, #];
     Do[If[MemberQ[unvisited, neighbor],
       maze = DeleteCases[
         maze, {#,
           neighbor - {1, 1}} | {neighbor, # - {1, 1}}, {5}]; #[email protected]
        neighbor], {neighbor,
       [email protected]{# + {0, 1}, # - {0, 1}, # + {1, 0}, # - {1,
           0}}}]} &@[email protected]; maze];
maze = MazeGraphics[21, 13]


# Usage: GAWK -f MATRIX_MULTIPLICATION.AWK filename
# Separate matrices a and b by a blank line
BEGIN {
    ranka1 = 0; ranka2 = 0
    rankb1 = 0; rankb2 = 0
    matrix = 1 # Indicate first (1) or second (2) matrix
    i = 0
}
NF == 0 {
    if (++matrix > 2) {
        printf("Warning: Ignoring data below line %d.\n", NR)
    }
    i = 0
    next
}
{
    # Store first matrix in a, second matrix in b
    if (matrix == 1) {
        ranka1 = ++i
        ranka2 = max(ranka2, NF)
        for (j = 1; j <= NF; j++)
            a[i,j] = $j
    }
    if (matrix == 2) {
        rankb1 = ++i
        rankb2 = max(rankb2, NF)
        for (j = 1; j <= NF; j++)
            b[i,j] = $j
    }
}
END {
    # Check ranks of a and b
    if ((ranka1 < 1) || (ranka2 < 1) || (rankb1 < 1) || (rankb2 < 1) ||
        (ranka2 != rankb1)) {
        printf("Error: Incompatible ranks (%dx%d)*(%dx%d).\n", ranka1, ranka2, rankb1, rankb2)
        exit
    }
    # Multiplication c = a * b
    for (i = 1; i <= ranka1; i++) {
        for (j = 1; j <= rankb2; j++) {
            c[i,j] = 0
            for (k = 1; k <= ranka2; k++)
                c[i,j] += a[i,k] * b[k,j]
        }
    }
    # Print matrix c
    for (i = 1; i <= ranka1; i++) {
        for (j = 1; j <= rankb2; j++)
            printf("%g%s", c[i,j], j < rankb2 ? " " : "\n")
    }
}
function max(m, n) {
    return m > n ? m : n
}


define map_range(
	a1,
	a2,
	b1,
	b2,
	number
) => (decimal(#b1) + (decimal(#number) - decimal(#a1)) * (decimal(#b2) - decimal(#b1)) / (decimal(#a2) - decimal(#a1))) -> asstring(-Precision = 1)

with number in generateSeries(1,10) do {^
	#number
	': '
	map_range( 0, 10, -1, 0, #number)
	'<br />'

^}'


function M = makeMaze(n)
    showProgress = false;

    colormap([1,1,1;1,1,1;0,0,0]);
    set(gcf,'color','w');

    NoWALL      = 0;
    WALL        = 2;
    NotVISITED  = -1;
    VISITED     = -2;

    m = 2*n+3;
    M = NotVISITED(ones(m));
    offsets = [-1, m, 1, -m];

    M([1 2:2:end end],:) = WALL;
    M(:,[1 2:2:end end]) = WALL;

    currentCell = sub2ind(size(M),3,3);
    M(currentCell) = VISITED;

    S = currentCell;

    while (~isempty(S))
        moves = currentCell + 2*offsets;
        unvistedNeigbors = find(M(moves)==NotVISITED);

        if (~isempty(unvistedNeigbors))
            next = unvistedNeigbors(randi(length(unvistedNeigbors),1));
            M(currentCell + offsets(next)) = NoWALL;

            newCell = currentCell + 2*offsets(next);
            if (any(M(newCell+2*offsets)==NotVISITED))
                S = [S newCell];
            end

            currentCell = newCell;
            M(currentCell) = VISITED;
        else
            currentCell = S(1);
            S = S(2:end);
        end

        if (showProgress)
            image(M-VISITED);
            axis equal off;
            drawnow;
            pause(.01);
        end
    end

    image(M-VISITED);
    axis equal off;


Assume the matrices TO be multiplied are a AND b
 IF (LEN(a,2) = LEN(b)) 'if valid dims
        n = LEN(a,2)
        m = LEN(a)
        p = LEN(b,2)

        DIM ans(0 TO m - 1, 0 TO p - 1)

        FOR i = 0 TO m - 1
                FOR j = 0 TO p - 1
                        FOR k = 0 TO n - 1
                                ans(i, j) = ans(i, j) + (a(i, k) * b(k, j))
                        NEXT k, j, i

        'print answer
        FOR i = 0 TO m - 1
                FOR j = 0 TO p - 1
                        PRINT ans(i, j);
                NEXT j
                PRINT
        NEXT i
 ELSE
        PRINT "invalid dimensions"
 END IF


      DIM matrix1(3,1), matrix2(1,2), product(3,2)

      matrix1() = 1, 2, \
      \           3, 4, \
      \           5, 6, \
      \           7, 8

      matrix2() = 1, 2, 3, \
      \           4, 5, 6

      product() = matrix1() . matrix2()

      FOR row% = 0 TO DIM(product(),1)
        FOR col% = 0 TO DIM(product(),2)
          PRINT product(row%,col%),;
        NEXT
        PRINT
      NEXT


For i = 0 To 10
    Print "f(";i;") maps to ";mapToRange(i, 0, 10, -1, 0)
Next i
End

Function mapToRange(value, inputMin, inputMax, outputMin, outputMax)
  mapToRange = (((value - inputMin) * (outputMax - outputMin)) / (inputMax - inputMin)) + outputMin
End Function


to interpolate :s :a1 :a2 :b1 :b2
  output (:s-:a1) / (:a2-:a1) * (:b2-:b1) + :b1
end

for [i 0 10] [print interpolate :i 0 10 -1 0]


function map_range( a1, a2, b1, b2, s )
    return b1 + (s-a1)*(b2-b1)/(a2-a1)
end

for i = 0, 10 do
    print( string.format( "f(%d) = %f", i, map_range( 0, 10, -1, 0, i ) ) )
end


import random, sequtils, strutils
randomize()

iterator randomCover[T](xs: openarray[T]): T =
  var js = toSeq 0..xs.high
  for i in countdown(js.high, 0):
    let j = random(i)
    swap(js[i], js[j])
  for j in js:
    yield xs[j]

const
  w = 14
  h = 10

var
  vis = newSeqWith(h, newSeq[bool](w))
  hor = newSeqWith(h+1, newSeqWith(w, "+---"))
  ver = newSeqWith(h, newSeqWith(w, "|   ") & "|")

proc walk(x, y: int) =
  vis[y][x] = true
  for p in [[x-1,y], [x,y+1], [x+1,y], [x,y-1]].randomCover:
    if p[0] notin 0 ..< w or p[1] notin 0 ..< h or vis[p[1]][p[0]]: continue
    if p[0] == x: hor[max(y, p[1])][x] = "+   "
    if p[1] == y: ver[y][max(x, p[0])] = "    "
    walk p[0], p[1]

walk rand(0..<w), rand(0..<h)
for a,b in zip(hor, ver & @[""]).items:
  echo join(a & "+\n" & b)