├── .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 '' [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 } : $"{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