From e0cf76549ee80559014bcf3bd16daf4fc711ce56 Mon Sep 17 00:00:00 2001
From: WhiteBlackGoose <wbg@angouri.org>
Date: Sun, 27 Jun 2021 14:05:19 +0300
Subject: [PATCH 1/3] Working on ASCII output

---
 Sources/Samples/Samples/Program.cs | 125 ++++++++++++++++++++++++++++-
 1 file changed, 122 insertions(+), 3 deletions(-)

diff --git a/Sources/Samples/Samples/Program.cs b/Sources/Samples/Samples/Program.cs
index 6d8efcab1..c72eacfee 100644
--- a/Sources/Samples/Samples/Program.cs
+++ b/Sources/Samples/Samples/Program.cs
@@ -1,8 +1,127 @@
-
+using AngouriMath;
 
+using HonkSharp.Fluency;
 using System;
+using System.Collections.Generic;
+using System.Collections;
+using static AngouriMath.Entity;
 
-var a = 3;
 
-Console.WriteLine(a);
+Console.WriteLine(Draw("213/43 + 3/4"));
+
+
+
+
+
+
+
+
+static Figure Draw(Entity expr)
+    => expr switch
+    {
+        Number n => new BlockFigure(n.ToString()),
+        Divf(var a, var b) => new RationalFigure(Draw(a), Draw(b)),
+        Sumf(var a, var b) => new BinaryOpFigure(Draw(a), Draw(b), '+'),
+        _ => throw new()
+    };
+
+
+
+
+public abstract class Figure
+{
+    // should be protected
+    public readonly char[,] table;
+
+    public int Width => table.GetLength(1);
+    public int Height => table.GetLength(0);
+
+    private protected Figure(char[,] table)
+        => this.table = table;
+
+    public override string ToString()
+        => "\n"
+            .Join(
+                (..(Height - 1)).Select(h =>
+                    (..(Width - 1)).Select(w => table[h, w]).AsString()
+                )
+            );
+}
+
+public sealed class BlockFigure : Figure
+{
+    public BlockFigure(string s) : base(GenerateTable(s)) { }
+
+    private static char[,] GenerateTable(string source)
+    {
+        var res = new char[1, source.Length];
+        foreach (var (index, ch) in source.Enumerate())
+            res[0, index] = ch;
+        return res;
+    }
+}
+
+public sealed class RationalFigure : Figure
+{
+    public RationalFigure(Figure num, Figure den) : base(GenerateTable(num, den)) { }
+
+    private static char[,] GenerateTable(Figure num, Figure den)
+    {
+        var res = new char[num.Height + 1 + den.Height, Math.Max(num.Width, den.Width) + 2].WithSpaces();
+
+        num.table.CopyWidthAlignedCenterTo(res, 0);
+        den.table.CopyWidthAlignedCenterTo(res, num.Height + 1);
+
+        foreach (var x in 0..(res.GetLength(1) - 1))
+            res[num.Height, x] = '-';
+
+        return res;
+    }
+}
+
+public sealed class BinaryOpFigure : Figure
+{
+    public BinaryOpFigure(Figure left, Figure right, char op) : base(GenerateTable(left, right, op)) { }
+
+    private static char[,] GenerateTable(Figure left, Figure right, char op)
+    {
+        var res = new char[Math.Max(left.Height, right.Height), left.Width + 3 + right.Width].WithSpaces();
+
+        left.table.CopyHeightAlignedCenterTo(res, 0);
+        right.table.CopyHeightAlignedCenterTo(res, left.Width + 3);
+
+        res[res.GetLength(0) / 2, left.Width + 1] = op;
+
+        return res;
+    }
+}
+
+
+
+public static class ArrayExtensions
+{
+    public static void CopyWidthAlignedCenterTo(this char[,] src, char[,] dst, int heightOffset)
+    {
+        var widthOffset = (dst.GetLength(1) - src.GetLength(1)) / 2;
+        foreach (var x in 0..(src.GetLength(1) - 1))
+            foreach (var y in 0..(src.GetLength(0) - 1))
+                dst[y + heightOffset, x + widthOffset] = src[y, x];
+    }
+
+    public static void CopyHeightAlignedCenterTo(this char[,] src, char[,] dst, int widthOffset)
+    {
+        var heightOffset = (dst.GetLength(0) - src.GetLength(0)) / 2;
+        foreach (var x in 0..(src.GetLength(1) - 1))
+            foreach (var y in 0..(src.GetLength(0) - 1))
+                dst[y + heightOffset, x + widthOffset] = src[y, x];
+    }
+
+    public static char[,] WithSpaces(this char[,] chars)
+    {
+        foreach (var x in 0..(chars.GetLength(0) - 1))
+            foreach (var y in 0..(chars.GetLength(1) - 1))
+                chars[x, y] = ' ';
+        return chars;
+    }
+}
 

