├── .gitignore ├── LICENSE ├── README.md ├── Sources ├── Daviburg.Utilities │ ├── Daviburg.FixToXmlCharacters │ │ ├── .gitignore │ │ ├── CorrectedXmlFile.xml │ │ ├── Daviburg.FixToXmlCharacters.csproj │ │ ├── InvalidXmlFile.xml │ │ ├── SampleInput.json │ │ ├── SampleOutput.Json │ │ ├── XmlCharacters.cs │ │ └── host.json │ ├── Daviburg.Recode │ │ ├── .gitignore │ │ ├── Daviburg.Recode.csproj │ │ ├── RecodeFunction.cs │ │ └── host.json │ ├── Daviburg.Utilities.sln │ ├── Daviburg.Utilities │ │ ├── CharExtensions.cs │ │ ├── CoPrime.cs │ │ ├── Composite.cs │ │ ├── ConcurrentLockDictionary.cs │ │ ├── Daviburg.Utilities.csproj │ │ ├── EncodedStringWriter.cs │ │ ├── Factorials.cs │ │ ├── Fibonacci.cs │ │ ├── Graphs │ │ │ └── DirectedGraphNode.cs │ │ ├── HighComposite.cs │ │ ├── HighComposites.cs │ │ ├── IEnumerableExtensions.cs │ │ ├── IntExtensions.cs │ │ ├── IntegerPower.cs │ │ ├── IntegerPowerValueComparer.cs │ │ ├── MathAlgorithms.cs │ │ ├── Power.cs │ │ ├── PowerDigits.cs │ │ ├── PrimeFactor.cs │ │ ├── Primes.cs │ │ ├── PythagoreanTriple.cs │ │ ├── ReferencedLock.cs │ │ ├── StringExtensions.cs │ │ ├── Trees │ │ │ └── TreeNode.cs │ │ ├── Triangular.cs │ │ ├── UtilitiesEventIds.cs │ │ ├── UtilitiesEventSource.cs │ │ └── longExtensions.cs │ └── Daviburg.Utilities2.Tests │ │ ├── BinaryDirectedAcyclicGraphTests.cs │ │ ├── Daviburg.Utilities2.Tests.csproj │ │ ├── IntExtensions2Tests.cs │ │ ├── MathAlgorithms2Tests.cs │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ ├── SmallIntSeriesTests.cs │ │ ├── TestData │ │ ├── p018_triangle.txt │ │ └── p067_triangle.txt │ │ ├── XmlSchemaExtensionsTests.cs │ │ └── packages.config └── Daviburg.Utilities2 │ └── ClassLibrary1 │ ├── AutoResizeArray.cs │ ├── Daviburg.Utilities2.csproj │ ├── ExceptionExtensions.cs │ ├── Graphs │ └── BinaryDirectedAcyclicGraphNode.cs │ ├── IntExtensions2.cs │ ├── MathAlgorithms2.cs │ ├── SmallIntGrid.cs │ ├── SmallIntSeries.cs │ ├── Trees │ └── BinaryTreeNode.cs │ └── XmlSchemaExtensions.cs └── Tests └── Daviburg.Utilities.Tests ├── CoPrimeTests.cs ├── ConcurrentLockDictionaryTests.cs ├── Daviburg.Utilities.Tests.csproj ├── EventRecordingForUtilities.cs ├── FibonacciTests.cs ├── HighCompositesTests.cs ├── IntExtensionsTests.cs ├── LongExtensionsTests.cs ├── MathAlgorithmsTests.cs ├── PrimesTests.cs ├── Properties └── AssemblyInfo.cs ├── PythagoreanTripleTests.cs ├── TestData └── p022_names.txt ├── TestEventListener.cs ├── app.config └── packages.config /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | 56 | # StyleCop 57 | StyleCopReport.xml 58 | 59 | # Files built by Visual Studio 60 | *_i.c 61 | *_p.c 62 | *_i.h 63 | *.ilk 64 | *.meta 65 | *.obj 66 | *.iobj 67 | *.pch 68 | *.pdb 69 | *.ipdb 70 | *.pgc 71 | *.pgd 72 | *.rsp 73 | *.sbr 74 | *.tlb 75 | *.tli 76 | *.tlh 77 | *.tmp 78 | *.tmp_proj 79 | *.log 80 | *.vspscc 81 | *.vssscc 82 | .builds 83 | *.pidb 84 | *.svclog 85 | *.scc 86 | 87 | # Chutzpah Test files 88 | _Chutzpah* 89 | 90 | # Visual C++ cache files 91 | ipch/ 92 | *.aps 93 | *.ncb 94 | *.opendb 95 | *.opensdf 96 | *.sdf 97 | *.cachefile 98 | *.VC.db 99 | *.VC.VC.opendb 100 | 101 | # Visual Studio profiler 102 | *.psess 103 | *.vsp 104 | *.vspx 105 | *.sap 106 | 107 | # Visual Studio Trace Files 108 | *.e2e 109 | 110 | # TFS 2012 Local Workspace 111 | $tf/ 112 | 113 | # Guidance Automation Toolkit 114 | *.gpState 115 | 116 | # ReSharper is a .NET coding add-in 117 | _ReSharper*/ 118 | *.[Rr]e[Ss]harper 119 | *.DotSettings.user 120 | 121 | # JustCode is a .NET coding add-in 122 | .JustCode 123 | 124 | # TeamCity is a build add-in 125 | _TeamCity* 126 | 127 | # DotCover is a Code Coverage Tool 128 | *.dotCover 129 | 130 | # AxoCover is a Code Coverage Tool 131 | .axoCover/* 132 | !.axoCover/settings.json 133 | 134 | # Visual Studio code coverage results 135 | *.coverage 136 | *.coveragexml 137 | 138 | # NCrunch 139 | _NCrunch_* 140 | .*crunch*.local.xml 141 | nCrunchTemp_* 142 | 143 | # MightyMoose 144 | *.mm.* 145 | AutoTest.Net/ 146 | 147 | # Web workbench (sass) 148 | .sass-cache/ 149 | 150 | # Installshield output folder 151 | [Ee]xpress/ 152 | 153 | # DocProject is a documentation generator add-in 154 | DocProject/buildhelp/ 155 | DocProject/Help/*.HxT 156 | DocProject/Help/*.HxC 157 | DocProject/Help/*.hhc 158 | DocProject/Help/*.hhk 159 | DocProject/Help/*.hhp 160 | DocProject/Help/Html2 161 | DocProject/Help/html 162 | 163 | # Click-Once directory 164 | publish/ 165 | 166 | # Publish Web Output 167 | *.[Pp]ublish.xml 168 | *.azurePubxml 169 | # Note: Comment the next line if you want to checkin your web deploy settings, 170 | # but database connection strings (with potential passwords) will be unencrypted 171 | *.pubxml 172 | *.publishproj 173 | 174 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 175 | # checkin your Azure Web App publish settings, but sensitive information contained 176 | # in these scripts will be unencrypted 177 | PublishScripts/ 178 | 179 | # NuGet Packages 180 | *.nupkg 181 | # The packages folder can be ignored because of Package Restore 182 | **/[Pp]ackages/* 183 | # except build/, which is used as an MSBuild target. 184 | !**/[Pp]ackages/build/ 185 | # Uncomment if necessary however generally it will be regenerated when needed 186 | #!**/[Pp]ackages/repositories.config 187 | # NuGet v3's project.json files produces more ignorable files 188 | *.nuget.props 189 | *.nuget.targets 190 | 191 | # Microsoft Azure Build Output 192 | csx/ 193 | *.build.csdef 194 | 195 | # Microsoft Azure Emulator 196 | ecf/ 197 | rcf/ 198 | 199 | # Windows Store app package directories and files 200 | AppPackages/ 201 | BundleArtifacts/ 202 | Package.StoreAssociation.xml 203 | _pkginfo.txt 204 | *.appx 205 | 206 | # Visual Studio cache files 207 | # files ending in .cache can be ignored 208 | *.[Cc]ache 209 | # but keep track of directories ending in .cache 210 | !*.[Cc]ache/ 211 | 212 | # Others 213 | ClientBin/ 214 | ~$* 215 | *~ 216 | *.dbmdl 217 | *.dbproj.schemaview 218 | *.jfm 219 | *.pfx 220 | *.publishsettings 221 | orleans.codegen.cs 222 | 223 | # Including strong name files can present a security risk 224 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 225 | #*.snk 226 | 227 | # Since there are multiple workflows, uncomment next line to ignore bower_components 228 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 229 | #bower_components/ 230 | 231 | # RIA/Silverlight projects 232 | Generated_Code/ 233 | 234 | # Backup & report files from converting an old project file 235 | # to a newer Visual Studio version. Backup files are not needed, 236 | # because we have git ;-) 237 | _UpgradeReport_Files/ 238 | Backup*/ 239 | UpgradeLog*.XML 240 | UpgradeLog*.htm 241 | ServiceFabricBackup/ 242 | *.rptproj.bak 243 | 244 | # SQL Server files 245 | *.mdf 246 | *.ldf 247 | *.ndf 248 | 249 | # Business Intelligence projects 250 | *.rdl.data 251 | *.bim.layout 252 | *.bim_*.settings 253 | *.rptproj.rsuser 254 | 255 | # Microsoft Fakes 256 | FakesAssemblies/ 257 | 258 | # GhostDoc plugin setting file 259 | *.GhostDoc.xml 260 | 261 | # Node.js Tools for Visual Studio 262 | .ntvs_analysis.dat 263 | node_modules/ 264 | 265 | # Visual Studio 6 build log 266 | *.plg 267 | 268 | # Visual Studio 6 workspace options file 269 | *.opt 270 | 271 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 272 | *.vbw 273 | 274 | # Visual Studio LightSwitch build output 275 | **/*.HTMLClient/GeneratedArtifacts 276 | **/*.DesktopClient/GeneratedArtifacts 277 | **/*.DesktopClient/ModelManifest.xml 278 | **/*.Server/GeneratedArtifacts 279 | **/*.Server/ModelManifest.xml 280 | _Pvt_Extensions 281 | 282 | # Paket dependency manager 283 | .paket/paket.exe 284 | paket-files/ 285 | 286 | # FAKE - F# Make 287 | .fake/ 288 | 289 | # JetBrains Rider 290 | .idea/ 291 | *.sln.iml 292 | 293 | # CodeRush 294 | .cr/ 295 | 296 | # Python Tools for Visual Studio (PTVS) 297 | __pycache__/ 298 | *.pyc 299 | 300 | # Cake - Uncomment if you are using it 301 | # tools/** 302 | # !tools/packages.config 303 | 304 | # Tabs Studio 305 | *.tss 306 | 307 | # Telerik's JustMock configuration file 308 | *.jmconfig 309 | 310 | # BizTalk build output 311 | *.btp.cs 312 | *.btm.cs 313 | *.odx.cs 314 | *.xsd.cs 315 | 316 | # OpenCover UI analysis results 317 | OpenCover/ 318 | 319 | # Azure Stream Analytics local run output 320 | ASALocalRun/ 321 | 322 | # MSBuild Binary and Structured Log 323 | *.binlog 324 | 325 | # NVidia Nsight GPU debugger configuration file 326 | *.nvuser 327 | 328 | # MFractors (Xamarin productivity tool) working folder 329 | .mfractor/ 330 | 331 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSharpUtilities 2 | 3 | Utilities for C#. 4 | 5 | The utilities assembly targets .NET Standard 1.1 for maximum re-usability accross platforms. 6 | 7 | The test project for the assembly is based on Visual Studio Unit Tests, targeting .NET Framework 4.6 because it leverages functionalities only added then. A lower .NET Framework version (4.5) could be used for projects taking a dependency on the utilities provided per the chart published at https://docs.microsoft.com/en-us/dotnet/standard/net-standard 8 | 9 | Initially the utilities contain only one main class, a concurrent (thread-safe) dictionary for lock objects. The referenced lock class is used by the dictionary to keep track of reference count on the lock entries. 10 | A secondary class and enum provide ETW tracing based on .NET EventSource. While used by the concurrent lock dictionary, they are generic and could be used idenpendently and for other utilities. They illustrate several tricks for the implementation of an event source, including lazy-initialized singleton pattern, enum-declared event ids, region-grouping of event-class. 11 | 12 | I came up with the concurrent lock dictionary while working on clean-up of connections to line of business application servers, and I didn't find any pre-existing (open-source) art in the matter. Do share any issue, bug or improvement you see with the code. I am using these as part of some Azure services at Microsoft and would be happy to correct any problem. 13 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.FixToXmlCharacters/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # Azure Functions localsettings file 5 | local.settings.json 6 | 7 | # User-specific files 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | [Ll]og/ 27 | 28 | # Visual Studio 2015 cache/options directory 29 | .vs/ 30 | # Uncomment if you have tasks that create the project's static files in wwwroot 31 | #wwwroot/ 32 | 33 | # MSTest test Results 34 | [Tt]est[Rr]esult*/ 35 | [Bb]uild[Ll]og.* 36 | 37 | # NUNIT 38 | *.VisualState.xml 39 | TestResult.xml 40 | 41 | # Build Results of an ATL Project 42 | [Dd]ebugPS/ 43 | [Rr]eleasePS/ 44 | dlldata.c 45 | 46 | # DNX 47 | project.lock.json 48 | project.fragment.lock.json 49 | artifacts/ 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # NCrunch 117 | _NCrunch_* 118 | .*crunch*.local.xml 119 | nCrunchTemp_* 120 | 121 | # MightyMoose 122 | *.mm.* 123 | AutoTest.Net/ 124 | 125 | # Web workbench (sass) 126 | .sass-cache/ 127 | 128 | # Installshield output folder 129 | [Ee]xpress/ 130 | 131 | # DocProject is a documentation generator add-in 132 | DocProject/buildhelp/ 133 | DocProject/Help/*.HxT 134 | DocProject/Help/*.HxC 135 | DocProject/Help/*.hhc 136 | DocProject/Help/*.hhk 137 | DocProject/Help/*.hhp 138 | DocProject/Help/Html2 139 | DocProject/Help/html 140 | 141 | # Click-Once directory 142 | publish/ 143 | 144 | # Publish Web Output 145 | *.[Pp]ublish.xml 146 | *.azurePubxml 147 | # TODO: Comment the next line if you want to checkin your web deploy settings 148 | # but database connection strings (with potential passwords) will be unencrypted 149 | #*.pubxml 150 | *.publishproj 151 | 152 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 153 | # checkin your Azure Web App publish settings, but sensitive information contained 154 | # in these scripts will be unencrypted 155 | PublishScripts/ 156 | 157 | # NuGet Packages 158 | *.nupkg 159 | # The packages folder can be ignored because of Package Restore 160 | **/packages/* 161 | # except build/, which is used as an MSBuild target. 162 | !**/packages/build/ 163 | # Uncomment if necessary however generally it will be regenerated when needed 164 | #!**/packages/repositories.config 165 | # NuGet v3's project.json files produces more ignoreable files 166 | *.nuget.props 167 | *.nuget.targets 168 | 169 | # Microsoft Azure Build Output 170 | csx/ 171 | *.build.csdef 172 | 173 | # Microsoft Azure Emulator 174 | ecf/ 175 | rcf/ 176 | 177 | # Windows Store app package directories and files 178 | AppPackages/ 179 | BundleArtifacts/ 180 | Package.StoreAssociation.xml 181 | _pkginfo.txt 182 | 183 | # Visual Studio cache files 184 | # files ending in .cache can be ignored 185 | *.[Cc]ache 186 | # but keep track of directories ending in .cache 187 | !*.[Cc]ache/ 188 | 189 | # Others 190 | ClientBin/ 191 | ~$* 192 | *~ 193 | *.dbmdl 194 | *.dbproj.schemaview 195 | *.jfm 196 | *.pfx 197 | *.publishsettings 198 | node_modules/ 199 | orleans.codegen.cs 200 | 201 | # Since there are multiple workflows, uncomment next line to ignore bower_components 202 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 203 | #bower_components/ 204 | 205 | # RIA/Silverlight projects 206 | Generated_Code/ 207 | 208 | # Backup & report files from converting an old project file 209 | # to a newer Visual Studio version. Backup files are not needed, 210 | # because we have git ;-) 211 | _UpgradeReport_Files/ 212 | Backup*/ 213 | UpgradeLog*.XML 214 | UpgradeLog*.htm 215 | 216 | # SQL Server files 217 | *.mdf 218 | *.ldf 219 | 220 | # Business Intelligence projects 221 | *.rdl.data 222 | *.bim.layout 223 | *.bim_*.settings 224 | 225 | # Microsoft Fakes 226 | FakesAssemblies/ 227 | 228 | # GhostDoc plugin setting file 229 | *.GhostDoc.xml 230 | 231 | # Node.js Tools for Visual Studio 232 | .ntvs_analysis.dat 233 | 234 | # Visual Studio 6 build log 235 | *.plg 236 | 237 | # Visual Studio 6 workspace options file 238 | *.opt 239 | 240 | # Visual Studio LightSwitch build output 241 | **/*.HTMLClient/GeneratedArtifacts 242 | **/*.DesktopClient/GeneratedArtifacts 243 | **/*.DesktopClient/ModelManifest.xml 244 | **/*.Server/GeneratedArtifacts 245 | **/*.Server/ModelManifest.xml 246 | _Pvt_Extensions 247 | 248 | # Paket dependency manager 249 | .paket/paket.exe 250 | paket-files/ 251 | 252 | # FAKE - F# Make 253 | .fake/ 254 | 255 | # JetBrains Rider 256 | .idea/ 257 | *.sln.iml 258 | 259 | # CodeRush 260 | .cr/ 261 | 262 | # Python Tools for Visual Studio (PTVS) 263 | __pycache__/ 264 | *.pyc -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.FixToXmlCharacters/CorrectedXmlFile.xml: -------------------------------------------------------------------------------- 1 |  2 | Not a printable character in between thisandthat. 3 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.FixToXmlCharacters/Daviburg.FixToXmlCharacters.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | v2 5 | 6 | 7 | 8 | 9 | 10 | 11 | PreserveNewest 12 | 13 | 14 | PreserveNewest 15 | Never 16 | 17 | 18 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.FixToXmlCharacters/InvalidXmlFile.xml: -------------------------------------------------------------------------------- 1 |  2 | Not a printable character in between thisandthat. 3 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.FixToXmlCharacters/SampleInput.json: -------------------------------------------------------------------------------- 1 | { 2 | "text": "77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+DQo8cm9vdD5Ob3QgYSBwcmludGFibGUgY2hhcmFjdGVyIGluIGJldHdlZW4gdGhpcw9hbmQPdGhhdC48L3Jvb3Q+DQo=" 3 | } -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.FixToXmlCharacters/SampleOutput.Json: -------------------------------------------------------------------------------- 1 | { 2 | "text": "77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+DQo8cm9vdD5Ob3QgYSBwcmludGFibGUgY2hhcmFjdGVyIGluIGJldHdlZW4gdGhpcyYjeDAwMEY7YW5kJiN4MDAwRjt0aGF0Ljwvcm9vdD4NCg==" 3 | } -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.FixToXmlCharacters/XmlCharacters.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.FixToXmlCharacters 21 | { 22 | using System; 23 | using System.IO; 24 | using System.Linq; 25 | using System.Text; 26 | using System.Xml; 27 | using Microsoft.AspNetCore.Mvc; 28 | using Microsoft.Azure.WebJobs; 29 | using Microsoft.Azure.WebJobs.Extensions.Http; 30 | using Microsoft.AspNetCore.Http; 31 | using Microsoft.Extensions.Logging; 32 | using Newtonsoft.Json; 33 | 34 | public static class XmlCharacters 35 | { 36 | [FunctionName("FixCharacters")] 37 | public static IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]HttpRequest req, ILogger log) 38 | { 39 | log.LogInformation("C# HTTP trigger function processing a request."); 40 | 41 | string requestBody = new StreamReader(req.Body).ReadToEnd(); 42 | dynamic data = JsonConvert.DeserializeObject(requestBody); 43 | 44 | // Consider adding || data.escapeStyle == null later 45 | if (data == null || data.text == null) 46 | { 47 | return new BadRequestObjectResult("Please pass text properties in the input Json object."); 48 | } 49 | 50 | /* Consider adding optional behaviors with different escape styles 51 | switch (data.escapeStyle) 52 | { 53 | case "": 54 | break; 55 | default: 56 | return new BadRequestObjectResult("escapeStyle value not recognized."); 57 | }*/ 58 | 59 | // See reference https://www.w3.org/TR/xml11/#sec-normalization-checking 60 | // XML 1.1 "All XML parsed entities (including document entities) should be fully normalized[...]" 61 | // See reference https://www.w3.org/TR/xml11/#sec-references 62 | // for hexadecimal character reference format '&#x' [0-9a-fA-F]+ ';' 63 | // See reference https://docs.microsoft.com/en-us/dotnet/api/system.char.maxvalue?view=netframework-4.7.2 64 | // for hexadecimal maximum length of char (0xFFFF) hence 4 digits representation and not just the 2 of the W3C examples. 65 | return (ActionResult)new JsonResult( 66 | value: new 67 | { 68 | text = Convert.ToBase64String( 69 | inArray: Encoding.UTF8.GetBytes( 70 | s: new string( 71 | value: ((string)Encoding.UTF8.GetString(Convert.FromBase64String((string)data.text))) 72 | .Normalize() 73 | .SelectMany(character => XmlConvert.IsXmlChar(character) ? new[] { character } : $"&#x{Convert.ToInt32(character):X4};".ToArray()) 74 | .ToArray()))) 75 | }); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.FixToXmlCharacters/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0" 3 | } -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Recode/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # Azure Functions localsettings file 5 | local.settings.json 6 | 7 | # User-specific files 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | [Ll]og/ 27 | 28 | # Visual Studio 2015 cache/options directory 29 | .vs/ 30 | # Uncomment if you have tasks that create the project's static files in wwwroot 31 | #wwwroot/ 32 | 33 | # MSTest test Results 34 | [Tt]est[Rr]esult*/ 35 | [Bb]uild[Ll]og.* 36 | 37 | # NUNIT 38 | *.VisualState.xml 39 | TestResult.xml 40 | 41 | # Build Results of an ATL Project 42 | [Dd]ebugPS/ 43 | [Rr]eleasePS/ 44 | dlldata.c 45 | 46 | # DNX 47 | project.lock.json 48 | project.fragment.lock.json 49 | artifacts/ 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # NCrunch 117 | _NCrunch_* 118 | .*crunch*.local.xml 119 | nCrunchTemp_* 120 | 121 | # MightyMoose 122 | *.mm.* 123 | AutoTest.Net/ 124 | 125 | # Web workbench (sass) 126 | .sass-cache/ 127 | 128 | # Installshield output folder 129 | [Ee]xpress/ 130 | 131 | # DocProject is a documentation generator add-in 132 | DocProject/buildhelp/ 133 | DocProject/Help/*.HxT 134 | DocProject/Help/*.HxC 135 | DocProject/Help/*.hhc 136 | DocProject/Help/*.hhk 137 | DocProject/Help/*.hhp 138 | DocProject/Help/Html2 139 | DocProject/Help/html 140 | 141 | # Click-Once directory 142 | publish/ 143 | 144 | # Publish Web Output 145 | *.[Pp]ublish.xml 146 | *.azurePubxml 147 | # TODO: Comment the next line if you want to checkin your web deploy settings 148 | # but database connection strings (with potential passwords) will be unencrypted 149 | #*.pubxml 150 | *.publishproj 151 | 152 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 153 | # checkin your Azure Web App publish settings, but sensitive information contained 154 | # in these scripts will be unencrypted 155 | PublishScripts/ 156 | 157 | # NuGet Packages 158 | *.nupkg 159 | # The packages folder can be ignored because of Package Restore 160 | **/packages/* 161 | # except build/, which is used as an MSBuild target. 162 | !**/packages/build/ 163 | # Uncomment if necessary however generally it will be regenerated when needed 164 | #!**/packages/repositories.config 165 | # NuGet v3's project.json files produces more ignoreable files 166 | *.nuget.props 167 | *.nuget.targets 168 | 169 | # Microsoft Azure Build Output 170 | csx/ 171 | *.build.csdef 172 | 173 | # Microsoft Azure Emulator 174 | ecf/ 175 | rcf/ 176 | 177 | # Windows Store app package directories and files 178 | AppPackages/ 179 | BundleArtifacts/ 180 | Package.StoreAssociation.xml 181 | _pkginfo.txt 182 | 183 | # Visual Studio cache files 184 | # files ending in .cache can be ignored 185 | *.[Cc]ache 186 | # but keep track of directories ending in .cache 187 | !*.[Cc]ache/ 188 | 189 | # Others 190 | ClientBin/ 191 | ~$* 192 | *~ 193 | *.dbmdl 194 | *.dbproj.schemaview 195 | *.jfm 196 | *.pfx 197 | *.publishsettings 198 | node_modules/ 199 | orleans.codegen.cs 200 | 201 | # Since there are multiple workflows, uncomment next line to ignore bower_components 202 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 203 | #bower_components/ 204 | 205 | # RIA/Silverlight projects 206 | Generated_Code/ 207 | 208 | # Backup & report files from converting an old project file 209 | # to a newer Visual Studio version. Backup files are not needed, 210 | # because we have git ;-) 211 | _UpgradeReport_Files/ 212 | Backup*/ 213 | UpgradeLog*.XML 214 | UpgradeLog*.htm 215 | 216 | # SQL Server files 217 | *.mdf 218 | *.ldf 219 | 220 | # Business Intelligence projects 221 | *.rdl.data 222 | *.bim.layout 223 | *.bim_*.settings 224 | 225 | # Microsoft Fakes 226 | FakesAssemblies/ 227 | 228 | # GhostDoc plugin setting file 229 | *.GhostDoc.xml 230 | 231 | # Node.js Tools for Visual Studio 232 | .ntvs_analysis.dat 233 | 234 | # Visual Studio 6 build log 235 | *.plg 236 | 237 | # Visual Studio 6 workspace options file 238 | *.opt 239 | 240 | # Visual Studio LightSwitch build output 241 | **/*.HTMLClient/GeneratedArtifacts 242 | **/*.DesktopClient/GeneratedArtifacts 243 | **/*.DesktopClient/ModelManifest.xml 244 | **/*.Server/GeneratedArtifacts 245 | **/*.Server/ModelManifest.xml 246 | _Pvt_Extensions 247 | 248 | # Paket dependency manager 249 | .paket/paket.exe 250 | paket-files/ 251 | 252 | # FAKE - F# Make 253 | .fake/ 254 | 255 | # JetBrains Rider 256 | .idea/ 257 | *.sln.iml 258 | 259 | # CodeRush 260 | .cr/ 261 | 262 | # Python Tools for Visual Studio (PTVS) 263 | __pycache__/ 264 | *.pyc -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Recode/Daviburg.Recode.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | v2 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | PreserveNewest 13 | 14 | 15 | PreserveNewest 16 | Never 17 | 18 | 19 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Recode/RecodeFunction.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Recode 21 | { 22 | using System; 23 | using System.IO; 24 | using System.Text; 25 | using Microsoft.AspNetCore.Mvc; 26 | using Microsoft.Azure.WebJobs; 27 | using Microsoft.Azure.WebJobs.Extensions.Http; 28 | using Microsoft.AspNetCore.Http; 29 | using Microsoft.Azure.WebJobs.Host; 30 | using Newtonsoft.Json; 31 | 32 | public static class RecodeFunction 33 | { 34 | [FunctionName("RecodeFunction")] 35 | public static IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]HttpRequest req, TraceWriter log) 36 | { 37 | log.Info("C# HTTP trigger function processing a request."); 38 | 39 | Encoding inputEncoding = null; 40 | 41 | string requestBody = new StreamReader(req.Body).ReadToEnd(); 42 | dynamic data = JsonConvert.DeserializeObject(requestBody); 43 | 44 | if (data == null || data.text == null || data.encodingInput == null || data.encodingOutput == null) 45 | { 46 | return new BadRequestObjectResult("Please pass text/encodingOutput properties in the input Json object."); 47 | } 48 | 49 | Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 50 | 51 | try 52 | { 53 | string encodingInput = data.encodingInput.Value; 54 | inputEncoding = Encoding.GetEncoding(name: encodingInput); 55 | } 56 | catch (ArgumentException) 57 | { 58 | return new BadRequestObjectResult($"Input char set value '{data.encodingInput.Value}' is not supported. Supported value are listed at https://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.110).aspx."); 59 | } 60 | 61 | Encoding encodingOutput = null; 62 | try 63 | { 64 | string outputEncoding = data.encodingOutput.Value; 65 | encodingOutput = Encoding.GetEncoding(outputEncoding); 66 | } 67 | catch (ArgumentException) 68 | { 69 | return new BadRequestObjectResult($"Output char set value '{data.encodingOutput.Value}' is not supported. Supported value are listed at https://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.110).aspx."); 70 | } 71 | 72 | return (ActionResult)new JsonResult( 73 | value: new 74 | { 75 | text = Convert.ToBase64String( 76 | Encoding.Convert( 77 | srcEncoding: inputEncoding, 78 | dstEncoding: encodingOutput, 79 | bytes: Convert.FromBase64String((string)data.text))) 80 | }); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Recode/host.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27004.2010 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Daviburg.Utilities", "Daviburg.Utilities\Daviburg.Utilities.csproj", "{6F57FC32-46D2-4EA7-8CD7-B31078D74923}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Daviburg.Utilities.Tests", "..\..\Tests\Daviburg.Utilities.Tests\Daviburg.Utilities.Tests.csproj", "{020B6349-1DC7-4753-B68A-F1AE1CDF13BB}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{40E95D3B-66CD-4184-8731-6024456D2847}" 11 | ProjectSection(SolutionItems) = preProject 12 | ..\..\LICENSE = ..\..\LICENSE 13 | ..\..\README.md = ..\..\README.md 14 | EndProjectSection 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Daviburg.Utilities2", "..\Daviburg.Utilities2\ClassLibrary1\Daviburg.Utilities2.csproj", "{C3A11C8C-42A8-47C9-A2B1-70E51E937168}" 17 | EndProject 18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Daviburg.Utilities2.Tests", "Daviburg.Utilities2.Tests\Daviburg.Utilities2.Tests.csproj", "{1AC0FE91-1E21-439C-93F1-977A8D7769C2}" 19 | EndProject 20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Daviburg.Recode", "Daviburg.Recode\Daviburg.Recode.csproj", "{9BBFBF81-A026-4122-B38F-C05D3C7598BE}" 21 | EndProject 22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Daviburg.FixToXmlCharacters", "Daviburg.FixToXmlCharacters\Daviburg.FixToXmlCharacters.csproj", "{D3EFF063-EDA6-4A37-B866-497ED037917F}" 23 | EndProject 24 | Global 25 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 26 | Debug|Any CPU = Debug|Any CPU 27 | Release|Any CPU = Release|Any CPU 28 | EndGlobalSection 29 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 30 | {6F57FC32-46D2-4EA7-8CD7-B31078D74923}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {6F57FC32-46D2-4EA7-8CD7-B31078D74923}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {6F57FC32-46D2-4EA7-8CD7-B31078D74923}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {6F57FC32-46D2-4EA7-8CD7-B31078D74923}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {020B6349-1DC7-4753-B68A-F1AE1CDF13BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {020B6349-1DC7-4753-B68A-F1AE1CDF13BB}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {020B6349-1DC7-4753-B68A-F1AE1CDF13BB}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {020B6349-1DC7-4753-B68A-F1AE1CDF13BB}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {C3A11C8C-42A8-47C9-A2B1-70E51E937168}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {C3A11C8C-42A8-47C9-A2B1-70E51E937168}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {C3A11C8C-42A8-47C9-A2B1-70E51E937168}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {C3A11C8C-42A8-47C9-A2B1-70E51E937168}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {1AC0FE91-1E21-439C-93F1-977A8D7769C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {1AC0FE91-1E21-439C-93F1-977A8D7769C2}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {1AC0FE91-1E21-439C-93F1-977A8D7769C2}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {1AC0FE91-1E21-439C-93F1-977A8D7769C2}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {9BBFBF81-A026-4122-B38F-C05D3C7598BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {9BBFBF81-A026-4122-B38F-C05D3C7598BE}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {9BBFBF81-A026-4122-B38F-C05D3C7598BE}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {9BBFBF81-A026-4122-B38F-C05D3C7598BE}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {D3EFF063-EDA6-4A37-B866-497ED037917F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {D3EFF063-EDA6-4A37-B866-497ED037917F}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {D3EFF063-EDA6-4A37-B866-497ED037917F}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {D3EFF063-EDA6-4A37-B866-497ED037917F}.Release|Any CPU.Build.0 = Release|Any CPU 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | GlobalSection(NestedProjects) = preSolution 59 | {1AC0FE91-1E21-439C-93F1-977A8D7769C2} = {40E95D3B-66CD-4184-8731-6024456D2847} 60 | EndGlobalSection 61 | GlobalSection(ExtensibilityGlobals) = postSolution 62 | SolutionGuid = {5F8DBBFE-0375-4811-9234-2A34CA1B80B8} 63 | EndGlobalSection 64 | EndGlobal 65 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/CharExtensions.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | public static class CharExtensions 23 | { 24 | public static int ToInt32(this char character) => character & 0x0f; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/CoPrime.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System.Collections.Generic; 23 | 24 | /// 25 | /// Pair of integers which greatest common divisor is one. 26 | /// 27 | /// 28 | /// See also . 29 | /// This implementation is limited to positive coprimes. 30 | /// 31 | public class CoPrime 32 | { 33 | private CoPrime() 34 | { 35 | } 36 | 37 | public int IntegerA { get; private set; } 38 | 39 | public int IntegerB { get; private set; } 40 | 41 | public static CoPrime OddOddRootVertex => new CoPrime { IntegerA = 3, IntegerB = 1 }; 42 | public static CoPrime EvenOddRootVertex => new CoPrime { IntegerA = 2, IntegerB = 1 }; 43 | 44 | public List NextTriplet => 45 | new List() 46 | { 47 | new CoPrime { IntegerA = this.IntegerA * 2 - this.IntegerB, IntegerB = this.IntegerA }, 48 | new CoPrime { IntegerA = this.IntegerA * 2 + this.IntegerB, IntegerB = this.IntegerA }, 49 | new CoPrime { IntegerA = this.IntegerA + this.IntegerB * 2, IntegerB = this.IntegerB } 50 | }; 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/Composite.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System; 23 | using System.Collections.Generic; 24 | using System.Linq; 25 | 26 | public class Composite 27 | { 28 | private int? countofDivisors; 29 | private long? value; 30 | 31 | /// 32 | /// Instantiate a composite number from its value 33 | /// 34 | /// The composite number value 35 | /// 36 | /// To avoid performance overhead, this constructor does not validate that the value is not prime. 37 | /// A prime value input would not result in a valid composite number class instance. 38 | /// 39 | public Composite(long value) 40 | { 41 | this.PrimeFactors = value.BlendPrimeFactorization(); 42 | } 43 | 44 | public Composite(IReadOnlyList primeFactors) 45 | { 46 | this.PrimeFactors = primeFactors; 47 | } 48 | 49 | public IReadOnlyList PrimeFactors { get; private set; } 50 | 51 | public int CountOfDivisors => this.countofDivisors ?? 52 | (this.countofDivisors = this.PrimeFactors.Aggregate(seed: 1, func: (partialCount, primeFactor) => partialCount * (primeFactor.Exponent + 1))).Value; 53 | 54 | public long Value => this.value ?? 55 | (this.value = this.PrimeFactors.Aggregate( 56 | seed: new Tuple(0, 1), 57 | func: (indexAndPartialProduct, primeFactor) => new Tuple(indexAndPartialProduct.Item1 + 1, indexAndPartialProduct.Item2 * primeFactor.Value), 58 | resultSelector: finalIndexAndProduct => finalIndexAndProduct.Item2)) 59 | .Value; 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/ConcurrentLockDictionary.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System.Collections.Concurrent; 23 | using System.Collections.Generic; 24 | 25 | /// 26 | /// A generic class for thread-safe dictionary of lock objects. 27 | /// 28 | /// The key type. 29 | public class ConcurrentLockDictionary : ConcurrentDictionary 30 | { 31 | /// 32 | /// Acquires a reference to the lock. 33 | /// 34 | /// The key of the lock to acquire a reference to. 35 | /// The current lock and reference count. 36 | /// This does not enter the lock. To enter a lock use either lock code block or .Enter. 37 | public ReferencedLock Acquire(TKey key) 38 | { 39 | var currentReferencedLock = this.AddOrUpdate(key: key, addValue: new ReferencedLock().Acquire(), updateValueFactory: (_, value) => value.Acquire()); 40 | 41 | UtilitiesEventSource.Log.ConcurrentLockDictionaryAcquired(key.ToString(), currentReferencedLock.ReferenceCount); 42 | 43 | return currentReferencedLock; 44 | } 45 | 46 | /// 47 | /// Releases one reference from the lock. 48 | /// 49 | /// The key of the lock to release one reference from. 50 | /// True if the reference count reach zero *and* the lock object was removed before some other thread took a new reference. False otherwise. 51 | public bool Release(TKey key) 52 | { 53 | var currentReferencedLock = this.AddOrUpdate(key: key, addValue: new ReferencedLock(), updateValueFactory: (_, value) => value.Release()); 54 | 55 | UtilitiesEventSource.Log.ConcurrentLockDictionaryReleased(key.ToString(), currentReferencedLock.ReferenceCount); 56 | 57 | if (currentReferencedLock.ReferenceCount != 0) 58 | { 59 | return false; 60 | } 61 | 62 | // NOTE(daviburg): This is a thread safe way to remove a value *only* if it hasn't changed. A pity .NET authors did not expose it publicly. 63 | // If the value has changed, someone is newly taking a reference and we do not want to remove the value. 64 | var removed = ((ICollection>)this).Remove(new KeyValuePair(key: key, value: currentReferencedLock)); 65 | 66 | if (removed) 67 | { 68 | UtilitiesEventSource.Log.ConcurrentLockDictionaryRemoved(key.ToString()); 69 | } 70 | 71 | return removed; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/Daviburg.Utilities.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard1.1 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/EncodedStringWriter.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System; 23 | using System.IO; 24 | using System.Text; 25 | 26 | /// 27 | /// The string writer with character encoding. 28 | /// 29 | /// This class is implemented because the base class string writer encoding property is read-only with no constructor overload to set it. 30 | public class EncodedStringWriter : StringWriter 31 | { 32 | /// 33 | /// The character encoding. 34 | /// 35 | private readonly Encoding encoding; 36 | 37 | /// 38 | /// Initializes a new instance of the class with specific character encoding. 39 | /// 40 | /// The character encoding. 41 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor", Justification = "We are specifically only changing the encoding property of the existing base class.")] 42 | public EncodedStringWriter(Encoding encoding) 43 | { 44 | this.encoding = encoding; 45 | } 46 | 47 | /// 48 | /// Initializes a new instance of the class with the specified format control and with specific character encoding. 49 | /// 50 | /// An object that controls formatting. 51 | /// The encoding. 52 | public EncodedStringWriter(IFormatProvider formatProvider, Encoding encoding) 53 | : base(formatProvider) 54 | { 55 | this.encoding = encoding; 56 | } 57 | 58 | /// 59 | /// Initializes a new instance of the class that writes to the specified and with specific character encoding. 60 | /// 61 | /// The object to write to. 62 | /// The encoding. 63 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor(System.Text.StringBuilder)", Justification = "We are specifically only changing the encoding property of the existing base class.")] 64 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "sb", Justification = "As-is from inherited base class.")] 65 | public EncodedStringWriter(StringBuilder sb, Encoding encoding) 66 | : base(sb) 67 | { 68 | this.encoding = encoding; 69 | } 70 | 71 | /// 72 | /// Initializes a new instance of the class that writes to the specified , with specific character encoding and has the specified format provider. 73 | /// 74 | /// The object to write to. 75 | /// An object that controls formatting. 76 | /// The encoding. 77 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "sb", Justification = "As-is from inherited base class.")] 78 | public EncodedStringWriter(StringBuilder sb, IFormatProvider formatProvider, Encoding encoding) 79 | : base(sb, formatProvider) 80 | { 81 | this.encoding = encoding; 82 | } 83 | 84 | /// 85 | /// Gets the character encoding. 86 | /// 87 | public override Encoding Encoding 88 | { 89 | get { return this.encoding ?? base.Encoding; } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/Factorials.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System; 23 | 24 | /// 25 | /// A table of pre-computed factorial values. 26 | /// 27 | /// 28 | /// Because the growth of factorial quickly exceeds the long type capacity, the table is small and a good compromize of memory use vs computation. 29 | /// . 30 | /// 31 | public class Factorials 32 | { 33 | private static readonly Lazy FactorialsInstance = new Lazy(() => new Factorials()); 34 | private long[] factorials = 35 | { 36 | 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 37 | 20922789888000, 355687428096000, 6402373705728000, 121645100408832000, 2432902008176640000 38 | }; 39 | 40 | public static Factorials Singleton => FactorialsInstance.Value; 41 | 42 | /// 43 | /// Prevents construction of instances by others, enforcing singleton pattern. 44 | /// 45 | private Factorials() 46 | { 47 | } 48 | 49 | public long this[int index] 50 | { 51 | get 52 | { 53 | if (index >= this.factorials.Length) 54 | { 55 | throw new OverflowException($"Arithmetic operation resulted in an overflow. The factorial of {index} exceeds the capacity of type long."); 56 | } 57 | 58 | return this.factorials[index]; 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/Fibonacci.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System; 23 | 24 | public class Fibonacci 25 | { 26 | private static readonly Lazy lazyFiveSquareRoot = new Lazy(() => Math.Sqrt(5)); 27 | private static readonly Lazy lazyVarphi = new Lazy(() => (1 + Fibonacci.lazyFiveSquareRoot.Value) / 2); 28 | private static readonly Lazy lazyPsi = new Lazy(() => (1 - Fibonacci.lazyFiveSquareRoot.Value) / 2); 29 | 30 | private static double FiveSquareRoot => lazyFiveSquareRoot.Value; 31 | private static double Varphi => lazyVarphi.Value; 32 | private static double Psi => lazyPsi.Value; 33 | 34 | public static uint Compute(uint n) 35 | { 36 | return Convert.ToUInt32(Math.Round((Math.Pow(Fibonacci.Varphi, n) - Math.Pow(Fibonacci.Psi, n)) / Fibonacci.FiveSquareRoot)); 37 | } 38 | 39 | public static uint ClosestInputForOutcome(uint outcome) 40 | { 41 | return Convert.ToUInt32(Math.Floor(Math.Log(Fibonacci.FiveSquareRoot * outcome) / Math.Log(Fibonacci.Varphi))); 42 | } 43 | 44 | public static uint SummationOfEvenFibonacci(uint n) 45 | { 46 | var target = n / 3; 47 | uint sum = 0; 48 | for (uint index = 1; index <= target; index++) 49 | { 50 | sum += Fibonacci.Compute(index * 3); 51 | } 52 | 53 | return sum; 54 | } 55 | 56 | public static uint SmallestNumberForNDigitsFibonacci(uint digits) 57 | { 58 | if (digits == 1) 59 | { 60 | return 1; 61 | } 62 | 63 | return Convert.ToUInt32(Math.Ceiling((((digits - 1) * Math.Log(10)) + Math.Log(Fibonacci.lazyFiveSquareRoot.Value)) / Math.Log(Fibonacci.Varphi))); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/Graphs/DirectedGraphNode.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities.Graphs 21 | { 22 | using System.Collections.Generic; 23 | 24 | public class DirectedGraphNode 25 | { 26 | public List> parents; 27 | 28 | public DirectedGraphNode() 29 | { 30 | } 31 | 32 | public DirectedGraphNode(T value) 33 | { 34 | this.Value = value; 35 | } 36 | 37 | public T Value { get; set; } 38 | 39 | public List> Parents 40 | { 41 | get => this.parents; 42 | } 43 | 44 | public void AddParent(DirectedGraphNode parent) => (this.parents ?? (this.parents = new List>())).Add(parent); 45 | 46 | /// 47 | /// Gets the child nodes. 48 | /// 49 | /// This property is virtual so derived classes may override with additional constraints specific to a type of tree. 50 | public virtual List> Children { get; set; } 51 | 52 | public bool IsLeaf => this.Children == null || this.Children.Count == 0; 53 | public bool IsRoot => this.Parents == null; 54 | } 55 | } -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/HighComposite.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System; 23 | using System.Collections.Generic; 24 | using System.Linq; 25 | 26 | public partial class HighComposites 27 | { 28 | /// 29 | /// A high composite number initialized from the ordered list of exponents of its prime factorization form. 30 | /// 31 | /// This class is only meant to be instantiated by containing class . 32 | public class HighComposite : IEquatable, IComparable 33 | { 34 | private int? countofDivisors; 35 | private long? value; 36 | 37 | internal HighComposite(IReadOnlyList exponents) => this.Exponents = exponents; 38 | 39 | public readonly IReadOnlyList Exponents; 40 | 41 | /// 42 | /// d(n) aka the count of divisors is the product of all exponents each increased by one, exponents of the prime factorization of n. 43 | /// 44 | public int CountOfDivisors => this.countofDivisors ?? (this.countofDivisors = this.Exponents.Aggregate(1, (partialCount, exponent) => partialCount * (exponent + 1))).Value; 45 | 46 | public long Value => this.value ?? 47 | (this.value = this.Exponents.Aggregate( 48 | seed: new Tuple(0, 1), 49 | func: (indexAndPartialProduct, exponent) => new Tuple(indexAndPartialProduct.Item1 + 1, indexAndPartialProduct.Item2 * Primes.Singleton[indexAndPartialProduct.Item1].Power(exponent)), 50 | resultSelector: finalIndexAndProduct => finalIndexAndProduct.Item2)) 51 | .Value; 52 | 53 | /// 54 | /// Tries computing value, returns true if overflows long during the value computation. 55 | /// 56 | public bool Overflows 57 | { 58 | get 59 | { 60 | var overflows = false; 61 | try 62 | { 63 | checked 64 | { 65 | this.value = this.Exponents.Aggregate( 66 | seed: new Tuple(0, 1), 67 | func: (indexAndPartialProduct, exponent) => new Tuple(indexAndPartialProduct.Item1 + 1, indexAndPartialProduct.Item2 * Primes.Singleton[indexAndPartialProduct.Item1].Power(exponent)), 68 | resultSelector: finalIndexAndProduct => finalIndexAndProduct.Item2); 69 | } 70 | } 71 | catch (OverflowException) 72 | { 73 | overflows = true; 74 | } 75 | 76 | return overflows; 77 | } 78 | } 79 | 80 | public override bool Equals(Object otherObject) 81 | { 82 | return otherObject is HighComposite && this == (HighComposite)otherObject; 83 | } 84 | 85 | public override int GetHashCode() 86 | { 87 | // Comparing the exponents is tempting but value is computed once then all comparisons are O(1) 88 | // otherwise the list of exponents is traversed again and again as a list gets sorted. 89 | return this.Value.GetHashCode() ^ this.Value.GetHashCode(); 90 | } 91 | 92 | public bool Equals(HighComposite other) 93 | { 94 | return this == other; 95 | } 96 | 97 | public int CompareTo(HighComposite other) 98 | { 99 | // A null value means that this object is greater. 100 | return (other == null) ? 1 : this.Value.CompareTo(other.Value); 101 | } 102 | 103 | public static bool operator ==(HighComposite leftHcn, HighComposite rightHcn) 104 | { 105 | return leftHcn?.Value == rightHcn?.Value; 106 | } 107 | 108 | public static bool operator !=(HighComposite leftHcn, HighComposite rightHcn) 109 | { 110 | return !(leftHcn == rightHcn); 111 | } 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/HighComposites.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System; 23 | using System.Collections.Generic; 24 | using System.Linq; 25 | 26 | /// 27 | /// Helper class to incrementally discover small high composite numbers (HCNs) aka anti-primes. 28 | /// 29 | public partial class HighComposites 30 | { 31 | 32 | private static readonly Lazy HighCompositesInstance = new Lazy(() => new HighComposites()); 33 | ////private long[] highComposites = { 1, 2, 4, 6, 12, 24, 36, 48 }; 34 | ////private long[] divisorsCounts = { 1, 2, 3, 4, 6, 8, 9, 10 }; 35 | private readonly List highComposites = new List { new HighComposite(new List { 0 } ) }; 36 | 37 | // Seed the binary tree with 2^1. Because we only look at the 'tree' from each generation of nodes we don't keep a tree structure in memory, just lists. 38 | private List leafNodeCandidates = new List { new HighComposite(new List { 1 }) }; 39 | 40 | // Staged candidates are candidate HCNs which we haven't decided yet if they are actual HCN. 41 | private List stagedCandidates = new List { new HighComposite(new List { 1 }) }; 42 | 43 | public static HighComposites Singleton => HighCompositesInstance.Value; 44 | 45 | /// 46 | /// Prevents construction of instances by others, enforcing singleton pattern so HCNs are only computed once. 47 | /// 48 | private HighComposites() 49 | { 50 | } 51 | 52 | public HighComposite this[int index] 53 | { 54 | get 55 | { 56 | if (index < this.highComposites.Count) 57 | { 58 | return this.highComposites[index]; 59 | } 60 | 61 | this.FindHcns(index + 1); 62 | return this.highComposites[index]; 63 | } 64 | } 65 | 66 | public void FindHcns(int orderOfHcnToFind) 67 | { 68 | do 69 | { 70 | // Generate the next round of leaves 71 | leafNodeCandidates = leafNodeCandidates 72 | .SelectMany( 73 | selector: existingCandidate => 74 | { 75 | var newNodes = new List(); 76 | 77 | // Always add a right node with a new exponent for one more prime 78 | var rightNode = new HighComposite( 79 | new List(existingCandidate.Exponents) 80 | { 81 | 1 82 | }); 83 | 84 | // ... if it doesn't overflow. 85 | if (!rightNode.Overflows) 86 | { 87 | newNodes.Add(rightNode); 88 | } 89 | 90 | // Prepare a left node incrementing the last exponent but add it only if it doesn't exceed the previous exponent. 91 | // (Or there is only one exponent.) 92 | // This because HCN must satisfy the condition that the sequence of exponents is non-increasing. 93 | var newLeftList = new List(existingCandidate.Exponents); 94 | newLeftList[newLeftList.Count - 1]++; 95 | var leftNode = new HighComposite(newLeftList); 96 | 97 | if ((newLeftList.Count == 1 || newLeftList[newLeftList.Count - 2] >= newLeftList[newLeftList.Count - 1]) && 98 | !leftNode.Overflows) 99 | { 100 | newNodes.Add(leftNode); 101 | } 102 | 103 | return newNodes; 104 | }) 105 | .ToList(); 106 | 107 | if (leafNodeCandidates.Count == 0) 108 | { 109 | throw new OverflowException("Cannot find further highly composable number - reached the limits of C#'s 64-bit long."); 110 | } 111 | 112 | stagedCandidates.AddRange(leafNodeCandidates); 113 | 114 | // 1. Of the new leaves, order them by smallest to largest value 115 | leafNodeCandidates.Sort(); 116 | 117 | // 2. Any staged candidate of even lesser value (and greater count of divisors than other less values) is a confirmed HCN 118 | // as we won't be able to generate any further candidate of lesser value. 119 | // Remove confirmed HCNs from the staged list. 120 | // Also remove staged candidates which count of divisors is less than the best confirmed HCN or better candidates. 121 | // Using a for iteration with index so we can modify the list as we walk it, patching the index along the way. 122 | stagedCandidates.Sort(); 123 | int currentHighestCountOfDivisors = this.highComposites.Last().CountOfDivisors; 124 | for (int index = 0; index < stagedCandidates.Count; index++) 125 | { 126 | HighComposite candidate = stagedCandidates[index]; 127 | 128 | // Filter out higher value candidates which count of divisors is less or equal than best confirmed HCN or lower candidates 129 | if (candidate.CountOfDivisors <= currentHighestCountOfDivisors) 130 | { 131 | stagedCandidates.RemoveAt(index); 132 | index--; 133 | continue; 134 | } 135 | 136 | currentHighestCountOfDivisors = candidate.CountOfDivisors; 137 | 138 | // We already know this candidate has a higher count of divisors. Is it also of lower value than the new generation of leaves? 139 | if (candidate.Value <= leafNodeCandidates.First().Value) 140 | { 141 | this.highComposites.Add(candidate); 142 | stagedCandidates.RemoveAt(index); 143 | index--; 144 | } 145 | } 146 | } while (this.highComposites.Count < orderOfHcnToFind); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/IEnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System; 23 | using System.Collections.Generic; 24 | 25 | public static class IEnumerableExtensions 26 | { 27 | /// 28 | /// In case it is not blatent enough, ForEach is design to take effect. 29 | /// 30 | public static void ForEach(this IEnumerable enumeration, Action action) 31 | { 32 | foreach (T item in enumeration) 33 | { 34 | action(item); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/IntegerPower.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System; 23 | using System.Numerics; 24 | 25 | /// 26 | /// A integer base number raised by an integer exponent with JIT value computation, and custom comparison. 27 | /// 28 | public class IntegerPower : IEquatable 29 | { 30 | private long? value; 31 | private BigInteger? bigValue; 32 | 33 | /// 34 | /// Instantiate a 35 | /// 36 | /// The base. 37 | /// The exponent 38 | /// Base been a reserved word in C# the argument has the verbose name baseNumber. 39 | public IntegerPower(long baseNumber, int exponent) 40 | { 41 | this.Base = baseNumber; 42 | this.Exponent = exponent; 43 | } 44 | 45 | public long Base { get; private set; } 46 | 47 | public int Exponent { get; private set; } 48 | 49 | public long Value => (value ?? (value = this.Base.Power(this.Exponent))).Value; 50 | 51 | public BigInteger BigValue => (bigValue ?? (bigValue = BigInteger.Pow(this.Base, this.Exponent))).Value; 52 | 53 | public override bool Equals(Object otherObject) 54 | { 55 | return otherObject is IntegerPower && this == (IntegerPower)otherObject; 56 | } 57 | 58 | public bool Equals(IntegerPower other) 59 | { 60 | return this == other; 61 | } 62 | 63 | public override int GetHashCode() 64 | { 65 | // NOTE(daviburg): It is unnecessary to compare the actual values as they are determined by the base and exponent. 66 | return this.Base.GetHashCode() ^ this.Exponent.GetHashCode(); 67 | } 68 | 69 | public static bool operator ==(IntegerPower leftPower, IntegerPower rightPower) 70 | { 71 | return leftPower?.Base == rightPower?.Base && leftPower?.Exponent == rightPower?.Exponent; 72 | } 73 | 74 | public static bool operator !=(IntegerPower leftPower, IntegerPower rightPower) 75 | { 76 | return !(leftPower == rightPower); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/IntegerPowerValueComparer.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System; 23 | using System.Collections.Generic; 24 | 25 | public class IntegerPowerValueComparer : IEqualityComparer 26 | { 27 | private static readonly Lazy ComparerInstance = new Lazy(() => new IntegerPowerValueComparer()); 28 | 29 | public static IntegerPowerValueComparer Singleton => ComparerInstance.Value; 30 | 31 | /// 32 | /// Prevents construction of instances by others, enforcing singleton pattern so the comparer is not constructed again and again. 33 | /// 34 | private IntegerPowerValueComparer() 35 | { 36 | } 37 | 38 | public bool Equals(IntegerPower x, IntegerPower y) 39 | { 40 | return object.ReferenceEquals(x, y) ? 41 | true : 42 | x == null || y == null ? 43 | false : 44 | x.BigValue == y.BigValue; 45 | } 46 | 47 | public int GetHashCode(IntegerPower product) 48 | { 49 | return product == null ? 0 : product.BigValue.GetHashCode(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/Power.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System; 23 | 24 | /// 25 | /// A base number raised by an exponent with JIT value computation, and custom comparison. 26 | /// 27 | public class Power : IEquatable 28 | { 29 | private double? value; 30 | 31 | /// 32 | /// Instantiate a 33 | /// 34 | /// The base. 35 | /// The exponent 36 | /// Base been a reserved word in C# the argument has the verbose name baseNumber. 37 | public Power(double baseNumber, double exponent) 38 | { 39 | this.Base = baseNumber; 40 | this.Exponent = exponent; 41 | } 42 | 43 | public double Base { get; private set; } 44 | 45 | public double Exponent { get; private set; } 46 | 47 | public double Value => (value ?? (value = Math.Pow(this.Base, this.Exponent))).Value; 48 | 49 | public override bool Equals(Object otherObject) 50 | { 51 | return otherObject is Power && this == (Power)otherObject; 52 | } 53 | 54 | public bool Equals(Power other) 55 | { 56 | return this == other; 57 | } 58 | 59 | public override int GetHashCode() 60 | { 61 | // NOTE(daviburg): It is unnecessary to compare the actual values as they are determined by the base and exponent. 62 | // Also two different powers may have save value, e.g. 2^4 has the same value (16) as 4^2. 63 | return this.Base.GetHashCode() ^ this.Exponent.GetHashCode(); 64 | } 65 | 66 | public static bool operator ==(Power leftPower, Power rightPower) 67 | { 68 | return leftPower?.Base == rightPower?.Base && leftPower?.Exponent == rightPower?.Exponent; 69 | } 70 | 71 | public static bool operator !=(Power leftPower, Power rightPower) 72 | { 73 | return !(leftPower == rightPower); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/PowerDigits.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System; 23 | using System.Collections.Concurrent; 24 | using System.Linq; 25 | 26 | public class PowerDigitsSingletons 27 | { 28 | private static readonly Lazy Instance = new Lazy(() => new PowerDigitsSingletons()); 29 | 30 | private static readonly ConcurrentDictionary Instances = new ConcurrentDictionary(); 31 | 32 | public static PowerDigitsSingletons Singleton => Instance.Value; 33 | 34 | /// 35 | /// Prevents construction of instances by others, enforcing singleton pattern. 36 | /// 37 | private PowerDigitsSingletons() 38 | { 39 | } 40 | 41 | public long[] this[int exponent] => PowerDigitsSingletons.Instances.GetOrAdd(exponent, key => new PowerDigits(key)).digitPowers; 42 | 43 | internal class PowerDigits 44 | { 45 | internal long[] digitPowers; 46 | 47 | internal PowerDigits(int exponent) 48 | { 49 | digitPowers = Enumerable.Range(0, 10).Select(digit => new IntegerPower(digit, exponent).Value).ToArray(); 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/PrimeFactor.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | /// 23 | /// A prime factor, expressed by its order or by its prime number, and by its exponent 24 | /// 25 | public class PrimeFactor : IntegerPower 26 | { 27 | /// 28 | /// Initializes a instance from the prime order and exponent. 29 | /// 30 | /// The prime order. 31 | /// The exponent to apply to the prime. 32 | // NOTE(daviburg): the primes table is zero-based while the order of primes starts at 1 33 | public PrimeFactor(int order, int exponent): base(Primes.Singleton[order - 1], exponent) 34 | { 35 | } 36 | 37 | /// 38 | /// Initializes a instance from the prime number and exponent. 39 | /// 40 | /// The prime number. 41 | /// The exponent to apply to the prime. 42 | public PrimeFactor(long baseNumber, int exponent) : base(baseNumber, exponent) 43 | { 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/PythagoreanTriple.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System; 23 | 24 | /// 25 | /// Pythagorean triple, i.e. three positive integers a, b, and c, such that a^2 + b^2 = c^2. 26 | /// 27 | /// See also . 28 | public class PythagoreanTriple 29 | { 30 | #region private cached values 31 | 32 | private int integerA; 33 | private int integerB; 34 | private int integerC; 35 | 36 | #endregion 37 | 38 | /// 39 | /// Constructs a primitive Pythagorean triple from a pair of integer for the Euclid formula 40 | /// 41 | /// Integer M. 42 | /// Integer N. 43 | public PythagoreanTriple(int euclidM, int euclidN) 44 | : this(euclidM, euclidN, 1) 45 | { 46 | } 47 | 48 | /// 49 | /// Constructs a Pythagorean triple from a pair of integer for the Euclid formula 50 | /// 51 | /// Integer M. 52 | /// Integer N. 53 | /// Factor K, 1 for primitive triples. 54 | public PythagoreanTriple(int euclidM, int euclidN, int factorK) 55 | { 56 | if (factorK < 1) 57 | { 58 | throw new ArgumentOutOfRangeException(nameof(factorK), factorK, "Factor k for Euclid formula must be strictly greater than zero."); 59 | } 60 | 61 | if (euclidN < 1) 62 | { 63 | throw new ArgumentOutOfRangeException(nameof(euclidN), euclidN, "Value N for Euclid formula must be strictly greater than zero."); 64 | } 65 | 66 | if (euclidM <= euclidN) 67 | { 68 | throw new ArgumentOutOfRangeException(nameof(euclidM), euclidM, "Value M for Euclid formula must be strictly greater than value N."); 69 | } 70 | 71 | this.EuclidM = euclidM; 72 | this.EuclidN = euclidN; 73 | this.FactorK = factorK; 74 | } 75 | 76 | public int EuclidM { get; private set; } 77 | public int EuclidN { get; private set; } 78 | public int FactorK { get; private set; } 79 | 80 | /// 81 | /// A = k * (m^2 - n^2) 82 | /// 83 | public int IntegerA { get { return integerA != 0 ? integerA : integerA = this.FactorK * (this.EuclidM * this.EuclidM - this.EuclidN * this.EuclidN); } } 84 | 85 | /// 86 | /// B = k * (2 * m * n) 87 | /// 88 | public int IntegerB { get { return integerB != 0 ? integerB : integerB = this.FactorK * (2 * this.EuclidM * this.EuclidN); } } 89 | 90 | /// 91 | /// C = k * (m^2 + n^2) 92 | /// 93 | public int IntegerC { get { return integerC != 0 ? integerC : integerC = this.FactorK * (this.EuclidM * this.EuclidM + this.EuclidN * this.EuclidN); } } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/ReferencedLock.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System.Collections.Generic; 23 | 24 | /// 25 | /// A lock object with reference count for use in . 26 | /// 27 | public sealed class ReferencedLock : IEqualityComparer 28 | { 29 | /// 30 | /// The lock object. 31 | /// 32 | /// The value factory of may be called multiple times before an update is successful. Hence the value factory must be idem potent. The cloning and increment clone reference count ensures idem potency. 33 | public object LockObject { get; } = new object(); 34 | 35 | /// 36 | /// The current reference count. 37 | /// 38 | /// This count is only representing the value at the time this instance was read in the . 39 | public int ReferenceCount { get; private set; } 40 | 41 | /// 42 | /// (Idempotent) Acquires a reference to the lock through cloning. 43 | /// 44 | /// A cloned instance with increased reference count. 45 | public ReferencedLock Acquire() 46 | { 47 | var newLock = (ReferencedLock)this.MemberwiseClone(); 48 | newLock.ReferenceCount++; 49 | return newLock; 50 | } 51 | 52 | /// 53 | /// (Idempotent) Releases one reference from the lock through cloning. 54 | /// 55 | /// A cloned instance with decreased reference count. 56 | public ReferencedLock Release() 57 | { 58 | var newLock = (ReferencedLock)this.MemberwiseClone(); 59 | newLock.ReferenceCount--; 60 | return newLock; 61 | } 62 | 63 | /// 64 | public bool Equals(ReferencedLock leftLock, ReferencedLock rightLock) 65 | { 66 | return leftLock?.ReferenceCount == rightLock?.ReferenceCount && object.ReferenceEquals(leftLock?.LockObject, rightLock?.LockObject); 67 | } 68 | 69 | /// 70 | public int GetHashCode(ReferencedLock referencedLock) 71 | { 72 | return referencedLock.ReferenceCount.GetHashCode() ^ referencedLock.LockObject.GetHashCode(); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // Do note that this file contains a single method TryParseExact which *different* license terms are described below. 19 | // 20 | // 21 | // -------------------------------------------------------------------------------------------------------------------- 22 | 23 | namespace Daviburg.Utilities 24 | { 25 | using System.Text.RegularExpressions; 26 | 27 | /// 28 | /// Extensions for . 29 | /// 30 | public static class StringExtensions 31 | { 32 | /// 33 | /// Tries parsing exactly the provided string per the specified format to extract the arguments. The format of the string representation must match the specified format exactly. 34 | /// 35 | /// The formatted string. 36 | /// A format specifier that defines the required format of data. 37 | /// Out parameter for the argument values. 38 | /// Whether to ignore the casing of characters or not. 39 | /// MIT License - from https://github.com/mikeobrien/mikeobrien.github.com/blob/master/LICENSE and code at https://github.com/mikeobrien/mikeobrien.github.com/blob/master/_posts/2009-2-18-parseexact-for-strings.html 40 | /// 41 | /// Copyright(c) 2010 Ultraviolet Catastrophe 42 | /// 43 | /// Permission is hereby granted, free of charge, to any person obtaining a copy 44 | /// of this software and associated documentation files(the "Software"), to deal 45 | /// in the Software without restriction, including without limitation the rights 46 | /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 47 | /// copies of the Software, and to permit persons to whom the Software is furnished 48 | /// to do so, subject to the following conditions: 49 | /// 50 | /// The above copyright notice and this permission notice shall be included in all 51 | /// copies or substantial portions of the Software. 52 | /// 53 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 54 | /// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 55 | /// PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 56 | /// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 57 | /// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 58 | /// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 59 | /// 60 | public static bool TryParseExact( 61 | this string data, 62 | string format, 63 | out string[] values, 64 | bool ignoreCase) 65 | { 66 | if (data == null) 67 | { 68 | values = new string[] { }; 69 | return false; 70 | } 71 | 72 | int tokenCount = 0; 73 | format = Regex.Escape(format).Replace(oldValue: "\\{", newValue: "{"); 74 | 75 | for (tokenCount = 0; ; tokenCount++) 76 | { 77 | string token = $"{{{tokenCount}}}"; 78 | if (!format.Contains(token)) 79 | { 80 | break; 81 | } 82 | 83 | format = format.Replace(oldValue: token, newValue: $"(?'group{tokenCount}'.*)"); 84 | } 85 | 86 | var match = new Regex(format, ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None).Match(data); 87 | 88 | if (tokenCount != (match.Groups.Count - 1)) 89 | { 90 | values = new string[] { }; 91 | return false; 92 | } 93 | else 94 | { 95 | values = new string[tokenCount]; 96 | for (int index = 0; index < tokenCount; index++) 97 | { 98 | values[index] = match.Groups[$"group{index}"].Value; 99 | } 100 | 101 | return true; 102 | } 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/Trees/TreeNode.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities.Trees 21 | { 22 | using System.Collections.Generic; 23 | 24 | public class TreeNode 25 | { 26 | private int? level; 27 | private TreeNode parent; 28 | 29 | public TreeNode() 30 | { 31 | } 32 | 33 | public TreeNode(T value) 34 | { 35 | this.Value = value; 36 | } 37 | 38 | public T Value { get; set; } 39 | 40 | /// 41 | /// Gets or sets the parent node. 42 | /// 43 | /// Setting the parent node resets the level of this node. 44 | public TreeNode Parent 45 | { 46 | get => this.parent; 47 | set 48 | { 49 | this.parent = value; 50 | this.level = null; 51 | } 52 | } 53 | 54 | public int Level { get => (this.level ?? (this.level = this.Parent != null ? this.Parent.Level + 1 : 1)).Value; } 55 | 56 | /// 57 | /// Gets the child nodes. 58 | /// 59 | /// This property is virtual so derived classes may override with additional constraints specific to a type of tree. 60 | public virtual List> Children { get; set; } 61 | 62 | public TreeNode Predecessor { get; set; } 63 | public TreeNode Successor { get; set; } 64 | public bool IsLeaf => this.Children == null || this.Children.Count == 0; 65 | public bool IsRoot => this.Parent == null; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/Triangular.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | public class Triangular 23 | { 24 | private long? value; 25 | 26 | public Triangular(long order) 27 | { 28 | this.Order = order; 29 | } 30 | 31 | private Triangular(long order, long value) 32 | { 33 | this.Order = order; 34 | this.value = value; 35 | } 36 | 37 | public long Order { get; private set; } 38 | 39 | public long Value => (value ?? (value = this.Order.Summation())).Value; 40 | 41 | public Triangular NextTriangularNumber() 42 | { 43 | var nextOrder = this.Order + 1; 44 | return new Triangular(nextOrder, this.Value + nextOrder); 45 | } 46 | 47 | public static Triangular ClosestTriangularNumber(long value) 48 | { 49 | // Triangular numbers of order n is also the summation of natural numbers up to n. 50 | // So the anti-summation will give us the order of the closest triangular number. 51 | // Then re-doing the summation gives us the triangular number. 52 | return new Triangular(value.AntiSummation()); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/UtilitiesEventIds.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | /// 23 | /// Utilities ETW Event Source Event Ids 24 | /// 25 | /// Each ETW Event method must have its unique id, used for generating the event source metadata. 26 | public enum UtilitiesEventIds 27 | { 28 | ConcurrentLockDictionaryAcquired = 1, 29 | 30 | ConcurrentLockDictionaryReleased = 2, 31 | 32 | ConcurrentLockDictionaryRemoved = 3 33 | } 34 | } -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities/UtilitiesEventSource.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities 21 | { 22 | using System; 23 | using System.Diagnostics.Tracing; 24 | 25 | /// 26 | /// ETW event tracing for utilities. 27 | /// 28 | [EventSource(Name = "Daviburg-Utilities")] 29 | public class UtilitiesEventSource : EventSource 30 | { 31 | private static readonly Lazy EventSourceInstance = new Lazy(() => new UtilitiesEventSource()); 32 | 33 | public static UtilitiesEventSource Log => EventSourceInstance.Value; 34 | 35 | /// 36 | /// Prevents construction of instances by others, enforcing singleton pattern as intended by .NET team authors of EventSource 37 | /// 38 | private UtilitiesEventSource() 39 | { 40 | } 41 | 42 | #region Concurrent Lock Dictionary 43 | 44 | [Event(eventId: (int)UtilitiesEventIds.ConcurrentLockDictionaryAcquired, Level = EventLevel.Verbose)] 45 | public void ConcurrentLockDictionaryAcquired(string key, int count) 46 | { 47 | this.WriteEvent((int)UtilitiesEventIds.ConcurrentLockDictionaryAcquired, key, count); 48 | } 49 | 50 | [Event(eventId: (int)UtilitiesEventIds.ConcurrentLockDictionaryReleased, Level = EventLevel.Verbose)] 51 | public void ConcurrentLockDictionaryReleased(string key, int count) 52 | { 53 | this.WriteEvent((int)UtilitiesEventIds.ConcurrentLockDictionaryReleased, key, count); 54 | } 55 | 56 | [Event(eventId: (int)UtilitiesEventIds.ConcurrentLockDictionaryRemoved, Level = EventLevel.Verbose)] 57 | public void ConcurrentLockDictionaryRemoved(string key) 58 | { 59 | this.WriteEvent((int)UtilitiesEventIds.ConcurrentLockDictionaryRemoved, key); 60 | } 61 | 62 | #endregion 63 | } 64 | } -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities2.Tests/BinaryDirectedAcyclicGraphTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities2.Tests 21 | { 22 | using Daviburg.Utilities2.Graphs; 23 | using Microsoft.VisualStudio.TestTools.UnitTesting; 24 | using System; 25 | using System.Collections.Generic; 26 | using System.Diagnostics.CodeAnalysis; 27 | using System.Linq; 28 | 29 | [TestClass] 30 | [ExcludeFromCodeCoverage] 31 | public class BinaryDirectedAcyclicGraphTests 32 | { 33 | [TestMethod] 34 | [ExcludeFromCodeCoverage] 35 | public void BinaryDirectedAcyclicGraphLoadFromFileTest() 36 | { 37 | var graphRoot = BinaryDirectedAcyclicGraphNode.LoadFromTextFile(@".\TestData\p067_triangle.txt"); 38 | for ( 39 | var currentNodeList = new List>() { graphRoot.LeftChild, graphRoot.RightChild }; 40 | currentNodeList.Any(node => node != null); 41 | currentNodeList = currentNodeList 42 | .Aggregate( 43 | seed: new List>(), 44 | func: (runningList, oldNode) => 45 | { 46 | if (runningList.Count == 0) 47 | { 48 | runningList.Add(((BinaryDirectedAcyclicGraphNode)oldNode).LeftChild); 49 | } 50 | 51 | runningList.Add(((BinaryDirectedAcyclicGraphNode)oldNode).RightChild); 52 | return runningList; 53 | })) 54 | { 55 | foreach (var node in currentNodeList) 56 | { 57 | node.Value += node.Parents.Aggregate(0, (currentMax, parentNode) => parentNode.Value > currentMax ? parentNode.Value : currentMax); 58 | } 59 | } 60 | 61 | var leftMostLeaf = graphRoot; 62 | while (leftMostLeaf.LeftChild != null) 63 | { 64 | leftMostLeaf = leftMostLeaf.LeftChild; 65 | } 66 | 67 | var max = 0; 68 | var inspectedLeaf = leftMostLeaf; 69 | while (inspectedLeaf != null) 70 | { 71 | max = inspectedLeaf.Value > max ? inspectedLeaf.Value : max; 72 | inspectedLeaf = inspectedLeaf.Successor; 73 | } 74 | 75 | Console.WriteLine($"Maximum total is {max}."); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities2.Tests/Daviburg.Utilities2.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {1AC0FE91-1E21-439C-93F1-977A8D7769C2} 8 | Library 9 | Properties 10 | Daviburg.Utilities2.Tests 11 | Daviburg.Utilities2.Tests 12 | v4.6.1 13 | 512 14 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 15 | 15.0 16 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 17 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 18 | False 19 | UnitTest 20 | 21 | 22 | 23 | 24 | true 25 | full 26 | false 27 | bin\Debug\ 28 | DEBUG;TRACE 29 | prompt 30 | 4 31 | 32 | 33 | pdbonly 34 | true 35 | bin\Release\ 36 | TRACE 37 | prompt 38 | 4 39 | 40 | 41 | 42 | ..\packages\MSTest.TestFramework.1.2.1\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll 43 | 44 | 45 | ..\packages\MSTest.TestFramework.1.2.1\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | {c3a11c8c-42a8-47c9-a2b1-70e51e937168} 65 | Daviburg.Utilities2 66 | 67 | 68 | {6F57FC32-46D2-4EA7-8CD7-B31078D74923} 69 | Daviburg.Utilities 70 | 71 | 72 | 73 | 74 | PreserveNewest 75 | 76 | 77 | PreserveNewest 78 | 79 | 80 | 81 | 82 | 83 | 84 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities2.Tests/IntExtensions2Tests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities2.Tests 21 | { 22 | using System; 23 | using System.Diagnostics.CodeAnalysis; 24 | using Microsoft.VisualStudio.TestTools.UnitTesting; 25 | 26 | [TestClass] 27 | [ExcludeFromCodeCoverage] 28 | public class IntExtensions2Tests 29 | { 30 | [TestMethod] 31 | [ExcludeFromCodeCoverage] 32 | public void DigitsSummationPowerOfTwoTests() 33 | { 34 | var OeisA001370 = new[] { 1, 2, 4, 8, 7, 5, 10, 11, 13, 8, 7, 14, 19, 20, 22, 26, 25, 14, 19, 29, 31, 26, 25, 41, 37, 29, 40, 35, 43, 41, 37, 47, 58, 62, 61, 59, 64, 56, 67, 71, 61, 50, 46, 56, 58, 62, 70, 68, 73, 65, 76, 80, 79, 77, 82, 92, 85, 80, 70, 77 }; 35 | for (var exponent = 0; exponent < OeisA001370.Length; exponent++) 36 | { 37 | Assert.AreEqual(OeisA001370[exponent], exponent.DigitsSummationPowerOfTwo()); 38 | } 39 | 40 | Console.WriteLine($"The sum of digits of the number 2 power 1000 is {1000.DigitsSummationPowerOfTwo()}."); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities2.Tests/MathAlgorithms2Tests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities2.Tests 21 | { 22 | using System; 23 | using System.Diagnostics.CodeAnalysis; 24 | using Microsoft.VisualStudio.TestTools.UnitTesting; 25 | 26 | [TestClass] 27 | [ExcludeFromCodeCoverage] 28 | public class MathAlgorithms2Tests 29 | { 30 | [TestMethod] 31 | [ExcludeFromCodeCoverage] 32 | public void LongestCollatzSequenceStartingNumberTests() 33 | { 34 | Assert.AreEqual(new Tuple(1, 1), MathAlgorithms2.LongestCollatzSequenceStartingNumber(2)); 35 | Assert.AreEqual(new Tuple(2, 2), MathAlgorithms2.LongestCollatzSequenceStartingNumber(3)); 36 | Assert.AreEqual(new Tuple(3, 8), MathAlgorithms2.LongestCollatzSequenceStartingNumber(4)); 37 | Assert.AreEqual(new Tuple(3, 8), MathAlgorithms2.LongestCollatzSequenceStartingNumber(5)); 38 | Assert.AreEqual(new Tuple(3, 8), MathAlgorithms2.LongestCollatzSequenceStartingNumber(6)); 39 | Assert.AreEqual(new Tuple(6, 9), MathAlgorithms2.LongestCollatzSequenceStartingNumber(7)); 40 | Assert.AreEqual(new Tuple(7, 17), MathAlgorithms2.LongestCollatzSequenceStartingNumber(8)); 41 | Assert.AreEqual(new Tuple(7, 17), MathAlgorithms2.LongestCollatzSequenceStartingNumber(9)); 42 | Assert.AreEqual(new Tuple(9, 20), MathAlgorithms2.LongestCollatzSequenceStartingNumber(10)); 43 | Assert.AreEqual(new Tuple(9, 20), MathAlgorithms2.LongestCollatzSequenceStartingNumber(11)); 44 | Assert.AreEqual(new Tuple(9, 20), MathAlgorithms2.LongestCollatzSequenceStartingNumber(12)); 45 | 46 | // Test values from https://en.wikipedia.org/wiki/Collatz_conjecture#Examples 47 | // Note that Wikipedia measures the count of steps while we measure the sequence length such that our values are added one from theirs. 48 | Assert.AreEqual(new Tuple(27, 112), MathAlgorithms2.LongestCollatzSequenceStartingNumber(28)); 49 | Assert.AreEqual(new Tuple(97, 119), MathAlgorithms2.LongestCollatzSequenceStartingNumber(100)); 50 | Assert.AreEqual(new Tuple(871, 179), MathAlgorithms2.LongestCollatzSequenceStartingNumber(1000)); 51 | Assert.AreEqual(new Tuple(6171, 262), MathAlgorithms2.LongestCollatzSequenceStartingNumber(10000)); 52 | 53 | // Higher input value 100000 will fail because the sequence will go sufficiently high such that array allocation will fail. A sparsed array approach is required. 54 | } 55 | 56 | [TestMethod] 57 | [ExcludeFromCodeCoverage] 58 | public void LongestCollatzSequenceStartingNumber2Tests() 59 | { 60 | Assert.AreEqual(new Tuple(1, 1), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(2)); 61 | Assert.AreEqual(new Tuple(2, 2), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(3)); 62 | Assert.AreEqual(new Tuple(3, 8), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(4)); 63 | Assert.AreEqual(new Tuple(3, 8), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(5)); 64 | Assert.AreEqual(new Tuple(3, 8), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(6)); 65 | Assert.AreEqual(new Tuple(6, 9), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(7)); 66 | Assert.AreEqual(new Tuple(7, 17), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(8)); 67 | Assert.AreEqual(new Tuple(7, 17), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(9)); 68 | Assert.AreEqual(new Tuple(9, 20), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(10)); 69 | Assert.AreEqual(new Tuple(9, 20), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(11)); 70 | Assert.AreEqual(new Tuple(9, 20), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(12)); 71 | 72 | // Test values from https://en.wikipedia.org/wiki/Collatz_conjecture#Examples 73 | // Note that Wikipedia measures the count of steps while we measure the sequence length such that our values are added one from theirs. 74 | Assert.AreEqual(new Tuple(27, 112), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(28)); 75 | Assert.AreEqual(new Tuple(97, 119), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(100)); 76 | Assert.AreEqual(new Tuple(871, 179), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(1000)); 77 | Assert.AreEqual(new Tuple(6171, 262), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(10000)); 78 | Assert.AreEqual(new Tuple(77031, 351), MathAlgorithms2.LongestCollatzSequenceStartingNumber2(100000)); 79 | 80 | var theSecret = MathAlgorithms2.LongestCollatzSequenceStartingNumber2(1000000); 81 | Console.WriteLine($"The longest Collatz sequence with a starting number less than one million starts with {theSecret.Item1} with a lenght of {theSecret.Item2} elements."); 82 | } 83 | 84 | [TestMethod] 85 | [ExcludeFromCodeCoverage] 86 | public void PowerDigitsSumEqualityTests() 87 | { 88 | Assert.AreEqual(expected: 19316, actual: MathAlgorithms2.SumOfPowerDigitsSumEquals(4)); 89 | Console.WriteLine($"The sum of all the numbers that can be written as the sum of {5}th powers of their digits is {MathAlgorithms2.SumOfPowerDigitsSumEquals(5)}."); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities2.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("Daviburg.Utilities2.Tests")] 6 | [assembly: AssemblyDescription("")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("Daviburg.Utilities2.Tests")] 10 | [assembly: AssemblyCopyright("Copyright © 2018")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | 14 | [assembly: ComVisible(false)] 15 | 16 | [assembly: Guid("1ac0fe91-1e21-439c-93f1-977a8d7769c2")] 17 | 18 | // [assembly: AssemblyVersion("1.0.*")] 19 | [assembly: AssemblyVersion("1.0.0.0")] 20 | [assembly: AssemblyFileVersion("1.0.0.0")] 21 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities2.Tests/SmallIntSeriesTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities2.Tests 21 | { 22 | using System; 23 | using System.Diagnostics.CodeAnalysis; 24 | using System.Linq; 25 | using Microsoft.VisualStudio.TestTools.UnitTesting; 26 | 27 | /// 28 | /// Tests for code embedded in the test class and not part of the utilities. 29 | /// 30 | [TestClass] 31 | [ExcludeFromCodeCoverage] 32 | public class SmallIntSeriesTests 33 | { 34 | [TestMethod] 35 | [ExcludeFromCodeCoverage] 36 | public void SearchGreatestProduct() 37 | { 38 | var stringOfInt = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"; 39 | var series = new SmallIntSeries(stringOfInt); 40 | 41 | Assert.AreEqual(81, series.GreatestProduct(2)); 42 | Assert.AreEqual(5832, series.GreatestProduct(4)); 43 | series.GreatestProduct(13); 44 | } 45 | 46 | [TestMethod] 47 | [ExcludeFromCodeCoverage] 48 | public void SearchGreatestProductInMatrix() 49 | { 50 | var gridInString = @"08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 51 | 49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 52 | 81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 53 | 52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 54 | 22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 55 | 24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 56 | 32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70 57 | 67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 58 | 24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 59 | 21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 60 | 78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 61 | 16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 62 | 86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 63 | 19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 64 | 04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66 65 | 88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 66 | 04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 67 | 20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 68 | 20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54 69 | 01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48"; 70 | 71 | var grid = new SmallIntGrid(gridInString); 72 | 73 | Assert.AreEqual(8, grid[0, 0]); 74 | 75 | Console.WriteLine("The grid"); 76 | for (var rowIndex = 0; rowIndex < grid.RowCount; rowIndex++) 77 | { 78 | for (var columnIndex = 0; columnIndex < grid.ColumnCount; columnIndex++) 79 | { 80 | Console.Write($"{grid[rowIndex, columnIndex]:D2} "); 81 | } 82 | 83 | Console.WriteLine(); 84 | } 85 | 86 | 87 | for (var columnIndex = 0; columnIndex < grid.ColumnCount; columnIndex++) 88 | { 89 | Console.WriteLine($"Column {columnIndex}: {String.Join(", ", grid.GetColumn(columnIndex).Select(value => value.ToString("D2")))}"); 90 | } 91 | 92 | Console.WriteLine(""); 93 | for (var rowIndex = 0; rowIndex < grid.RowCount; rowIndex++) 94 | { 95 | Console.WriteLine($"Row {rowIndex}: {String.Join(", ", grid.GetRow(rowIndex).Select(value => value.ToString("D2")))}"); 96 | } 97 | 98 | for (var diagonalIndex = 0; diagonalIndex < grid.DiagonalHalfCount; diagonalIndex++) 99 | { 100 | Console.WriteLine($"Right-down diagonal {diagonalIndex}: {String.Join(", ", grid.GetRightDownDiagonal(diagonalIndex).Select(value => value.ToString("D2")))}"); 101 | Console.WriteLine($"Right-up diagonal {diagonalIndex}: {String.Join(", ", grid.GetRightUpDiagonal(diagonalIndex).Select(value => value.ToString("D2")))}"); 102 | } 103 | 104 | Console.WriteLine($"The greatest product of 4 adjacent numbers in the grid is {grid.GreatestProductOfAdjacentNumbers(4)}."); 105 | Assert.AreEqual((long)9603, grid.GreatestProductOfAdjacentNumbers(2)); 106 | Assert.AreEqual((long)811502, grid.GreatestProductOfAdjacentNumbers(3)); 107 | Assert.AreEqual((long)3318231678, grid.GreatestProductOfAdjacentNumbers(5)); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities2.Tests/TestData/p018_triangle.txt: -------------------------------------------------------------------------------- 1 | 75 2 | 95 64 3 | 17 47 82 4 | 18 35 87 10 5 | 20 04 82 47 65 6 | 19 01 23 75 03 34 7 | 88 02 77 73 07 63 67 8 | 99 65 04 28 06 16 70 92 9 | 41 41 26 56 83 40 80 70 33 10 | 41 48 72 33 47 32 37 16 94 29 11 | 53 71 44 65 25 43 91 52 97 51 14 12 | 70 11 33 28 77 73 17 78 39 68 17 57 13 | 91 71 52 38 17 14 91 43 58 50 27 29 48 14 | 63 66 04 68 89 53 67 30 73 16 69 87 40 31 15 | 04 62 98 27 23 09 70 98 73 93 38 53 60 04 23 -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities2.Tests/XmlSchemaExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities2.Tests 21 | { 22 | using System.Text; 23 | using System.Threading.Tasks; 24 | using System.Xml; 25 | using System.Xml.Schema; 26 | using Microsoft.VisualStudio.TestTools.UnitTesting; 27 | 28 | [TestClass] 29 | public class XmlSchemaExtensionsTests 30 | { 31 | [TestMethod] 32 | public async Task SchemaToStringAsyncTest() 33 | { 34 | XmlSchema schema = GetTestSchema(); 35 | 36 | var xmlAsString = await schema.ToStringAsync(Encoding.UTF8); 37 | StringAssert.StartsWith(xmlAsString, ""); 38 | 39 | xmlAsString = await schema.ToStringAsync(Encoding.Unicode); 40 | StringAssert.StartsWith(xmlAsString, ""); 41 | } 42 | 43 | [TestMethod] 44 | public void SchemaToStringTest() 45 | { 46 | XmlSchema schema = GetTestSchema(); 47 | 48 | var xmlAsString = schema.ToString(Encoding.UTF8); 49 | StringAssert.StartsWith(xmlAsString, ""); 50 | 51 | xmlAsString = schema.ToString(Encoding.Unicode); 52 | StringAssert.StartsWith(xmlAsString, ""); 53 | } 54 | 55 | private static XmlSchema GetTestSchema() 56 | { 57 | XmlSchema schema = new XmlSchema(); 58 | 59 | // 60 | XmlSchemaElement elementCat = new XmlSchemaElement(); 61 | schema.Items.Add(elementCat); 62 | elementCat.Name = "cat"; 63 | elementCat.SchemaTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema"); 64 | 65 | // 66 | XmlSchemaElement elementDog = new XmlSchemaElement(); 67 | schema.Items.Add(elementDog); 68 | elementDog.Name = "dog"; 69 | elementDog.SchemaTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema"); 70 | 71 | // 72 | XmlSchemaElement elementRedDog = new XmlSchemaElement(); 73 | schema.Items.Add(elementRedDog); 74 | elementRedDog.Name = "redDog"; 75 | elementRedDog.SubstitutionGroup = new XmlQualifiedName("dog"); 76 | 77 | // 78 | XmlSchemaElement elementBrownDog = new XmlSchemaElement(); 79 | schema.Items.Add(elementBrownDog); 80 | elementBrownDog.Name = "brownDog"; 81 | elementBrownDog.SubstitutionGroup = new XmlQualifiedName("dog"); 82 | 83 | // 84 | XmlSchemaElement elementPets = new XmlSchemaElement(); 85 | schema.Items.Add(elementPets); 86 | elementPets.Name = "pets"; 87 | 88 | // 89 | XmlSchemaComplexType complexType = new XmlSchemaComplexType(); 90 | elementPets.SchemaType = complexType; 91 | 92 | // 93 | XmlSchemaChoice choice = new XmlSchemaChoice(); 94 | complexType.Particle = choice; 95 | choice.MinOccurs = 0; 96 | choice.MaxOccursString = "unbounded"; 97 | 98 | // 99 | XmlSchemaElement catRef = new XmlSchemaElement(); 100 | choice.Items.Add(catRef); 101 | catRef.RefName = new XmlQualifiedName("cat"); 102 | 103 | // 104 | XmlSchemaElement dogRef = new XmlSchemaElement(); 105 | choice.Items.Add(dogRef); 106 | dogRef.RefName = new XmlQualifiedName("dog"); 107 | return schema; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities/Daviburg.Utilities2.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities2/ClassLibrary1/Daviburg.Utilities2.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities2/ClassLibrary1/ExceptionExtensions.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities2 21 | { 22 | using System; 23 | using System.Resources; 24 | using System.Xml; 25 | using Daviburg.Utilities; 26 | 27 | public static class ExceptionExtensions 28 | { 29 | /// 30 | /// The resource id of the invalid XML character exception message, as found in the code shared at 31 | /// 32 | private const string InvalidXmlCharExceptionMessageFormatResourceId = "Xml_InvalidCharacter"; 33 | 34 | /// 35 | /// for containing assembly. 36 | /// 37 | private static Lazy systemXmlResourceManager = new Lazy(() => new ResourceManager("System.Xml", typeof(XmlElement).Assembly)); 38 | 39 | /// 40 | /// Determines if the exception is for an invalid XML character. 41 | /// 42 | /// The exception to analyze. 43 | /// 44 | /// .NET is using generic ArgumentException type exception which makes it difficult to programmatically say with confidence the reason of the exception. 45 | /// Due to 64 bit inlining of InvalidXmlChar private method, we can't rely on stack frame matching. 46 | /// This helper is matching the localized string back to the format resource string to match with high reliability regardless of local the exception reason. 47 | /// 48 | public static bool IsInvalidXmlCharException(this Exception ex) 49 | { 50 | return ex is ArgumentException && 51 | ex.Message.TryParseExact( 52 | format: systemXmlResourceManager.Value.GetString(name: ExceptionExtensions.InvalidXmlCharExceptionMessageFormatResourceId, culture: null), 53 | values: out string[] values, 54 | ignoreCase: false); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities2/ClassLibrary1/Graphs/BinaryDirectedAcyclicGraphNode.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities2.Graphs 21 | { 22 | using Daviburg.Utilities.Graphs; 23 | using System; 24 | using System.Collections.Generic; 25 | using System.ComponentModel; 26 | using System.IO; 27 | using System.Linq; 28 | 29 | public class BinaryDirectedAcyclicGraphNode : DirectedGraphNode 30 | { 31 | private List> children; 32 | private BinaryDirectedAcyclicGraphNode leftChild; 33 | private BinaryDirectedAcyclicGraphNode rightChild; 34 | 35 | public BinaryDirectedAcyclicGraphNode Predecessor { get; set; } 36 | public BinaryDirectedAcyclicGraphNode Successor { get; set; } 37 | 38 | /// 39 | /// Gets or sets the left child node. 40 | /// 41 | /// Setting the child node resets the children list. 42 | public BinaryDirectedAcyclicGraphNode LeftChild 43 | { 44 | get => this.leftChild; 45 | set 46 | { 47 | if (value != null) 48 | { 49 | value.Predecessor = this.leftChild?.Predecessor; 50 | } 51 | 52 | this.leftChild = value; 53 | value.AddParent(this); 54 | 55 | if (this.rightChild != null) 56 | { 57 | value.Successor = this.rightChild; 58 | this.rightChild.Predecessor = value; 59 | } 60 | 61 | this.children = null; 62 | } 63 | } 64 | 65 | /// 66 | /// Gets or sets the right child node. 67 | /// 68 | /// Setting the child node resets the children list. 69 | public BinaryDirectedAcyclicGraphNode RightChild 70 | { 71 | get => this.rightChild; 72 | set 73 | { 74 | if (value != null) 75 | { 76 | value.Successor = this.rightChild?.Successor; 77 | } 78 | 79 | this.rightChild = value; 80 | value.AddParent(this); 81 | 82 | if (this.leftChild != null) 83 | { 84 | value.Predecessor = this.leftChild; 85 | this.leftChild.Successor = value; 86 | } 87 | 88 | this.children = null; 89 | } 90 | } 91 | 92 | public override List> Children 93 | { 94 | get => this.children ?? (this.children = new List> { this.LeftChild, this.RightChild }); 95 | set 96 | { 97 | this.children = value; 98 | 99 | if (value != null && value.Count > 2) 100 | { 101 | throw new ArgumentException($"Invalid argument to set child nodes for a binary tree node. At most two children must be povided but {value.Count} were passed."); 102 | } 103 | 104 | this.LeftChild = (BinaryDirectedAcyclicGraphNode)this.children?.ElementAtOrDefault(0); 105 | this.RightChild = (BinaryDirectedAcyclicGraphNode)this.children?.ElementAtOrDefault(1); 106 | } 107 | } 108 | 109 | public static BinaryDirectedAcyclicGraphNode LoadFromTextFile(string path) 110 | { 111 | var lines = File.ReadAllLines(path); 112 | BinaryDirectedAcyclicGraphNode root = null; 113 | BinaryDirectedAcyclicGraphNode leftMostNode = null; 114 | foreach (var line in lines) 115 | { 116 | if (leftMostNode == null) 117 | { 118 | root = leftMostNode = new BinaryDirectedAcyclicGraphNode() { Value = (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(line) }; 119 | continue; 120 | } 121 | 122 | var childNodes = line.Split(' ').Select(valueAsString => new BinaryDirectedAcyclicGraphNode() { Value = (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(valueAsString) }).ToList(); 123 | 124 | var enumerator = childNodes.GetEnumerator(); 125 | enumerator.MoveNext(); 126 | do 127 | { 128 | leftMostNode.LeftChild = enumerator.Current; 129 | 130 | if (!enumerator.MoveNext()) 131 | { 132 | throw new ArgumentException($"Invalid text file at '{path}' provided to load as binary directed acyclic graph. Only full binary directed acyclic graph can be loaded."); 133 | } 134 | 135 | leftMostNode.RightChild = enumerator.Current; 136 | 137 | leftMostNode = (BinaryDirectedAcyclicGraphNode)leftMostNode.Successor; 138 | } while (leftMostNode != null); 139 | 140 | leftMostNode = childNodes.First(); 141 | } 142 | 143 | return root; 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities2/ClassLibrary1/IntExtensions2.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities2 21 | { 22 | using Daviburg.Utilities; 23 | using System.Linq; 24 | using System.Numerics; 25 | 26 | public static class IntExtensions2 27 | { 28 | /// 29 | /// Sum of digits of 2^n. 30 | /// 31 | /// The power of 2 exponent. 32 | /// 33 | public static int DigitsSummationPowerOfTwo(this int exponent) => (new BigInteger(1) << exponent).ToString().Aggregate(seed: 0, func: (partialSummation, digit) => partialSummation + digit.ToInt32()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities2/ClassLibrary1/MathAlgorithms2.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities2 21 | { 22 | using Daviburg.Utilities; 23 | using System; 24 | using System.Collections.Generic; 25 | using System.Threading; 26 | using System.Threading.Tasks; 27 | 28 | public static class MathAlgorithms2 29 | { 30 | /// 31 | /// Searches the starting number less that the provided limit which produces the longest Collatz chain. 32 | /// 33 | /// The exclusive upper search limit value. 34 | /// The tuple starting number and length of the series. 35 | public static Tuple LongestCollatzSequenceStartingNumber(int upperLimit) 36 | { 37 | var collatzSequenceLength = new AutoResizeArray(3 * upperLimit); 38 | var maximumLength = new Tuple(1, collatzSequenceLength[1] = 1); 39 | for (var startingNumber = 2; startingNumber < upperLimit; startingNumber++) 40 | { 41 | // If we've seen this number before in a sequence it won't be the start of a longer sequence and can be skipped over. 42 | if (collatzSequenceLength[startingNumber] != default(int)) 43 | { 44 | continue; 45 | } 46 | 47 | var collatzSequenceFragment = new Queue(); 48 | var adjustment = default(int); 49 | 50 | // Walk the sequence until we reach an element we've seen before, such as 1 51 | for (var currentValue = startingNumber; 52 | adjustment == default(int); 53 | adjustment = collatzSequenceLength[currentValue = currentValue.CollatzSequenceNext()]) 54 | { 55 | // Stack this element of the Collatz fragment, element we haven't seen before 56 | collatzSequenceFragment.Enqueue(currentValue); 57 | } 58 | 59 | // Capture the new maximum length if found 60 | maximumLength = maximumLength.Item2 >= collatzSequenceFragment.Count + adjustment ? maximumLength : new Tuple(startingNumber, collatzSequenceFragment.Count + adjustment); 61 | 62 | for(; collatzSequenceFragment.Count != 0; collatzSequenceFragment.Dequeue()) 63 | { 64 | collatzSequenceLength[collatzSequenceFragment.Peek()] = collatzSequenceFragment.Count + adjustment; 65 | } 66 | } 67 | 68 | return maximumLength; 69 | } 70 | 71 | /// 72 | /// Searches the starting number less that the provided limit which produces the longest Collatz chain. 73 | /// 74 | /// The exclusive upper search limit value. 75 | /// The tuple starting number and length of the series. 76 | public static Tuple LongestCollatzSequenceStartingNumber2(int upperLimit) 77 | { 78 | // Although the start number is a 32 bits integer, because odd numbers in the sequence can increase intermediary value wildly, 79 | // sequences can have values exceeding 32 bits capacity, hence keep track of known length with a 64 bits integer key. 80 | var collatzSequenceLength = new Dictionary(3 * upperLimit); 81 | var maximumLength = new Tuple(1, collatzSequenceLength[1] = 1); 82 | 83 | // Longer sequences are within the higher half starting numbers as if we can double this number while staying within the limit, 84 | // that starting number will result in a longer chain. 85 | // Also avoid starting with less than 2. 86 | for (var startingNumber = upperLimit > 6 ? (upperLimit - 1) >> 1 : 2; startingNumber < upperLimit; startingNumber++) 87 | { 88 | // If we've seen this number before in a sequence it won't be the start of a longer sequence and can be skipped over. 89 | if (collatzSequenceLength.TryGetValue(startingNumber, out int sequenceFragmentLength)) 90 | { 91 | continue; 92 | } 93 | 94 | var collatzSequenceFragment = new Queue(); 95 | var adjustment = default(int); 96 | 97 | // Walk the sequence until we reach an element we've seen before, such as 1 98 | for (long currentValue = startingNumber; 99 | adjustment == default(int); 100 | collatzSequenceLength.TryGetValue(currentValue = currentValue.CollatzSequenceNext(), out adjustment)) 101 | { 102 | // Stack this element of the Collatz fragment, element we haven't seen before 103 | collatzSequenceFragment.Enqueue(currentValue); 104 | } 105 | 106 | // Capture the new maximum length if found 107 | maximumLength = maximumLength.Item2 >= collatzSequenceFragment.Count + adjustment ? maximumLength : new Tuple(startingNumber, collatzSequenceFragment.Count + adjustment); 108 | 109 | for (; collatzSequenceFragment.Count != 0; collatzSequenceFragment.Dequeue()) 110 | { 111 | collatzSequenceLength[collatzSequenceFragment.Peek()] = collatzSequenceFragment.Count + adjustment; 112 | } 113 | } 114 | 115 | return maximumLength; 116 | } 117 | 118 | public static long SumOfPowerDigitsSumEquals(int exponent) 119 | { 120 | long sumOfEqualPowerDigitsSum = 0; 121 | 122 | Parallel.For( 123 | fromInclusive: 2, 124 | toExclusive: (PowerDigitsSingletons.Singleton[exponent][9].Log10() + 2) * PowerDigitsSingletons.Singleton[exponent][9], 125 | localInit: () => 0, 126 | body: (index, loop, subtotal) => 127 | subtotal += index.PowerDigitsSum(exponent) == index ? index : (long)0, 128 | localFinally: x => 129 | { 130 | if (x != 0) 131 | { 132 | Interlocked.Add(ref sumOfEqualPowerDigitsSum, x); 133 | } 134 | }); 135 | 136 | return sumOfEqualPowerDigitsSum; 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities2/ClassLibrary1/SmallIntGrid.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities2 21 | { 22 | using System; 23 | using System.Collections.Generic; 24 | using System.Linq; 25 | using System.Text; 26 | 27 | public class SmallIntGrid 28 | { 29 | private sbyte[,] grid; 30 | 31 | public SmallIntGrid(string gridInString) 32 | { 33 | var rows = gridInString.Split('\n'); 34 | for (int rowIndex = 0; rowIndex < rows.Length; rowIndex++) 35 | { 36 | var rowInString = rows[rowIndex]; 37 | var integers = rowInString.Split(' ').Select(valueAsString => sbyte.Parse(valueAsString)).ToList(); 38 | if (this.grid == null) 39 | { 40 | this.grid = new sbyte[integers.Count(), rows.Count()]; 41 | } 42 | 43 | for (int columnIndex = 0; columnIndex < integers.Count; columnIndex++) 44 | { 45 | this.grid[rowIndex, columnIndex] = integers[columnIndex]; 46 | } 47 | } 48 | } 49 | 50 | public long this[int rowIndex, int columnIndex] 51 | { 52 | get => this.grid[rowIndex, columnIndex]; 53 | } 54 | 55 | public sbyte[] GetRow(int rowIndex) 56 | { 57 | var row = new sbyte[this.ColumnCount]; 58 | Buffer.BlockCopy( 59 | src: this.grid, 60 | srcOffset: rowIndex * this.ColumnCount * sizeof(sbyte), 61 | dst: row, 62 | dstOffset: 0, 63 | count: this.ColumnCount * sizeof(sbyte)); 64 | return row; 65 | } 66 | 67 | public sbyte[] GetColumn(int columnIndex) 68 | { 69 | return Enumerable.Range(0, this.RowCount - 1) 70 | .Select(rowIndex => this.grid[rowIndex, columnIndex]) 71 | .ToArray(); 72 | } 73 | 74 | public int ColumnCount => this.grid.GetLength(0); 75 | public int RowCount => this.grid.GetLength(1); 76 | public int DiagonalHalfCount => this.ColumnCount + this.RowCount - 1; 77 | 78 | /// 79 | /// Gets the Nth diagonal progressing right and up the grid 80 | /// 81 | /// The diagonal index. 82 | /// 83 | /// There are column count + row count - 1 diagonal in the grid. 84 | /// Diagonal zero is the upper right value of the grid, the last diagonal is the lower left value of the grid. 85 | /// 86 | public sbyte[] GetRightDownDiagonal(int diagonalIndex) 87 | { 88 | var diagonalLength = diagonalIndex < this.RowCount ? 89 | Math.Min(diagonalIndex + 1, this.ColumnCount) : 90 | Math.Min(this.ColumnCount + this.RowCount - (diagonalIndex + 1), this.RowCount); 91 | return diagonalIndex < this.RowCount ? 92 | Enumerable 93 | .Range(0, diagonalLength) 94 | .Select(position => this.grid[position, position + this.RowCount - (diagonalIndex + 1)]) 95 | .ToArray() : 96 | Enumerable 97 | .Range(0, diagonalLength) 98 | .Select(position => this.grid[position + (diagonalIndex - this.RowCount), position + diagonalIndex + 1 - this.RowCount]) 99 | .ToArray(); 100 | } 101 | 102 | /// 103 | /// Gets the Nth diagonal progressing right and up the grid 104 | /// 105 | /// The diagonal index. 106 | /// 107 | /// There are column count + row count - 1 diagonal in the grid. 108 | /// Diagonal zero is the upper left value of the grid, the last diagonal is the lower right value of the grid. 109 | /// 110 | public sbyte[] GetRightUpDiagonal(int diagonalIndex) 111 | { 112 | var diagonalLength = diagonalIndex < this.RowCount ? 113 | Math.Min(diagonalIndex + 1, this.ColumnCount) : 114 | Math.Min(this.ColumnCount + this.RowCount - (diagonalIndex + 1), this.RowCount); 115 | return diagonalIndex < this.RowCount ? 116 | Enumerable 117 | .Range(0, diagonalLength) 118 | .Select(position => this.grid[diagonalIndex - position, position]) 119 | .ToArray() : 120 | Enumerable 121 | .Range(0, diagonalLength) 122 | .Select(position => this.grid[this.RowCount - (position + 1), position + diagonalIndex + 1 - this.RowCount]) 123 | .ToArray(); 124 | } 125 | 126 | public long GreatestProductOfAdjacentNumbers(int countOfAdjacentNumbers) 127 | { 128 | var arraysOfNumbers = new List(); 129 | for (var columnIndex = 0; columnIndex < this.ColumnCount; columnIndex++) 130 | { 131 | arraysOfNumbers.Add(this.GetColumn(columnIndex)); 132 | } 133 | 134 | for (var rowIndex = 0; rowIndex < this.RowCount; rowIndex++) 135 | { 136 | arraysOfNumbers.Add(this.GetRow(rowIndex)); 137 | } 138 | 139 | for (var diagonalIndex = 0; diagonalIndex < this.DiagonalHalfCount; diagonalIndex++) 140 | { 141 | arraysOfNumbers.Add(this.GetRightDownDiagonal(diagonalIndex)); 142 | arraysOfNumbers.Add(this.GetRightUpDiagonal(diagonalIndex)); 143 | } 144 | 145 | return arraysOfNumbers.Max(array => new SmallIntSeries(array).GreatestProduct(countOfAdjacentNumbers)); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities2/ClassLibrary1/SmallIntSeries.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities2 21 | { 22 | // Enable if you use console output 23 | ////using System; 24 | using System.Collections.Generic; 25 | using System.Linq; 26 | 27 | /// 28 | /// Series of small integers such as single and double digits integers. 29 | /// 30 | /// Used sbyte to represent single digits as the smallest integer type available in C#. 31 | public class SmallIntSeries 32 | { 33 | private IEnumerable seriesOfSmallIntegers; 34 | 35 | public SmallIntSeries(IEnumerable seriesOfDigits) 36 | { 37 | this.seriesOfSmallIntegers = seriesOfDigits; 38 | } 39 | 40 | public SmallIntSeries(string stringOfInt) 41 | { 42 | this.seriesOfSmallIntegers = stringOfInt.Select(character => (sbyte)char.GetNumericValue(character)); 43 | } 44 | 45 | /// 46 | /// Searches the greatest product from n adjacent numbers in a series 47 | /// 48 | /// The series of digits. 49 | /// The count of adjacent numbers to compute the product. 50 | public long GreatestProduct(int countOfAdjacentNumbers) 51 | { 52 | long greatestProduct = 0; 53 | var greatestProductFactors = new List(); 54 | long runningProduct = 1; 55 | var sequentialDigits = new List(); 56 | foreach (var digit in this.seriesOfSmallIntegers) 57 | { 58 | // Any zero will zero the product hence we can restart from an empty sequence after it 59 | if (digit == 0) 60 | { 61 | sequentialDigits = new List(); 62 | runningProduct = 1; 63 | continue; 64 | } 65 | 66 | sequentialDigits.Add(digit); 67 | runningProduct *= digit; 68 | 69 | // Test if we are at the desired count of adjacent digits 70 | if (sequentialDigits.Count == countOfAdjacentNumbers) 71 | { 72 | // Capture new max product if any 73 | if (runningProduct > greatestProduct) 74 | { 75 | greatestProduct = runningProduct; 76 | greatestProductFactors = new List(sequentialDigits); 77 | } 78 | 79 | // To avoid recomputing the whole sequence, remove just the first/oldest digit 80 | runningProduct /= sequentialDigits[0]; 81 | sequentialDigits.RemoveAt(0); 82 | } 83 | } 84 | 85 | // Enable the following line if you'd like to see what numbers were used to get the greatest product. 86 | ////Console.WriteLine($"The greatest product is {greatestProduct} from multiplying the {countOfAdjacentNumbers} numbers {String.Join(", ", greatestProductFactors.Select(digit => digit.ToString()))}."); 87 | return greatestProduct; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities2/ClassLibrary1/Trees/BinaryTreeNode.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities2.Trees 21 | { 22 | using Daviburg.Utilities.Trees; 23 | using System; 24 | using System.Collections.Generic; 25 | using System.ComponentModel; 26 | using System.IO; 27 | using System.Linq; 28 | 29 | public class BinaryTreeNode : TreeNode 30 | { 31 | private List> children; 32 | private BinaryTreeNode leftChild; 33 | private BinaryTreeNode rightChild; 34 | 35 | /// 36 | /// Gets or sets the left child node. 37 | /// 38 | /// Setting the child node resets the children list. 39 | public BinaryTreeNode LeftChild 40 | { 41 | get => this.leftChild; 42 | set 43 | { 44 | if (value != null) 45 | { 46 | value.Predecessor = this.leftChild?.Predecessor; 47 | } 48 | 49 | this.leftChild = value; 50 | value.Parent = this; 51 | 52 | if (this.rightChild != null) 53 | { 54 | value.Successor = this.rightChild; 55 | this.rightChild.Predecessor = value; 56 | } 57 | 58 | this.children = null; 59 | } 60 | } 61 | 62 | /// 63 | /// Gets or sets the right child node. 64 | /// 65 | /// Setting the child node resets the children list. 66 | public BinaryTreeNode RightChild 67 | { 68 | get => this.rightChild; 69 | set 70 | { 71 | if (value != null) 72 | { 73 | value.Successor = this.rightChild?.Successor; 74 | } 75 | 76 | this.rightChild = value; 77 | value.Parent = this; 78 | 79 | if (this.leftChild != null) 80 | { 81 | value.Predecessor = this.leftChild; 82 | this.leftChild.Successor = value; 83 | } 84 | 85 | this.children = null; 86 | } 87 | } 88 | 89 | public override List> Children 90 | { 91 | get => this.children ?? (this.children = new List> { this.LeftChild, this.RightChild }); 92 | set 93 | { 94 | this.children = value; 95 | 96 | if (value != null && value.Count > 2) 97 | { 98 | throw new ArgumentException($"Invalid argument to set child nodes for a binary tree node. At most two children must be povided but {value.Count} were passed."); 99 | } 100 | 101 | this.LeftChild = (BinaryTreeNode)this.children?.ElementAtOrDefault(0); 102 | this.RightChild = (BinaryTreeNode)this.children?.ElementAtOrDefault(1); 103 | } 104 | } 105 | 106 | public static BinaryTreeNode LoadFromTextFile(string path) 107 | { 108 | var lines = File.ReadAllLines(path); 109 | BinaryTreeNode root = null; 110 | BinaryTreeNode leftMostNode = null; 111 | foreach (var line in lines) 112 | { 113 | if (leftMostNode == null) 114 | { 115 | root = leftMostNode = new BinaryTreeNode() { Value = (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(line) }; 116 | continue; 117 | } 118 | 119 | var childNodes = line.Split(' ').Select(valueAsString => new BinaryTreeNode() { Value = (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(valueAsString) }).ToList(); 120 | 121 | if ((childNodes.Count & 1) != 0) 122 | { 123 | throw new ArgumentException($"Invalid text file at '{path}' provided to load as binary tree. Only full binary tree can be loaded."); 124 | } 125 | 126 | BinaryTreeNode previousChild = null; 127 | var enumerator = childNodes.GetEnumerator(); 128 | while (enumerator.MoveNext()) 129 | { 130 | leftMostNode.LeftChild = enumerator.Current; 131 | enumerator.MoveNext(); 132 | leftMostNode.RightChild = enumerator.Current; 133 | 134 | if (previousChild != null) 135 | { 136 | previousChild.Successor = leftMostNode.LeftChild; 137 | leftMostNode.LeftChild.Predecessor = previousChild; 138 | } 139 | 140 | previousChild = leftMostNode.RightChild; 141 | 142 | leftMostNode = (BinaryTreeNode)leftMostNode.Successor; 143 | } 144 | 145 | leftMostNode = childNodes.First(); 146 | } 147 | 148 | return root; 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /Sources/Daviburg.Utilities2/ClassLibrary1/XmlSchemaExtensions.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities2 21 | { 22 | using Daviburg.Utilities; 23 | using System.IO; 24 | using System.Text; 25 | using System.Xml; 26 | using System.Xml.Schema; 27 | 28 | public static class XmlSchemaExtensions 29 | { 30 | // TODO: move these to XmlSchemaExtensions, add XmlDoc extensions if needed. Write a version not using a memorystream but maybe a stringbuilder instead for large schemas. 31 | public static async System.Threading.Tasks.Task ToStringAsync(this XmlSchema schema, Encoding encoding) 32 | { 33 | var xmlWriterSettings = new XmlWriterSettings 34 | { 35 | Async = true, 36 | NewLineHandling = NewLineHandling.None 37 | }; 38 | var outputMemoryStream = new MemoryStream(); 39 | try 40 | { 41 | using (var stringWriter = new StreamWriter(stream: outputMemoryStream, encoding: encoding, bufferSize: 512, leaveOpen: true)) 42 | using (var xmlTextWriter = XmlWriter.Create(stringWriter, xmlWriterSettings)) 43 | using(var streamReader = new StreamReader(outputMemoryStream)) 44 | { 45 | schema.Write(xmlTextWriter); 46 | await xmlTextWriter 47 | .FlushAsync() 48 | .ConfigureAwait(continueOnCapturedContext: false); 49 | 50 | outputMemoryStream.Seek(0, SeekOrigin.Begin); 51 | return await streamReader.ReadToEndAsync(); 52 | } 53 | } 54 | finally 55 | { 56 | if (outputMemoryStream != null) 57 | { 58 | outputMemoryStream.Dispose(); 59 | } 60 | } 61 | } 62 | 63 | // TODO: also move to .net std 1.1 helper 64 | public static string ToString(this XmlSchema schema, Encoding encoding) 65 | { 66 | using (var stringWriter = new EncodedStringWriter(encoding)) 67 | { 68 | schema.Write(stringWriter); 69 | return stringWriter.ToString(); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Tests/Daviburg.Utilities.Tests/CoPrimeTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities.Tests 21 | { 22 | using System; 23 | using System.Collections.Generic; 24 | using System.Diagnostics.CodeAnalysis; 25 | using Microsoft.VisualStudio.TestTools.UnitTesting; 26 | 27 | [TestClass] 28 | [ExcludeFromCodeCoverage] 29 | public class CoPrimeTests 30 | { 31 | [TestMethod] 32 | [ExcludeFromCodeCoverage] 33 | public void OddOddCoPrimesTest() 34 | { 35 | var oddOddCoPrimes = CoPrime.OddOddRootVertex.NextTriplet; 36 | Assert.AreEqual(5, oddOddCoPrimes[0].IntegerA); 37 | Assert.AreEqual(3, oddOddCoPrimes[0].IntegerB); 38 | Assert.AreEqual(7, oddOddCoPrimes[1].IntegerA); 39 | Assert.AreEqual(3, oddOddCoPrimes[1].IntegerB); 40 | Assert.AreEqual(5, oddOddCoPrimes[2].IntegerA); 41 | Assert.AreEqual(1, oddOddCoPrimes[2].IntegerB); 42 | } 43 | 44 | [TestMethod] 45 | [ExcludeFromCodeCoverage] 46 | public void EvenOddCoPrimesTest() 47 | { 48 | var oddOddCoPrimes = CoPrime.EvenOddRootVertex.NextTriplet; 49 | Assert.AreEqual(3, oddOddCoPrimes[0].IntegerA); 50 | Assert.AreEqual(2, oddOddCoPrimes[0].IntegerB); 51 | Assert.AreEqual(5, oddOddCoPrimes[1].IntegerA); 52 | Assert.AreEqual(2, oddOddCoPrimes[1].IntegerB); 53 | Assert.AreEqual(4, oddOddCoPrimes[2].IntegerA); 54 | Assert.AreEqual(1, oddOddCoPrimes[2].IntegerB); 55 | 56 | var rank2OddOddCoPrimes = oddOddCoPrimes[0].NextTriplet; 57 | Assert.AreEqual(4, rank2OddOddCoPrimes[0].IntegerA); 58 | Assert.AreEqual(3, rank2OddOddCoPrimes[0].IntegerB); 59 | Assert.AreEqual(8, rank2OddOddCoPrimes[1].IntegerA); 60 | Assert.AreEqual(3, rank2OddOddCoPrimes[1].IntegerB); 61 | Assert.AreEqual(7, rank2OddOddCoPrimes[2].IntegerA); 62 | Assert.AreEqual(2, rank2OddOddCoPrimes[2].IntegerB); 63 | 64 | rank2OddOddCoPrimes = oddOddCoPrimes[1].NextTriplet; 65 | Assert.AreEqual(8, rank2OddOddCoPrimes[0].IntegerA); 66 | Assert.AreEqual(5, rank2OddOddCoPrimes[0].IntegerB); 67 | Assert.AreEqual(12, rank2OddOddCoPrimes[1].IntegerA); 68 | Assert.AreEqual(5, rank2OddOddCoPrimes[1].IntegerB); 69 | Assert.AreEqual(9, rank2OddOddCoPrimes[2].IntegerA); 70 | Assert.AreEqual(2, rank2OddOddCoPrimes[2].IntegerB); 71 | } 72 | 73 | [TestMethod] 74 | [ExcludeFromCodeCoverage] 75 | public void SearchPythagoreanTripleTest() 76 | { 77 | var tripleSummingToThousand = SearchPythagoreanTriple(1000); 78 | Console.WriteLine($"The PythagoreanTriple for 1000 is A: {tripleSummingToThousand.IntegerA}, B: {tripleSummingToThousand.IntegerB}, C: {tripleSummingToThousand.IntegerC} and of product {tripleSummingToThousand.IntegerA * tripleSummingToThousand.IntegerB * tripleSummingToThousand.IntegerC}, generated from M: {tripleSummingToThousand.EuclidM}, N: {tripleSummingToThousand.EuclidN} and factor K: {tripleSummingToThousand.FactorK}."); 79 | } 80 | 81 | /// 82 | /// Finds a Pythagorean triple which sum equals to the goal. 83 | /// 84 | /// Goal sum. 85 | private PythagoreanTriple SearchPythagoreanTriple(int sumGoal) 86 | { 87 | var evenOddCoPrimesToTest = new List() { CoPrime.EvenOddRootVertex }; 88 | 89 | do 90 | { 91 | var testingCoPrime = evenOddCoPrimesToTest[0]; 92 | evenOddCoPrimesToTest.RemoveAt(0); 93 | var magicNumber = 2 * testingCoPrime.IntegerA * testingCoPrime.IntegerA + 2 * testingCoPrime.IntegerA * testingCoPrime.IntegerB; 94 | if (magicNumber == sumGoal) 95 | { 96 | return new PythagoreanTriple(testingCoPrime.IntegerA, testingCoPrime.IntegerB); 97 | } 98 | 99 | if (magicNumber < sumGoal) 100 | { 101 | if (sumGoal % magicNumber == 0) 102 | { 103 | var factor = sumGoal / magicNumber; 104 | return new PythagoreanTriple(testingCoPrime.IntegerA, testingCoPrime.IntegerB, factor); 105 | } 106 | 107 | evenOddCoPrimesToTest.AddRange(testingCoPrime.NextTriplet); 108 | } 109 | } 110 | while (true); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Tests/Daviburg.Utilities.Tests/EventRecordingForUtilities.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities.Tests 21 | { 22 | using System.Diagnostics.CodeAnalysis; 23 | using System.Linq; 24 | using Microsoft.VisualStudio.TestTools.UnitTesting; 25 | 26 | [TestClass] 27 | [ExcludeFromCodeCoverage] 28 | public class EventRecordingForUtilities 29 | { 30 | [TestMethod] 31 | public void EventRecordingTest() 32 | { 33 | TestEventListener.Log.AddEventSource(UtilitiesEventSource.Log.Guid); 34 | try 35 | { 36 | var concurrentLockDictionaryTests = new ConcurrentLockDictionaryTests(); 37 | concurrentLockDictionaryTests.ImmutableAcquireDictionaryTest(); 38 | concurrentLockDictionaryTests.ReentryDictionaryTest(); 39 | concurrentLockDictionaryTests.ReferencedLockEqualityTest(); 40 | concurrentLockDictionaryTests.RemoveNotFoundLockDictionaryTest(); 41 | concurrentLockDictionaryTests.SimpleLockDictionaryTest(); 42 | 43 | // If count is 1, look at the content of Payload for an error description such as 'ERROR: Exception in Command Processing for EventSource' 44 | Assert.IsTrue(TestEventListener.Log.ReceivedEvents.Count > 100); 45 | 46 | // Because logging is not disabled yet and events may trickle in, we need to make a copy of the enumeration with .ToList before .Where 47 | var eventSourceFailures = TestEventListener.Log.ReceivedEvents 48 | .ToList() 49 | .Where( 50 | eventArgs => 51 | { 52 | var formattedEvent = TestEventListener.FormatPayload(eventArgs.Payload); 53 | return formattedEvent.Contains("ERROR: Exception in Command Processing for EventSource") 54 | || formattedEvent.Contains("Tracing failed"); 55 | }) 56 | .ToList(); 57 | Assert.IsFalse(condition: eventSourceFailures.Any(), message: TestEventListener.FormatPayload(eventSourceFailures.FirstOrDefault()?.Payload)); 58 | } 59 | finally 60 | { 61 | TestEventListener.Log.Disable(); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Tests/Daviburg.Utilities.Tests/FibonacciTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities.Tests 21 | { 22 | using System; 23 | using System.Diagnostics.CodeAnalysis; 24 | using Microsoft.VisualStudio.TestTools.UnitTesting; 25 | 26 | [TestClass] 27 | [ExcludeFromCodeCoverage] 28 | public class FibonacciTests 29 | { 30 | [TestMethod] 31 | [ExcludeFromCodeCoverage] 32 | public void FibonacciSimpleTests() 33 | { 34 | Assert.AreEqual(expected: (uint)0, actual: Fibonacci.Compute(0)); 35 | Assert.AreEqual(expected: (uint)1, actual: Fibonacci.Compute(1)); 36 | Assert.AreEqual(expected: (uint)1, actual: Fibonacci.Compute(2)); 37 | Assert.AreEqual(expected: (uint)2, actual: Fibonacci.Compute(3)); 38 | Assert.AreEqual(expected: (uint)3, actual: Fibonacci.Compute(4)); 39 | Assert.AreEqual(expected: (uint)5, actual: Fibonacci.Compute(5)); 40 | Assert.AreEqual(expected: (uint)8, actual: Fibonacci.Compute(6)); 41 | Assert.AreEqual(expected: (uint)13, actual: Fibonacci.Compute(7)); 42 | Assert.AreEqual(expected: (uint)21, actual: Fibonacci.Compute(8)); 43 | Assert.AreEqual(expected: (uint)34, actual: Fibonacci.Compute(9)); 44 | Assert.AreEqual(expected: (uint)55, actual: Fibonacci.Compute(10)); 45 | Assert.AreEqual(expected: (uint)89, actual: Fibonacci.Compute(11)); 46 | Assert.AreEqual(expected: (uint)144, actual: Fibonacci.Compute(12)); 47 | Assert.AreEqual(expected: (uint)233, actual: Fibonacci.Compute(13)); 48 | Assert.AreEqual(expected: (uint)377, actual: Fibonacci.Compute(14)); 49 | Assert.AreEqual(expected: (uint)610, actual: Fibonacci.Compute(15)); 50 | Assert.AreEqual(expected: (uint)987, actual: Fibonacci.Compute(16)); 51 | Assert.AreEqual(expected: (uint)1597, actual: Fibonacci.Compute(17)); 52 | Assert.AreEqual(expected: (uint)2584, actual: Fibonacci.Compute(18)); 53 | Assert.AreEqual(expected: (uint)4181, actual: Fibonacci.Compute(19)); 54 | Assert.AreEqual(expected: (uint)6765, actual: Fibonacci.Compute(20)); 55 | Assert.AreEqual(expected: (uint)10946, actual: Fibonacci.Compute(21)); 56 | Assert.AreEqual(expected: (uint)17711, actual: Fibonacci.Compute(22)); 57 | Assert.AreEqual(expected: (uint)28657, actual: Fibonacci.Compute(23)); 58 | Assert.AreEqual(expected: (uint)46368, actual: Fibonacci.Compute(24)); 59 | Assert.AreEqual(expected: (uint)75025, actual: Fibonacci.Compute(25)); 60 | Assert.AreEqual(expected: (uint)121393, actual: Fibonacci.Compute(26)); 61 | Assert.AreEqual(expected: (uint)196418, actual: Fibonacci.Compute(27)); 62 | Assert.AreEqual(expected: (uint)317811, actual: Fibonacci.Compute(28)); 63 | Assert.AreEqual(expected: (uint)514229, actual: Fibonacci.Compute(29)); 64 | Assert.AreEqual(expected: (uint)832040, actual: Fibonacci.Compute(30)); 65 | Assert.AreEqual(expected: (uint)1346269, actual: Fibonacci.Compute(31)); 66 | Assert.AreEqual(expected: (uint)2178309, actual: Fibonacci.Compute(32)); 67 | Assert.AreEqual(expected: (uint)3524578, actual: Fibonacci.Compute(33)); 68 | } 69 | 70 | [TestMethod] 71 | [ExcludeFromCodeCoverage] 72 | public void SummationOfEvenFibonacciSimpleTests() 73 | { 74 | Assert.AreEqual(expected: (uint)0, actual: Fibonacci.SummationOfEvenFibonacci(0)); 75 | Assert.AreEqual(expected: (uint)0, actual: Fibonacci.SummationOfEvenFibonacci(1)); 76 | Assert.AreEqual(expected: (uint)0, actual: Fibonacci.SummationOfEvenFibonacci(2)); 77 | Assert.AreEqual(expected: (uint)2, actual: Fibonacci.SummationOfEvenFibonacci(3)); 78 | Assert.AreEqual(expected: (uint)2, actual: Fibonacci.SummationOfEvenFibonacci(4)); 79 | Assert.AreEqual(expected: (uint)2, actual: Fibonacci.SummationOfEvenFibonacci(5)); 80 | Assert.AreEqual(expected: (uint)10, actual: Fibonacci.SummationOfEvenFibonacci(6)); 81 | Assert.AreEqual(expected: (uint)44, actual: Fibonacci.SummationOfEvenFibonacci(9)); 82 | Assert.AreEqual(expected: (uint)188, actual: Fibonacci.SummationOfEvenFibonacci(12)); 83 | Assert.AreEqual(expected: (uint)798, actual: Fibonacci.SummationOfEvenFibonacci(15)); 84 | } 85 | 86 | [TestMethod] 87 | [ExcludeFromCodeCoverage] 88 | public void InputSearchFibonacciTests() 89 | { 90 | Assert.AreEqual((uint)33, Fibonacci.ClosestInputForOutcome(4000000)); 91 | 92 | // Next values are sanitized to not spoil some online challenge 93 | //// Assert.AreEqual(expected: (uint)*sanitized*, actual: Fibonacci.SumationOfEvenFibonacci(Fibonacci.ClosestInputForOutcome(4000000))); 94 | } 95 | 96 | [TestMethod] 97 | [ExcludeFromCodeCoverage] 98 | public void SmallestNumberForNDigitsFibonacciTests() 99 | { 100 | // This is https://oeis.org/A072354 with a padding 0 in front 101 | var a072354Sequence = new uint[] { 0, 1, 7, 12, 17, 21, 26, 31, 36, 40, 45, 50, 55, 60, 64, 69, 74, 79, 84, 88, 93, 98, 103, 107, 112, 117, 122, 127, 131, 136, 141, 146, 151, 155, 160, 165, 170, 174, 179, 184, 189, 194, 198, 203, 208, 213, 217, 222, 227, 232, 237 }; 102 | 103 | for (uint value = 1; value < a072354Sequence.Length; value++) 104 | { 105 | Assert.AreEqual(expected: a072354Sequence[value], actual: Fibonacci.SmallestNumberForNDigitsFibonacci(value)); 106 | } 107 | 108 | Console.WriteLine($"The first Fibonacci number with 1000 digits is of order {Fibonacci.SmallestNumberForNDigitsFibonacci(1000)}"); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Tests/Daviburg.Utilities.Tests/HighCompositesTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities.Tests 21 | { 22 | using System; 23 | using System.Diagnostics.CodeAnalysis; 24 | using Microsoft.VisualStudio.TestTools.UnitTesting; 25 | 26 | [TestClass] 27 | [ExcludeFromCodeCoverage] 28 | public class HighCompositesTests 29 | { 30 | [TestMethod] 31 | [ExcludeFromCodeCoverage] 32 | public void HighCompositesTest() 33 | { 34 | long[] highComposites = { 1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720, 840, 1260, 1680, 2520, 5040, 7560, 10080, 15120, 20160, 25200, 27720, 45360, 50400, 55440, 83160, 110880, 166320, 221760, 277200, 332640, 498960, 554400, 665280, 720720 }; 35 | long[] divisorsCounts = { 1, 2, 3, 4, 6, 8, 9, 10, 12, 16, 18, 20, 24, 30, 32, 36, 40, 48, 60, 64, 72, 80, 84, 90, 96, 100, 108, 120, 128, 144, 160, 168, 180, 192, 200, 216, 224, 240 }; 36 | 37 | // Find 5 but let the remaining be discovered on-demand 38 | HighComposites.Singleton.FindHcns(5); 39 | 40 | for (int index = 0; index < highComposites.Length; index++) 41 | { 42 | Assert.AreEqual(highComposites[index], HighComposites.Singleton[index].Value); 43 | Assert.AreEqual(divisorsCounts[index], HighComposites.Singleton[index].CountOfDivisors); 44 | } 45 | } 46 | 47 | [TestMethod] 48 | [ExcludeFromCodeCoverage] 49 | public void LargeHighCompositeTest() 50 | { 51 | // Famous numbers: 6746328388800 last on the list from Ramanujan (1915). 52 | // 4497552259200 at index 102 because Ramanujan didn't include 1 in his list (likely intentionally). 53 | // 293318625600 which he missed but this algorithm doesn't. 54 | Assert.AreEqual((long)293318625600, HighComposites.Singleton[90].Value); 55 | Assert.AreEqual((long)4497552259200, HighComposites.Singleton[102].Value); 56 | Assert.AreEqual((long)6746328388800, HighComposites.Singleton[103].Value); 57 | for (var index = 0; index < 164; index++) 58 | { 59 | Console.WriteLine($"Order {index + 1:D3} has {HighComposites.Singleton[index].CountOfDivisors:D5} divisors for value {HighComposites.Singleton[index].Value}."); 60 | } 61 | 62 | Assert.AreEqual((long)4488062423933088000, HighComposites.Singleton[163].Value); 63 | Assert.AreEqual(138240, HighComposites.Singleton[163].CountOfDivisors); 64 | } 65 | 66 | [TestMethod] 67 | [ExcludeFromCodeCoverage] 68 | public void TriangularCompositeTest() 69 | { 70 | // First search for the lowest HCN that has more than 500 divisors. 71 | // Any number less that than, triangular or not, will have no more than 500 divisors, by definition of HCN. 72 | var index = 0; 73 | while (HighComposites.Singleton[index].CountOfDivisors <= 500) 74 | { 75 | index++; 76 | } 77 | 78 | Console.WriteLine($"First HCN with over 500 divisors is {HighComposites.Singleton[index].Value} with {HighComposites.Singleton[index].CountOfDivisors} divisors."); 79 | 80 | var triangular = Triangular.ClosestTriangularNumber(HighComposites.Singleton[index].Value); 81 | 82 | Console.WriteLine($"Jump-starting the search at triangular number of order {triangular.Order} and value {triangular.Value}."); 83 | 84 | while (triangular.Value.CountOfDivisors() < 500) 85 | { 86 | triangular = triangular.NextTriangularNumber(); 87 | } 88 | 89 | Console.WriteLine($"The secret number is the triangular number of order {triangular.Order} and value {triangular.Value}."); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Tests/Daviburg.Utilities.Tests/PrimesTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities.Tests 21 | { 22 | using System; 23 | using System.Diagnostics; 24 | using System.Diagnostics.CodeAnalysis; 25 | using Microsoft.VisualStudio.TestTools.UnitTesting; 26 | 27 | [TestClass] 28 | [ExcludeFromCodeCoverage] 29 | public class PrimesTests 30 | { 31 | [TestMethod] 32 | [ExcludeFromCodeCoverage] 33 | public void PrimesSimpleTests() 34 | { 35 | Assert.AreEqual(expected: 2, actual: Primes.Singleton[0]); 36 | Assert.AreEqual(expected: 3, actual: Primes.Singleton[1]); 37 | Assert.AreEqual(expected: 5, actual: Primes.Singleton[2]); 38 | Assert.AreEqual(expected: 7, actual: Primes.Singleton[3]); 39 | Assert.AreEqual(expected: 11, actual: Primes.Singleton[4]); 40 | Assert.AreEqual(expected: 13, actual: Primes.Singleton[5]); 41 | Assert.AreEqual(expected: 17, actual: Primes.Singleton[6]); 42 | Assert.AreEqual(expected: 19, actual: Primes.Singleton[7]); 43 | Assert.AreEqual(expected: 23, actual: Primes.Singleton[8]); 44 | //// Assert.AreEqual(expected: *sanitized *, actual: Primes.Singleton[10000]); 45 | } 46 | 47 | [TestMethod] 48 | [ExcludeFromCodeCoverage] 49 | public void ParallelPrimesTests() 50 | { 51 | var stopwatch = new Stopwatch(); 52 | var iterationCount = 0; 53 | do 54 | { 55 | iterationCount++; 56 | stopwatch.Restart(); 57 | Primes.Singleton.ParallelRangePrimeCompute(searchSizeLimit: 8000000, chunkSizeLimit: 600000); 58 | Console.WriteLine($"Round {iterationCount} in '{stopwatch.Elapsed}'. Discovered {Primes.Singleton.DiscoveredPrimesCount} primes which largest is {Primes.Singleton.LargestDiscoveredPrime}."); 59 | } while (iterationCount < 10); 60 | 61 | Assert.AreEqual(expected: 23, actual: Primes.Singleton[8]); 62 | Assert.AreEqual(expected: 37, actual: Primes.Singleton[11]); 63 | Assert.AreEqual(expected: 557, actual: Primes.Singleton[101]); 64 | Assert.AreEqual(expected: 7933, actual: Primes.Singleton[1001]); 65 | Assert.AreEqual(expected: 104759, actual: Primes.Singleton[10001]); 66 | Assert.AreEqual(expected: 1299743, actual: Primes.Singleton[100001]); 67 | 68 | // Raise iteration count to 26 for these. Execution time around 50 seconds on 12 core machine. 69 | ////Assert.AreEqual(expected: 15485917, actual: Primes.Singleton[1000001]); 70 | ////Assert.AreEqual(expected: 196026521, actual: Primes.Singleton[10871296]); 71 | } 72 | 73 | [TestMethod] 74 | [ExcludeFromCodeCoverage] 75 | public void SievePrimesTests() 76 | { 77 | Primes.Singleton.SieveSearch(searchSizeLimit: 20000000); 78 | Assert.IsTrue(Primes.Singleton.DiscoveredPrimesCount > 1000000); 79 | 80 | 81 | Assert.AreEqual(expected: 23, actual: Primes.Singleton[8]); 82 | Assert.AreEqual(expected: 37, actual: Primes.Singleton[11]); 83 | Assert.AreEqual(expected: 557, actual: Primes.Singleton[101]); 84 | Assert.AreEqual(expected: 7933, actual: Primes.Singleton[1001]); 85 | Assert.AreEqual(expected: 104759, actual: Primes.Singleton[10001]); 86 | Assert.AreEqual(expected: 1299743, actual: Primes.Singleton[100001]); 87 | Assert.AreEqual(expected: 15485917, actual: Primes.Singleton[1000001]); 88 | ////Assert.AreEqual(expected: 196026521, actual: Primes.Singleton[10871296]); 89 | } 90 | 91 | [TestMethod] 92 | [ExcludeFromCodeCoverage] 93 | public void PrimeSummationTests() 94 | { 95 | while (Primes.Singleton.LargestDiscoveredPrime < 2000000) 96 | { 97 | Primes.Singleton.ParallelRangePrimeCompute(searchSizeLimit: 2000100 - (int)Primes.Singleton.LargestDiscoveredPrime, chunkSizeLimit: 600000); 98 | } 99 | 100 | long sumOfPrimes = 0; 101 | for (int index = 0; Primes.Singleton[index] < 2000000; index++) 102 | { 103 | sumOfPrimes += Primes.Singleton[index]; 104 | } 105 | 106 | Console.WriteLine($"{sumOfPrimes}"); 107 | } 108 | 109 | [TestMethod] 110 | [ExcludeFromCodeCoverage] 111 | public void LargestPrimeFactorOfTests() 112 | { 113 | Assert.AreEqual(expected: 29, actual: Primes.Singleton.LargestPrimeFactorOf(13195)); 114 | 115 | // Next values are sanitized to not spoil some online challenge 116 | //// Assert.AreEqual(expected: *sanitized*, actual: Primes.Singleton.LargestPrimeFactorOf(*sanitized*)); 117 | } 118 | 119 | [TestMethod] 120 | [ExcludeFromCodeCoverage] 121 | public void SmallestMultipleOfAllNumbersToTests() 122 | { 123 | Assert.AreEqual(expected: 2, actual: Primes.Singleton.SmallestMultipleOfAllNumbersTo(2)); 124 | Assert.AreEqual(expected: 6, actual: Primes.Singleton.SmallestMultipleOfAllNumbersTo(3)); 125 | Assert.AreEqual(expected: 12, actual: Primes.Singleton.SmallestMultipleOfAllNumbersTo(4)); 126 | Assert.AreEqual(expected: 2520, actual: Primes.Singleton.SmallestMultipleOfAllNumbersTo(10)); 127 | 128 | // Next values are sanitized to not spoil some online challenge 129 | //// Assert.AreEqual(expected: *sanitized*, actual: Primes.Singleton.SmallestMultipleOfAllNumbersTo(*sanitized*)); 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /Tests/Daviburg.Utilities.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("Daviburg.Utilities.Tests")] 5 | [assembly: AssemblyDescription("Tests utilities for C# developpers")] 6 | [assembly: AssemblyConfiguration("")] 7 | [assembly: AssemblyCompany("Microsoft")] 8 | [assembly: AssemblyProduct("Daviburg.Utilities.Tests")] 9 | [assembly: AssemblyCopyright("Copyright © 2018 - GNU GPL v3")] 10 | [assembly: AssemblyTrademark("")] 11 | [assembly: AssemblyCulture("")] 12 | 13 | [assembly: ComVisible(false)] 14 | 15 | [assembly: Guid("020b6349-1dc7-4753-b68a-f1ae1cdf13bb")] 16 | 17 | // [assembly: AssemblyVersion("1.0.*")] 18 | [assembly: AssemblyVersion("1.0.0.0")] 19 | [assembly: AssemblyFileVersion("1.0.0.0")] 20 | -------------------------------------------------------------------------------- /Tests/Daviburg.Utilities.Tests/PythagoreanTripleTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities.Tests 21 | { 22 | using System.Diagnostics.CodeAnalysis; 23 | using Microsoft.VisualStudio.TestTools.UnitTesting; 24 | 25 | [TestClass] 26 | [ExcludeFromCodeCoverage] 27 | public class PythagoreanTripleTests 28 | { 29 | [TestMethod] 30 | [ExcludeFromCodeCoverage] 31 | public void PythagoreanTripleSimpleTests() 32 | { 33 | var simplestTriple = new PythagoreanTriple(2, 1); 34 | Assert.AreEqual(3, simplestTriple.IntegerA); 35 | Assert.AreEqual(4, simplestTriple.IntegerB); 36 | Assert.AreEqual(5, simplestTriple.IntegerC); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Tests/Daviburg.Utilities.Tests/TestEventListener.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // This file is part of Daviburg Utilities. 4 | // 5 | // Daviburg Utilities is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Daviburg Utilities is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with Daviburg Utilities. If not, see . 17 | // 18 | // -------------------------------------------------------------------------------------------------------------------- 19 | 20 | namespace Daviburg.Utilities.Tests 21 | { 22 | using System; 23 | using System.Collections.Generic; 24 | using System.Collections.ObjectModel; 25 | using System.Diagnostics.CodeAnalysis; 26 | using System.Diagnostics.Tracing; 27 | using System.Linq; 28 | 29 | /// 30 | /// A basic event listener helper class that records all event data for added event source(s) 31 | /// 32 | [ExcludeFromCodeCoverage] 33 | public sealed class TestEventListener : EventListener 34 | { 35 | private static readonly Lazy EventListenerInstance = new Lazy(() => new TestEventListener()); 36 | 37 | public static TestEventListener Log => EventListenerInstance.Value; 38 | 39 | private TestEventListener() 40 | { 41 | } 42 | 43 | private readonly List receivedEvents = new List(); 44 | public IReadOnlyList ReceivedEvents => this.receivedEvents as IReadOnlyList; 45 | 46 | public bool AddEventSource(Guid sourceGuid) 47 | { 48 | var matchedEventSource = EventSource.GetSources().SingleOrDefault(eventSource => eventSource.Guid.Equals(sourceGuid)); 49 | if (matchedEventSource == default(EventSource)) 50 | { 51 | return false; 52 | } 53 | 54 | this.EnableEvents(matchedEventSource, EventLevel.LogAlways); 55 | return true; 56 | } 57 | 58 | public void Disable() 59 | { 60 | this.DisableEvents(new EventSource(string.Empty)); 61 | } 62 | 63 | /// 64 | /// Helper to format the event payload 65 | /// 66 | public static string FormatPayload(ReadOnlyCollection payload) 67 | { 68 | return payload == null || !payload.Any() ? null : string.Join(" ", payload.Select(obj => $"[{obj}]")); 69 | } 70 | 71 | protected override void OnEventWritten(EventWrittenEventArgs eventData) 72 | { 73 | if (this.receivedEvents.Count < 10000) 74 | { 75 | this.receivedEvents.Add(eventData); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Tests/Daviburg.Utilities.Tests/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Tests/Daviburg.Utilities.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | --------------------------------------------------------------------------------