using System;
using System.Text;
class CustomMatrix<ELEM, MATRIX>
where MATRIX : CustomMatrix<ELEM, MATRIX>
{
public readonly uint sizeY, sizeX;
public readonly ELEM[,] data;
protected CustomMatrix(uint sizeY, uint sizeX)
{
this.sizeY = sizeY;
this.sizeX = sizeX;
data = new ELEM[sizeY, sizeX];
}
protected CustomMatrix(uint sizeY, uint sizeX, Func<uint, uint, ELEM> get) :
this(sizeY, sizeX)
{
for (uint y = 0; y < sizeY; y++)
for (uint x = 0; x < sizeX; x++)
data[y, x] = get(y, x);
}
public MATRIX Transpose()
{
Func<uint, uint, ELEM> transposer = (y, x) => data[x, y];
return (MATRIX)Activator.CreateInstance(
typeof(MATRIX), new object[]{ sizeX, sizeY, transposer });
}
public ELEM this[uint y, uint x]
{
get { return data[y, x]; }
set { data[y, x] = value; }
}
public override string ToString()
{
var sb = new StringBuilder();
for (uint y = 0; y < sizeY; y++)
{
if (y > 0) sb.Append("\n");
for (uint x = 0; x < sizeX; x++)
{
if (x > 0) sb.Append(" ");
sb.Append(data[y, x]);
}
}
return sb.ToString();
}
}
class Matrix<ELEM> : CustomMatrix<ELEM, Matrix<ELEM>>
{
public Matrix(uint sizeY, uint sizeX) : base(sizeY, sizeX) { }
public Matrix(uint sizeY, uint sizeX, Func<uint, uint, ELEM> get) : base(sizeY, sizeX, get) { }
public static explicit operator SquareMatrix<ELEM>(Matrix<ELEM> m)
{
return new SquareMatrix<ELEM>(m.sizeY, m.sizeX, (y, x) => m[y, x]);
}
}
class SquareMatrix<ELEM> : CustomMatrix<ELEM, SquareMatrix<ELEM>>
{
public SquareMatrix(uint size) : base(size, size) { }
public SquareMatrix(uint size, Func<uint, uint, ELEM> get) : base(size, size, get) { }
public SquareMatrix(uint sizeY, uint sizeX, Func<uint, uint, ELEM> get) : base(sizeY, sizeX, get)
{
if (sizeY != sizeX) throw new ArgumentException(string.Format("SquareMatrix не может быть размера {0}×{1}.", sizeY, sizeX));
}
public static explicit operator Matrix<ELEM>(SquareMatrix<ELEM> m)
{
return new Matrix<ELEM>(m.sizeY, m.sizeX, (y, x) => m[y, x]);
}
}
public class MainClass
{
public static void Main()
{
Matrix<double> m = new Matrix<double>(3, 5, (y, x) => 2*y + x);
Console.WriteLine("m: Matrix =\n{0}", m);
Matrix<double> m_t = m.Transpose();
Console.WriteLine("\nm.Transpose() =\n{0}", m_t);
string m_as_sm_s;
try
{
m_as_sm_s = ((SquareMatrix<double>)m).ToString();
} catch (ArgumentException e)
{
m_as_sm_s = e.Message;
}
Console.WriteLine("\n(SquareMatrix) m =\n{0}", m_as_sm_s);
SquareMatrix<double> sm = new SquareMatrix<double>(5, (y, x) => 5 + (int)x - (int)y);
Console.WriteLine("\nsm: SquareMatrix =\n{0}", sm);
SquareMatrix<double> sm_t = sm.Transpose();
Console.WriteLine("\nsm.Transpose() =\n{0}", sm_t);
Matrix<double> sm_as_m = (Matrix<double>)sm;
Console.WriteLine("\n(Matrix) sm =\n{0}", sm_as_m);
SquareMatrix<double> sm_as_m_as_sm = (SquareMatrix<double>)sm_as_m;
Console.WriteLine("\n(SquareMatrix) (Matrix) sm =\n{0}", sm_as_m_as_sm);
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uVGV4dDsKCmNsYXNzIEN1c3RvbU1hdHJpeDxFTEVNLCBNQVRSSVg+Cgl3aGVyZSBNQVRSSVggOiBDdXN0b21NYXRyaXg8RUxFTSwgTUFUUklYPgp7CglwdWJsaWMgcmVhZG9ubHkgdWludCBzaXplWSwgc2l6ZVg7CglwdWJsaWMgcmVhZG9ubHkgRUxFTVssXSBkYXRhOwoKCXByb3RlY3RlZCBDdXN0b21NYXRyaXgodWludCBzaXplWSwgdWludCBzaXplWCkKCXsKCQl0aGlzLnNpemVZID0gc2l6ZVk7CgkJdGhpcy5zaXplWCA9IHNpemVYOwoJCWRhdGEgPSBuZXcgRUxFTVtzaXplWSwgc2l6ZVhdOwoJfQoKCXByb3RlY3RlZCBDdXN0b21NYXRyaXgodWludCBzaXplWSwgdWludCBzaXplWCwgRnVuYzx1aW50LCB1aW50LCBFTEVNPiBnZXQpIDoKCQl0aGlzKHNpemVZLCBzaXplWCkKCXsKCQlmb3IgKHVpbnQgeSA9IDA7IHkgPCBzaXplWTsgeSsrKQoJCQlmb3IgKHVpbnQgeCA9IDA7IHggPCBzaXplWDsgeCsrKQoJCQkJZGF0YVt5LCB4XSA9IGdldCh5LCB4KTsKCX0KCglwdWJsaWMgTUFUUklYIFRyYW5zcG9zZSgpCgl7CgkJRnVuYzx1aW50LCB1aW50LCBFTEVNPiB0cmFuc3Bvc2VyID0gKHksIHgpID0+IGRhdGFbeCwgeV07CgkJcmV0dXJuIChNQVRSSVgpQWN0aXZhdG9yLkNyZWF0ZUluc3RhbmNlKAoJCQl0eXBlb2YoTUFUUklYKSwgbmV3IG9iamVjdFtdeyBzaXplWCwgc2l6ZVksIHRyYW5zcG9zZXIgfSk7Cgl9CgoJcHVibGljIEVMRU0gdGhpc1t1aW50IHksIHVpbnQgeF0KCXsKCQlnZXQgeyByZXR1cm4gZGF0YVt5LCB4XTsgfQoJCXNldCB7IGRhdGFbeSwgeF0gPSB2YWx1ZTsgfQoJfQoKCXB1YmxpYyBvdmVycmlkZSBzdHJpbmcgVG9TdHJpbmcoKQoJewoJCXZhciBzYiA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7CgkJZm9yICh1aW50IHkgPSAwOyB5IDwgc2l6ZVk7IHkrKykKCQl7CgkJCWlmICh5ID4gMCkgc2IuQXBwZW5kKCJcbiIpOwoJCQlmb3IgKHVpbnQgeCA9IDA7IHggPCBzaXplWDsgeCsrKQoJCQl7CgkJCQlpZiAoeCA+IDApIHNiLkFwcGVuZCgiICAiKTsKCQkJCXNiLkFwcGVuZChkYXRhW3ksIHhdKTsKCQkJfQoJCX0KCQlyZXR1cm4gc2IuVG9TdHJpbmcoKTsKCX0KfQoKY2xhc3MgTWF0cml4PEVMRU0+IDogQ3VzdG9tTWF0cml4PEVMRU0sIE1hdHJpeDxFTEVNPj4KewoJcHVibGljIE1hdHJpeCh1aW50IHNpemVZLCB1aW50IHNpemVYKSA6IGJhc2Uoc2l6ZVksIHNpemVYKSB7IH0KCXB1YmxpYyBNYXRyaXgodWludCBzaXplWSwgdWludCBzaXplWCwgRnVuYzx1aW50LCB1aW50LCBFTEVNPiBnZXQpIDogYmFzZShzaXplWSwgc2l6ZVgsIGdldCkgeyB9CgoJcHVibGljIHN0YXRpYyBleHBsaWNpdCBvcGVyYXRvciBTcXVhcmVNYXRyaXg8RUxFTT4oTWF0cml4PEVMRU0+IG0pCgl7CgkJcmV0dXJuIG5ldyBTcXVhcmVNYXRyaXg8RUxFTT4obS5zaXplWSwgbS5zaXplWCwgKHksIHgpID0+IG1beSwgeF0pOwoJfQp9CgpjbGFzcyBTcXVhcmVNYXRyaXg8RUxFTT4gOiBDdXN0b21NYXRyaXg8RUxFTSwgU3F1YXJlTWF0cml4PEVMRU0+Pgp7CglwdWJsaWMgU3F1YXJlTWF0cml4KHVpbnQgc2l6ZSkgOiBiYXNlKHNpemUsIHNpemUpIHsgfQoJcHVibGljIFNxdWFyZU1hdHJpeCh1aW50IHNpemUsIEZ1bmM8dWludCwgdWludCwgRUxFTT4gZ2V0KSA6IGJhc2Uoc2l6ZSwgc2l6ZSwgZ2V0KSB7IH0KCXB1YmxpYyBTcXVhcmVNYXRyaXgodWludCBzaXplWSwgdWludCBzaXplWCwgRnVuYzx1aW50LCB1aW50LCBFTEVNPiBnZXQpIDogYmFzZShzaXplWSwgc2l6ZVgsIGdldCkKCXsKCQlpZiAoc2l6ZVkgIT0gc2l6ZVgpIHRocm93IG5ldyBBcmd1bWVudEV4Y2VwdGlvbihzdHJpbmcuRm9ybWF0KCJTcXVhcmVNYXRyaXgg0L3QtSDQvNC+0LbQtdGCINCx0YvRgtGMINGA0LDQt9C80LXRgNCwIHswfcOXezF9LiIsIHNpemVZLCBzaXplWCkpOwoJfQoKCXB1YmxpYyBzdGF0aWMgZXhwbGljaXQgb3BlcmF0b3IgTWF0cml4PEVMRU0+KFNxdWFyZU1hdHJpeDxFTEVNPiBtKQoJewoJCXJldHVybiBuZXcgTWF0cml4PEVMRU0+KG0uc2l6ZVksIG0uc2l6ZVgsICh5LCB4KSA9PiBtW3ksIHhdKTsKCX0KfQoKcHVibGljIGNsYXNzIE1haW5DbGFzcwp7CglwdWJsaWMgc3RhdGljIHZvaWQgTWFpbigpCgl7CgkJTWF0cml4PGRvdWJsZT4gbSA9IG5ldyBNYXRyaXg8ZG91YmxlPigzLCA1LCAoeSwgeCkgPT4gMip5ICsgeCk7CgkJQ29uc29sZS5Xcml0ZUxpbmUoIm06IE1hdHJpeCA9XG57MH0iLCBtKTsKCgkJTWF0cml4PGRvdWJsZT4gbV90ID0gbS5UcmFuc3Bvc2UoKTsKCQlDb25zb2xlLldyaXRlTGluZSgiXG5tLlRyYW5zcG9zZSgpID1cbnswfSIsIG1fdCk7CgoJCXN0cmluZyBtX2FzX3NtX3M7CgkJdHJ5CgkJewoJCQltX2FzX3NtX3MgPSAoKFNxdWFyZU1hdHJpeDxkb3VibGU+KW0pLlRvU3RyaW5nKCk7CgkJfSBjYXRjaCAoQXJndW1lbnRFeGNlcHRpb24gZSkKCQl7CgkJCW1fYXNfc21fcyA9IGUuTWVzc2FnZTsKCQl9CgkJQ29uc29sZS5Xcml0ZUxpbmUoIlxuKFNxdWFyZU1hdHJpeCkgbSA9XG57MH0iLCBtX2FzX3NtX3MpOwoKCQlTcXVhcmVNYXRyaXg8ZG91YmxlPiBzbSA9IG5ldyBTcXVhcmVNYXRyaXg8ZG91YmxlPig1LCAoeSwgeCkgPT4gNSArIChpbnQpeCAtIChpbnQpeSk7CgkJQ29uc29sZS5Xcml0ZUxpbmUoIlxuc206IFNxdWFyZU1hdHJpeCA9XG57MH0iLCBzbSk7CgoJCVNxdWFyZU1hdHJpeDxkb3VibGU+IHNtX3QgPSBzbS5UcmFuc3Bvc2UoKTsKCQlDb25zb2xlLldyaXRlTGluZSgiXG5zbS5UcmFuc3Bvc2UoKSA9XG57MH0iLCBzbV90KTsKCgkJTWF0cml4PGRvdWJsZT4gc21fYXNfbSA9IChNYXRyaXg8ZG91YmxlPilzbTsKCQlDb25zb2xlLldyaXRlTGluZSgiXG4oTWF0cml4KSBzbSA9XG57MH0iLCBzbV9hc19tKTsKCgkJU3F1YXJlTWF0cml4PGRvdWJsZT4gc21fYXNfbV9hc19zbSA9IChTcXVhcmVNYXRyaXg8ZG91YmxlPilzbV9hc19tOwoJCUNvbnNvbGUuV3JpdGVMaW5lKCJcbihTcXVhcmVNYXRyaXgpIChNYXRyaXgpIHNtID1cbnswfSIsIHNtX2FzX21fYXNfc20pOwoJfQp9