From 7774d3fa34808fd3a9e6b15d103e691d4960fed6 Mon Sep 17 00:00:00 2001
From: WhiteBlackGoose <wbg@angouri.org>
Date: Sun, 27 Jun 2021 18:14:44 +0300
Subject: [PATCH 2/3] Radical

---
 Sources/Samples/Samples/Program.cs | 57 +++++++++++++++++++++++++-----
 1 file changed, 48 insertions(+), 9 deletions(-)

diff --git a/Sources/Samples/Samples/Program.cs b/Sources/Samples/Samples/Program.cs
index c72eacfee..a17596e0d 100644
--- a/Sources/Samples/Samples/Program.cs
+++ b/Sources/Samples/Samples/Program.cs
@@ -5,9 +5,9 @@
 using System.Collections.Generic;
 using System.Collections;
 using static AngouriMath.Entity;
+using static AngouriMath.Entity.Number;
 
-
-Console.WriteLine(Draw("213/43 + 3/4"));
+Console.WriteLine(Draw("sqrt(213/43 + 3/4)"));
 
 
 
@@ -22,6 +22,7 @@ static Figure Draw(Entity expr)
         Number n => new BlockFigure(n.ToString()),
         Divf(var a, var b) => new RationalFigure(Draw(a), Draw(b)),
         Sumf(var a, var b) => new BinaryOpFigure(Draw(a), Draw(b), '+'),
+        Powf(var a, Rational(Integer(1), Integer(2))) => new RadicalFigure(Draw(a), null),
         _ => throw new()
     };
 
