wizzard: (Default)
[personal profile] wizzard

Вчера после разнообразных бредодискуссий мне внезапно вспомнилось вот это: Multi-Dimensional Analog Literals

(Для тех, кто не понял, что это такое и зачем оно:
каждая такая штука это выражение. после его вычисления получается обьект со свойствами Width, Height и Depth, соответствующими реальным размерам обьекта в коде :))

Где-то 15 минут втыкания на темплейты, “блин, я их не понимаю. и еще, а почему в C# нет темплейтов?” –> хм, стоп, а зачем нам здесь вообще темплейты?

Линейный литерал получился достаточно тривиальным, жаль, что не с таким красивым синтаксисом, плоский – тоже достаточно быстро. С трехмерным пришлось помучиться. Но не прошло и 4 часов, как на свет явилось


чудовище:

Использование:

private static void Main(string[] args)
{
var I = new AnalogLiteral();
var o = new AnalogLiteral();
var L = new AnalogLiteral();
//2
Console.WriteLine((o-0-o).ToString());
//Point (a point does not have a size)
Console.WriteLine((o).ToString());
//6
Console.WriteLine(o-o-0-o-0-o-o);
//7x3
var a = o-o-0-o-o-o-o-o
| !
! !
! !
o-o-o-o-0-o-o-o;
Console.WriteLine(a.ToString());
//8x3
var b = o-0-0-o-0-o-o-o-o
| !
! !
! !
o-o-o-o-o-0-o-o-o;
Console.WriteLine(b.ToString());
//8x4
var b2 = o-o-0-o-o-o-o-o-0
| !
! !
! !
! !
o-o-0-o-o-o-o-o-o;
Console.WriteLine(b2.ToString());
//2x4x2
var c = o-o-o
|L & L
| L & L
| o-o-o
| ! !
o | !
L | !
L| !
o-o-o;
Console.WriteLine(c.ToString());
//3x4x2
var d = o-0-o-o
|L & L
| L & L
| o-o-o-o
| ! !
o | !
L | !
L| !
o-0-o-o;

Console.WriteLine(d.ToString());
//3x5x2
var d2= o-o-o-o
|L & L
| L & L
| o-o-0-o
| ! !
! ! !
o | !
L | !
L| !
o-o-o-o;

Console.WriteLine(d2.ToString());
//3x5x3
var d3= 0-o-o-0
|L & L
| L & L
| L & L
| 0-o-o-o
| ! !
! ! !
o | !
L | !
L | !
L| !
o-0-o-o;

Console.WriteLine(d3.ToString());
//3x12x3
var e = o-o-o-o
|L & L
| L & L
| L & L
| o-o-o-o
| ! !
! ! !
! ! !
! ! !
! ! !
! ! !
! ! !
! ! !
o | !
L | !
L | !
L| !
o-o-o-o;
Console.WriteLine(e.ToString());
//5x14x5
var f = o-o-o-o-o-o
|L & L
| L & L
| L & L
| L & L
| L & L
| o-o-o-o-o-o
| ! !
! ! !
! ! !
! ! !
! ! !
! ! !
! ! !
! ! !
o | !
L | !
L | !
L | !
L | !
L| !
o-o-o-o-o-o;
Console.WriteLine(f.ToString());
Console.ReadLine();
}

Сам класс:


чудовище 2:
 
 



public class AnalogLiteral
{
int d1, d2, d3;
/// <summary>
/// Is the literal already constructed and frozen?
/// </summary>
public bool Frozen { get; private set; }
AnalogLiteral(int d1, int d2, int d3)
{
if (d1 <= 0) throw new ArgumentException("d1");
if (d2 <= 0) throw new ArgumentException("d2");
if (d3 <= 0) throw new ArgumentException("d3");
this.d1 = d1;
this.d2 = d2;
this.d3 = d3;
this.Frozen = false;
}
AnalogLiteral(int d1, int d2) : this(d1, d2, 1) { }
AnalogLiteral(int d1) : this(d1, 1, 1) { }
public AnalogLiteral() : this(1, 1, 1) { }
public static implicit operator int(AnalogLiteral a)
{
int w, h, d;
int sz = Freeze(out w, out h, out d, a);
return sz;
}
public static implicit operator AnalogLiteral(int i)
{
if (i == 0) return new AnalogLiteral(); // 0 = point
if (i < 0) throw new ArgumentException("i");
return new AnalogLiteral(i) { Frozen = true };
}
/// <summary>
/// convert from evil form to normal form
/// </summary>
static int Freeze(out int w, out int h, out int d, AnalogLiteral a)
{
if (a.Frozen)
{
w = a.d1;
h = a.d2;
d = a.d3;
}
else
{
if (a.d1 == 1 && a.d2 == 1 && a.d3 == 1)
{
throw new InvalidOperationException("You can't freeze point literals!");
}
a.Frozen = true;
if (a.d3 == 1)
{
w = a.d1 - 1;
h = 1;
d = 1;
}
else if (a.d3 == 2)
{
w = ((a.d1 - 2) / 2);
h = ((a.d2 - 1) / 2);
d = 1;
}
else
{
d = (a.d3 - 4) / 3;
h = (a.d2 - 1) / 3;
w = (a.d1 - 2 - d * 2) / 3;
}
a.d1 = w;
a.d2 = h;
a.d3 = d;
}
return w * h * d;
}
public int Width
{
get
{
int w, h, d;
int sz = Freeze(out w, out h, out d, this);
return w;
}
}
public int Height
{
get
{
int w, h, d;
int sz = Freeze(out w, out h, out d, this);
return h;
}
}
public int Depth
{
get
{
int w, h, d;
int sz = Freeze(out w, out h, out d, this);
return d;
}
}
public static AnalogLiteral operator |(AnalogLiteral a, AnalogLiteral b)
{
if (a.Frozen || b.Frozen) throw new ArgumentException("You can't modify frozen literals!");
return new AnalogLiteral(a.d1 + b.d1,
a.d2 + b.d2, a.d3 + b.d3);
}
public static AnalogLiteral operator !(AnalogLiteral a)
{
if (a.Frozen) throw new ArgumentException("You can't modify frozen literals!");
return new AnalogLiteral(a.d1, a.d2 + 1, a.d3);
}
public static AnalogLiteral operator -(AnalogLiteral a, AnalogLiteral b)
{
if (a.Frozen || b.Frozen) throw new ArgumentException("You can't modify frozen literals!");
return new AnalogLiteral(Math.Max(a.d1, b.d1) + 1,
Math.Max(a.d2, b.d2), Math.Max(a.d3, b.d3));
}

public static AnalogLiteral operator &(AnalogLiteral a, AnalogLiteral b)
{
if (a.Frozen || b.Frozen) throw new ArgumentException("You can't modify frozen literals!");
return new AnalogLiteral(Math.Max(a.d1, b.d1),
Math.Max(a.d2, b.d2), Math.Max(a.d3, b.d3) + 1);
}

public override string ToString()
{
if (d1 == 1 && d2 == 1 && d3 == 1 && Frozen == false)
{
return "<Point>";
}
else
{
return String.Format("<{0}; {1}; {2}>", this.Width, this.Height, this.Depth);
}
}

}

 
На умножение и деление меня, правда, не хватило. Но их, вроде, достаточно тривиально дописать…

Profile

wizzard: (Default)
wizzard

January 2019

S M T W T F S
  12 345
6789101112
1314 1516171819
202122 23242526
2728293031  

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 8th, 2025 07:50 pm
Powered by Dreamwidth Studios