commit a7923bfd04a6f24bf4bfb61d683e95c0b86a7188 Author: Michael Chen Date: Wed Aug 29 17:02:00 2018 +0200 Initial commit from 29th of August 2018 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a30d25 --- /dev/null +++ b/.gitignore @@ -0,0 +1,398 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml diff --git a/SortingVisualization.sln b/SortingVisualization.sln new file mode 100644 index 0000000..ad80ae1 --- /dev/null +++ b/SortingVisualization.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27703.2035 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SortingVisualization", "SortingVisualization\SortingVisualization.csproj", "{3CED6ADB-ADB8-499E-8A0E-6DB4B064F514}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3CED6ADB-ADB8-499E-8A0E-6DB4B064F514}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CED6ADB-ADB8-499E-8A0E-6DB4B064F514}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CED6ADB-ADB8-499E-8A0E-6DB4B064F514}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CED6ADB-ADB8-499E-8A0E-6DB4B064F514}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1223C2EB-90ED-4CF4-AF4F-E50B86D26D8B} + EndGlobalSection +EndGlobal diff --git a/SortingVisualization/Algorithms/Bubblesort.cs b/SortingVisualization/Algorithms/Bubblesort.cs new file mode 100644 index 0000000..643e1d6 --- /dev/null +++ b/SortingVisualization/Algorithms/Bubblesort.cs @@ -0,0 +1,24 @@ +namespace SortingVisualization.Algorithms { + public class Bubblesort : SortingAlgorithm { + public override string GetAlgorithmName() => "Bubblesort"; + + public override void Sort(ref DataSet set) { + Simulate(ref set); + System.Console.WriteLine("Doing {0}...", this.GetAlgorithmName()); + int n = set.Size; + do { + int newn = 1; + for (int i = 0; i < n - 1; i++) { + if (set.GreaterThan(i, i + 1)) { + set.Swap(i, i + 1); + newn = i + 1; + } + } + n = newn; + } while (n > 1); + System.Console.WriteLine("{0} complete!", this.GetAlgorithmName()); + if (!set.SimulateMode) + set.FinalizeVideo(); + } + } +} diff --git a/SortingVisualization/Algorithms/Cocktailshakersort.cs b/SortingVisualization/Algorithms/Cocktailshakersort.cs new file mode 100644 index 0000000..654fe4e --- /dev/null +++ b/SortingVisualization/Algorithms/Cocktailshakersort.cs @@ -0,0 +1,37 @@ +namespace SortingVisualization.Algorithms { + public class Cocktailshakersort : SortingAlgorithm { + public override string GetAlgorithmName() => "Cocktailshakersort"; + + public override void Sort(ref DataSet set) { + Simulate(ref set); + System.Console.WriteLine("Doing {0}...", this.GetAlgorithmName()); + int beginn = -1; + int ende = set.Size - 2; + bool vertauscht; + do { + vertauscht = false; + beginn++; + for (int i = beginn; i < ende; i++) { + if (set.GreaterThan(i, i + 1)) { + set.Swap(i, i + 1); + vertauscht = true; + } + } + if (!vertauscht) { + break; + } + vertauscht = false; + ende--; + for (int i = ende; i >= beginn - 1; i--) { + if (set.GreaterThan(i, i + 1)) { + set.Swap(i, i + 1); + vertauscht = true; + } + } + } while (vertauscht); + System.Console.WriteLine("{0} complete!", this.GetAlgorithmName()); + if (!set.SimulateMode) + set.FinalizeVideo(); + } + } +} diff --git a/SortingVisualization/Algorithms/Gravitysort.cs b/SortingVisualization/Algorithms/Gravitysort.cs new file mode 100644 index 0000000..72a8948 --- /dev/null +++ b/SortingVisualization/Algorithms/Gravitysort.cs @@ -0,0 +1,43 @@ +using System; + +namespace SortingVisualization.Algorithms { + public class Gravitysort : SortingAlgorithm { + public override string GetAlgorithmName() => "Gravitysort"; + + public override void Sort(ref DataSet set) { + Simulate(ref set); + System.Console.WriteLine("Doing {0}...", this.GetAlgorithmName()); + int i, j, max, sum; + byte[] beads; + + for (i = 1, max = set.ReadOperation(0); i < set.Size; ++i) + if (set.ReadOperation(i) > max) + max = set.ReadOperation(i); + + beads = new byte[max * set.Size]; + + for (i = 0; i < set.Size; ++i) + for (j = 0; j < set.ReadOperation(i); ++j) + beads[i * max + j] = 1; + + for (j = 0; j < max; ++j) { + for (sum = i = 0; i < set.Size; ++i) { + sum += beads[i * max + j]; + beads[i * max + j] = 0; + } + + for (i = set.Size - sum; i < set.Size; ++i) + beads[i * max + j] = 1; + } + + for (i = 0; i < set.Size; ++i) { + for (j = 0; j < max && Convert.ToBoolean(beads[i * max + j]); ++j) + ; + set.WriteOperation(i, j); + } + System.Console.WriteLine("{0} complete!", this.GetAlgorithmName()); + if (!set.SimulateMode) + set.FinalizeVideo(); + } + } +} diff --git a/SortingVisualization/Algorithms/Insertionsort.cs b/SortingVisualization/Algorithms/Insertionsort.cs new file mode 100644 index 0000000..5e561a1 --- /dev/null +++ b/SortingVisualization/Algorithms/Insertionsort.cs @@ -0,0 +1,20 @@ +namespace SortingVisualization.Algorithms { + public class Insertionsort : SortingAlgorithm { + public override string GetAlgorithmName() => "Insertionsort"; + + public override void Sort(ref DataSet set) { + Simulate(ref set); + System.Console.WriteLine("Doing {0}...", this.GetAlgorithmName()); + for (int i = 0; i < set.Size - 1; i++) { + for (int j = i + 1; j > 0; j--) { + if (set.GreaterThan(j - 1, j)) { + set.Swap(j - 1, j); + } + } + } + System.Console.WriteLine("{0} complete!", this.GetAlgorithmName()); + if (!set.SimulateMode) + set.FinalizeVideo(); + } + } +} diff --git a/SortingVisualization/Algorithms/Mergesort.cs b/SortingVisualization/Algorithms/Mergesort.cs new file mode 100644 index 0000000..7bb67de --- /dev/null +++ b/SortingVisualization/Algorithms/Mergesort.cs @@ -0,0 +1,57 @@ +namespace SortingVisualization.Algorithms { + public class Mergesort : SortingAlgorithm { + public override string GetAlgorithmName() => "Mergesort"; + + public override void Sort(ref DataSet set) { + Simulate(ref set); + System.Console.WriteLine("Doing {0}...", this.GetAlgorithmName()); + MergeSort(ref set, 0, set.Size - 1); + System.Console.WriteLine("{0} complete!", this.GetAlgorithmName()); + if (!set.SimulateMode) + set.FinalizeVideo(); + } + public static void MergeSort(ref DataSet set, int l, int r) { + if (l < r) { + int mid = (l / 2) + (r / 2); + MergeSort(ref set, l, mid); + MergeSort(ref set, mid + 1, r); + Merge(ref set, l, mid, r); + } + } + + private static void Merge(ref DataSet set, int l, int m, int r) { + int left = l; + int right = m + 1; + int[] tmp = new int[(r - l) + 1]; + int tmpIndex = 0; + + while ((left <= m) && (right <= r)) { + if (set.LessThan(left, right)) { + tmp[tmpIndex] = set.ReadOperation(left); + left++; + } else { + tmp[tmpIndex] = set.ReadOperation(right); + right++; + } + tmpIndex++; + } + + while (left <= m) { + tmp[tmpIndex] = set.ReadOperation(left); + left++; + tmpIndex++; + } + + while (right <= r) { + tmp[tmpIndex] = set.ReadOperation(right); + right++; + tmpIndex++; + } + + for (int i = 0; i < tmp.Length; i++) { + set.WriteOperation(l + i, tmp[i]); + } + + } + } +} diff --git a/SortingVisualization/Algorithms/Quicksort.cs b/SortingVisualization/Algorithms/Quicksort.cs new file mode 100644 index 0000000..474a0f5 --- /dev/null +++ b/SortingVisualization/Algorithms/Quicksort.cs @@ -0,0 +1,37 @@ +namespace SortingVisualization.Algorithms { + public class Quicksort : SortingAlgorithm { + public override string GetAlgorithmName() => "Quicksort"; + public override void Sort(ref DataSet set) { + Simulate(ref set); + System.Console.WriteLine("Doing {0}...", this.GetAlgorithmName()); + SortRecursion(ref set, 0, set.Size - 1); + System.Console.WriteLine("{0} complete!", this.GetAlgorithmName()); + if (!set.SimulateMode) + set.FinalizeVideo(); + } + public static void SortRecursion(ref DataSet set, int l, int r) { + int i = l, j = r; + int pivot = (l + r) / 2; + while (i <= j) { + while (set.LessThan(i, pivot)) + i++; + while (set.GreaterThan(j, pivot)) + j--; + + if (i <= j) { + set.Swap(i, j); + if (pivot == i) + pivot = j; + else if (pivot == j) + pivot = i; + i++; + j--; + } + } + if (l < j) + SortRecursion(ref set, l, j); + if (i < r) + SortRecursion(ref set, i, r); + } + } +} diff --git a/SortingVisualization/Algorithms/Radixsort.cs b/SortingVisualization/Algorithms/Radixsort.cs new file mode 100644 index 0000000..68f2450 --- /dev/null +++ b/SortingVisualization/Algorithms/Radixsort.cs @@ -0,0 +1,37 @@ +namespace SortingVisualization.Algorithms { + public class Radixsort : SortingAlgorithm { + public override string GetAlgorithmName() => "Radixsort"; + + public override void Sort(ref DataSet set) { + Simulate(ref set); + System.Console.WriteLine("Doing {0}...", this.GetAlgorithmName()); + int n; // Fachnummer + int[] nPart = new int[2]; // Anzahl der Elemente in den beiden Faechern + int[,] part = new int[2, set.Size]; // die beiden Faecher haben die Groesse des Arrays a + + // Schleife ueber alle Bits der Schluessel (bei int: 32 Bit) + for (int i = 0; i < 32; i++) { + nPart[0] = 0; + nPart[1] = 0; + + // Partitionierungsphase: teilt "a" auf die Faecher auf + for (int j = 0; j < set.Size; j++) { + int tmp = set.ReadOperation(j); + n = (tmp >> i) & 1; // ermittelt die Fachnummer: 0 oder 1 + part[n, nPart[n]++] = tmp; // kopiert j-tes Element ins richtige Fach + } + + // Sammelphase: kopiert die beiden Faecher wieder nach "a" zusammen + for (int k = 0; k < nPart[0]; k++) { + set.WriteOperation(k, part[0, k]); + } + for (int k = nPart[0]; k < set.Size; k++) { + set.WriteOperation(k, part[1, k]); + } + } + System.Console.WriteLine("{0} complete!", this.GetAlgorithmName()); + if (!set.SimulateMode) + set.FinalizeVideo(); + } + } +} diff --git a/SortingVisualization/Algorithms/Selectionsort.cs b/SortingVisualization/Algorithms/Selectionsort.cs new file mode 100644 index 0000000..e7caac5 --- /dev/null +++ b/SortingVisualization/Algorithms/Selectionsort.cs @@ -0,0 +1,20 @@ +namespace SortingVisualization.Algorithms { + public class Selectionsort : SortingAlgorithm { + public override string GetAlgorithmName() => "Selectionsort"; + + public override void Sort(ref DataSet set) { + Simulate(ref set); + System.Console.WriteLine("Doing {0}...", this.GetAlgorithmName()); + for (int i = 0; i < set.Size; i++) { + int min = i; + for (int j = i + 1; j < set.Size; j++) + if (set.LessThan(j, min)) + min = j; + set.Swap(min, i); + } + System.Console.WriteLine("{0} complete!", this.GetAlgorithmName()); + if (!set.SimulateMode) + set.FinalizeVideo(); + } + } +} diff --git a/SortingVisualization/App.config b/SortingVisualization/App.config new file mode 100644 index 0000000..731f6de --- /dev/null +++ b/SortingVisualization/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SortingVisualization/DataSet.cs b/SortingVisualization/DataSet.cs new file mode 100644 index 0000000..2c74480 --- /dev/null +++ b/SortingVisualization/DataSet.cs @@ -0,0 +1,420 @@ +using Accord.Video.FFMPEG; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SortingVisualization { + public enum SetType { + Ordererd, + Reversed, + Random, + SingleError + } + public class DataSet { + #region Props + /// + /// Gibt die Größe (Anzahl der zu sortierenden Werte) an. + /// + public int Size { get; private set; } + /// + /// Speichert das initale Datenset um verschiedene Algorithmen auf dasselbe Set anzuwenden (direkter Vergleich). + /// + private readonly int[] _InitialData; + public int Seed { get; private set; } + private int[] _Data; + public int ReadOperations { get; private set; } = 0; + public int WriteOperations { get; private set; } = 0; + public int CompareOperations { get; private set; } = 0; + public int SwapOperations { get; private set; } = 0; + public long Ticks { get; private set; } = 0; + public string SortingAlgorithm { + get => _sortingAlgorithm; + set { + _sortingAlgorithm = value; + if (!Directory.Exists(this.SortingAlgorithm)) { + Directory.CreateDirectory(this.SortingAlgorithm); + } + _Directory = Path.Combine(this.SortingAlgorithm, DataSet.SetTypeToString(this.SetType)); + if (!Directory.Exists(_Directory)) { + Directory.CreateDirectory(_Directory); + } + _Directory = Path.Combine(_Directory, this.Size.ToString()); + if (!Directory.Exists(_Directory)) { + Directory.CreateDirectory(_Directory); + } + if (this.SetType == SetType.Random || this.SetType == SetType.SingleError) { + _Directory = Path.Combine(_Directory, this.Seed.ToString()); + if (!Directory.Exists(_Directory)) { + Directory.CreateDirectory(_Directory); + } + } + if (!VideoRenderer.IsOpen) { + VideoRenderer.Open(Path.Combine(_Directory, this.SortingAlgorithm + ".mkv"), 3000, 2000, new Accord.Math.Rational(60), VideoCodec.Default, int.MaxValue); + } + } + } + private string _Directory = "uninitialized"; + private long _StartTime = 0; + public SetType SetType { get; } + private int _ExpectedFrameCount = 1; + private bool _simulateMode; + private int _frameSkipping = 0; + private int _skippedFrames = 0; + public bool SimulateMode { + get => _simulateMode; + set { + if (value) { + _ExpectedFrameCount = int.MaxValue; + Console.WriteLine("Simulating {0} with {1} values (Set: {2} - Seed {3})...", this.SortingAlgorithm, this.Size, DataSet.SetTypeToString(this.SetType), this.Seed); + } else { + Console.WriteLine("Simulation ended! Results:\n\t{0} Reads\n\t{1} Writes\n\t{2} Comparisons\n\t{3} Swaps\n\t{4} Frames", this.ReadOperations, this.WriteOperations, this.CompareOperations, this.SwapOperations, this.FrameCount + this.Size); + _ExpectedFrameCount = this.FrameCount + this.Size; + this.ResetToInitial(); + _frameSkipping = _ExpectedFrameCount / 3600; + Console.WriteLine("Drawing 1 in every {0} frames", _frameSkipping + 1); + Console.SetOut(TextWriter.Null); + } + _simulateMode = value; + } + } + #endregion + #region Constructors + public DataSet(int size, SetType type, int seed) { + this.SetType = type; + this.Seed = seed; + this.Size = size; + _InitialData = new int[size]; + var rnd = new Random(seed); + switch (type) { + case SetType.Ordererd: + for (int i = 0; i < size; i++) + _InitialData[i] = i + 1; + break; + case SetType.Reversed: + for (int i = 0; i < size; i++) + _InitialData[i] = size - i; + break; + case SetType.Random: + for (int i = 0; i < size; i++) { + int tmp; + do { + tmp = rnd.Next(1, size + 1); // TODO: Do this better! + } while (_InitialData.Contains(tmp)); + _InitialData[i] = tmp; + } + break; + case SetType.SingleError: + for (int i = 1; i < size - 1; i++) + _InitialData[i] = i + 1; + _InitialData[0] = size; + _InitialData[size - 1] = 1; + break; + default: + throw new ArgumentException("Unhandled Enumeration type when initializing the dataset values!", "type"); + } + _Data = new int[size]; + _InitialData.CopyTo(_Data, 0); + _yScale = (double)_FrameHeight / (double)(this.Size); + _xScale = (double)_FrameWidth / (double)(this.Size); + _BarWidth = (int)Math.Ceiling(_xScale); + } + public DataSet(int size, SetType type) : this(size, type, Guid.NewGuid().GetHashCode()) { } + public override string ToString() => $"{this.SortingAlgorithm} - {this.Size} Values - {DataSet.SetTypeToString(this.SetType)} Set - Seed {this.Seed}"; + #endregion + #region Operations + public static string SetTypeToString(SetType type) { + switch (type) { + case SetType.Ordererd: + return "Ordered"; + case SetType.Reversed: + return "Reversed"; + case SetType.Random: + return "Random"; + case SetType.SingleError: + return "SingleError"; + default: + return "Unkown"; + } + } + /// + /// Gibt das Element des Datensets aus, das an (index + 1)-ter Stelle steht. + /// + /// Zugriffsindex, wirft einen Fehler, wenn der Index nicht gültig ist. + /// Kopie des Werts aus dem Datenset. + private int this[int index] { + get { + this.ReadOperations++; + return _Data[index]; + } + set { + this.WriteOperations++; + _Data[index] = value; + } + } + /// + /// Reads the value at an index (same as this[index]) but generates a frame. + /// + /// + /// + public int ReadOperation(int index) { + this.DrawReadFrame(index); + return this[index]; + } + public void WriteOperation(int index, int value) { + this[index] = value; + this.DrawWriteFrame(index); + } + private void Comparation(int left, int right) { + this.CompareOperations++; + this.DrawCompareFrame(left, right); + } + public bool GreaterThan(int left, int right) { + this.Comparation(left, right); + return (this[left] > this[right]); + } + public bool GreaterThanOrEqual(int left, int right) { + this.Comparation(left, right); + return (this[left] >= this[right]); + } + public bool LessThan(int left, int right) { + this.Comparation(left, right); + return (this[left] < this[right]); + } + public bool LessThanOrEqual(int left, int right) { + this.Comparation(left, right); + return (this[left] <= this[right]); + } + public bool Equal(int left, int right) { + this.Comparation(left, right); + return (this[left] == this[right]); + } + public bool Unequal(int left, int right) { + this.Comparation(left, right); + return (this[left] != this[right]); + } + public void Swap(int left, int right) { + int tmp = this[left]; + this[left] = this[right]; + this[right] = tmp; + this.SwapOperations++; + this.DrawSwapFrame(left, right); + } + #endregion + #region Timing + public void StartTimer() => _StartTime = DateTime.Now.Ticks; + public void StopTimer() => this.Ticks = DateTime.Now.Ticks - _StartTime; + #endregion + #region Visualizing + public Brush BackgroundBrush = new SolidBrush(Color.Black); + public Brush ReadColor = new SolidBrush(Color.Blue); + public Brush WriteColor = new SolidBrush(Color.Magenta); + public Brush CheckColor = new SolidBrush(Color.Green); + public Brush BarColor = new SolidBrush(Color.White); + public Brush CompareColor = new SolidBrush(Color.Red); + public Brush SwapColor = new SolidBrush(Color.Yellow); + private Bitmap _Frame = new Bitmap(_FrameWidth, _FrameHeight); + private VideoFileWriter VideoRenderer = new VideoFileWriter(); + int _progress = 0; + private int FrameCount { + get => _FrameCount; + set { + if (!this.SimulateMode) + VideoRenderer.WriteVideoFrame(_Frame); + // _Frame.Save(Path.Combine(this.SortingAlgorithm, DataSet.SetTypeToString(this.SetType), $"Image{ _FrameCount.ToString("d6")}.png"), ImageFormat.Png); + _FrameCount = value; + int newprogress = (_FrameCount * 100) / _ExpectedFrameCount; + if (newprogress > _progress) { + _progress = newprogress; + Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { + AutoFlush = true + }); + Console.Write("\rProgress: {0}% - {1} frames", newprogress, _FrameCount); + Console.SetOut(TextWriter.Null); + } + } + } + private static readonly int _FrameHeight = 2000; + private static readonly int _FrameWidth = 3000; + private readonly double _yScale = 1; + private readonly double _xScale = 1; + private readonly int _BarWidth = 1; + private int _FrameCount = 0; + private string _sortingAlgorithm = "DefaultAlgorithm"; + + private void DrawFrame() { + this.ClearFrame(); + } + + private void ClearFrame() { + DrawRect(0, 0, _FrameWidth, _FrameHeight, ref this.BackgroundBrush); + } + + private void DrawRect(int x1, int y1, int w, int h, ref Brush brush) { + int wn = w - 1; + if (wn <= 0) + wn = 1; + int hn = h - 1; + if (hn <= 0) + hn = 1; + using (var graphics = Graphics.FromImage(_Frame)) { + graphics.FillRectangle(brush, x1, y1, wn, hn); + } + } + + private void DrawCompareFrame(int left, int right) { + if (this.SimulateMode) { + this.FrameCount++; + } else { + if (this.SkipFrame()) + return; + DrawFrame(); + for (int i = 0; i < this.Size; i++) { + int xpos = (int)(_xScale * i); + int ypos = (int)(_yScale * this._Data[i]); + if (i == left || i == right) + DrawRect(xpos, _FrameHeight - ypos, _BarWidth, ypos, ref this.CompareColor); + else + DrawRect(xpos, _FrameHeight - ypos, _BarWidth, ypos, ref this.BarColor); + } + ++this.FrameCount; + //Console.WriteLine("Compare frame {0} was drawn",this.FrameCount); + } + } + + private void DrawReadFrame(int index) { + DataSet dataSet = this; + if (dataSet.SimulateMode) { + this.FrameCount++; + } else { + if (this.SkipFrame()) + return; + DrawFrame(); + for (int i = 0; i < this.Size; i++) { + int xpos = (int)(_xScale * i); + int ypos = (int)(_yScale * this._Data[i]); + if (i == index) + DrawRect(xpos, _FrameHeight - ypos, _BarWidth, ypos, ref this.ReadColor); + else + DrawRect(xpos, _FrameHeight - ypos, _BarWidth, ypos, ref this.BarColor); + } + ++this.FrameCount; + //Console.WriteLine("Read frame {0} was drawn", this.FrameCount); + } + } + + private void DrawWriteFrame(int index) { + if (this.SimulateMode) { + this.FrameCount++; + } else { + if (this.SkipFrame()) + return; + DrawFrame(); + for (int i = 0; i < this.Size; i++) { + int xpos = (int)(_xScale * i); + int ypos = (int)(_yScale * this._Data[i]); + if (i == index) + DrawRect(xpos, _FrameHeight - ypos, _BarWidth, ypos, ref this.WriteColor); + else + DrawRect(xpos, _FrameHeight - ypos, _BarWidth, ypos, ref this.BarColor); + } + ++this.FrameCount; + //Console.WriteLine("Write frame {0} was drawn", this.FrameCount); + } + } + + private void DrawSwapFrame(int left, int right) { + if (this.SimulateMode) { + this.FrameCount++; + } else { + if (this.SkipFrame()) + return; + DrawFrame(); + for (int i = 0; i < this.Size; i++) { + int xpos = (int)(_xScale * i); + int ypos = (int)(_yScale * this._Data[i]); + if (i == left || i == right) + DrawRect(xpos, _FrameHeight - ypos, _BarWidth, ypos, ref this.SwapColor); + else + DrawRect(xpos, _FrameHeight - ypos, _BarWidth, ypos, ref this.BarColor); + } + ++this.FrameCount; + //Console.WriteLine("Swap frame {0} was drawn", this.FrameCount); + } + } + + private bool SkipFrame() { + if (_skippedFrames++ < _frameSkipping) { + ++this._FrameCount; // Avoid automatic drawing trough property + return true; + } else { + _skippedFrames = 0; + return false; + } + } + + public void FinalizeVideo() { + Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { + AutoFlush = true + }); + Console.WriteLine("\n\nFinalizing..."); + for (int i = 0; i < this.Size; i++) { + int xpos = (int)(_xScale * i); + int ypos = (int)(_yScale * this._Data[i]); + DrawRect(xpos, _FrameHeight - ypos, _BarWidth, ypos, ref this.BarColor); + } + //if (!this.SkipFrame()) + ++this.FrameCount; + //Console.WriteLine("Finalizing Frame {0} was drawn", this.FrameCount); + for (int d = 0; d < this.Size; d++) { // Add 1 checked bar per frame + int xpos = (int)(_xScale * d); + int ypos = (int)(_yScale * this._Data[d]); + DrawRect(xpos, _FrameHeight - ypos, _BarWidth, ypos, ref this.CheckColor); + //if (this.SkipFrame()) + // continue; + ++this.FrameCount; + //Console.WriteLine("Finalizing Frame {0} was drawn", this.FrameCount); + } + Console.WriteLine("Encoding video from frames..."); + //var startInfo = new System.Diagnostics.ProcessStartInfo { + // WorkingDirectory = _Directory, + // WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal, + // FileName = "ffmpeg.exe", + // Arguments = $"-r 60 -f image2 -s {_FrameWidth}x{_FrameHeight} -i Image%06d.png -vcodec libx264 -crf 25 -pix_fmt yuv420p {this.SortingAlgorithm}.mp4", + // RedirectStandardInput = true, + // UseShellExecute = false, + // RedirectStandardOutput = true, + // CreateNoWindow = false + //}; + //Process.Start(startInfo); + VideoRenderer.Close(); + VideoRenderer.Dispose(); + VideoRenderer = null; + VideoRenderer = new VideoFileWriter(); + Console.WriteLine("Video encoded!"); + } + #endregion + #region Resetting + public void ResetToInitial() { + _Data = null; + _Data = new int[this.Size]; + _InitialData.CopyTo(_Data, 0); + _Frame?.Dispose(); + _Frame = null; + _Frame = new Bitmap(_FrameWidth, _FrameHeight); + this.ReadOperations = 0; + this.WriteOperations = 0; + this.CompareOperations = 0; + this.Ticks = 0; + this.FrameCount = 0; + this._progress = 0; + this._skippedFrames = 0; + } + #endregion + } +} diff --git a/SortingVisualization/Program.cs b/SortingVisualization/Program.cs new file mode 100644 index 0000000..a3ae556 --- /dev/null +++ b/SortingVisualization/Program.cs @@ -0,0 +1,96 @@ +using SortingVisualization.Algorithms; +using System; + +namespace SortingVisualization { + class Program { + static void Main(string[] args) { + SortingAlgorithm sort; + Console.WriteLine("Select an algorithm:\n\t1. Bubblesort\n\t2. Insertion Sort\n\t3. Selection Sort\n\t4. Quicksort\n\t5. Radixsort\n\t6. Shell Sort\n\t7. Mergesort\n\t8. Heapsort\n\t9. Cocktailshakersort\n\t10. Gravitysort"); + string input; + + int SetSize = 20; + int selection; + do { input = Console.ReadLine(); } + while (!int.TryParse(input, out selection)); + switch (selection) { + case 1: + sort = new Bubblesort(); + break; + case 2: + sort = new Insertionsort(); + break; + case 3: + sort = new Selectionsort(); + break; + case 4: + sort = new Quicksort(); + break; + case 5: + sort = new Radixsort(); + break; + case 7: + sort = new Mergesort(); + break; + case 9: + sort = new Cocktailshakersort(); + break; + case 10: + sort = new Gravitysort(); + break; + default: + Console.WriteLine("Not Implemented or invalid selection!"); + return; + } + Console.WriteLine("Select the set Size:"); + do { + input = Console.ReadLine(); + } while (!int.TryParse(input, out SetSize)); + Console.WriteLine("Select a set:\n\t1. Random\n\t2. Ordered\n\t3. Reversed\n\t4. Single Error"); + do { input = Console.ReadLine(); } + while (!int.TryParse(input, out selection)); + SetType type; + switch (selection) { + case 1: + type = SetType.Random; + break; + case 2: + type = SetType.Ordererd; + break; + case 3: + type = SetType.Reversed; + break; + case 4: + type = SetType.SingleError; + break; + default: + Console.WriteLine("Not Implemented or invalid selection!"); + return; + } + DataSet set; + if (type == SetType.Random || type == SetType.SingleError) { + Console.WriteLine("Do you want to enter a seed? (y/n)"); + ConsoleKeyInfo key; + do { + int seed; + key = Console.ReadKey(true); + if (key.Key == ConsoleKey.Y) { + Console.WriteLine("Enter a seed: "); + do { + input = Console.ReadLine(); + } while (!int.TryParse(input, out seed)); + set = new DataSet(SetSize, type, seed); + break; + } + if (key.Key == ConsoleKey.N) { + Console.WriteLine("Generating with random seed..."); + set = new DataSet(SetSize, type); + break; + } + } while (true); + } else { + set = new DataSet(SetSize, type); + } + sort.Sort(ref set); + } + } +} diff --git a/SortingVisualization/Properties/AssemblyInfo.cs b/SortingVisualization/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f6dd6b1 --- /dev/null +++ b/SortingVisualization/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die einer Assembly zugeordnet sind. +[assembly: AssemblyTitle("SortingVisualization")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SortingVisualization")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly +// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("3ced6adb-adb8-499e-8a0e-6db4b064f514")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +// übernehmen, indem Sie "*" eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SortingVisualization/SortingAlgorithm.cs b/SortingVisualization/SortingAlgorithm.cs new file mode 100644 index 0000000..356d635 --- /dev/null +++ b/SortingVisualization/SortingAlgorithm.cs @@ -0,0 +1,14 @@ +namespace SortingVisualization { + public abstract class SortingAlgorithm { + public abstract void Sort(ref DataSet set); + public abstract string GetAlgorithmName(); + public void Simulate(ref DataSet set) { + if (!set.SimulateMode) { + set.SimulateMode = true; + Sort(ref set); + set.SimulateMode = false; + set.SortingAlgorithm = this.GetAlgorithmName(); + } + } + } +} diff --git a/SortingVisualization/SortingVisualization.csproj b/SortingVisualization/SortingVisualization.csproj new file mode 100644 index 0000000..169944d --- /dev/null +++ b/SortingVisualization/SortingVisualization.csproj @@ -0,0 +1,84 @@ + + + + + Debug + AnyCPU + {3CED6ADB-ADB8-499E-8A0E-6DB4B064F514} + Exe + SortingVisualization + SortingVisualization + v4.6.1 + 512 + true + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Accord.3.8.0\lib\net46\Accord.dll + + + ..\packages\Accord.Video.3.8.0\lib\net46\Accord.Video.dll + + + ..\packages\Accord.Video.FFMPEG.3.8.0\lib\net46\Accord.Video.FFMPEG.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". + + + + + + \ No newline at end of file diff --git a/SortingVisualization/packages.config b/SortingVisualization/packages.config new file mode 100644 index 0000000..3537728 --- /dev/null +++ b/SortingVisualization/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file