diff --git a/Lab1/BMP File Format.url b/Lab1/BMP File Format.url new file mode 100644 index 0000000..4691316 --- /dev/null +++ b/Lab1/BMP File Format.url @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,2 +[InternetShortcut] +IDList= +URL=http://www.ece.ualberta.ca/~elliott/ee552/studentAppNotes/2003_w/misc/bmp_file_format/bmp_file_format.htm diff --git a/Lab1/BMP formatas.docx b/Lab1/BMP formatas.docx new file mode 100644 index 0000000..a86ed45 Binary files /dev/null and b/Lab1/BMP formatas.docx differ diff --git a/Lab1/BMPImage.cs b/Lab1/BMPImage.cs new file mode 100644 index 0000000..75a4cea --- /dev/null +++ b/Lab1/BMPImage.cs @@ -0,0 +1,359 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; + +namespace Lab1 +{ + internal struct Color + { + public byte r = 0, g = 0, b = 0; + + public Color(byte r, byte g, byte b) + { + this.r = r; + this.g = g; + this.b = b; + } + + public Color(Color color) + { + this.r = color.r; + this.g = color.g; + this.b = color.b; + } + + public override string ToString() + { + return $"Color({r}, {g}, {b})"; + } + } + + internal class BMPImage + { + public uint width, height; + public Color[] data; + + public BMPImage(uint width, uint height) + { + Debug.Assert(width > 0, "Width must be at least 1"); + Debug.Assert(height > 0, "Height must be at least 1"); + + this.width = width; + this.height = height; + + this.data = new Color[width * height]; + } + + public void SetPixel(int x, int y, int r, int g, int b) + { + if (x < 0 || y < 0 || x >= width || y >= height) return; + data[width * y + x].r = (byte)r; + data[width * y + x].g = (byte)g; + data[width * y + x].b = (byte)b; + } + + public Color GetPixel(int x, int y) + { + if (x < 0 || y < 0 || x >= width || y >= height) return new Color(0, 0, 0); + return new Color(data[width * y + x]); + } + + public void SetPixel(int x, int y, Color color) + { + SetPixel(x, y, color.r, color.g, color.b); + } + + public void Fill(Color color) + { + Rectangle(0, 0, (int)width, (int)height, color); + } + + public void Rectangle(int x, int y, int width, int height, Color color) + { + for (int dy = 0; dy < height; dy++) + { + for (int dx = 0; dx < width; dx++) + { + SetPixel(x + dx, y + dy, color); + } + } + } + + private static void swap(ref int a, ref int b) + { + int c = a; + a = b; + b = c; + } + + public void Line(int x1, int y1, int x2, int y2, Color color) + { + int dx = x2 - x1; + int dy = y2 - y1; + + if (dx == 0 && dy == 0) + { + SetPixel(x1, y1, color); + return; + } + + if (Math.Abs(dx) > Math.Abs(dy)) + { + if (x1 > x2) + { + swap(ref x1, ref x2); + swap(ref y1, ref y2); + } + + for (int x = x1; x <= x2; ++x) + { + int y = dy * (x - x1) / dx + y1; + SetPixel(x, y, color); + } + } else + { + if (y1 > y2) + { + swap(ref x1, ref x2); + swap(ref y1, ref y2); + } + + for (int y = y1; y <= y2; ++y) + { + int x = dx * (y - y1) / dy + x1; + SetPixel(x, y, color); + } + } + } + + private static void SortPointsByX(ref int x1, ref int y1, ref int x2, ref int y2, ref int x3, ref int y3) + { + if (x1 > x2) + { + swap(ref x1, ref x2); + swap(ref y1, ref y2); + } + + if (x1 > x3) + { + swap(ref x1, ref x3); + swap(ref y1, ref y3); + } + + if (x2 > x3) + { + swap(ref x2, ref x3); + swap(ref y2, ref y3); + } + } + + public void Triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color) + { + SortPointsByX(ref x1, ref y1, ref x2, ref y2, ref x3, ref y3); + + if (x2 - x1 == 0) return; + if (x3 - x1 == 0) return; + if (x3 - x2 == 0) return; + if (x3 - x1 == 0) return; + + for (int x = x1; x <= x2; x++) + { + int yEdge1 = (y2 - y1) * (x - x1) / (x2 - x1) + y1; + int yEdge2 = (y3 - y1) * (x - x1) / (x3 - x1) + y1; + for (int y = Math.Min(yEdge1, yEdge2); y < Math.Max(yEdge1, yEdge2); y++) + { + SetPixel(x, y, color); + } + } + + for (int x = x2; x <= x3; x++) + { + int yEdge1 = (y3 - y2) * (x - x2) / (x3 - x2) + y2; + int yEdge2 = (y3 - y1) * (x - x1) / (x3 - x1) + y1; + for (int y = Math.Min(yEdge1, yEdge2); y < Math.Max(yEdge1, yEdge2); y++) + { + SetPixel(x, y, color); + } + } + } + + public void Circle(int x, int y, int radius, Color color) + { + for (int dy = -(int)radius; dy < radius; dy++) + { + for (int dx = -(int)radius; dx < radius; dx++) + { + if (dx*dx + dy*dy < radius*radius) + { + SetPixel(x + dx, y + dy, color); + } + } + } + } + + private static void WriteBytes(FileStream f, params byte[] bytes) + { + f.Write(bytes); + } + + private static void WriteUInt16(FileStream f, UInt16 number) + { + WriteBytes(f, + (byte)((number >> 8 * 0) & 0xFF), + (byte)((number >> 8 * 1) & 0xFF) + ); + } + private static void WriteUInt32(FileStream f, UInt32 number) + { + WriteBytes(f, + (byte)((number >> 8 * 0) & 0xFF), + (byte)((number >> 8 * 1) & 0xFF), + (byte)((number >> 8 * 2) & 0xFF), + (byte)((number >> 8 * 3) & 0xFF) + ); + } + + private static ushort DetermineBPP(ICollection colors) + { + int count = colors.Count; + if (count <= 2) + { + return 1; + } else if (count <= 16) + { + return 4; + } else if (count <= 256) + { + return 8; + } + return 24; + } + + private static uint GetScanlineSize(uint width, uint bpp) + { + return ((width * bpp + 31) / 32 * 32) / 8u; + } + + private byte[] EncodePixelData(uint bpp, List usedColors) + { + uint scanline = GetScanlineSize(width, bpp); + byte[] pixelData = new byte[height * scanline]; + if (bpp == 1) + { + for (int y = 0; y < height; y++) + { + int idx = 0; + for (int x = 0; x < width; x += 8) + { + byte pix1 = (byte)(usedColors.IndexOf(GetPixel(x + 0, y)) & 1); + byte pix2 = (byte)(usedColors.IndexOf(GetPixel(x + 1, y)) & 1); + byte pix3 = (byte)(usedColors.IndexOf(GetPixel(x + 2, y)) & 1); + byte pix4 = (byte)(usedColors.IndexOf(GetPixel(x + 3, y)) & 1); + byte pix5 = (byte)(usedColors.IndexOf(GetPixel(x + 4, y)) & 1); + byte pix6 = (byte)(usedColors.IndexOf(GetPixel(x + 5, y)) & 1); + byte pix7 = (byte)(usedColors.IndexOf(GetPixel(x + 6, y)) & 1); + byte pix8 = (byte)(usedColors.IndexOf(GetPixel(x + 7, y)) & 1); + pixelData[scanline * y + idx] = (byte)(pix1 << 7 | pix2 << 6 | pix3 << 5 | pix4 << 4 | pix5 << 3 | pix6 << 2 | pix7 << 1 | pix8 << 0); + idx++; + } + } + } + else if (bpp == 4) + { + for (int y = 0; y < height; y++) + { + int idx = 0; + for (int x = 0; x < width; x += 2) + { + byte pix1 = (byte)(usedColors.IndexOf(GetPixel(x + 0, y)) & 0xF); + byte pix2 = (byte)(usedColors.IndexOf(GetPixel(x + 1, y)) & 0xF); + pixelData[scanline * y + idx] = (byte)(pix1 << 4 | pix2 << 0); + idx++; + } + } + } + else if (bpp == 8) + { + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + pixelData[scanline * y + x] = (byte)(usedColors.IndexOf(GetPixel(x, y)) & 0xFF); + } + } + } + else if (bpp == 24) + { + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + Color color = GetPixel(x, y); + pixelData[scanline * y + 3 * x + 0] = color.b; + pixelData[scanline * y + 3 * x + 1] = color.g; + pixelData[scanline * y + 3 * x + 2] = color.r; + } + } + } + else + { + throw new NotImplementedException(); + } + + return pixelData; + } + + public void Write(string filename) + { + List usedColors = new List(); + for (int i = 0; i < width*height; i++) + { + if (!usedColors.Contains(data[i])) + { + usedColors.Add(data[i]); + } + } + + ushort bpp = DetermineBPP(usedColors); + byte[] pixelData = EncodePixelData(bpp, usedColors); + + using (FileStream f = new FileStream(filename, FileMode.Create, FileAccess.Write)) + { + // Write header + WriteBytes(f, 0x42, 0x4d); // signature + WriteUInt32(f, 0); // file size + WriteUInt32(f, 0); // reserved + WriteUInt32(f, 0); // data offset + + // Write info header + WriteUInt32(f, 40); // info header size, always 40 + WriteUInt32(f, width); // width + WriteUInt32(f, height); // height + WriteUInt16(f, 1); // number of planes + WriteUInt16(f, bpp); // bits per pixel + WriteUInt32(f, 0); // compression + WriteUInt32(f, 0); // size of compressed image + WriteUInt32(f, 0); // x pixel per meter + WriteUInt32(f, 0); // y pixel per meter + WriteUInt32(f, 0); // colors used + WriteUInt32(f, 0); // important colors, 0 = all + + if (bpp <= 8) + { + foreach (Color color in usedColors) + { + WriteBytes(f, color.b, color.g, color.r, 0); + } + for (int i = 0; i < Math.Pow(2, bpp) - usedColors.Count; i++) + { + WriteBytes(f, 0, 0, 0, 0); + } + } + + // Write pixel data + f.Write(pixelData); + } + } + } +} diff --git a/Lab1/Lab1.csproj b/Lab1/Lab1.csproj new file mode 100644 index 0000000..41f1d5a --- /dev/null +++ b/Lab1/Lab1.csproj @@ -0,0 +1,8 @@ + + + + Exe + net6.0 + + + diff --git a/Lab1/Program.cs b/Lab1/Program.cs new file mode 100644 index 0000000..ea2830b --- /dev/null +++ b/Lab1/Program.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace Lab1 +{ + class Program + { + // O(n^5) + public static double T1(int[] n, int size) + { + if (size >= 1) + { + int sum = 0; + for (int i = 0; i < Math.Pow(size, 5); i++) + { + sum += i; + } + return 2 * T1(n, size / 9) + sum; + } + return 0; + } + + public static double T1(int[] n) + { + return T1(n, n.Length); + } + + // O(n) + public static double T2(int[] n, int size) + { + if (size >= 1) + { + int sum = 0; + for (int i = 0; i < size; i++) + { + sum += i; + } + return T2(n, size / 6) + T2(n, size / 7) + sum; + } + return 0; + } + + public static double T2(int[] n) + { + return T2(n, n.Length); + } + + // O(n^2) + public static double T3(int[] n, int size) + { + if (size >= 1) + { + int sum = 0; + for (int i = 0; i < size; i++) + { + sum += i; + } + return T3(n, size - 8) + T3(n, size - 6) + sum; + } + return 0; + } + + public static double T3(int[] n) + { + return T3(n, n.Length); + } + + // O(log4(n)) + public static void TrianglesRecursive(BMPImage image, int x, int y, uint width, uint height) + { + if (width <= 3 || height <= 3) return; + + image.Triangle( + x + (int)(width / 3 * 1 ), (y + (int)height / 3 * 2), + x + (int)(width / 3 * 2 ), (y + (int)height / 3 * 2), + x + (int)(width / 3 * 1.5), (y + (int)height / 3 * 1), + new Color(0, 0, 0) + ); + + TrianglesRecursive( + image, x, y, width/3, height/3 + ); + TrianglesRecursive( + image, x + (int)width/3*2, y, width / 3, height / 3 + ); + TrianglesRecursive( + image, x, y + (int)height/3*2, width / 3, height / 3 + ); + TrianglesRecursive( + image, x + (int)width / 3 * 2, y + (int)height / 3 * 2, width / 3, height / 3 + ); + } + + public static void Triangles() + { + BMPImage image = new BMPImage(1000, 1000); + image.Fill(new Color(255, 255, 255)); + TrianglesRecursive(image, 0, 0, image.width, image.height); + image.Write("result.bmp"); + } + + public static double TestFunc(Func T, uint n) + { + int[] data = new int[n]; + for (int i = 0; i < n; i++) + { + data[i] = i; + } + + var before = DateTime.Now; + T(data); + var duration = DateTime.Now - before; + return duration.TotalSeconds; + } + + static void Main() + { + // T1(10) => 0.0056552 + // T1(20) => 0.0699722 + // T1(40) => 2.1500858 + // T1(50) => 6.4564238 + + // T2(100) => 0.0039419 + // T2(1_000_000) => 0.0048064 + // T2(250_000_000) => 0.3011757 + // T2(500_000_000) => 0.6046134 + // T2(1_000_000_000) => 1.1902643 + + // T3(100) => 0.0041945 + // T3(150) => 0.0759872 + // T3(180) => 1.4428123 + // T3(190) => 3.9067703 + + //Triangles(); + } + } +} diff --git a/Lab1/README.md b/Lab1/README.md new file mode 100644 index 0000000..640a70d --- /dev/null +++ b/Lab1/README.md @@ -0,0 +1,34 @@ +# Lab1 + +## 1 užduotis +Kiekvienai rekurentinei lygčiai (gautai atlikus užduoties pasirinkimo testą): + +* Realizuoti metodą, kuris atitiktų pateiktos rekurentinės lygties sudėtingumą, t. y. + programinio kodo rekursinių iškvietimų ir kiekvieno iškvietimo metu atliekamų veiksmų + priklausomybę nuo duomenų. Metodas per parametrus turi priimti masyvą, kurio duomenų kiekis + yra rekurentinės lygties kintamasis n (arba masyvą ir indeksų rėžius, kurie atitinkamai + nurodo masyvo nagrinėjamų elementų indeksus atitinkamame iškvietime) (2 balai). + +* Kiekvienam realizuotam metodui atlikti programinio kodo analizę, parodant jog jis atitinka + pateiktą rekurentinę lygtį (1 balas). + +* Išspręskite rekurentinę lygtį ir apskaičiuokite jos asimptotinį sudėtingumą (taikoma + pagrindinė teorema, medžių ar kitas sprendimo metodas) (1 balas) + +* Atlikti eksperimentinį tyrimą (našumo testus: vykdymo laiką ir veiksmų skaičių) ir patikrinkite + ar apskaičiuotas metodo asimptotinis sudėtingumas atitinka eksperimentinius rezultatus (1 balas). + +## 2 užduoties dalis +Naudojant rekursiją ir nenaudojant grafinių bibliotekų sudaryti nurodytos struktūros +BMP formato ( gautą atlikus užduoties pasirinkimo testą): + +* Programos rezultatas BMP formato bylos demonstruojančios programos rekursijas. (3 balai) + +* Eksperimentiškai nustatykite darbo laiko ir veiksmų skaičiaus priklausomybę nuo generuojamo + paveikslėlio dydžio (taškų skaičiaus). Gautus rezultatus atvaizduokite grafikais. + Grafiką turi sudaryti nemažiau kaip 5 taškai ir paveikslėlio taškų skaičius turi didėti + proporcingai (kartais). (1 balas) + +* Analitiškai įvertinkite procedūros, kuri generuoja paveikslėlį, veiksmų skaičių sudarydami + rekurentinę lygtį ir ją išspręskite. Gautas rezultatas turi patvirtinti eksperimentinius + rezultatus (našumo testus: vykdymo laiką ir veiksmų skaičių). (1 balas) diff --git a/Labs.sln b/Labs.sln new file mode 100644 index 0000000..f7c0701 --- /dev/null +++ b/Labs.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32328.378 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lab1", "Lab1\Lab1.csproj", "{497767A1-722A-4F48-86E5-C2AE6E0B9C9A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {497767A1-722A-4F48-86E5-C2AE6E0B9C9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {497767A1-722A-4F48-86E5-C2AE6E0B9C9A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {497767A1-722A-4F48-86E5-C2AE6E0B9C9A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {497767A1-722A-4F48-86E5-C2AE6E0B9C9A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E792B7A8-715B-485D-AB55-1DC957C988CF} + EndGlobalSection +EndGlobal