@@ -97,20 +98,58 @@ public BinaryOpFigure(Figure left, Figure right, char op) : base(GenerateTable(l
 }
 
 
+public sealed class RadicalFigure : Figure
+{
+    public RadicalFigure(Figure expr, Figure? pow) : base(GenerateTable(expr, pow)) { }
+
+    private static char[,] GenerateTable(Figure expr, Figure? pow)
+    {
+//      
+//           /----|      <-- this is right glyph (the '|' thing)
+//          / HHH
+//      \  /  HHH
+//       \/   HHH
+//      ^
+// this is left glyph
+        const double LeftGlyphShare = 0.3;
+        const double RightGlyphShare = 0.2;
+
+        var leftGlyphSize = (int)(LeftGlyphShare * expr.Height) + 1;
+        var rightGlyphSize = (int)(RightGlyphShare * expr.Height) + 1;
+
+        var resWidth = leftGlyphSize + expr.Height + expr.Width + 1;
+        var resHeight = expr.Height + 1;
+
+        var res = new char[resHeight, resWidth].WithSpaces();
+        expr.table.CopyTo(res, 1, leftGlyphSize + expr.Height);
+
+        foreach (var i in 0..(leftGlyphSize - 1))
+            res[resHeight - i - 1, i] = '\\';
+
+        foreach (var (y, x) in (0..(resHeight - 1)).AsRange().Enumerate())
+            res[resHeight - y - 1, x + 1] = '/';
+            
+        foreach (var i in resHeight..(resWidth - resHeight + 2))
+            res[0, i + 1] = '-';
+
+        foreach (var i in ..(rightGlyphSize - 1))
+            res[i, resWidth - 1] = '|';
+
+        return res;
+    }
+}
+
 
 public static class ArrayExtensions
 {
     public static void CopyWidthAlignedCenterTo(this char[,] src, char[,] dst, int heightOffset)
-    {
-        var widthOffset = (dst.GetLength(1) - src.GetLength(1)) / 2;
-        foreach (var x in 0..(src.GetLength(1) - 1))
-            foreach (var y in 0..(src.GetLength(0) - 1))
-                dst[y + heightOffset, x + widthOffset] = src[y, x];
-    }
+        => src.CopyTo(dst, heightOffset, (dst.GetLength(1) - src.GetLength(1)) / 2);
 
     public static void CopyHeightAlignedCenterTo(this char[,] src, char[,] dst, int widthOffset)
+        => src.CopyTo(dst, (dst.GetLength(0) - src.GetLength(0)) / 2, widthOffset);
+
+    public static void CopyTo(this char[,] src, char[,] dst, int heightOffset, int widthOffset)
     {
-        var heightOffset = (dst.GetLength(0) - src.GetLength(0)) / 2;
         foreach (var x in 0..(src.GetLength(1) - 1))
             foreach (var y in 0..(src.GetLength(0) - 1))
                 dst[y + heightOffset, x + widthOffset] = src[y, x];

From c45a52a4e37b6a1afbdb724030f7c0778a43c5ac Mon Sep 17 00:00:00 2001
From: WhiteBlackGoose <wbg@angouri.org>
Date: Tue, 29 Jun 2021 12:51:02 +0300
Subject: [PATCH 3/3] Refactored to records

---
 Sources/Samples/Samples/Program.cs | 75 +++++++++++++-----------------
 1 file changed, 33 insertions(+), 42 deletions(-)

diff --git a/Sources/Samples/Samples/Program.cs b/Sources/Samples/Samples/Program.cs
index a17596e0d..178829af2 100644
--- a/Sources/Samples/Samples/Program.cs
+++ b/Sources/Samples/Samples/Program.cs
@@ -6,8 +6,9 @@
 using System.Collections;
 using static AngouriMath.Entity;
 using static AngouriMath.Entity.Number;
+using HonkSharp.Laziness;
 
-Console.WriteLine(Draw("sqrt(213/43 + 3/4)"));
+Console.WriteLine(Draw("sqrt((((1/a + 1)/b + 1)/c + 1)/d)"));
 
 
 
@@ -19,7 +20,7 @@
 static Figure Draw(Entity expr)
     => expr switch
     {
-        Number n => new BlockFigure(n.ToString()),
+        Number or Variable => new BlockFigure(expr.ToString()),
         Divf(var a, var b) => new RationalFigure(Draw(a), Draw(b)),
         Sumf(var a, var b) => new BinaryOpFigure(Draw(a), Draw(b), '+'),
         Powf(var a, Rational(Integer(1), Integer(2))) => new RadicalFigure(Draw(a), null),
@@ -29,80 +30,70 @@ static Figure Draw(Entity expr)
 
 
 
-public abstract class Figure
+public abstract record Figure
 {
-    // should be protected
-    public readonly char[,] table;
+    public int Width => Table.GetLength(1);
+    public int Height => Table.GetLength(0);
 
-    public int Width => table.GetLength(1);
-    public int Height => table.GetLength(0);
-
-    private protected Figure(char[,] table)
-        => this.table = table;
+    protected abstract char[,] GenerateTable();
+    internal protected char[,] Table => table.GetValue(@this => @this.GenerateTable(), this);
+    private readonly LazyPropertyA<char[,]> table;
 
     public override string ToString()
         => "\n"
             .Join(
                 (..(Height - 1)).Select(h =>
-                    (..(Width - 1)).Select(w => table[h, w]).AsString()
+                    (..(Width - 1)).Select(w => Table[h, w]).AsString()
                 )
             );
 }
 
-public sealed class BlockFigure : Figure
+public sealed record BlockFigure(string Source) : Figure
 {
-    public BlockFigure(string s) : base(GenerateTable(s)) { }
-
-    private static char[,] GenerateTable(string source)
+    protected override char[,] GenerateTable()
     {
-        var res = new char[1, source.Length];
-        foreach (var (index, ch) in source.Enumerate())
+        var res = new char[1, Source.Length];
+        foreach (var (index, ch) in Source.Enumerate())
             res[0, index] = ch;
         return res;
     }
 }
 
-public sealed class RationalFigure : Figure
+public sealed record RationalFigure(Figure Numerator, Figure Denominator) : Figure
 {
-    public RationalFigure(Figure num, Figure den) : base(GenerateTable(num, den)) { }
-
-    private static char[,] GenerateTable(Figure num, Figure den)
+    protected override char[,] GenerateTable()
     {
-        var res = new char[num.Height + 1 + den.Height, Math.Max(num.Width, den.Width) + 2].WithSpaces();
+        var res = new char[Numerator.Height + 1 + Denominator.Height, Math.Max(Numerator.Width, Denominator.Width) + 2].WithSpaces();
 
-        num.table.CopyWidthAlignedCenterTo(res, 0);
-        den.table.CopyWidthAlignedCenterTo(res, num.Height + 1);
+        Numerator.Table.CopyWidthAlignedCenterTo(res, 0);
+        Denominator.Table.CopyWidthAlignedCenterTo(res, Numerator.Height + 1);
 
         foreach (var x in 0..(res.GetLength(1) - 1))
-            res[num.Height, x] = '-';
+            res[Numerator.Height, x] = '-';
 
         return res;
     }
 }
 
-public sealed class BinaryOpFigure : Figure
+public sealed record BinaryOpFigure(Figure Left, Figure Right, char Operator) : Figure
 {
-    public BinaryOpFigure(Figure left, Figure right, char op) : base(GenerateTable(left, right, op)) { }
-
-    private static char[,] GenerateTable(Figure left, Figure right, char op)
+    protected override char[,] GenerateTable()
     {
-        var res = new char[Math.Max(left.Height, right.Height), left.Width + 3 + right.Width].WithSpaces();
+        var res = new char[Math.Max(Left.Height, Right.Height), Left.Width + 3 + Right.Width].WithSpaces();
 
-        left.table.CopyHeightAlignedCenterTo(res, 0);
-        right.table.CopyHeightAlignedCenterTo(res, left.Width + 3);
+        Left.Table.CopyHeightAlignedCenterTo(res, 0);
+        Right.Table.CopyHeightAlignedCenterTo(res, Left.Width + 3);
 
-        res[res.GetLength(0) / 2, left.Width + 1] = op;
+        res[res.GetLength(0) / 2, Left.Width + 1] = Operator;
 
         return res;
     }
 }
 
 
-public sealed class RadicalFigure : Figure
+public sealed record RadicalFigure(Figure Expression, Figure? Power) : Figure
 {
-    public RadicalFigure(Figure expr, Figure? pow) : base(GenerateTable(expr, pow)) { }
-
-    private static char[,] GenerateTable(Figure expr, Figure? pow)
+    protected override char[,] GenerateTable()
     {
 //      
 //           /----|      <-- this is right glyph (the '|' thing)
@@ -114,14 +105,14 @@ public RadicalFigure(Figure expr, Figure? pow) : base(GenerateTable(expr, pow))
         const double LeftGlyphShare = 0.3;
         const double RightGlyphShare = 0.2;
 
-        var leftGlyphSize = (int)(LeftGlyphShare * expr.Height) + 1;
-        var rightGlyphSize = (int)(RightGlyphShare * expr.Height) + 1;
+        var leftGlyphSize = (int)(LeftGlyphShare * Expression.Height) + 1;
+        var rightGlyphSize = (int)(RightGlyphShare * Expression.Height) + 1;
 
-        var resWidth = leftGlyphSize + expr.Height + expr.Width + 1;
-        var resHeight = expr.Height + 1;
+        var resWidth = leftGlyphSize + Expression.Height + Expression.Width + 1;
+        var resHeight = Expression.Height + 1;
 
         var res = new char[resHeight, resWidth].WithSpaces();
-        expr.table.CopyTo(res, 1, leftGlyphSize + expr.Height);
+        Expression.Table.CopyTo(res, 1, leftGlyphSize + Expression.Height);
 
         foreach (var i in 0..(leftGlyphSize - 1))
             res[resHeight - i - 1, i] = '\\';