*        Holidays related to Easter    29/05/2016
HOLIDAYS CSECT
         USING  HOLIDAYS,R13       base register
         B      72(R15)            skip savearea
         DC     17F'0'             savearea
         STM    R14,R12,12(R13)    prolog
         ST     R13,4(R15)         "
         ST     R15,8(R13)         "
         LR     R13,R15            "
         LA     R9,2               nn=2
LOOPNN   C      R9,=F'2'           if nn=2
         BNE    NN2
NN1      MVC    I1,=F'400'         i1=400
         MVC    I2,=F'2100'        i2=2100
         MVC    I3,=F'100'         i3=100
         B      NN3
NN2      MVC    I1,=F'2010'        i1=2010
         MVC    I2,=F'2020'        i2=2020
         MVC    I3,=F'1'           i3=1
NN3      MVC    PG(L'PGT),PGT      pg=pgt
         L      R1,I1              i1
         XDECO  R1,XDEC            edit i1
         MVC    PG+24(4),XDEC+8    output i1
         L      R1,I2              i2
         XDECO  R1,XDEC            edit i2
         MVC    PG+32(4),XDEC+8    output i2
         L      R1,I3              i3
         XDECO  R1,XDEC            edit i3
         MVC    PG+42(3),XDEC+9    output i3
         XPRNT  PG,L'PGT           print buffer
         L      R6,I1              y=i1
LOOPY    C      R6,I2              do y=i1 to i2 by i3
         BH     ELOOPY             leave y
         LR     R4,R6              y
         SRDA   R4,32              ~
         D      R4,=F'19'          /19
         ST     R4,A               a=y//19
         LR     R4,R6              y
         SRDA   R4,32              ~
         D      R4,=F'100'         /100
         ST     R5,B               b=y/100
         ST     R4,C               c=y//100
         L      R4,B               b
         SRDA   R4,32              ~
         D      R4,=F'4'           /4
         ST     R5,D               d=b/4
         ST     R4,E               e=b//4
         L      R4,B               b
         LA     R4,8(R4)           +8
         SRDA   R4,32              ~
         D      R4,=F'25'          /25
         ST     R5,F               f=(b+8)/25
         L      R4,B               b
         S      R4,F               -f
         LA     R4,1(R4)           +1
         SRDA   R4,32              ~
         D      R4,=F'3'           /3
         ST     R5,G               g=(b-f+1)/3
         L      R5,A               a
         M      R4,=F'19'          *19
         LR     R4,R5              .
         A      R4,B               +b
         S      R4,D               -d
         S      R4,G               -g
         LA     R4,15(R4)          +15
         SRDA   R4,32              ~
         D      R4,=F'30'          /30
         ST     R4,H               h=(19*a+b-d-g+15)//30
         L      R4,C               c
         SRDA   R4,32              ~
         D      R4,=F'4'           /4
         ST     R5,I               i=c/4
         ST     R4,K               k=c//4
         L      R4,E               e
         SLA    R4,1               <<1 <=> *2
         LA     R4,32(R4)          +32
         L      R2,I               i
         SLA    R2,1               <<1 <=> *2
         AR     R2,R4              32+2*e+2*i
         S      R2,H               -h
         S      R2,K               -k
         SRDA   R2,32              ~
         D      R2,=F'7'           /7
         ST     R2,L               l=(32+2*e+2*i-h-k)//7
         L      R5,H               h
         M      R4,=F'11'          *11
         A      R5,A               +a
         L      R3,L               l
         M      R2,=F'22'          *22
         AR     R3,R5              a+11*h+22*l
         LR     R4,R3              .
         SRDA   R4,32              ~
         D      R4,=F'451'         /451
         ST     R5,M               m=(a+11*h+22*l)/451
         L      R2,H               h
         A      R2,L               +l
         L      R5,M               m
         M      R4,=F'7'           *7
         SR     R2,R5              (h+l)-(7*m)
         LA     R2,114(R2)         +114
         ST     R2,N               n=h+l-7*m+114
         L      R4,N               n
         SRDA   R4,32              ~
         D      R4,=F'31'          /31
         ST     R5,XM              xm=n/31
         LA     R4,1(R4)           +1
         ST     R4,XD              xd=n//31+1
         LA     R10,PG             pgi=0
         MVC    PG,=CL84' '        pg=' '
         XDECO  R6,XDEC            edit y
         MVC    0(4,R10),XDEC+8    output y
         LA     R10,4(R10)         pgi=pgi+3
         LA     R8,5               loop counter for loopi
         LA     R7,1               i=1
LOOPI    LR     R1,R7              do i=1 to 5; r1=i
         SLA    R1,1               *2
         LH     R2,OFFSET-2(R1)    offset(i)
         L      R4,XD              xd
         AR     R4,R2              wd=xd+offset(i)
WHILE    L      R1,XM              xm
         SLA    R1,1               *2
         LH     R2,DAYS-2(R1)      days(xm)
         CR     R4,R2              while wd>days(xm)
         BNH    WEND               leave while
         SR     R4,R2              wd=wd-days(xm)
         L      R2,XM              xm
         LA     R2,1(R2)           xm+1
         ST     R2,XM              xm=xm+1
         B      WHILE              loop while
WEND     ST     R4,XD              xd=wd
         LA     R10,1(R10)         pgi=pgi+1
         LR     R1,R7              i
         MH     R1,=AL2(L'HOLIDAY) *9
         LA     R14,HOLIDAY-9(R1)  @holiday(i)
         MVC    0(L'HOLIDAY,R10),0(R14)  output holiday(i)
         LA     R10,9(R10)         pgi=pgi+9
         L      R1,XD              xd
         XDECO  R1,XDEC            edit xd
         MVC    0(3,R10),XDEC+9    output xd
         LA     R10,3(R10)         pgi=pgi+3
         L      R1,XM              xm
         MH     R1,=AL2(L'MONTH)   *3
         LA     R14,MONTH-3(R1)    @month(xm)
         MVC    0(L'MONTH,R10),0(R14)  output month(xm)
         LA     R10,3(R10)         pgi=pgi+3
         LA     R7,1(R7)           i+1
         BCT    R8,LOOPI           next i
         XPRNT  PG,L'PG            print buffer
         A      R6,I3              y=y+i3
         B      LOOPY              next y
ELOOPY   BCT    R9,LOOPNN          next nn
         L      R13,4(0,R13)       epilog
         LM     R14,R12,12(R13)    "
         XR     R15,R15            "
         BR     R14                exit
A        DS     F                  a=y//19
B        DS     F                  b=y/100
C        DS     F                  c=y//100
D        DS     F                  d=b/4
E        DS     F                  e=b//4
F        DS     F                  f=(b+8)/25
G        DS     F                  g=(b-f+1)/3
H        DS     F                  h=(19*a+b-d-g+15)//30
I        DS     F                  i=c/4
K        DS     F                  k=c//4
L        DS     F                  l=(32+2*e+2*i-h-k)//7
M        DS     F                  m=(a+11*h+22*l)/451
N        DS     F                  n=h+l-7*m+114
XM       DS     F                  month
XD       DS     F                  day
I1       DS     F                  from year i1
I2       DS     F                  to   year i2
I3       DS     F                  step year i3
MONTH    DC     CL3'jan',CL3'feb',CL3'mar',CL3'apr',CL3'may',CL3'jun'
DAYS     DC     H'31',H'28',H'31',H'30',H'31',H'30'
HOLIDAY  DC     CL9'Easter',CL9'Ascension',CL9'Pentecost'
         DC     CL9'Trinity',CL9'Corpus'
OFFSET   DC     H'0',H'39',H'10',H'7',H'4'
PGT      DC     CL45'Christian holidays from .... to .... step ...'
PG       DC     CL84' '            buffer
XDEC     DS     CL12               temp for edit
         YREGS
         END    HOLIDAYS


const hilbert = (width, spacing, points) => (x, y, lg, i1, i2, f) => {
    if (lg === 1) {
        const px = (width - x) * spacing;
        const py = (width - y) * spacing;
        points.push(px, py);
        return;
    }
    lg >>= 1;
    f(x + i1 * lg, y + i1 * lg, lg, i1, 1 - i2, f);
    f(x + i2 * lg, y + (1 - i2) * lg, lg, i1, i2, f);
    f(x + (1 - i1) * lg, y + (1 - i1) * lg, lg, i1, i2, f);
    f(x + (1 - i2) * lg, y + i2 * lg, lg, 1 - i1, i2, f);
    return points;
};

/**
 * Draw a hilbert curve of the given order.
 * Outputs a svg string. Save the string as a .svg file and open in a browser.
 * @param {!Number} order
 */
const drawHilbert = order => {
    if (!order || order < 1) {
        throw 'You need to give a valid positive integer';
    } else {
        order = Math.floor(order);
    }

    // Curve Constants
    const width = 2 ** order;
    const space = 10;

    // SVG Setup
    const size = 500;
    const stroke = 2;
    const col = "red";
    const fill = "transparent";

    // Prep and run function
    const f = hilbert(width, space, []);
    const points = f(0, 0, width, 0, 0, f);
    const path = points.join(' ');

    console.log(
        `<svg xmlns="http://www.w3.org/2000/svg"
    width="${size}"
    height="${size}"
    viewBox="${space / 2} ${space / 2} ${width * space} ${width * space}">
  <path d="M${path}" stroke-width="${stroke}" stroke="${col}" fill="${fill}"/>
</svg>`);

};

drawHilbert(6);


with Ada.Calendar.Arithmetic;
with Ada.Calendar.Formatting;
with Ada.Text_IO;

procedure Main is
   use Ada.Calendar;
   use Arithmetic;

   function Get_Easter (Year : Year_Number) return Time is
      A : Integer := Year mod 19;
      B : Integer := Year / 100;
      C : Integer := Year mod 100;
      D : Integer := B / 4;
      E : Integer := B mod 4;
      F : Integer := (B + 8) / 25;
      G : Integer := (B - F + 1) / 3;
      H : Integer := (19 * A + B - D - G + 15) mod 30;
      I : Integer := C / 4;
      K : Integer := C mod 4;
      L : Integer := (32 + 2 * E + 2 * I - H - K) mod 7;
      M : Integer := (A + 11 * H + 22 * L) / 451;
      N : Integer := H + L - 7 * M + 114;
   begin
      return Time_Of (Year, N / 31, N mod 31 + 1, 43200.0);
   end Get_Easter;

   procedure Print_Easter (Year : Year_Number) is
      Days_To_Ascension : constant Day_Count := 39;
      Days_To_Pentecost : constant Day_Count := 49;
      Days_To_Trinity   : constant Day_Count := 56;
      Days_To_Corpus    : constant Day_Count := 60;
      Easter : Time := Get_Easter (Year);
   begin
      Ada.Text_IO.Put (Integer'Image (Year));
      Ada.Text_IO.Put (": Easter: " &
                       Formatting.Image (Easter) (6 .. 10));
      Ada.Text_IO.Put (", Ascension: " &
                       Formatting.Image (Easter + Days_To_Ascension) (6 .. 10));
      Ada.Text_IO.Put (", Pentecost: " &
                       Formatting.Image (Easter + Days_To_Pentecost) (6 .. 10));
      Ada.Text_IO.Put (", Trinity: " &
                       Formatting.Image (Easter + Days_To_Trinity) (6 .. 10));
      Ada.Text_IO.Put_Line (", Corpus: " &
                       Formatting.Image (Easter + Days_To_Corpus) (6 .. 10));
   end Print_Easter;
begin
   Ada.Text_IO.Put_Line
     ("Christian holidays, related to Easter, for years from 2010 to 2020 CE:");
   for I in 2010 .. 2020 loop
      Print_Easter (I);
   end loop;
end Main;


include "simple-turtle" {search: "."};

def rules:
   { A: "-BF+AFA+FB-",
     B: "+AF-BFB-FA+" };

def hilbert($count):
  rules as $rules
  | def p($count):
      if $count <= 0 then .
      else gsub("A"; "a") | gsub("B"; $rules["B"]) | gsub("a"; $rules["A"])
      | p($count-1)
      end;
  "A" | p($count) ;

def interpret($x):
  if   $x == "+" then turtleRotate(90)
  elif $x == "-" then turtleRotate(-90)
  elif $x == "F" then turtleForward(5)
  else .
  end;

def hilbert_curve($n):
  hilbert($n)
  | split("")
  | reduce .[] as $action (turtle([0,5]) | turtleDown;
      interpret($action) ) ;

hilbert_curve(5)
| path("none"; "red"; 1) | svg(170)


using Gtk, Graphics, Colors

Base.isless(p1::Vec2, p2::Vec2) = (p1.x == p2.x ? p1.y < p2.y : p1.x < p2.x)

struct Line
	p1::Point
	p2::Point
end

dist(p1, p2) = sqrt((p2.y - p1.y)^2 + (p2.x - p1.x)^2)
length(ln::Line) = dist(ln.p1, ln.p2)
isvertical(line) = (line.p1.x == line.p2.x)
ishorizontal(line) = (line.p1.y == line.p2.y)

const colorseq = [colorant"blue", colorant"red", colorant"green"]
const linewidth = 1
const toporder = 3

function drawline(ctx, p1, p2, color, width)
    move_to(ctx, p1.x, p1.y)
    set_source(ctx, color)
    line_to(ctx, p2.x, p2.y)
    set_line_width(ctx, width)
    stroke(ctx)
end
drawline(ctx, line, color, width=linewidth) = drawline(ctx, line.p1, line.p2, color, width)

function hilbertmutateboxes(ctx, line, order, maxorder=toporder)
    if line.p1 < line.p2
        p1, p2 = line.p1, line.p2
    else
        p2, p1 = line.p1, line.p2
    end
    color = colorseq[order % 3 + 1]
	d = dist(p1, p2) / 3
    if ishorizontal(line)
        pl = Point(p1.x + d, p1.y)
        plu = Point(p1.x + d, p1.y - d)
        pld = Point(p1.x + d, p1.y + d)
        pr = Point(p2.x - d, p2.y)
        pru = Point(p2.x - d, p2.y - d)
        prd = Point(p2.x - d, p2.y + d)
        lines = [Line(plu, pl), Line(plu, pru), Line(pru, pr),
                 Line(pr, prd), Line(pld, prd), Line(pld, pl)]
    else # vertical
        pu = Point(p1.x, p1.y + d)
        pul = Point(p1.x - d, p1.y + d)
        pur = Point(p1.x + d, p1.y + d)
        pd = Point(p2.x, p2.y - d)
        pdl = Point(p2.x - d, p2.y - d)
        pdr = Point(p2.x + d, p2.y - d)
        lines = [Line(pul, pu), Line(pul, pdl), Line(pdl, pd),
                 Line(pu, pur), Line(pur, pdr), Line(pd, pdr)]
    end
    for li in lines
        drawline(ctx, li, color)
    end
    if order <= maxorder
        for li in lines
            hilbertmutateboxes(ctx, li, order + 1, maxorder)
        end
    end
end

const can = @GtkCanvas()
const win = GtkWindow(can, "Hilbert 2D", 400, 400)

@guarded draw(can) do widget
    ctx = getgc(can)
    h = height(can)
    w = width(can)
    line = Line(Point(0, h/2), Point(w, h/2))
    drawline(ctx, line, colorant"black", 2)
    hilbertmutateboxes(ctx, line, 0)
end

show(can)
const cond = Condition()
endit(w) = notify(cond)
signal_connect(endit, win, :destroy)
wait(cond)


// Version 1.2.40

data class Point(var x: Int, var y: Int)

fun d2pt(n: Int, d: Int): Point {
    var x = 0
    var y = 0
    var t = d
    var s = 1
    while (s < n) {
        val rx = 1 and (t / 2)
        val ry = 1 and (t xor rx)
        val p = Point(x, y)
        rot(s, p, rx, ry)
        x = p.x + s * rx
        y = p.y + s * ry
        t /= 4
        s *= 2
    }
    return Point(x, y)
}

fun rot(n: Int, p: Point, rx: Int, ry: Int) {
    if (ry == 0) {
        if (rx == 1) {
            p.x = n - 1 - p.x
            p.y = n - 1 - p.y
        }
        val t  = p.x
        p.x = p.y
        p.y = t
    }
}

fun main(args:Array<String>) {
    val n = 32
    val k = 3
    val pts = List(n * k) { CharArray(n * k) { ' ' } }
    var prev = Point(0, 0)
    pts[0][0] = '.'
    for (d in 1 until n * n) {
        val curr = d2pt(n, d)
        val cx = curr.x * k
        val cy = curr.y * k
        val px = prev.x * k
        val py = prev.y * k
        pts[cx][cy] = '.'
        if (cx == px ) {
            if (py < cy)
                for (y in py + 1 until cy) pts[cx][y] = '|'
            else
                for (y in cy + 1 until py) pts[cx][y] = '|'
        }
        else {
            if (px < cx)
               for (x in px + 1 until cx) pts[x][cy] = '_'
            else
               for (x in cx + 1 until px) pts[x][cy] = '_'
        }
        prev = curr
    }
    for (i in 0 until n * k) {
        for (j in 0 until n * k) print(pts[j][i])
        println()
    }
}


MODE YEAR = INT, MONTH = INT, WEEK = INT, DAY = INT;

MODE DATE = STRUCT(
  YEAR year,  #DAY year day, #
  MONTH month, DAY month day,#
  WEEK week,  #DAY week day);

FORMAT mon fmt =      $c("Jan", "Feb", "Mar", "Apr", "May", "Jun",
                         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")$,
FORMAT week day fmt = $c("Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri")$;

PROC year days = (YEAR year)DAY: # Ignore 1752 CE for the moment #
  ( month days(year, 2) = 28 | 365 | 366 );

PROC month days = (YEAR year, MONTH month) DAY:
  ( month | 31,
            28 + ABS (year MOD 4 = 0 AND year MOD 100 /= 0 OR year MOD 400 = 0),
            31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

MONTH year months = 12;
DAY week days = 7; # France 1793 to 1805 had 10 day weeks! #

OP + = (DATE in date, DAY in days)DATE:
    BEGIN # todo: eliminate loops, handle year <= 1752 #
       DAY days := in days;
       DATE date := in date;
    # Normalize the days to be less then 1 year #
       WHILE days < 0 DO
         year OF date -:= 1;
         days +:= year days(year OF date)
       OD;
       WHILE days > year days(year OF date) DO
         days -:= year days(year OF date);
         year OF date +:= 1
       OD;
       month day OF date +:= days;
    # Normalize the days to be the same month #
       WHILE month day OF date > month days(year OF date, month OF date) DO
          month day OF date -:= month days(year OF date, month OF date);
          month OF date +:= 1;
          IF month OF date > year months THEN
             month OF date -:= year months;
             year OF date +:= 1
          FI
       OD;
       week day OF date := week day(date);
       date
    END;

OP +:= = (REF DATE date, DAY in days)DATE:
   date := date + in days;

PROC easter = (YEAR year)DATE:
   BEGIN
      COMMENT
         Easter date algorithm from J.M. Oudin (1940), reprinted in:
         P.K. Seidelmann ed., "Explanatory Supplement to the Astronomical
         Almanac" [1992] (Chapter 12, "Calendars", by L.E. Doggett)
      COMMENT
      DATE date; year OF date := year;
      INT c = year OVER 100, n = year MOD 19; # 19 years: Metonic cycle #
      INT i := (c - c OVER 4 - (c - (c - 17) OVER 25) OVER 3 + 19 * n + 15) MOD 30;
      i -:= (i OVER 28) * (1 - (i OVER 28) * (29 OVER (i + 1)) * ((21 - n) OVER 11));
      INT l = i - (year + year OVER 4 + i + 2 - c + c OVER 4) MOD 7;
      month OF date := 3 + (l + 40) OVER 44;
      month day OF date := l + 28 - 31 * (month OF date OVER 4);
      week day OF date := week day(date);
      date
   END;

PROC week day = (DATE date)DAY:
   # Zeller’s Congruence algorithm from 1887. #
   BEGIN
      INT year := year OF date, month := month OF date, month day := month day OF date, c;
      (month <= 2 | (month +:= 12, year -:= 1));
      c := year OVER 100;
      year MODAB 100;
      1 + (month day + ((month + 1) * 26) OVER 10
         + year + year OVER 4 + c OVER 4 - 2 * c) MOD 7
   END;

FORMAT wdmdm fmt = $f(week day fmt)z-dxf(mon fmt)$,

MODE EASTERRELATED = STRUCT(DATE easter, ascension, pentecost, trinity, corpus christi);

PROC easter related init = (YEAR year)EASTERRELATED:
BEGIN
  DATE date;
  EASTERRELATED holidays;
# Easter date, always a Sunday. #
   easter OF holidays := date := easter(year);
# Ascension day is 39 days after Easter.#
   ascension OF holidays := ( date +:= 39);
# Pentecost is 10 days after Ascension day.#
   pentecost OF holidays := date +:= 10;
# Trinity is 7 days after Pentecost.#
   trinity OF holidays := date +:= 7;
# Corpus Christi is 4 days after Trinity.#
   corpus christi OF holidays := date +:= 4;
   holidays
END;

# Note: Y10K bug here... :-) #
FORMAT easter related fmt = $g(-4)" Easter: "f(wdmdm fmt) ", Ascension: "f(wdmdm fmt)
    ", Pentecost: "f(wdmdm fmt) ", Trinity: "f(wdmdm fmt)", Corpus: "f(wdmdm fmt)$;

PROC easter related print = (YEAR year)VOID:
BEGIN
  EASTERRELATED holidays = easter related init(year);
  PROC wdmdm = (DATE date)STRUCT(DAY week day, DAY month day, MONTH month):
    (week day OF date, month day OF date, month OF date);
  printf((easter related fmt, year,
     wdmdm(easter OF holidays),  wdmdm(ascension OF holidays), wdmdm(pentecost OF holidays),
     wdmdm(trinity OF holidays), wdmdm(corpus christi OF holidays),
  $l$))
END;

printf (($"Christian holidays, related to Easter, for each centennial from 400 to 2100 CE:"l$));
FOR year FROM 400 BY 100 TO 2100 DO easter related print(year) OD;

printf (($l"Christian holidays, related to Easter, for years from 2010 to 2020 CE:"l$));
FOR year FROM 2010 TO 2020 DO easter related print(year) OD


1) two twinned recursive functions

{def left {lambda {:d :n}
 {if {< :n 1}
   then
   else T90      {right :d {- :n 1}}
        M:d T-90 {left  :d {- :n 1}}
        M:d      {left  :d {- :n 1}}
        T-90 M:d {right :d {- :n 1}}
        T90}}}

{def right {lambda {:d :n}
 {if {< :n 1}
   then
   else T-90    {left  :d {- :n 1}}
        M:d T90 {right :d {- :n 1}}
        M:d     {right :d {- :n 1}}
        T90 M:d {left  :d {- :n 1}}
        T-90}}}

The word Tθ rotates the drawing direction of a pen from θ degrees and the word Md moves it on d pixels.

{def H5 {left 18 5}}

The call {def H5 {left 18 5}} produces 2387 words begining with [T90 T-90 T90 T-90 T90 M10 T-90 M10 T-90 M10 T90 M10 T90 T-90 M10 T90 M10 T90 M10 T-90 M10 T-90 M10 T90 M10 T90 M10 T-90 T90 M10 T90 M10 T-90 M10 T-90 ...]

2) the SVG context

Lambdatalk comes with a primitive, turtle, translating the previous sequence of words into a sequence of SVG points [x0 y0 x1 y2 ... xn yn] feeding the "d" attribute of a SVG path.

{def stroke
 {lambda {:w :c}
  fill="transparent" stroke=":c" stroke-width=":w"}}

{svg
 {@ width="580px" height="580px"}
 {path {@ d="M {turtle 10 10 0 {H5}}" {stroke 8 #000}}}
 {path {@ d="M {turtle 10 10 0 {H5}}" {stroke 4 #000}}}
 {path {@ d="M {turtle 10 10 0 {H5}}" {stroke 1 #fff}}}
}


-- any version from LuaJIT 2.0/5.1, Lua 5.2, Lua 5.3 to LuaJIT 2.1.0-beta3-readline
local bit=bit32 or bit -- Lua 5.2/5.3 compatibilty
-- Hilbert curve implemented by Lindenmayer system
function string.hilbert(s, n)
	for i=1,n do
		s=s:gsub("[AB]",function(c)
			if c=="A" then
				c="-BF+AFA+FB-"
			else
				c="+AF-BFB-FA+"
			end
			return c
		end)
	end
	s=s:gsub("[AB]",""):gsub("%+%-",""):gsub("%-%+","")
	return s
end
-- Or the characters for ASCII line drawing
function charor(c1, c2)
	local bits={
		[" "]=0x0, ["╷"]=0x1, ["╶"]=0x2, ["┌"]=0x3, ["╵"]=0x4, ["│"]=0x5, ["└"]=0x6, ["├"]=0x7,
		["╴"]=0x8, ["┐"]=0x9, ["─"]=0xa, ["┬"]=0xb, ["┘"]=0xc, ["┤"]=0xd, ["┴"]=0xe, ["┼"]=0xf,}
	local char={" ", "╷", "╶", "┌", "╵", "│", "└", "├", "╴", "┐", "─", "┬", "┘", "┤", "┴", "┼",}
	local b1,b2=bits[c1] or 0,bits[c2] or 0
	return char[bit.bor(b1,b2)+1]
end
-- ASCII line drawing routine
function draw(s)
	local char={
		{"─","┘","╴","┐",}, -- r
		{"│","┐","╷","┌",}, -- up
		{"─","┌","╶","└",}, -- l
		{"│","└","╵","┘",},	-- down
	}
	local scr={}
	local move={{x=1,y=0},{x=0,y=1},{x=-1,y=0},{x=0,y=-1}}
	local x,y=1,1
	local minx,maxx,miny,maxy=1,1,1,1
	local dir,turn=0,0
	s=s.."F"
	local rep=0
	for c in s:gmatch(".") do
		if c=="F" then
			repeat
				if scr[y]==nil then scr[y]={} end
				scr[y][x]=charor(char[dir+1][turn%#char[1]+1],scr[y][x] or " ")
				dir = (dir+turn) % #move
				x, y = x+move[dir+1].x,y+move[dir+1].y
				maxx,maxy=math.max(maxx,x),math.max(maxy,y)
				minx,miny=math.min(minx,x),math.min(miny,y)
				turn=0
				rep=rep>1 and rep-1 or 0
			until rep==0
		elseif c=="-" then
			repeat
				turn=turn+1
				rep=rep>1 and rep-1 or 0
			until rep==0
		elseif c=="+" then
			repeat
				turn=turn-1
				rep=rep>1 and rep-1 or 0
			until rep==0
		elseif c:match("%d") then -- allow repeated commands
			rep=rep*10+tonumber(c)
		else
			repeat
				x, y = x+move[dir+1].x,y+move[dir+1].y
				maxx,maxy=math.max(maxx,x),math.max(maxy,y)
				minx,miny=math.min(minx,x),math.min(miny,y)
				rep=rep>1 and rep-1 or 0
			until rep==0
		end
	end
	for i=maxy,miny,-1 do
		local oneline={}
		for x=minx,maxx do
			oneline[1+x-minx]=scr[i] and scr[i][x] or " "
		end
		local line=table.concat(oneline)
		io.write(line, "\n")
	end
end
-- MAIN --
local n=arg[1] and tonumber(arg[1]) or 3
local str=arg[2] or "A"
draw(str:hilbert(n))


      INSTALL @lib$+"DATELIB"

      PRINT "Year      Easter    Ascension Pentecost Trinity   Corpus"
      FOR year% = 1800 TO 2100 STEP 100
        e% = FNeaster(year%) : f$ = "dd MMM"
        PRINT ;year%, FN_date$(e%,f$), FN_date$(e%+39,f$), \
        \     FN_date$(e%+49,f$), FN_date$(e%+56,f$), FN_date$(e%+60,f$)
      NEXT
      PRINT
      FOR year% = 2010 TO 2020
        e% = FNeaster(year%) : f$ = "dd MMM"
        PRINT ;year%, FN_date$(e%,f$), FN_date$(e%+39,f$), \
        \     FN_date$(e%+49,f$), FN_date$(e%+56,f$), FN_date$(e%+60,f$)
      NEXT
      END

      DEF FNeaster(year%)
      LOCAL a%, b%, c%, d%, e%
      a% = year% MOD 19
      b% = year% >>> 2
      c% = b% DIV 25 + 1
      d% = (c% * 3) >>> 2
      e% = ((a% * 19) - ((c% * 8 + 5) DIV 25) + d% + 15) MOD 30
      e% += (29578 - a% - e% * 32) >>> 10
      e% -= ((year% MOD 7) + b% - d% + e% + 2) MOD 7
      d% = e% >>> 5
      = FN_mjd(e% - d% * 31, d% + 3, year%)


scale = 0

/* Format d days after March 21. Assumes March, April, May or June. */
define format(d) {
	if (d > 80) {		print "     Jun ",  d - 71
	} else if (d > 71) { 	print "     Jun 0", d - 71
	} else if (d > 49) {	print "     May ",  d - 40
	} else if (d > 40) {	print "     May 0", d - 40
	} else if (d > 19) {	print "     Apr ",  d - 10
	} else if (d > 10) {	print "     Apr 0", d - 10
	} else {		print "     Mar ",  d + 21
	}
}

/*
 * For year n, print Easter and related holidays.
 * Assumes n >= 1, scale = 0.
 */
define easter(n) {
	auto a, b, d, e, j

	/*
	 * Calculate e = day of Easter, following the 1886 paper,
	 * Kalender-Formeln (Calendar Formulae) by Chr. Zeller.
	 *   http://www.merlyn.demon.co.uk/zel-1886.htm
	 *
	 * With bc, p % 7 gives the wrong result when p < 0. To give the
	 * correct result, this code uses "+ 6 * j" where one might have
	 * used "- j". This works because because 6 == -1 (mod 7).
	 */
	if (n < 1583) {
		/* Julian calendar (before October 1582) */
		b = (19 * (n % 19) + 15) % 30
		d = (b + n + n / 4) % 7
	} else {
		/* Gregorian calendar (after October 1582) */
		j = n / 100
		a = n % 19
		b = (19 * a + 15 + j - (8 * j + 13) / 25 - j / 4) % 30
		d = (b + n + n / 4 + 6 * j + j / 4 + 2) % 7
		if (d == 0 && (b == 29 || (b == 28 && a > 10))) d = 7
	}
	e = b + 7 - d		/* This counts days after 21 March. */

	if(n < 1000) " "
	print n
	z = format(e)		/* Easter */
	z = format(e + 39)	/* Ascension Thursday */
	z = format(e + 49)	/* Pentecost */
	z = format(e + 56)	/* Trinity Sunday */
	z = format(e + 60)	/* Corpus Christi */
	print "\n"
}

print "         Easter     Ascension             Trinity    Corpus\n"
print "  AD     Sunday     Thursday   Pentecost  Sunday     Christi\n"
for (year =  400; year <= 2000; year += 100) z = easter(year)
for (year = 2010; year <= 2020; year +=   1) z = easter(year)
z = easter(2100)
quit


const
  Level = 4
  Side = (1 shl Level) * 2 - 2

type Direction = enum E, N, W, S

const

  # Strings to use according to direction.
  Drawings1: array[Direction, string] = ["──", " │", "──", " │"]

  # Strings to use according to old and current direction.
  Drawings2: array[Direction, array[Direction, string]] = [["──", "─╯", " ?", "─╮"],
                                                           [" ╭", " │", "─╮", " ?"],
                                                           [" ?", " ╰", "──", " ╭"],
                                                           [" ╰", " ?", "─╯", " │"]]

type Curve = object
  grid: array[-Side..1, array[0..Side, string]]
  x, y: int
  dir, oldDir: Direction

proc newCurve(): Curve =
  ## Create a new curve.
  result.x = 0
  result.y = 0
  result.dir = E
  result.oldDir = E
  for row in result.grid.mitems:
    for item in row.mitems:
      item = "  "

proc left(dir: var Direction) =
  ## Turn on the left.
  dir = if dir == S: E else: succ(dir)

proc right(dir: var Direction) =
  ## Turn on the right.
  dir = if dir == E: S else: pred(dir)

proc move(curve: var Curve) =
  ## Move to next position according to current direction.
  case curve.dir
  of E: inc curve.x
  of N: dec curve.y
  of W: dec curve.x
  of S: inc curve.y

proc forward(curve: var Curve) =
  # Do one step: draw a corner, draw a segment and advance to next corner.

  # Draw corner.
  curve.grid[curve.y][curve.x] = Drawings2[curve.oldDir][curve.dir]
  curve.move()

  # Draw segment.
  curve.grid[curve.y][curve.x] = Drawings1[curve.dir]

  # Advance to next corner.
  curve.move()
  curve.oldDir = curve.dir

# Forward reference.
proc b(curve: var Curve; level: int)

proc a(curve: var Curve; level: int) =
  ## "A" function.
  if level > 0:
    curve.dir.left()
    curve.b(level - 1)
    curve.forward()
    curve.dir.right()
    curve.a(level - 1)
    curve.forward()
    curve.a(level - 1)
    curve.dir.right()
    curve.forward()
    curve.b(level - 1)
    curve.dir.left()

proc b(curve: var Curve; level: int) =
  ## "B" function.
  if level > 0:
    curve.dir.right()
    curve.a(level - 1)
    curve.forward()
    curve.dir.left()
    curve.b(level - 1)
    curve.forward()
    curve.b(level - 1)
    curve.dir.left()
    curve.forward()
    curve.a(level - 1)
    curve.dir.right()

### Main code

var curve = newCurve()

# Draw.
curve.a(Level)

# Print.
for row in curve.grid:
  for s in row:
    stdout.write(s)
  stdout.writeLine("")


use SVG;
use List::Util qw(max min);

use constant pi => 2 * atan2(1, 0);

# Compute the curve with a Lindemayer-system
%rules = (
    A => '-BF+AFA+FB-',
    B => '+AF-BFB-FA+'
);
$hilbert = 'A';
$hilbert =~ s/([AB])/$rules{$1}/eg for 1..6;

# Draw the curve in SVG
($x, $y) = (0, 0);
$theta   = pi/2;
$r       = 5;

for (split //, $hilbert) {
    if (/F/) {
        push @X, sprintf "%.0f", $x;
        push @Y, sprintf "%.0f", $y;
        $x += $r * cos($theta);
        $y += $r * sin($theta);
    }
    elsif (/\+/) { $theta += pi/2; }
    elsif (/\-/) { $theta -= pi/2; }
}

$max =  max(@X,@Y);
$xt  = -min(@X)+10;
$yt  = -min(@Y)+10;
$svg = SVG->new(width=>$max+20, height=>$max+20);
$points = $svg->get_path(x=>\@X, y=>\@Y, -type=>'polyline');
$svg->rect(width=>"100%", height=>"100%", style=>{'fill'=>'black'});
$svg->polyline(%$points, style=>{'stroke'=>'orange', 'stroke-width'=>1}, transform=>"translate($xt,$yt)");

open  $fh, '>', 'hilbert_curve.svg';
print $fh  $svg->xmlify(-namespace=>'svg');
close $fh;


#include <stdio.h>

typedef int year_t, month_t, week_t, day_t;

typedef struct{
  year_t year; /* day_t year_day, */
  month_t month;  day_t month_day;/*
  week_t week, */ day_t week_day; } date_t;

const char *mon_fmt[] =      {0, "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
const char *week_day_fmt[] = {0, "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"};

day_t month_days(year_t year, month_t month)
  { day_t days[]={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    return (month==2) ? 28 + (( year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0) : days[month];
  }

day_t year_days(year_t year) /* Ignore 1752 CE for the moment */
  { return (month_days(year, 2) == 28) ? 365 : 366; }

month_t year_months = 12;
week_t week_days = 7; /* France 1793 to 1805 had 10 day weeks! */

date_t plusab(date_t *date, day_t days)
    { /* todo: eliminate loops, handle year <== 1752 */
    /* Normalize the days to be less then 1 year */
       while(days < 0){
         date->year -= 1;
         days += year_days(date->year);
       };
       while(days > year_days(date->year)){
         days -= year_days(date->year);
         date->year += 1;
       };
       date->month_day += days;
    /* Normalize the days to be the same month */
       while(date->month_day > month_days(date->year, date->month)){
          date->month_day -= month_days(date->year, date->month);
          date->month += 1;
          if(date->month > year_months){
             date->month -= year_months;
             date->year += 1;
          }
       }
       date->week_day = week_day(*date);
       return *date;
    }

date_t easter (year_t year)
   {
      /*
         Easter date algorithm from J.M. Oudin (1940), reprinted in:
         P.K. Seidelmann ed., "Explanatory Supplement to the Astronomical
         Almanac" [1992] (Chapter 12, "Calendars", by L.E. Doggett)
      */
      date_t date; date.year = year;
      int c = year / 100, n = year % 19; /* 19 years: Metonic cycle */
      int i = (c - c / 4 - (c - (c - 17) / 25) / 3 + 19 * n + 15) % 30;
      i -= (i / 28) * (1 - (i / 28) * (29 / (i + 1)) * ((21 - n) / 11));
      int l = i - (year + year / 4 + i + 2 - c + c / 4) % 7;
      date.month = 3 + (l + 40) / 44;
      date.month_day = l + 28 - 31 * (date.month / 4);
      date.week_day = week_day(date);
      return date;
   }

day_t week_day (date_t date)
   /* Zeller’s Congruence algorithm from 1887. */
   {
      int year = date.year, month = date.month, month_day = date.month_day, c;
      if(month <= 2){month += 12; year -= 1;}
      c = year / 100;
      year %= 100;
      return 1 + ((month_day + ((month + 1) * 26) / 10
         + year + year / 4 + c / 4 - 2 * c) % 7 + 7) % 7;
   }

#define wdmdm_fmt "%s %2d %s"

typedef struct{date_t easter, ascension, pentecost, trinity, corpus_christi;}easter_related_t;

easter_related_t easter_related_init (year_t year)
{
   date_t date;
   easter_related_t holidays;
/* Easter date, always a Sunday. */
   holidays.easter = date = easter(year);
/* Ascension day is 39 days after Easter.*/
   holidays.ascension = plusab(&date, 39);
/* Pentecost is 10 days after Ascension day.*/
   holidays.pentecost = plusab(&date, 10);
/* Trinity is 7 days after Pentecost.*/
   holidays.trinity = plusab(&date, 7);
/* Corpus Christi is 4 days after Trinity.*/
   holidays.corpus_christi = plusab(&date, 4);
   return holidays;
}

/* note: y10k bug here... :-) */
#define easter_related_fmt "%4d Easter: "wdmdm_fmt", Ascension: "wdmdm_fmt\
    ", Pentecost: "wdmdm_fmt", Trinity: "wdmdm_fmt", Corpus: "wdmdm_fmt"\n"

void easter_related_print(year_t year)
{
  easter_related_t holidays = easter_related_init(year);
#define wdmdm(date) week_day_fmt[date.week_day], date.month_day, mon_fmt[date.month]
  printf(easter_related_fmt, year,
    wdmdm(holidays.easter),  wdmdm(holidays.ascension), wdmdm(holidays.pentecost),
    wdmdm(holidays.trinity), wdmdm(holidays.corpus_christi));
}

int main(){
  year_t year;

  printf ("Christian holidays, related to Easter, for each centennial from 400 to 2100 CE:\n");
  for(year=400; year<=2100; year+=100){ easter_related_print(year); }

  printf ("\nChristian holidays, related to Easter, for years from 2010 to 2020 CE:\n");
  for(year=2010; year<=2020; year++){ easter_related_print(year); }
  return 0;
}


--
-- demo\rosetta\hilbert_curve.exw
-- ==============================
--
--  Draws a hilbert curve.
--
with javascript_semantics
include pGUI.e

constant title = "Hilbert Curve"
Ihandle dlg, canvas
cdCanvas cddbuffer, cdcanvas

constant width = 64

sequence points = {}

procedure hilbert(integer x, y, lg, i1, i2)
    if lg=1 then
        integer px := (width-x) * 10,
                py := (width-y) * 10
        points = append(points, {px, py})
        return
    end if
    lg /= 2
    hilbert(x+i1*lg, y+i1*lg, lg, i1, 1-i2)
    hilbert(x+i2*lg, y+(1-i2)*lg, lg, i1, i2)
    hilbert(x+(1-i1)*lg, y+(1-i1)*lg, lg, i1, i2)
    hilbert(x+(1-i2)*lg, y+i2*lg, lg, 1-i1, i2)
end procedure

function redraw_cb(Ihandle /*ih*/, integer /*posx*/, /*posy*/)
    cdCanvasActivate(cddbuffer)
    cdCanvasBegin(cddbuffer, CD_OPEN_LINES)
    for i=1 to length(points) do
        integer {x,y} = points[i]
        cdCanvasVertex(cddbuffer, x, y)
    end for
    cdCanvasEnd(cddbuffer)
    cdCanvasFlush(cddbuffer)
    return IUP_DEFAULT
end function

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

procedure main()
    hilbert(0, 0, width, 0, 0)
    IupOpen()
    canvas = IupCanvas("RASTERSIZE=655x655")
    IupSetCallbacks(canvas, {"MAP_CB", Icallback("map_cb"),
                             "ACTION", Icallback("redraw_cb")})
    dlg = IupDialog(canvas,`TITLE="%s"`, {title})
    -- no resize here (since width is the constant 64...)
    IupSetAttribute(dlg, "DIALOGFRAME", "YES")
    IupShow(dlg)
    if platform()!=JS then
        IupMainLoop()
        IupClose()
    end if
end procedure

main()


using System;
using System.Collections;
using System.Collections.Specialized;
using System.Linq;

internal class Program
{
    private static readonly OrderedDictionary _holidayOffsets = new OrderedDictionary
                                                                    {
                                                                        {"Easter", 0},
                                                                        {"Ascension", 39},
                                                                        {"Pentecost", 49},
                                                                        {"Trinity", 56},
                                                                        {"Corpus", 60},
                                                                    };

    static void Main(string[] args)
    {
        Console.WriteLine("Christian holidays, related to Easter, for each centennial from 400 to 2100 CE:");
        for (int year = 400; year <= 2100; year += 100)
            OutputHolidays(year);

        Console.WriteLine();
        Console.WriteLine("Christian holidays, related to Easter, for years from 2010 to 2020 CE:");
        for (int year = 2010; year <= 2020; year += 1)
            OutputHolidays(year);
    }

    static void OutputHolidays(int year)
    {
        var easter = CalculateEaster(year);
        var holidays = from kp in _holidayOffsets.OfType<DictionaryEntry>()
                       let holiday = easter.AddDays(Convert.ToInt32(kp.Value))
                       select kp.Key + ": " + string.Format("{0,2:ddd} {0,2:%d} {0:MMM}", holiday);
        Console.WriteLine("{0,4} {1}", year, string.Join(", ", holidays.ToArray()));
    }

    static DateTime CalculateEaster(int year)
    {
        var a = year % 19;
        var b = year / 100;
        var c = year %100;
        var d = b / 4;
        var e = b % 4;
        var f = (b + 8) / 25;
        var g = (b - f + 1) / 3;
        var h = (19 * a + b - d - g + 15) % 30;
        var i = c / 4;
        var k = c % 4;
        var l = (32 + 2 * e + 2 * i - h - k) % 7;
        var m = (a + 11 * h + 22 * l) / 451;
        var numerator = h + l - 7 * m + 114;
        var month = numerator / 31;
        var day = (numerator % 31) + 1;
        return new DateTime(year, month, day);
    }
}


int  iterations = 7;
float strokeLen = 600;
int angleDeg = 90;
String axiom = "L";
StringDict rules = new StringDict();
String sentence = axiom;
int xo, yo;

void setup() {
  size(700, 700);
  xo= 50;
  yo = height - 50;
  strokeWeight(1);
  noFill();

  rules.set("L", "+RF-LFL-FR+");
  rules.set("R", "-LF+RFR+FL-");

  generate(iterations);
}

void draw() {
  background(0);
  translate(xo, yo);
  plot(radians(angleDeg));
}

void generate(int n) {
  for (int i=0; i < n; i++) {
    strokeLen *= 0.5;
    String nextSentence = "";
    for (int j=0; j < sentence.length(); j++) {
      char c = sentence.charAt(j);
      String ruleResult = rules.get(str(c), str(c));
      nextSentence += ruleResult;
    }
    sentence = nextSentence;
  }
}

void plot(float angle) {
  for (int i=0; i < sentence.length(); i++) {
    char c = sentence.charAt(i);
    if (c == 'F') {
      stroke(255);
      line(0, 0, 0, -strokeLen);
      translate(0, -strokeLen);
    } else if (c == '+') {
      rotate(angle);
    } else if (c == '-') {
      rotate(-angle);
    }
  }
}

void keyPressed() {
  if (key == '-') {
    angleDeg -= 1;
    println("Angle: " + angleDeg);
  }
  if (key == '=' || key == '+') {
    angleDeg += 1;
    println("Angle: " + angleDeg);
  }
  if (key == 'a') {
    strokeLen *= 2;
  }
  if (key == 'z') {
    strokeLen /= 2;
  }
  if (keyCode == LEFT) {
    xo -= 25;
  }
  if (keyCode == RIGHT) {
    xo += 25;
  }
  if (keyCode == UP) {
    yo -= 25;
  }
  if (keyCode == DOWN) {
    yo += 25;
  }
}


       identification division.
       program-id. Easter.

       environment division.
       configuration section.
       repository.
           function date-of-integer intrinsic
           function integer-of-date intrinsic
           function mod intrinsic.

       data division.
       working-storage section.
       77  days                   pic 9(2).
       77  a                      pic 9(2).
       77  b                      pic 9(2).
       77  c                      pic 9(2).
       77  d                      pic 9(2).
       77  e                      pic 9(2).
       77  f                      pic 9(2).
       77  g                      pic 9(2).
       77  h                      pic 9(2).
       77  i                      pic 9(2).
       77  k                      pic 9(2).
       77  l                      pic 9(2).
       77  m                      pic 9(2).
       77  week-day               pic 9(1).
       77  numerator              pic 9(4).
       77  integer-date           pic 9(18).

       01  month-tab              value "JanFebMarAprMayJunJulAugSepOctNovDec".
           05 month-abreviated    pic x(3) occurs 12.

       01  week-day-tab           value "SunMonTueWedThuFriSat".
           05 week-day-abreviated pic x(3) occurs 7.

       01  easter-date            pic 9(8).
       01  filler redefines easter-date.
           05 easter-year         pic 9(4).
           05 easter-month        pic 9(2).
           05 easter-day          pic 9(2).

       01  holiday-date           pic 9(8).
       01  filler redefines holiday-date.
           05 holiday-year        pic 9(4).
           05 holiday-month       pic 9(2).
           05 holiday-day         pic 9(2).

       01  edt-date.
           05 edt-week-day        pic x(3).
           05 filler              pic x value space.
           05 edt-day             pic z(2).
           05 filler              pic x value space.
           05 edt-month           pic x(3).

       procedure division.
       main.
           display "Christian holidays, related to Easter, for each centennial from 1700 to 2100 CE:"
           perform varying easter-year from 1700 by 100 until easter-year > 2100
              perform output-holydays
           end-perform
           display " "

           display "Christian holidays, related to Easter, for years from 2010 to 2020 CE:"
           perform varying easter-year from 2010 by 1 until easter-year > 2020
              perform output-holydays
           end-perform
           display " "

           stop run
           .
       output-holydays.
           display easter-year " " no advancing
           perform calculate-easter

           move 0 to days
           perform add-days
           display " Easter: " edt-date no advancing

           move 39 to days
           perform add-days
           display " Ascension: " edt-date no advancing

           move 49 to days
           perform add-days
           display " Pentecost: " edt-date no advancing

           move 56 to days
           perform add-days
           display " Trinity: " edt-date no advancing

           move 60 to days
           perform add-days
           display " Corpus: " edt-date
           .
       calculate-easter.
           compute a = mod(easter-year, 19)
           compute b = easter-year / 100
           compute c = mod(easter-year, 100)
           compute d = b / 4
           compute e = mod(b, 4)
           compute f = (b + 8) / 25
           compute g = (b - f + 1) / 3
           compute h = mod((19 * a + b - d - g + 15), 30)
           compute i = c / 4
           compute k = mod(c, 4)
           compute l = mod((32 + 2 * e + 2 * i - h - k), 7)
           compute m = (a + 11 * h + 22 * l) / 451
           compute numerator = h + l - 7 * m + 114
           compute easter-month = numerator / 31
           compute easter-day = mod(numerator, 31) + 1
           .
       add-days.
           if days = 0
              move easter-date to holiday-date
              move 1 to week-day
           else
              compute holiday-date = date-of-integer(integer-of-date(easter-date) + days)
              compute week-day = mod(integer-of-date(easter-date) + days, 7) + 1
           end-if
           move week-day-abreviated(week-day) to edt-week-day
           move month-abreviated(holiday-month) to edt-month
           move holiday-day to edt-day
           .


'''Hilbert curve'''

from itertools import (chain, islice)

# hilbertCurve :: Int -> SVG String
def hilbertCurve(n):
    '''An SVG string representing a
       Hilbert curve of degree n.
    '''
    w = 1024
    return svgFromPoints(w)(
        hilbertPoints(w)(
            hilbertTree(n)
        )
    )

# hilbertTree :: Int -> Tree Char
def hilbertTree(n):
    '''Nth application of a rule to a seedling tree.'''

    # rule :: Dict Char [Char]
    rule = {
        'a': ['d', 'a', 'a', 'b'],
        'b': ['c', 'b', 'b', 'a'],
        'c': ['b', 'c', 'c', 'd'],
        'd': ['a', 'd', 'd', 'c']
    }

    # go :: Tree Char -> Tree Char
    def go(tree):
        c = tree['root']
        xs = tree['nest']
        return Node(c)(
            map(go, xs) if xs else map(
                flip(Node)([]),
                rule[c]
            )
        )
    seed = Node('a')([])
    return list(islice(
        iterate(go)(seed), n
    ))[-1] if 0 < n else seed

# hilbertPoints :: Int -> Tree Char -> [(Int, Int)]
def hilbertPoints(w):
    '''Serialization of a tree to a list of points
       bounded by a square of side w.
    '''

    # vectors :: Dict Char [(Int, Int)]
    vectors = {
        'a': [(-1, 1), (-1, -1), (1, -1), (1, 1)],
        'b': [(1, -1), (-1, -1), (-1, 1), (1, 1)],
        'c': [(1, -1), (1, 1), (-1, 1), (-1, -1)],
        'd': [(-1, 1), (1, 1), (1, -1), (-1, -1)]
    }

    # points :: Int -> ((Int, Int), Tree Char) -> [(Int, Int)]
    def points(d):
        '''Size -> Centre of a Hilbert subtree -> All subtree points
        '''
        def go(xy, tree):
            r = d // 2

            def deltas(v):
                return (
                    xy[0] + (r * v[0]),
                    xy[1] + (r * v[1])
                )
            centres = map(deltas, vectors[tree['root']])
            return chain.from_iterable(
                map(points(r), centres, tree['nest'])
            ) if tree['nest'] else centres
        return go

    d = w // 2
    return lambda tree: list(points(d)((d, d), tree))

# svgFromPoints :: Int -> [(Int, Int)] -> SVG String
def svgFromPoints(w):
    '''Width of square canvas -> Point list -> SVG string'''

    def go(xys):
        def points(xy):
            return str(xy[0]) + ' ' + str(xy[1])
        xs = ' '.join(map(points, xys))
        return '\n'.join(
            ['<svg xmlns="http://www.w3.org/2000/svg"',
             f'width="512" height="512" viewBox="5 5 {w} {w}">',
             f'<path d="M{xs}" ',
             'stroke-width="2" stroke="red" fill="transparent"/>',
             '</svg>'
             ]
        )
    return go

# ------------------------- TEST --------------------------
def main():
    '''Testing generation of the SVG for a Hilbert curve'''
    print(
        hilbertCurve(6)
    )

# ------------------- GENERIC FUNCTIONS -------------------

# Node :: a -> [Tree a] -> Tree a
def Node(v):
    '''Contructor for a Tree node which connects a
       value of some kind to a list of zero or
       more child trees.'''
    return lambda xs: {'type': 'Node', 'root': v, 'nest': xs}

# flip :: (a -> b -> c) -> b -> a -> c
def flip(f):
    '''The (curried or uncurried) function f with its
       arguments reversed.
    '''
    return lambda a: lambda b: f(b)(a)

# iterate :: (a -> a) -> a -> Gen [a]
def iterate(f):
    '''An infinite list of repeated
       applications of f to x.
    '''
    def go(x):
        v = x
        while True:
            yield v
            v = f(v)
    return go

#  TEST ---------------------------------------------------
if __name__ == '__main__':
    main()


; Easter sunday. Result is a list '(month day)
;
; See:
; Jean Meeus, "Astronomical Formulae for Calculators",
; 4th edition, Willmann-Bell, 1988, p.31

(defun easter (year)
  (let (a b c d e f g h i k l m n p)
    (setq a (rem year 19))
    (multiple-value-setq (b c) (floor year 100))
    (multiple-value-setq (d e) (floor b 4))
    (setq f (floor (+ b 8) 25))
    (setq g (floor (- b f -1) 3))
    (setq h (rem (+ (* 19 a) (- b d g) 15) 30))
    (multiple-value-setq (i k) (floor c 4))
    (setq l (rem (+ 32 e e i (- i h k)) 7))
    (setq m (floor (+ a (* 11 h) (* 22 l)) 451))
    (multiple-value-setq (n p) (floor (+ h l (- 114 (* 7 m))) 31))
    (list n (1+ p))))


import std.stdio, std.datetime;

void printEasterRelatedHolidays(in int year) {
    static struct Holyday {
        string name;
        int offs;
    }
    static immutable Holyday[] holidayOffsets = [{"Easter",     0},
                                                 {"Ascension", 39},
                                                 {"Pentecost", 10},
                                                 {"Trinity",    7},
                                                 {"Corpus",     4}];

    // Calculate Easter.
    Date date;
    {
        immutable a = year % 19;
        immutable b = year / 100;
        immutable c = year %100;
        immutable d = b / 4;
        immutable e = b % 4;
        immutable f = (b + 8) / 25;
        immutable g = (b - f + 1) / 3;
        immutable h = (19 * a + b - d - g + 15) % 30;
        immutable i = c / 4;
        immutable k = c % 4;
        immutable l = (32 + 2 * e + 2 * i - h - k) % 7;
        immutable m = (a + 11 * h + 22 * l) / 451;
        immutable n = h + l - 7 * m + 114;
        immutable month = n / 31;
        immutable day = (n % 31) + 1;
        date = Date(year, month, day);
    }

    writef("%4d ", year);
    foreach (immutable hd; holidayOffsets) {
        date += days(hd.offs);
        writef("%s: %2d %s  ", hd.name, date.day, date.month);
    }
    writeln();
}

void main() {
    writeln("Christian holidays, related to Easter," ~
            " for each centennial from 400 to 2100 CE:");
    for (int y = 400; y <= 2100; y += 100)
        printEasterRelatedHolidays(y);

    writeln("\nChristian holidays, related to Easter," ~
            " for years from 2010 to 2020 CE:");
    foreach (immutable y; 2010 .. 2021)
        printEasterRelatedHolidays(y);
}


_Title "Hilbert Curve"
Dim Shared As Integer sw, sh, wide, cell

wide = 128: cell = 4
sw = wide * cell + cell
sh = sw

Screen _NewImage(sw, sh, 8)
Cls , 15: Color 0
PSet (wide * cell, wide * cell)

Call Hilbert(0, 0, wide, 0, 0)

Sleep
System

Sub Hilbert (x As Integer, y As Integer, lg As Integer, p As Integer, q As Integer)
    Dim As Integer iL, iX, iY
    iL = lg: iX = x: iY = y
    If iL = 1 Then
        Line -((wide - iX) * cell, (wide - iY) * cell)
        Exit Sub
    End If
    iL = iL \ 2
    Call Hilbert(iX + p * iL, iY + p * iL, iL, p, 1 - q)
    Call Hilbert(iX + q * iL, iY + (1 - q) * iL, iL, p, q)
    Call Hilbert(iX + (1 - p) * iL, iY + (1 - p) * iL, iL, p, q)
    Call Hilbert(iX + (1 - q) * iL, iY + q * iL, iL, 1 - p, q)
End Sub


  [ $ "turtleduck.qky" loadfile ] now!

  [ stack ]                      is switch.arg (   --> [ )

  [ switch.arg put ]             is switch     ( x -->   )

  [ switch.arg release ]         is otherwise  (   -->   )

  [ switch.arg share
    != iff ]else[ done
    otherwise ]'[ do ]done[ ]    is case       ( x -->   )

  [ $ "" swap witheach
      [ nested quackery join ] ] is expand     ( $ --> $ )

  [ $ "F" ]                      is F          ( $ --> $ )

  [ $ "L" ]                      is L          ( $ --> $ )

  [ $ "R" ]                      is R          ( $ --> $ )

  [ $ "LBFRAFARFBL" ]            is A          ( $ --> $ )

  [ $ "RAFLBFBLFAR" ]            is B          ( $ --> $ )

  $ "A"

  5 times expand

  turtle
  witheach
    [ switch
        [ char F case [ 10 1 walk ]
          char L case [ -1 4 turn ]
          char R case [  1 4 turn ]
          otherwise ( ignore ) ] ]


#lang racket

(require racket/draw)

(define rules '([A . (- B F + A F A + F B -)]
                [B . (+ A F - B F B - F A +)]))

(define (get-cmds n cmd)
  (cond
    [(= 0 n) (list cmd)]
    [else (append-map (curry get-cmds (sub1 n))
                      (dict-ref rules cmd (list cmd)))]))

(define (make-curve DIM N R OFFSET COLOR BACKGROUND-COLOR)
  (define target (make-bitmap DIM DIM))
  (define dc (new bitmap-dc% [bitmap target]))
  (send dc set-background BACKGROUND-COLOR)
  (send dc set-pen COLOR 1 'solid)
  (send dc clear)
  (for/fold ([x 0] [y 0] [θ (/ pi 2)])
            ([cmd (in-list (get-cmds N 'A))])
    (define (draw/values x* y* θ*)
      (send/apply dc draw-line (map (curry + OFFSET) (list x y x* y*)))
      (values x* y* θ*))
    (match cmd
      ['F (draw/values (+ x (* R (cos θ))) (+ y (* R (sin θ))) θ)]
      ['+ (values x y (+ θ (/ pi 2)))]
      ['- (values x y (- θ (/ pi 2)))]
      [_  (values x y θ)]))
  target)

(make-curve 500 6 7 30 (make-color 255 255 0) (make-color 0 0 0))


use SVG;

role Lindenmayer {
    has %.rules;
    method succ {
        self.comb.map( { %!rules{$^c} // $c } ).join but Lindenmayer(%!rules)
    }
}

my $hilbert = 'A' but Lindenmayer( { A => '-BF+AFA+FB-', B => '+AF-BFB-FA+' } );

$hilbert++ xx 7;
my @points = (647, 13);

for $hilbert.comb {
    state ($x, $y) = @points[0,1];
    state $d = -5 - 0i;
    when 'F' { @points.append: ($x += $d.re).round(1), ($y += $d.im).round(1) }
    when /< + - >/ { $d *= "{$_}1i" }
    default { }
}

say SVG.serialize(
    svg => [
        :660width, :660height, :style<stroke:blue>,
        :rect[:width<100%>, :height<100%>, :fill<white>],
        :polyline[ :points(@points.join: ','), :fill<white> ],
    ],
);


program Holidays_related_to_Easter;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

type
  THollyday = record
    name: string;
    offs: Integer;
  end;

const
  Holyday: array[0..4] of THollyday = ((
    name: 'Easter';
    offs: 0
  ), (
    name: 'Ascension';
    offs: 39
  ), (
    name: 'Pentecost';
    offs: 10
  ), (
    name: 'Trinity';
    offs: 7
  ), (
    name: 'Corpus';
    offs: 4
  ));

function Easter(year: Integer): TDateTime;
begin
  var a := year mod 19;
  var b := year div 100;
  var c := year mod 100;
  var d := b div 4;
  var e := b mod 4;
  var f := (b + 8) div 25;
  var g := (b - f + 1) div 3;
  var h := (19 * a + b - d - g + 15) mod 30;
  var i := c div 4;
  var k := c mod 4;
  var l := (32 + 2 * e + 2 * i - h - k) mod 7;
  var m := (a + 11 * h + 22 * l) div 451;
  var n := h + l - 7 * m + 114;
  var month := n div 31;
  var day := (n mod 31) + 1;

  Result := EncodeDate(year, month, day);
end;

procedure PrintEasterRelatedHolidays(year: Integer);
var
  y, m, d: word;
  fmt: TFormatSettings;
begin
  fmt := TFormatSettings.Create('en-US'); // just for use english name of month
  var date := Easter(year);
  write(year: 4, ' ');
  for var hd in Holyday do
  begin
    date := date + hd.offs;
    var dt := FormatDateTime('dd mmmm', date, fmt);
    write(format('%s: %s  ', [hd.name, dt]));
  end;
  writeln;
end;

begin
  writeln('Christian holidays, related to Easter,' +
    ' for each centennial from 400 to 2100 CE:');
  for var y := 4 to 21 do
    printEasterRelatedHolidays(y * 100);

  writeln(#10'Christian holidays, related to Easter,' +
    ' for years from 2010 to 2020 CE:');

  for var y := 2010 to 2020 do
    printEasterRelatedHolidays(y);
  readln;
end.


# Project : Hilbert curve

load "guilib.ring"

paint = null
x1 = 0
y1 = 0

new qapp
        {
        win1 = new qwidget() {
                  setwindowtitle("Hilbert curve")
                  setgeometry(100,100,400,500)
                  label1 = new qlabel(win1) {
                              setgeometry(10,10,400,400)
                              settext("")
                  }
                  new qpushbutton(win1) {
                          setgeometry(150,400,100,30)
                          settext("draw")
                          setclickevent("draw()")
                  }
                  show()
        }
        exec()
        }

func draw
        p1 = new qpicture()
               color = new qcolor() {
               setrgb(0,0,255,255)
        }
        pen = new qpen() {
                 setcolor(color)
                 setwidth(1)
        }
        paint = new qpainter() {
                  begin(p1)
                  setpen(pen)

        x1 = 0.5
        y1 = 0.5
        hilbert(0, 0, 200,  0,  0,  200,  4)

        endpaint()
        }
        label1 { setpicture(p1) show() }

func hilbert (x, y, xi, xj, yi, yj, n)
        cur = new QCursor() {
                 setpos(100, 100)
        }

        if (n <= 0)
           drawtoline(x + (xi + yi)/2, y + (xj + yj)/2)
       else
           hilbert(x, y, yi/2, yj/2, xi/2, xj/2, n-1)
           hilbert(x+xi/2, y+xj/2 , xi/2, xj/2, yi/2, yj/2, n-1)
           hilbert(x+xi/2+yi/2, y+xj/2+yj/2, xi/2, xj/2, yi/2, yj/2, n-1);
           hilbert(x+xi/2+yi, y+xj/2+yj, -yi/2,-yj/2, -xi/2, -xj/2, n-1)
       ok

func drawtoline x2, y2
        paint.drawline(x1, y1, x2, y2)
        x1 = x2
        y1 = y2


# frozen_string_literal: true

load_library :grammar
attr_reader :hilbert
def settings
  size 600, 600
end

def setup
  sketch_title '2D Hilbert'
  @hilbert = Hilbert.new
  hilbert.create_grammar 5
  no_loop
end

def draw
  background 0
  hilbert.render
end

Turtle = Struct.new(:x, :y, :theta)

# Hilbert Class has access to Sketch methods eg :line, :width, :height
class Hilbert
  include Processing::Proxy

  attr_reader :grammar, :axiom, :draw_length, :production, :turtle
  DELTA = 90.radians
  def initialize
    @axiom = 'FL'
    @grammar = Grammar.new(
      axiom,
      'L' => '+RF-LFL-FR+',
      'R' => '-LF+RFR+FL-'
    )
    @draw_length = 200
    stroke 0, 255, 0
    stroke_weight 2
    @turtle = Turtle.new(width / 9, height / 9, 0)
  end

  def render
    production.scan(/./) do |element|
      case element
      when 'F' # NB NOT using affine transforms
        draw_line(turtle)
      when '+'
        turtle.theta += DELTA
      when '-'
        turtle.theta -= DELTA
      when 'L'
      when 'R'
      else puts 'Grammar not recognized'
      end
    end
  end

  def draw_line(turtle)
    x_temp = turtle.x
    y_temp = turtle.y
    turtle.x += draw_length * Math.cos(turtle.theta)
    turtle.y += draw_length * Math.sin(turtle.theta)
    line(x_temp, y_temp, turtle.x, turtle.y)
  end

  ##############################
  # create grammar from axiom and
  # rules (adjust scale)
  ##############################

  def create_grammar(gen)
    @draw_length *= 0.6**gen
    @production = @grammar.generate gen
  end
end


defmodule Holiday do
  @offsets  [ Easter: 0, Ascension: 39, Pentecost: 49, Trinity: 56, Corpus: 60 ]
  @mon  { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }

  def easter_date(year) do
    a = rem(year, 19)
    b = div(year, 100)
    c = rem(year, 100)
    d = div(b, 4)
    e = rem(b, 4)
    f = div((b + 8), 25)
    g = div((b - f + 1), 3)
    h = rem((19*a + b - d - g + 15), 30)
    i = div(c, 4)
    k = rem(c, 4)
    l = rem((32 + 2*e + 2*i - h - k), 7)
    m = div((a + 11*h + 22*l), 451)
    numerator = h + l - 7*m + 114
    month = div(numerator, 31)
    day = rem(numerator, 31) + 1
    {year, month, day}
  end

  defp holidays(year) do
    IO.write String.rjust("#{year}:", 5)
    gday = :calendar.date_to_gregorian_days(easter_date(year))
    Enum.map_join(Keyword.values(@offsets), fn d ->
      {_year, month, day} = :calendar.gregorian_days_to_date(gday + d)
      String.rjust("#{day}  #{elem(@mon, month-1)}", 11)
    end)
  end

  def task do
    IO.puts "Year:" <> Enum.map_join(Keyword.keys(@offsets), &String.rjust("#{&1}",11))
    Enum.each(Enum.take_every(400..2100, 100), fn year -> IO.puts holidays(year) end)
    IO.puts ""
    Enum.each(2010..2020, fn year -> IO.puts holidays(year) end)
  end
end

Holiday.task


-module(holidays).
-export([task/0]).

offsets(easter)    ->  0;
offsets(ascension) -> 39;
offsets(pentecost) -> 49;
offsets(trinity)   -> 56;
offsets(corpus)    -> 60.

month(Month) ->
    element(Month, { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" } ).

easter_date(Year) ->
    A = Year rem 19,
    B = Year div 100,
    C = Year rem 100,
    D = B div 4,
    E = B rem 4,
    F = (B + 8) div 25,
    G = (B - F + 1) div 3,
    H = (19*A + B - D - G + 15) rem 30,
    I = C div 4,
    K = C rem 4,
    L = (32 + 2*E + 2*I - H - K) rem 7,
    M = (A + 11*H + 22*L) div 451,
    Numerator = H + L - 7*M + 114,
    Month = Numerator div 31,
    Day = Numerator rem 31 + 1,
    {Year, Month, Day}.

holidays() ->
    [ easter, ascension, pentecost, trinity, corpus ].

holidays(Year) ->
    io:format("~4w:", [Year]),
    Gday = calendar:date_to_gregorian_days(easter_date(Year)),
    holidays(Gday, holidays()).

holidays(_, []) ->
    io:format("~n");
holidays(Gday, [H | T]) ->
    Offset = offsets(H),
    {_Year, Month, Day} = calendar:gregorian_days_to_date(Gday + Offset),
    io:format("~6w  ~3s", [Day, month(Month)]),
    holidays(Gday, T).

title([]) ->
    io:format("~n");
title([H | T]) ->
    io:format("  ~9s", [H]),
    title(T).

task() ->
    io:format("Year:"),
    title(holidays()),
    task(400, 2100, 100),
    task(2010, 2020, 1).

task(Year, Max, _) when Year > Max ->
    io:format("~n");
task(Year, Max, Step) ->
    holidays(Year),
    task(Year+Step, Max, Step).


// [dependencies]
// svg = "0.8.0"

use svg::node::element::path::Data;
use svg::node::element::Path;

struct HilbertCurve {
    current_x: f64,
    current_y: f64,
    current_angle: i32,
    line_length: f64,
}

impl HilbertCurve {
    fn new(x: f64, y: f64, length: f64, angle: i32) -> HilbertCurve {
        HilbertCurve {
            current_x: x,
            current_y: y,
            current_angle: angle,
            line_length: length,
        }
    }
    fn rewrite(order: usize) -> String {
        let mut str = String::from("A");
        for _ in 0..order {
            let mut tmp = String::new();
            for ch in str.chars() {
                match ch {
                    'A' => tmp.push_str("-BF+AFA+FB-"),
                    'B' => tmp.push_str("+AF-BFB-FA+"),
                    _ => tmp.push(ch),
                }
            }
            str = tmp;
        }
        str
    }
    fn execute(&mut self, order: usize) -> Path {
        let mut data = Data::new().move_to((self.current_x, self.current_y));
        for ch in HilbertCurve::rewrite(order).chars() {
            match ch {
                'F' => data = self.draw_line(data),
                '+' => self.turn(90),
                '-' => self.turn(-90),
                _ => {}
            }
        }
        Path::new()
            .set("fill", "none")
            .set("stroke", "black")
            .set("stroke-width", "1")
            .set("d", data)
    }
    fn draw_line(&mut self, data: Data) -> Data {
        let theta = (self.current_angle as f64).to_radians();
        self.current_x += self.line_length * theta.cos();
        self.current_y -= self.line_length * theta.sin();
        data.line_to((self.current_x, self.current_y))
    }
    fn turn(&mut self, angle: i32) {
        self.current_angle = (self.current_angle + angle) % 360;
    }
    fn save(file: &str, size: usize, order: usize) -> std::io::Result<()> {
        use svg::node::element::Rectangle;
        let x = 10.0;
        let y = 10.0;
        let rect = Rectangle::new()
            .set("width", "100%")
            .set("height", "100%")
            .set("fill", "white");
        let mut hilbert = HilbertCurve::new(x, y, 10.0, 0);
        let document = svg::Document::new()
            .set("width", size)
            .set("height", size)
            .add(rect)
            .add(hilbert.execute(order));
        svg::save(file, &document)
    }
}

fn main() {
    HilbertCurve::save("hilbert_curve.svg", 650, 6).unwrap();
}


@js.annotation.JSExportTopLevel("ScalaFiddle")
object ScalaFiddle {
  // $FiddleStart
  import scala.util.Random

  case class Point(x: Int, y: Int)

  def xy2d(order: Int, d: Int): Point = {
    def rot(order: Int, p: Point, rx: Int, ry: Int): Point = {
      val np = if (rx == 1) Point(order - 1 - p.x, order - 1 - p.y) else p
      if (ry == 0) Point(np.y, np.x) else p
    }

    @scala.annotation.tailrec
    def iter(rx: Int, ry: Int, s: Int, t: Int, p: Point): Point = {
      if (s < order) {
        val _rx = 1 & (t / 2)
        val _ry = 1 & (t ^ _rx)
        val temp = rot(s, p, _rx, _ry)
        iter(_rx, _ry, s * 2, t / 4, Point(temp.x + s * _rx, temp.y + s * _ry))
      } else p
    }

    iter(0, 0, 1, d, Point(0, 0))
  }

  def randomColor =
    s"rgb(${Random.nextInt(240)}, ${Random.nextInt(240)}, ${Random.nextInt(240)})"

  val order = 64
  val factor = math.min(Fiddle.canvas.height, Fiddle.canvas.width) / order.toDouble
  val maxD = order * order
  var d = 0
  Fiddle.draw.strokeStyle = randomColor
  Fiddle.draw.lineWidth = 2
  Fiddle.draw.lineCap = "square"

  Fiddle.schedule(10) {
    val h = xy2d(order, d)
    Fiddle.draw.lineTo(h.x * factor, h.y * factor)
    Fiddle.draw.stroke
    if ({d += 1; d >= maxD})
    {d = 1; Fiddle.draw.strokeStyle = randomColor}
    Fiddle.draw.beginPath
    Fiddle.draw.moveTo(h.x * factor, h.y * factor)
  }
  // $FiddleEnd
}


USING: calendar formatting io kernel locals math math.ranges
sequences ;

! Calculate Easter.
:: my-easter ( year -- timestamp )
    year 19 mod                      :> a
    year 100 /i                      :> b
    year 100 mod                     :> c
    b 4 /i                           :> d
    b 4 mod                          :> e
    b 8 + 25 /i                      :> f
    b f - 1 + 3 /i                   :> g
    19 a * b + d - g - 15 + 30 mod   :> h
    c 4 /i                           :> i
    c 4 mod                          :> k
    32 2 e * + 2 i * + h - k - 7 mod :> l
    a 11 h * + 22 l * + 451 /i       :> m
    h l + 7 m * - 114 +              :> n
    n 31 /i                          :> month
    n 31 mod 1 +                     :> day
    year month day <date> ;

: show-related ( timestamp days-offset -- )
    days time+ "   %d %b   " strftime write ;

: holidays ( from to step -- )
    "Year     Easter      Ascension   Pentecost   Trinity     Corpus" print
    <range> [
        dup "%4d: " printf my-easter
        { 0 39 49 56 60 } [ show-related ] with each nl
    ] each ;

400 2100 100 holidays nl
2010 2020 1 holidays


variable year

: ea_a year @ 19 mod ;
: ea_b year @ 100 / ;
: ea_c year @ 100 mod ;
: ea_d ea_b 4 / ;
: ea_e ea_b 4 mod ;
: ea_f ea_b 8 + 25 / ;
: ea_g ea_b ea_f - 1 + 3 / ;
: ea_h 19 ea_a * ea_b + ea_d - ea_g - 15 + 30 mod ;
: ea_i ea_c 4 / ;
: ea_k ea_c 4 mod ;
: ea_l 32 2 ea_e * + 2 ea_i * + ea_h - ea_k - 7 mod ;
: ea_m ea_a 11 ea_h * + 22 ea_i * + 451 / ;
: ea_numerator ea_h ea_l + 7 ea_m * - 114 + ;
: ea_month ea_numerator 31 / ;
: ea_day ea_numerator 31 mod 1 + ;
: bs ( -- backspace )
  8 emit ;

: monthname ( monthnum -- name )
  case
  1 of ." Jan" endof
  2 of ." Feb" endof
  3 of ." Mar" endof
  4 of ." Apr" endof
  5 of ." May" endof
  6 of ." Jun" endof
  7 of ." Jul" endof
  8 of ." Aug" endof
  9 of ." Sep" endof
  10 of ." Oct" endof
  11 of ." Nov" endof
  12 of ." Dec" endof
  dup . ." wrong input"
  endcase
;

: eastern ( year -- )
  dup year ! . bs ." :" space ea_day . bs space ea_month monthname ;

: main
  cr .\" year: eastern" cr 2200 400
  DO i eastern cr 100
  +LOOP
  cr 2021 2010
  DO i eastern cr
  LOOP
  ;


      subroutine easter(year,month,day)
c Easter sunday
c
c Input
c   year
c Output
c   month
c   day
c
c See:
c Jean Meeus, "Astronomical Formulae for Calculators",
c 4th edition, Willmann-Bell, 1988, p.31
      implicit integer(a-z)
      a=mod(year,19)
      b=year/100
      c=mod(year,100)
      d=b/4
      e=mod(b,4)
      f=(b+8)/25
      g=(b-f+1)/3
      h=mod(19*a+b-d-g+15,30)
      i=c/4
      k=mod(c,4)
      l=mod(32+2*e+2*i-h-k,7)
      m=(a+11*h+22*l)/451
      n=h+l-7*m+114
      month=n/31
      day=mod(n,31)+1
      end


$ include "seed7_05.s7i";
  include "draw.s7i";
  include "keybd.s7i";

const integer: delta is 8;

const proc: drawDown (inout integer: x, inout integer: y, in integer: n) is forward;
const proc: drawUp (inout integer: x, inout integer: y, in integer: n) is forward;

const proc: drawRight (inout integer: x, inout integer: y, in integer: n) is func
  begin
    if n > 0 then
      drawDown(x, y, pred(n));
      line(x, y, 0, delta, white);
      y +:= delta;
      drawRight(x, y, pred(n));
      line(x, y, delta, 0, white);
      x +:= delta;
      drawRight(x, y, pred(n));
      line(x, y, 0, -delta, white);
      y -:= delta;
      drawUp(x, y, pred(n));
    end if;
  end func;

const proc: drawLeft (inout integer: x, inout integer: y, in integer: n) is func
  begin
    if n > 0 then
      drawUp(x, y, pred(n));
      line(x, y, 0, -delta, white);
      y -:= delta;
      drawLeft(x, y, pred(n));
      line(x, y, -delta, 0, white);
      x -:= delta;
      drawLeft(x, y, pred(n));
      line(x, y, 0, delta, white);
      y +:= delta;
      drawDown(x, y, pred(n));
    end if;
  end func;

const proc: drawDown (inout integer: x, inout integer: y, in integer: n) is func
  begin
    if n > 0 then
      drawRight(x, y, pred(n));
      line(x, y, delta, 0, white);
      x +:= delta;
      drawDown(x, y, pred(n));
      line(x, y, 0, delta, white);
      y +:= delta;
      drawDown(x, y, pred(n));
      line(x, y, -delta, 0, white);
      x -:= delta;
      drawLeft(x, y, pred(n));
    end if;
  end func;

const proc: drawUp (inout integer: x, inout integer: y, in integer: n) is func
  begin
    if n > 0 then
      drawLeft(x, y, pred(n));
      line(x, y, -delta, 0, white);
      x -:= delta;
      drawUp(x, y, pred(n));
      line(x, y, 0, -delta, white);
      y -:= delta;
      drawUp(x, y, pred(n));
      line(x, y, delta, 0, white);
      x +:= delta;
      drawRight(x, y, pred(n));
    end if;
  end func;

const proc: main is func
  local
    var integer: x is 11;
    var integer: y is 11;
  begin
    screen(526, 526);
    KEYBOARD := GRAPH_KEYBOARD;
    drawRight(x, y, 6);
    readln(KEYBOARD);
  end func;


require('Image::Magick')

class Turtle(
    x      = 500,
    y      = 500,
    angle  = 0,
    scale  = 1,
    mirror = 1,
    xoff   = 0,
    yoff   = 0,
    color  = 'black',
) {

    has im = %O<Image::Magick>.new(size => "#{x}x#{y}")

    method init {
        angle.deg2rad!
        im.ReadImage('canvas:white')
    }

    method forward(r) {
        var (newx, newy) = (x + r*sin(angle), y + r*-cos(angle))

        im.Draw(
            primitive => 'line',
            points    => join(' ',
                           round(x    * scale + xoff),
                           round(y    * scale + yoff),
                           round(newx * scale + xoff),
                           round(newy * scale + yoff),
                        ),
            stroke      => color,
            strokewidth => 1,
        )

        (x, y) = (newx, newy)
    }

    method save_as(filename) {
        im.Write(filename)
    }

    method turn(theta) {
        angle += theta*mirror
    }

    method state {
        [x, y, angle, mirror]
    }

    method setstate(state) {
        (x, y, angle, mirror) = state...
    }

    method mirror {
        mirror.neg!
    }
}

class LSystem(
    angle  = 90,
    scale  = 1,
    xoff   = 0,
    yoff   = 0,
    len    = 5,
    color  = 'black',
    width  = 500,
    height = 500,
    turn   = 0,
) {
    method execute(string, repetitions, filename, rules) {

        var theta  = angle.deg2rad
        var turtle = Turtle(
            x:     width,
            y:     height,
            angle: turn,
            scale: scale,
            color: color,
            xoff:  xoff,
            yoff:  yoff,
        )

        var stack = []
        var table = Hash(
            '+' => { turtle.turn(theta) },
            '-' => { turtle.turn(-theta) },
            ':' => { turtle.mirror },
            '[' => { stack.push(turtle.state) },
            ']' => { turtle.setstate(stack.pop) },
        )

        repetitions.times {
            string.gsub!(/(.)/, {|c| rules{c} \\ c })
        }

        string.each_char { |c|
            if (table.contains(c)) {
                table{c}.run
            }
            elsif (c.is_uppercase) {
                turtle.forward(len)
            }
        }

        turtle.save_as(filename)
    }
}


package main

import (
    "fmt"
    "time"
)

type holiday struct {
    time.Time
}

func easter(y int) holiday {
    c := y / 100
    n := mod(y, 19)
    i := mod(c-c/4-(c-(c-17)/25)/3+19*n+15, 30)
    i -= (i / 28) * (1 - (i/28)*(29/(i+1))*((21-n)/11))
    l := i - mod(y+y/4+i+2-c+c/4, 7)
    m := 3 + (l+40)/44
    d := l + 28 - 31*(m/4)
    return holiday{time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.UTC)}
}

func mod(a, n int) int {
    r := a % n
    if r < 0 {
        return r + n
    }
    return r
}

func (h holiday) addDays(d int) holiday {
    return holiday{h.Add(time.Duration(d) * 24 * time.Hour)}
}

type easterRelated struct {
    easter, ascension, pentecost, trinity, corpusChristi holiday
}

func newEasterRelated(y int) (er easterRelated) {
    er.easter = easter(y)
    er.ascension = er.easter.addDays(39)
    er.pentecost = er.ascension.addDays(10)
    er.trinity = er.pentecost.addDays(7)
    er.corpusChristi = er.trinity.addDays(4)
    return
}

func (er easterRelated) print() {
    const wdmdm = ": Mon _2 Jan"
    fmt.Printf("%4d %s, %s, %s, %s, %s\n",
        er.easter.Year(),
        er.easter.Format("Easter"+wdmdm),
        er.ascension.Format("Ascension"+wdmdm),
        er.pentecost.Format("Pentecost"+wdmdm),
        er.trinity.Format("Trinity"+wdmdm),
        er.corpusChristi.Format("Corpus"+wdmdm))
}

func main() {
    fmt.Println("Christian holidays, related to Easter, " +
        "for each centennial from 400 to 2100 CE:")
    for y := 400; y <= 2100; y += 100 {
        newEasterRelated(y).print()
    }
    fmt.Println("\nChristian holidays, related to Easter, " +
        "for years from 2010 to 2020 CE:")
    for y := 2010; y <= 2020; y++ {
        newEasterRelated(y).print()
    }
}


struct Point{
    int x;
    int y;
    Point(int px,int py){
        x=px;
        y=py;
    }
}

public class Hilbert : Gtk.DrawingArea {

    private int it = 1;
    private Point[] points;
    private const int WINSIZE = 300;

    public Hilbert() {
        set_size_request(WINSIZE, WINSIZE);
    }

    public void button_toggled_cb(Gtk.ToggleButton button){
        if(button.get_active()){
            it = int.parse(button.get_label());
            redraw_canvas();
        }
    }

    public override bool draw(Cairo.Context cr){
        int border_size = 20;
        int unit = (WINSIZE - 2 * border_size)/((1<<it)-1);

        //adjust border_size to center the drawing
        border_size = border_size + (WINSIZE - 2 * border_size - unit * ((1<<it)-1)) / 2;

        //white background
        cr.rectangle(0, 0, WINSIZE, WINSIZE);
        cr.set_source_rgb(1, 1, 1);
        cr.fill_preserve();
        cr.stroke();

        points = {};
        hilbert(0, 0, 1<<it, 0, 0);

        //magenta lines
        cr.set_source_rgb(1, 0, 1);

        // move to first point
        Point point = translate(border_size, WINSIZE, unit*points[0].x, unit*points[0].y);
        cr.move_to(point.x, point.y);

        foreach(Point i in points[1:points.length]){
            point = translate(border_size, WINSIZE, unit*i.x, unit*i.y);
            cr.line_to(point.x, point.y);
        }
        cr.stroke();
        return false;
    }

    private Point translate(int border_size, int size, int x, int y){
        return Point(border_size + x,size - border_size - y);
    }

    private void hilbert(int x, int y, int lg, int i1, int i2) {
        if (lg == 1) {
            points += Point(x,y);
            return;
        }
        lg >>= 1;
        hilbert(x+i1*lg,     y+i1*lg,     lg, i1,   1-i2);
        hilbert(x+i2*lg,     y+(1-i2)*lg, lg, i1,   i2);
        hilbert(x+(1-i1)*lg, y+(1-i1)*lg, lg, i1,   i2);
        hilbert(x+(1-i2)*lg, y+i2*lg,     lg, 1-i1, i2);
    }

    private void redraw_canvas(){
        var window = get_window();
        if (window == null)return;
        window.invalidate_region(window.get_clip_region(), true);
    }
}

int main(string[] args){
    Gtk.init (ref args);

    var window = new Gtk.Window();
    window.title = "Rosetta Code / Hilbert";
    window.window_position = Gtk.WindowPosition.CENTER;
    window.destroy.connect(Gtk.main_quit);
    window.set_resizable(false);

    var label = new Gtk.Label("Iterations:");

    // create radio buttons to select the number of iterations
    var rb1 = new Gtk.RadioButton(null);
    rb1.set_label("1");
    var rb2 = new Gtk.RadioButton.with_label_from_widget(rb1, "2");
    var rb3 = new Gtk.RadioButton.with_label_from_widget(rb1, "3");
    var rb4 = new Gtk.RadioButton.with_label_from_widget(rb1, "4");
    var rb5 = new Gtk.RadioButton.with_label_from_widget(rb1, "5");

    var hilbert = new Hilbert();

    rb1.toggled.connect(hilbert.button_toggled_cb);
    rb2.toggled.connect(hilbert.button_toggled_cb);
    rb3.toggled.connect(hilbert.button_toggled_cb);
    rb4.toggled.connect(hilbert.button_toggled_cb);
    rb5.toggled.connect(hilbert.button_toggled_cb);

    var box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
    box.pack_start(label, false, false, 5);
    box.pack_start(rb1, false, false, 0);
    box.pack_start(rb2, false, false, 0);
    box.pack_start(rb3, false, false, 0);
    box.pack_start(rb4, false, false, 0);
    box.pack_start(rb5, false, false, 0);

    var grid = new Gtk.Grid();
    grid.attach(box, 0, 0, 1, 1);
    grid.attach(hilbert, 0, 1, 1, 1);
    grid.set_border_width(5);
    grid.set_row_spacing(5);

    window.add(grid);
    window.show_all();

    //initialise the drawing with iteration = 4
    rb4.set_active(true);

    Gtk.main();
    return 0;
}


Imports System.Text

Module Module1

    Sub Swap(Of T)(ByRef a As T, ByRef b As T)
        Dim c = a
        a = b
        b = c
    End Sub

    Structure Point
        Dim x As Integer
        Dim y As Integer

        'rotate/flip a quadrant appropriately
        Sub Rot(n As Integer, rx As Boolean, ry As Boolean)
            If Not ry Then
                If rx Then
                    x = (n - 1) - x
                    y = (n - 1) - y
                End If
                Swap(x, y)
            End If
        End Sub

        Public Overrides Function ToString() As String
            Return String.Format("({0}, {1})", x, y)
        End Function
    End Structure

    Function FromD(n As Integer, d As Integer) As Point
        Dim p As Point
        Dim rx As Boolean
        Dim ry As Boolean
        Dim t = d
        Dim s = 1
        While s < n
            rx = ((t And 2) <> 0)
            ry = (((t Xor If(rx, 1, 0)) And 1) <> 0)
            p.Rot(s, rx, ry)
            p.x += If(rx, s, 0)
            p.y += If(ry, s, 0)
            t >>= 2

            s <<= 1
        End While
        Return p
    End Function

    Function GetPointsForCurve(n As Integer) As List(Of Point)
        Dim points As New List(Of Point)
        Dim d = 0
        While d < n * n
            points.Add(FromD(n, d))
            d += 1
        End While
        Return points
    End Function

    Function DrawCurve(points As List(Of Point), n As Integer) As List(Of String)
        Dim canvas(n, n * 3 - 2) As Char
        For i = 1 To canvas.GetLength(0)
            For j = 1 To canvas.GetLength(1)
                canvas(i - 1, j - 1) = " "
            Next
        Next

        For i = 1 To points.Count - 1
            Dim lastPoint = points(i - 1)
            Dim curPoint = points(i)
            Dim deltaX = curPoint.x - lastPoint.x
            Dim deltaY = curPoint.y - lastPoint.y
            If deltaX = 0 Then
                'vertical line
                Dim row = Math.Max(curPoint.y, lastPoint.y)
                Dim col = curPoint.x * 3
                canvas(row, col) = "|"
            Else
                'horizontal line
                Dim row = curPoint.y
                Dim col = Math.Min(curPoint.x, lastPoint.x) * 3 + 1
                canvas(row, col) = "_"
                canvas(row, col + 1) = "_"
            End If
        Next

        Dim lines As New List(Of String)
        For i = 1 To canvas.GetLength(0)
            Dim sb As New StringBuilder
            For j = 1 To canvas.GetLength(1)
                sb.Append(canvas(i - 1, j - 1))
            Next
            lines.Add(sb.ToString())
        Next
        Return lines
    End Function

    Sub Main()
        For order = 1 To 5
            Dim n = 1 << order
            Dim points = GetPointsForCurve(n)
            Console.WriteLine("Hilbert curve, order={0}", order)
            Dim lines = DrawCurve(points, n)
            For Each line In lines
                Console.WriteLine(line)
            Next
            Console.WriteLine()
        Next
    End Sub

End Module


HistoryVar equ $100200   ;assume this is work ram.

LEA HistoryVar+4,A0
MOVE.L #$11223344,D0
MOVE.L D0,-(A0)   ;store the 32-bit value #$11223344 starting at $100200
MOVE.L #$55667788,D0
MOVE.L D0,-(A0)   ;store the 32-bit value #$5566788 at $1001FC
MOVE.L #$AABBCCDD,D0
MOVE.L D0,-(A0)   ;store the 32-bit value #$AABBCCDD at $1001F8

;display the history
LEA HistoryVar,A0
MOVE.L (A0),D0        ;load #$11223344 into D0
MOVE.L (-4,A0),D1     ;load #$55667788 into D1
MOVE.L (-8,A0),D2     ;load #$AABBCCDD into D2

jsr PrintHex32        ;unimplemented routine that prints D0 as a 32-bit hex number
mov D1,D0
jsr PrintHex32
mov D2,D0
jsr PrintHex32


link printf

procedure main()
   printf("Christian holidays, related to Easter, for each centennial from 400 to 2100 CE:\n")
   every year := 400 to 2100 by 100 do
      OutputHolidays(year)

   printf("\nChristian holidays, related to Easter, for years from 2010 to 2020 CE:\n")
      every year := 2010 to 2020 do
          OutputHolidays(year)
end

procedure OutputHolidays(year)
static ho,hoo,monL,dayL
initial {
   ho := table()
   ho["Easter"] := 0
   ho["Ascension"] := 39
   ho["Pentecost"] := 49
   ho["Trinity"] := 56
   ho["Corpus"] := 60
   hoo := ["Easter","Ascension","Pentecost","Trinity","Corpus"] # order
   monL := ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
             "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
   dayL := ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri","Sat"]
   }

   easter := CalculateEaster(year)
   printf("%d ",year)
   every d := Add2Easter(easter,ho[k := !hoo]) do
      printf("%d: %s %d %s ", k, dayL[d.wday], d.day, monL[d.month])
   printf("\n")
end

record daterec(year,month,day,wday)

procedure CalculateEaster(year)  #: Calculates Gregorian Easter
   a := year % 19
   b := year / 100
   c := year % 100
   d := b / 4
   e := b % 4
   f := (b + 8) / 25
   g := (b - f + 1) / 3
   h := (19 * a + b - d - g + 15) % 30
   i := c / 4
   k := c % 4
   l := (32 + 2 * e + 2 * i - h - k) % 7
   m := (a + 11 * h + 22 * l) / 451
   n := h + l - 7 * m + 114
   return daterec(year, n / 31, (n % 31) + 1,1)  # year,month, day, "Sun"=1
end

procedure Add2Easter(dr,days)    #: very limited date addition
static dom
initial dom := [,,31,30,31,30,]  # limited days per month
   dr := copy(dr)
   dr.day +:= days
   dr.wday := (dr.wday + days - 1 ) % 7 + 1 # rely upon Easter=Sunday
   while dr.day > dom[dr.month] do {
      dr.day   -:= dom[dr.month]
      dr.month +:= 1
      }
   return dr
end


import "graphics" for Canvas, Color, Point
import "dome" for Window

class Game {
    static init() {
        Window.title = "Hilbert curve"
        Canvas.resize(650, 650)
        Window.resize(650, 650)
        __points = []
        __width = 64
        hilbert(0, 0, __width, 0, 0)
        var col = Color.hex("#90EE90") // light green
        var prev = __points[0]
        for (p in __points.skip(1)) {
            var curr = p
            Canvas.line(prev.x, prev.y, curr.x, curr.y, col)
            prev = curr
        }
    }

    static hilbert(x, y, lg, i1, i2) {
        if (lg == 1) {
            var px = (__width - x) * 10
            var py = (__width - y) * 10
            __points.add(Point.new(px, py))
            return
        }
        lg = lg >> 1
        hilbert(x+i1*lg, y+i1*lg, lg, i1, 1-i2)
        hilbert(x+i2*lg, y+(1-i2)*lg, lg, i1, i2)
        hilbert(x+(1-i1)*lg, y+(1-i1)*lg, lg, i1, i2)
        hilbert(x+(1-i2)*lg, y+i2*lg, lg, 1-i1, i2)
    }

    static update() {}

    static draw(dt) {}
}


private with Ada.Containers.Indefinite_Vectors;
generic
   type Item_Type (<>) is private;
package History_Variables is

   type Variable is tagged limited private;

   -- set and get current value
   procedure Set(V: in out Variable; Item: Item_Type);
   function Get(V: Variable) return Item_Type;

   -- number of items in history (including the current one)
   function Defined(V: Variable) return Natural;

   -- non-destructively search for old values
   function Peek(V: Variable; Generation: Natural := 1) return Item_Type;
   -- V.Peek(0) returns current value; V.Peek(1) the previous value, etc.
   -- when calling V.Peek(i), i must be in 0 .. V.Defined-1, else Constraint_Error is raised

   -- destructively restore previous value
   procedure Undo(V: in out Variable);
   -- old V.Peek(0) is forgotten, old V.Peek(i) is new V.Peek(i-1), etc.
   -- accordingly, V.Defined decrements by 1
   -- special case: if V.Defined=0 then V.Undo does not change V

private
   package Vectors is new Ada.Containers.Indefinite_Vectors
     (Index_Type   => Positive,
      Element_Type => Item_Type);

   type Variable is tagged limited record
      History: Vectors.Vector;
   end record;
end History_Variables;


begin
    % implements integer history variables                                 %
    % similar history types could be defined for other types of variable   %
    record HInteger ( integer iValue; reference(HInteger) iPrev );
    % sets the latest value of hv to n                                     %
    procedure setIhv ( reference(HInteger) value result hv; integer value n ) ; hv := HInteger( n, hv );
    % declare an integer history variable                                  %
    reference(HInteger) hv;
    % initialise the history to a null value                               %
    hv := null;
    % assign three values                                                  %
    setIhv( hv, 1 );
    setIhv( hv, 2 );
    setIhv( hv, 3 );
    % show the history of hv                                               %
    begin
        reference(HInteger) h;
        write( "hv history: " );
        h := hv;
        while h not = null do begin
            writeon( i_w := 3, s_w := 0, iValue(h), " " );
            h := iPrev(h)
        end while_h_ne_null
    end;
    % remove the values from hv, summing them as in the Ada sample         %
    begin
        integer s;
        s := 0;
        while hv not = null do begin
            s  := s + iValue(hv);
            hv := iPrev(hv)
        end while_hv_ne_null ;
        write( "Sum of the historic values: ", s )
    end
end.


public class HistoryVariable
{
    private Object value;

    public HistoryVariable(Object v)
    {
        value = v;
    }

    public void update(Object v)
    {
        value = v;
    }

    public Object undo()
    {
        return value;
    }

    @Override
    public String toString()
    {
        return value.toString();
    }

    public void dispose()
    {
    }
}


import java.text.DateFormatSymbols;
import java.util.*;

public class EasterRelatedHolidays {

    final static Map<String, Integer> holidayOffsets;

    static {
        holidayOffsets = new LinkedHashMap<>();
        holidayOffsets.put("Easter", 0);
        holidayOffsets.put("Ascension", 39);
        holidayOffsets.put("Pentecost", 10);
        holidayOffsets.put("Trinity", 7);
        holidayOffsets.put("Corpus", 4);
    }

    public static void main(String[] args) {
        System.out.println("Christian holidays, related to Easter,"
                + " for each centennial from 400 to 2100 CE:");

        for (int y = 400; y <= 2100; y += 100)
            printEasterRelatedHolidays(y);

        System.out.println("\nChristian holidays, related to Easter,"
                + " for years from 2010 to 2020 CE:");
        for (int y = 2010; y < 2021; y++)
            printEasterRelatedHolidays(y);
    }

    static void printEasterRelatedHolidays(int year) {
        final int a = year % 19;
        final int b = year / 100;
        final int c = year % 100;
        final int d = b / 4;
        final int e = b % 4;
        final int f = (b + 8) / 25;
        final int g = (b - f + 1) / 3;
        final int h = (19 * a + b - d - g + 15) % 30;
        final int i = c / 4;
        final int k = c % 4;
        final int l = (32 + 2 * e + 2 * i - h - k) % 7;
        final int m = (a + 11 * h + 22 * l) / 451;
        final int n = h + l - 7 * m + 114;
        final int month = n / 31 - 1;
        final int day = (n % 31) + 1;

        Calendar date = new GregorianCalendar(year, month, day);
        String[] months = new DateFormatSymbols(Locale.US).getShortMonths();

        System.out.printf("%4d ", year);
        for (String hd : holidayOffsets.keySet()) {
            date.add(Calendar.DATE, holidayOffsets.get(hd));
            System.out.printf("%s: %2d %s  ", hd,
                    date.get(Calendar.DAY_OF_MONTH),
                    months[date.get(Calendar.MONTH)]);
        }
        System.out.println();
    }
}


def Order=5, Size=15;   \length of line segment
int Dir, X, Y;

proc GoFwd;
[case Dir&3 of
 0: X:= X+Size;
 1: Y:= Y+Size;
 2: X:= X-Size;
 3: Y:= Y-Size
other   [];
Line(X, Y, \white\7);
];

proc Hilbert(Lev, Ang);
int  Lev, Ang;
[if Lev then
    [Dir:= Dir+Ang;
    Hilbert(Lev-1, -Ang);
    GoFwd;
    Dir:= Dir-Ang;
    Hilbert(Lev-1, Ang);
    GoFwd;
    Hilbert(Lev-1, Ang);
    Dir:= Dir-Ang;
    GoFwd;
    Hilbert(Lev-1, -Ang);
    Dir:= Dir+Ang;
    ];
];

[SetVid($12);   \640x480 graphics
Dir:= 0;  X:= 0;  Y:= 0;
Move(X, Y);
Hilbert(Order, 1);
]


width = 64

sub hilbert(x, y, lg, i1, i2)
    if lg = 1 then
        line to (width-x) * 10, (width-y) * 10
        return
    end if
    lg = lg / 2
    hilbert(x+i1*lg, y+i1*lg, lg, i1, 1-i2)
    hilbert(x+i2*lg, y+(1-i2)*lg, lg, i1, i2)
    hilbert(x+(1-i1)*lg, y+(1-i1)*lg, lg, i1, i2)
    hilbert(x+(1-i2)*lg, y+i2*lg, lg, 1-i1, i2)
end sub

open window 655, 655

hilbert(0, 0, width, 0, 0)


hilbert(6) : turtle(_);

fcn hilbert(n){	// Lindenmayer system --> Data of As & Bs
   var [const] A="-BF+AFA+FB-", B="+AF-BFB-FA+";
   buf1,buf2 := Data(Void,"A").howza(3), Data().howza(3);  // characters
   do(n){
      buf1.pump(buf2.clear(),fcn(c){ if(c=="A") A else if(c=="B") B else c });
      t:=buf1; buf1=buf2; buf2=t;	// swap buffers
   }
   buf1		// n=6 --> 13,651 letters
}

fcn turtle(hilbert){
   const D=10;
   ds,dir := T( T(D,0), T(0,-D), T(-D,0), T(0,D) ), 0;  // turtle offsets
   dx,dy := ds[dir];
   img:=PPM(650,650); x,y:=10,10; color:=0x00ff00;
   hilbert.replace("A","").replace("B","");  // A & B are no-op during drawing
   foreach c in (hilbert){
      switch(c){
	 case("F"){ img.line(x,y, (x+=dx),(y+=dy), color) }  // draw forward
	 case("+"){ dir=(dir+1)%4; dx,dy = ds[dir] } // turn right 90*
	 case("-"){ dir=(dir-1)%4; dx,dy = ds[dir] } // turn left 90*
      }
   }
   img.writeJPGFile("hilbert.zkl.jpg");
}


HV := new HistoryVariable
HV.var := 1
HV.var := 2
HV.var := "Latest value"
Msgbox % HV.var "`n" HV[2] "`n" HV[3]

class HistoryVariable {
	__Set(aName, aValue) {
		this.Insert(1,aValue)
		Return aValue
	}
	__Get(aName) {
		Return this[1]
	}
}


using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace History
{
    class Program
    {
        static void Main(string[] args)
        {
            var h = new HistoryObject();
            h.Value = 5;
            h.Value = "foo";
            h.Value += "bar";

            var history = h.ToArray();

            for (int i = 0; i < history.Length; i++)
            {
                Console.Write("{0}{1}", history[i], ((i >= history.Length - 1) ? "\n" : " <- "));
            }

            h.Undo();
            h.Undo();
            h.Undo();

            Console.WriteLine(h.Value);
        }

        private class HistoryObject : IEnumerable<object>
        {
            public HistoryObject()
            {
                _history = new Stack<object>(); // Initiates the history stack.
            }

            public object Value
            {
                get // Returns the top value from the history if there is one. Otherwise null.
                {
                    if (_history.Count > 0)
                        return _history.Peek();
                    return null;
                }
                set { _history.Push(value); } // Adds the specified value to the history.
            }

            public void Undo()
            {
                if (_history.Count > 0)
                    _history.Pop(); // Removes the current value from the history.
            }

            // History stack that will hold all previous values of the object.
            private readonly Stack<object> _history;

            public IEnumerator<object> GetEnumerator()
            {
                return _history.GetEnumerator();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }
    }
}


const Пасха = год => {
	let дата = (год % 19 * 19 + 15) % 30;
	дата += (год % 4 * 2 + год % 7 * 4 + 6 * дата + 6) % 7;
	if (год >= 1918) дата += (год / 100 | 0) - (год / 400 | 0) - 2;
	return new Date(год, 2, 22 + дата);
};

for (let год = 400; год <= 2100; год += год < 2000 ? 100 : год >= 2020 ? 80 : год < 2010 ? 10 : 1) {
	const дата_Пасхи = Пасха(год);
	document.write(
		год + ": " +
		[ ["Easter", 1], ["Ascension", 40], ["Trinity (Pentecost)", 50], ["All Saints' Sunday", 57] ].map(праздник => {
			let дата = new Date(дата_Пасхи);
			дата.setDate(дата.getDate() + праздник[1] - 1);
			return праздник[0] + ": " + new Intl.DateTimeFormat("ru", { month: "numeric", day: "numeric" }).format(дата);
		}).join("; ") + ".<br />"
	);
}


(def a (ref 0))
(def a-history (atom [@a])) ; define a history vector to act as a stack for changes on variable a
(add-watch a :hist (fn [key ref old new] (swap! a-history conj new)))


(defmacro make-hvar (value)
  `(list ,value))

(defmacro get-hvar (hvar)
  `(car ,hvar))

(defmacro set-hvar (hvar value)
  `(push ,value ,hvar))

;; Make sure that setf macro can be used
(defsetf get-hvar set-hvar)

(defmacro undo-hvar (hvar)
  `(pop ,hvar))

(let ((v (make-hvar 1)))
  (format t "Initial value = ~a~%" (get-hvar v))
  (set-hvar v 2)
  (setf (get-hvar v) 3) ;; Alternative using setf
  (format t "Current value = ~a~%" (get-hvar v))
  (undo-hvar v)
  (undo-hvar v)
  (format t "Restored value = ~a~%" (get-hvar v)))


import std.stdio, std.array, std.string, std.datetime, std.traits;

/// A history variable.
struct HistoryVariable(T) {
    /// A value in a point in time.
    static struct HistoryValue {
        SysTime time;
        T value;

        // Alternative to the more common toString.
        //void toString(scope void delegate(string) output) const {
        void toString(scope void delegate(const(char)[]) output)const {
            output(format("%s; %s", time, value));
        }
    }

    const(HistoryValue)[] values;

    private void addValue(T value) {
        values ~= HistoryValue(Clock.currTime(), value);
    }

    void opAssign(T value) {
        addValue(value);
    }

    @property T currentValue() const pure nothrow {
        return values.back.value;
    }

    alias currentValue this;

    @property auto history() const pure nothrow {
        return values;
    }

    /**
    Demonstrating D's compile-time reflection features. The member
    functions that are in this 'static if' block would be added for
    types T that are arrays (including strings). */
    static if (isArray!T) {
        // Append-with-assign operator.
        void opOpAssign(string op : "~")(T element) {
            addValue(currentValue ~ element);
        }

        // Similar implementation for other array operators...
    }
}

void main() {
    HistoryVariable!int x;
    x = 1;
    x = 2;
    x = 3;
    writefln("%(%s\n%)\n", x.history);

    HistoryVariable!string s;
    s = "hello";
    s ~= " world";
    s = "goodby";
    writefln("%(%s\n%)", s.history);
}


# v0.6

using Dates

function easter(year::Int)::Date
    a = rem(year, 19)
    b, c = divrem(year, 100)
    d = rem(19a + b - div(b, 4) - div(b - div(b + 8, 25) + 1, 3) + 15, 30)
    e = rem(32 + 2 * rem(b, 4) + 2 * div(c, 4) - d - rem(c, 4), 7)
    f = d + e - 7 * div(a + 11d + 22e, 451) + 114
    month, day = divrem(f, 31)
    day += 1
    return Date(year, month, day)
end

function holiday_values(year::Int)::Dict{String,Date}
    offsets = Dict{String,Day}("Easter" => Day(0), "Ascension" => Day(39),
    "Pentecost" => Day(49), "Trinity" => Day(56), "Corpus" => Day(60))
    easterdate = easter(year)
    rst = Dict{String,Date}(holiday => easterdate + days for (holiday, days) in offsets)
    return rst
end

function holiday2str(year::Int)::String
    function holiday2str(holiday::String, date::Date)::String
        dayname, daynumb, month = dayabbr(date), day(date), monthabbr(date)
        return @sprintf "%s: %s %2i %s" holiday dayname daynumb month
    end
    cal = holiday_values(year)
    rst = join(collect(holiday2str(hday, cal[hday]) for hday in
    ("Easter", "Ascension", "Pentecost", "Trinity", "Corpus")), ", ")
    return "$year -> " * rst
end

println("\nChristian holidays, related to Easter, for each centennial from 400 to 2100 CE:")
for yr in 400:100:2200
    println(holiday2str(yr))
end

println("\nChristian holidays, related to Easter, for years from 2010 to 2020 CE:")
for yr in 2010:2020
    println(holiday2str(yr))
end