From 5779001081401cdb57a8fa3b21cee1072f733f5f Mon Sep 17 00:00:00 2001 From: martincostello Date: Tue, 13 Feb 2024 22:32:08 +0000 Subject: [PATCH 01/22] Update to .NET 9 preview 1 Update to preview 1 of .NET 9. --- .vsconfig | 2 +- Directory.Build.props | 4 ++-- benchmark.ps1 | 4 ---- build.ps1 | 4 ---- crank.ps1 | 4 ---- crank.yml | 2 +- global.json | 2 +- src/ProjectEuler/ProjectEuler.csproj | 2 +- tests/ProjectEuler.Benchmarks/ProjectEuler.Benchmarks.csproj | 2 +- tests/ProjectEuler.Tests/ProjectEuler.Tests.csproj | 2 +- 10 files changed, 8 insertions(+), 20 deletions(-) diff --git a/.vsconfig b/.vsconfig index a991ed17..8114a325 100644 --- a/.vsconfig +++ b/.vsconfig @@ -3,7 +3,7 @@ "components": [ "Microsoft.VisualStudio.Component.CoreEditor", "Microsoft.VisualStudio.Workload.CoreEditor", - "Microsoft.NetCore.Component.Runtime.8.0", + "Microsoft.NetCore.Component.Runtime.9.0", "Microsoft.NetCore.Component.SDK", "Microsoft.VisualStudio.Component.Roslyn.Compiler", "Microsoft.VisualStudio.Component.Roslyn.LanguageServices" diff --git a/Directory.Build.props b/Directory.Build.props index a3f8502d..0ed4d7f8 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -20,7 +20,7 @@ latest true en-US - $(NoWarn);CS1591 + $(NoWarn);CA1515;CS1591 enable Apache-2.0 https://github.com/martincostello/project-euler @@ -36,7 +36,7 @@ snupkg true true - 8.0.0 + 9.0.0 diff --git a/benchmark.ps1 b/benchmark.ps1 index 81d8d914..b3c251a6 100755 --- a/benchmark.ps1 +++ b/benchmark.ps1 @@ -11,10 +11,6 @@ param( $ErrorActionPreference = "Stop" $ProgressPreference = "SilentlyContinue" -if ($null -eq ${env:MSBUILDTERMINALLOGGER}) { - ${env:MSBUILDTERMINALLOGGER} = "auto" -} - $solutionPath = $PSScriptRoot $sdkFile = Join-Path $solutionPath "global.json" diff --git a/build.ps1 b/build.ps1 index 98c90ce4..03e20d88 100755 --- a/build.ps1 +++ b/build.ps1 @@ -7,10 +7,6 @@ param( [Parameter(Mandatory = $false)][switch] $SkipTests ) -if ($null -eq ${env:MSBUILDTERMINALLOGGER}) { - ${env:MSBUILDTERMINALLOGGER} = "auto" -} - $Configuration = "Release" $ErrorActionPreference = "Stop" $ProgressPreference = "SilentlyContinue" diff --git a/crank.ps1 b/crank.ps1 index a917bc4f..12114e4a 100644 --- a/crank.ps1 +++ b/crank.ps1 @@ -12,10 +12,6 @@ param( $ErrorActionPreference = "Stop" $global:ProgressPreference = "SilentlyContinue" -if ($null -eq ${env:MSBUILDTERMINALLOGGER}) { - ${env:MSBUILDTERMINALLOGGER} = "auto" -} - $additionalArgs = @() if (![string]::IsNullOrEmpty($BranchOrCommitOrTag)) { diff --git a/crank.yml b/crank.yml index 5c2dca94..1a56bf02 100644 --- a/crank.yml +++ b/crank.yml @@ -15,7 +15,7 @@ jobs: scenarios: microbenchmarks: application: - framework: net8.0 + framework: net9.0 job: microbenchmarks profiles: diff --git a/global.json b/global.json index b962d273..b207f0ea 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.404", + "version": "9.0.100-preview.1.24101.2", "allowPrerelease": false, "rollForward": "latestMajor" } diff --git a/src/ProjectEuler/ProjectEuler.csproj b/src/ProjectEuler/ProjectEuler.csproj index ce1a1303..17d11833 100644 --- a/src/ProjectEuler/ProjectEuler.csproj +++ b/src/ProjectEuler/ProjectEuler.csproj @@ -7,7 +7,7 @@ true true MartinCostello.ProjectEuler - net8.0 + net9.0 diff --git a/tests/ProjectEuler.Benchmarks/ProjectEuler.Benchmarks.csproj b/tests/ProjectEuler.Benchmarks/ProjectEuler.Benchmarks.csproj index 613e8b52..f47a2855 100644 --- a/tests/ProjectEuler.Benchmarks/ProjectEuler.Benchmarks.csproj +++ b/tests/ProjectEuler.Benchmarks/ProjectEuler.Benchmarks.csproj @@ -5,7 +5,7 @@ Exe MartinCostello.ProjectEuler.Benchmarks Benchmarks for ProjectEuler. - net8.0 + net9.0 diff --git a/tests/ProjectEuler.Tests/ProjectEuler.Tests.csproj b/tests/ProjectEuler.Tests/ProjectEuler.Tests.csproj index 94fa435d..151c0578 100644 --- a/tests/ProjectEuler.Tests/ProjectEuler.Tests.csproj +++ b/tests/ProjectEuler.Tests/ProjectEuler.Tests.csproj @@ -5,7 +5,7 @@ $(NoWarn);CA1707;CA1812;CA1861;CA2007;SA1600 MartinCostello.ProjectEuler Tests for ProjectEuler. - net8.0 + net9.0 From 66cad8e8e91c5283f9ffbd58ff77e898e6c7b20e Mon Sep 17 00:00:00 2001 From: martincostello Date: Wed, 14 Feb 2024 14:59:41 +0000 Subject: [PATCH 02/22] Use Index() Use the new `Index()` method. --- src/ProjectEuler/Puzzles/Puzzle025.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/ProjectEuler/Puzzles/Puzzle025.cs b/src/ProjectEuler/Puzzles/Puzzle025.cs index 02a0bd16..052bc57d 100644 --- a/src/ProjectEuler/Puzzles/Puzzle025.cs +++ b/src/ProjectEuler/Puzzles/Puzzle025.cs @@ -45,15 +45,11 @@ internal static IEnumerable Fibonacci() /// protected override int SolveCore(string[] args) { - int index = 0; - - foreach (BigInteger value in Fibonacci()) + foreach ((int index, BigInteger value) in Fibonacci().Index()) { - index++; - if (value >= Limit) { - Answer = index; + Answer = index + 1; break; } } From 127f9fc8cd4d4b628ff71c858bdc7b6df6b9d8e3 Mon Sep 17 00:00:00 2001 From: costellobot <102549341+costellobot@users.noreply.github.com> Date: Tue, 12 Mar 2024 20:58:04 +0000 Subject: [PATCH 03/22] Update .NET SDK (#367) Update .NET SDK to version 9.0.100-preview.2.24157.14. --- updated-dependencies: - dependency-name: Microsoft.NET.Sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: costellobot <102549341+costellobot@users.noreply.github.com> --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index b207f0ea..2b2e49e1 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100-preview.1.24101.2", + "version": "9.0.100-preview.2.24157.14", "allowPrerelease": false, "rollForward": "latestMajor" } From bad2bcd668f3bb89b81378e10108c02068b2236b Mon Sep 17 00:00:00 2001 From: costellobot <102549341+costellobot@users.noreply.github.com> Date: Thu, 11 Apr 2024 18:12:27 +0100 Subject: [PATCH 04/22] Update .NET SDK (#396) Update .NET SDK to version 9.0.100-preview.3.24204.13. --- updated-dependencies: - dependency-name: Microsoft.NET.Sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: costellobot <102549341+costellobot@users.noreply.github.com> --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 2b2e49e1..b35a5aa7 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100-preview.2.24157.14", + "version": "9.0.100-preview.3.24204.13", "allowPrerelease": false, "rollForward": "latestMajor" } From 297b5a7ab69be70221563d06c532d9c8fb7622fa Mon Sep 17 00:00:00 2001 From: costellobot <102549341+costellobot@users.noreply.github.com> Date: Tue, 21 May 2024 16:51:00 +0100 Subject: [PATCH 05/22] Update .NET SDK (#430) Update .NET SDK to version 9.0.100-preview.4.24267.66. --- updated-dependencies: - dependency-name: Microsoft.NET.Sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: costellobot <102549341+costellobot@users.noreply.github.com> --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index b35a5aa7..4713f969 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100-preview.3.24204.13", + "version": "9.0.100-preview.4.24267.66", "allowPrerelease": false, "rollForward": "latestMajor" } From eb4b9ae40940cfa9a30e5adca175b822f9239271 Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Fri, 31 May 2024 12:15:54 +0100 Subject: [PATCH 06/22] Use C# 13 Set `LangVersion=preview` to use C# 13. --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 0ed4d7f8..23e14271 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -17,7 +17,7 @@ false true enable - latest + preview true en-US $(NoWarn);CA1515;CS1591 From e8c1c43ffa7981fa2d35c824b32297c09b61bd49 Mon Sep 17 00:00:00 2001 From: martincostello Date: Fri, 31 May 2024 12:29:03 +0100 Subject: [PATCH 07/22] Add batch files for testing Add batch files to launch Visual Studio (Code) with the locally installed .NET SDK version for use with daily builds. --- startvs.cmd | 24 ++++++++++++++++++++++++ startvscode.cmd | 29 +++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 startvs.cmd create mode 100644 startvscode.cmd diff --git a/startvs.cmd b/startvs.cmd new file mode 100644 index 00000000..6a073110 --- /dev/null +++ b/startvs.cmd @@ -0,0 +1,24 @@ +@ECHO OFF +SETLOCAL + +:: This command launches a Visual Studio solution with environment variables required to use a local version of the .NET SDK. + +:: This tells .NET to use the same dotnet.exe that the build script uses. +SET DOTNET_ROOT=%~dp0.dotnetcli +SET DOTNET_ROOT(x86)=%~dp0.dotnetcli\x86 + +:: Put our local dotnet.exe on PATH first so Visual Studio knows which one to use. +SET PATH=%DOTNET_ROOT%;%PATH% + +SET sln=%~dp0ProjectEuler.sln + +IF NOT EXIST "%DOTNET_ROOT%\dotnet.exe" ( + echo The .NET SDK has not yet been installed. Run `%~dp0build.ps1` to install it + exit /b 1 +) + +IF "%VSINSTALLDIR%" == "" ( + start "" "%sln%" +) else ( + "%VSINSTALLDIR%\Common7\IDE\devenv.com" "%sln%" +) diff --git a/startvscode.cmd b/startvscode.cmd new file mode 100644 index 00000000..45ea8f6d --- /dev/null +++ b/startvscode.cmd @@ -0,0 +1,29 @@ +@ECHO OFF +SETLOCAL + +:: This command launches Visual Studio Code with environment variables required to use a local version of the .NET SDK. + +:: This tells .NET to use the same dotnet.exe that the build script uses. +SET DOTNET_ROOT=%~dp0.dotnetcli +SET DOTNET_ROOT(x86)=%~dp0.dotnetcli\x86 + +:: Put our local dotnet.exe on PATH first so Visual Studio Code knows which one to use. +SET PATH=%DOTNET_ROOT%;%PATH% + +:: Sets the Target Framework for Visual Studio Code. +SET TARGET=net9.0 + +SET FOLDER=%~1 + +IF NOT EXIST "%DOTNET_ROOT%\dotnet.exe" ( + echo The .NET SDK has not yet been installed. Run `%~dp0build.ps1` to install it + exit /b 1 +) + +IF "%FOLDER%"=="" ( + code . +) else ( + code "%FOLDER%" +) + +exit /b 1 From f0d90e2a4b62303ba4e564674e590ecc75c548d5 Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Tue, 11 Jun 2024 08:38:18 +0100 Subject: [PATCH 08/22] Disable rule with ruleset Disable CA1515 in the ruleset file rather than with NoWarn. --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 23e14271..e7fdc835 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -20,7 +20,7 @@ preview true en-US - $(NoWarn);CA1515;CS1591 + $(NoWarn);CS1591 enable Apache-2.0 https://github.com/martincostello/project-euler From 98ba6a82b410c2bf49c9045b0b89308077bc91bf Mon Sep 17 00:00:00 2001 From: costellobot <102549341+costellobot@users.noreply.github.com> Date: Tue, 11 Jun 2024 20:20:42 +0100 Subject: [PATCH 09/22] Update .NET SDK (#455) Update .NET SDK to version 9.0.100-preview.5.24307.3. --- updated-dependencies: - dependency-name: Microsoft.NET.Sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: costellobot <102549341+costellobot@users.noreply.github.com> --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 4713f969..e841aeed 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100-preview.4.24267.66", + "version": "9.0.100-preview.5.24307.3", "allowPrerelease": false, "rollForward": "latestMajor" } From 25ccc413b2b7e002832b8b0df6bad4ca2b35b551 Mon Sep 17 00:00:00 2001 From: costellobot <102549341+costellobot@users.noreply.github.com> Date: Tue, 9 Jul 2024 18:56:37 +0100 Subject: [PATCH 10/22] Update .NET SDK (#474) Update .NET SDK to version 9.0.100-preview.6.24328.19. --- updated-dependencies: - dependency-name: Microsoft.NET.Sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: costellobot <102549341+costellobot@users.noreply.github.com> --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index e841aeed..76f24e30 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100-preview.5.24307.3", + "version": "9.0.100-preview.6.24328.19", "allowPrerelease": false, "rollForward": "latestMajor" } From a3f8e1f84819235b7df617427a267b956f1d4c45 Mon Sep 17 00:00:00 2001 From: martincostello Date: Thu, 11 Jul 2024 15:28:47 +0100 Subject: [PATCH 11/22] Use System.Threading.Lock Use `System.Threading.Lock` instead of an object to resolve `IDE0330` warning in .NET 9 preview 7. --- src/ProjectEuler/Puzzles/Puzzle014.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ProjectEuler/Puzzles/Puzzle014.cs b/src/ProjectEuler/Puzzles/Puzzle014.cs index ce09a472..94a4ae39 100644 --- a/src/ProjectEuler/Puzzles/Puzzle014.cs +++ b/src/ProjectEuler/Puzzles/Puzzle014.cs @@ -13,11 +13,7 @@ public sealed class Puzzle014 : Puzzle /// private static readonly Dictionary _cache = new(1_000_000); -#if NET9_0_OR_GREATER private static readonly System.Threading.Lock _lock = new(); -#else - private static readonly object _lock = new(); -#endif /// public override string Question => "Which starting number, under one million, produces the longest chain?"; From 45fe769907a525a84c3b43c04c494525ad9f5467 Mon Sep 17 00:00:00 2001 From: martincostello Date: Tue, 13 Aug 2024 16:27:55 +0100 Subject: [PATCH 12/22] Update to .NET 9 preview 7 Update to preview 7 of .NET 9. --- Directory.Build.props | 2 +- global.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index e7fdc835..30726d9b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -20,7 +20,7 @@ preview true en-US - $(NoWarn);CS1591 + $(NoWarn);CS1591;CS9057 enable Apache-2.0 https://github.com/martincostello/project-euler diff --git a/global.json b/global.json index 76f24e30..0ddd1707 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100-preview.6.24328.19", + "version": "9.0.100-preview.7.24407.12", "allowPrerelease": false, "rollForward": "latestMajor" } From 3c26270b3ea020ea431a83a1d9c5f81b07d77a39 Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Mon, 9 Sep 2024 09:06:35 +0100 Subject: [PATCH 13/22] Revert to LangVersion latest Revert back to using the latest version of C# instead of preview. --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 30726d9b..fe0cba31 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -17,7 +17,7 @@ false true enable - preview + latest true en-US $(NoWarn);CS1591;CS9057 From 7120c1590b7102c1d66facdc9486552e83a0bbfc Mon Sep 17 00:00:00 2001 From: costellobot <102549341+costellobot@users.noreply.github.com> Date: Tue, 10 Sep 2024 20:46:33 +0100 Subject: [PATCH 14/22] Update .NET SDK (#548) Update .NET SDK to version 9.0.100-rc.1.24452.12. --- updated-dependencies: - dependency-name: Microsoft.NET.Sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: costellobot <102549341+costellobot@users.noreply.github.com> --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 0ddd1707..809fc626 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100-preview.7.24407.12", + "version": "9.0.100-rc.1.24452.12", "allowPrerelease": false, "rollForward": "latestMajor" } From 986382af022e46eeba96a60a4180bade23987806 Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Tue, 10 Sep 2024 20:48:19 +0100 Subject: [PATCH 15/22] Remove CS9057 Remove CS9057 suppression. --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index fe0cba31..128a48a3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -20,7 +20,7 @@ latest true en-US - $(NoWarn);CS1591;CS9057 + $(NoWarn);CS1591 enable Apache-2.0 https://github.com/martincostello/project-euler From f0113df7a62d0865fd868d70486976259c3c78ae Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Sat, 14 Sep 2024 13:04:58 +0100 Subject: [PATCH 16/22] Refactor puzzle 59 with span (#553) Refactor puzzle 59 to operate on spans of characters. --- src/ProjectEuler/Puzzles/Puzzle059.cs | 113 ++++++++++++++------------ 1 file changed, 62 insertions(+), 51 deletions(-) diff --git a/src/ProjectEuler/Puzzles/Puzzle059.cs b/src/ProjectEuler/Puzzles/Puzzle059.cs index 24266e3c..84cb81a9 100644 --- a/src/ProjectEuler/Puzzles/Puzzle059.cs +++ b/src/ProjectEuler/Puzzles/Puzzle059.cs @@ -1,9 +1,6 @@ // Copyright (c) Martin Costello, 2015. All rights reserved. // Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. -using System.Buffers; -using System.Text; - namespace MartinCostello.ProjectEuler.Puzzles; /// @@ -17,65 +14,62 @@ public sealed class Puzzle059 : Puzzle /// protected override int SolveCore(string[] args) { - byte[] encrypted = LoadText(); - - byte[] alphabet = Enumerable.Range('a', 26) - .Select((p) => (byte)p) - .ToArray(); - - var passwords = new List((int)Math.Pow(alphabet.Length, 3)); + const int AlphabetLength = 26; + const int KeyLength = 3; - for (int x = 0; x < alphabet.Length; x++) + ReadOnlySpan passwords = string.Create( + AlphabetLength * AlphabetLength * AlphabetLength * KeyLength, + "abcdefghijklmnopqrstuvwxyz", + static (buffer, alphabet) => { - for (int y = 0; y < alphabet.Length; y++) + int i = 0; + + for (int x = 0; x < alphabet.Length; x++) { - for (int z = 0; z < alphabet.Length; z++) + for (int y = 0; y < alphabet.Length; y++) { - passwords.Add([alphabet[x], alphabet[y], alphabet[z]]); + for (int z = 0; z < alphabet.Length; z++) + { + buffer[i] = alphabet[x]; + buffer[i + 1] = alphabet[y]; + buffer[i + 2] = alphabet[z]; + i += KeyLength; + } } } - } + }); - var encoding = Encoding.ASCII; + var encrypted = LoadText(); + Span decrypted = stackalloc char[encrypted.Length]; // Five most common English words - string[] commonWords = - [ - " the ", - " of ", - " and ", - " a ", - " to ", - ]; + ReadOnlySpan commonWords = [" the", " of", " and", " a", " to"]; - byte[][] words = commonWords.Select(encoding.GetBytes).ToArray(); - - byte[] key = new byte[encrypted.Length]; - byte[] decrypted = new byte[encrypted.Length]; - - foreach (byte[] password in passwords) + for (int i = 0; i < passwords.Length; i += KeyLength) { - for (int i = 0; i < key.Length;) + var password = passwords.Slice(i, KeyLength); + + for (int j = 0; j < decrypted.Length; j += KeyLength) { - key[i++] = password[0]; - key[i++] = password[1]; - key[i++] = password[2]; + decrypted[j] = (char)(encrypted[j] ^ password[0]); + decrypted[j + 1] = (char)(encrypted[j + 1] ^ password[1]); + decrypted[j + 2] = (char)(encrypted[j + 2] ^ password[2]); } - for (int i = 0; i < decrypted.Length; i++) + if (decrypted.IndexOf(commonWords[0]) > -1 && + decrypted.IndexOf(commonWords[1]) > -1 && + decrypted.IndexOf(commonWords[2]) > -1 && + decrypted.IndexOf(commonWords[3]) > -1 && + decrypted.IndexOf(commonWords[4]) > -1) { - decrypted[i] = (byte)(encrypted[i] ^ key[i]); - } + int sum = 0; - ReadOnlySpan plaintext = decrypted; + for (int k = 0; k < decrypted.Length; k++) + { + sum += decrypted[k]; + } - if (plaintext.IndexOf(words[0]) > -1 && - plaintext.IndexOf(words[1]) > -1 && - plaintext.IndexOf(words[2]) > -1 && - plaintext.IndexOf(words[3]) > -1 && - plaintext.IndexOf(words[4]) > -1) - { - Answer = decrypted.Select((p) => (int)p).Sum(); + Answer = sum; break; } } @@ -83,17 +77,34 @@ protected override int SolveCore(string[] args) return 0; } - private byte[] LoadText() + private ReadOnlySpan LoadText() { using var stream = ReadResource(); using var reader = new StreamReader(stream); - string text = reader.ReadToEnd(); + int length = 0; + ReadOnlySpan text = reader.ReadToEnd(); - string[] split = text.Split(','); + return string.Create(text.Length, text, (buffer, value) => + { + int comma; + int index = 0; + + while ((comma = value.IndexOf(',')) > -1) + { + buffer[index++] = ParseChar(value[..comma]); + value = value[(comma + 1)..]; + length++; + } + + if (value.Length > 0) + { + buffer[index] = ParseChar(value); + length++; + } - return split - .Select((p) => byte.Parse(p, CultureInfo.InvariantCulture)) - .ToArray(); + static char ParseChar(ReadOnlySpan span) + => (char)byte.Parse(span, CultureInfo.InvariantCulture); + }).AsSpan()[..length]; } } From c130f1b99823420624a26d19d1d41669accb4f88 Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Sat, 14 Sep 2024 15:13:16 +0100 Subject: [PATCH 17/22] Narrow search (#554) Search for the unique word "Euler" rather than for common words. --- src/ProjectEuler/Puzzles/Puzzle059.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/ProjectEuler/Puzzles/Puzzle059.cs b/src/ProjectEuler/Puzzles/Puzzle059.cs index 84cb81a9..e0b3bff5 100644 --- a/src/ProjectEuler/Puzzles/Puzzle059.cs +++ b/src/ProjectEuler/Puzzles/Puzzle059.cs @@ -42,9 +42,6 @@ protected override int SolveCore(string[] args) var encrypted = LoadText(); Span decrypted = stackalloc char[encrypted.Length]; - // Five most common English words - ReadOnlySpan commonWords = [" the", " of", " and", " a", " to"]; - for (int i = 0; i < passwords.Length; i += KeyLength) { var password = passwords.Slice(i, KeyLength); @@ -56,17 +53,15 @@ protected override int SolveCore(string[] args) decrypted[j + 2] = (char)(encrypted[j + 2] ^ password[2]); } - if (decrypted.IndexOf(commonWords[0]) > -1 && - decrypted.IndexOf(commonWords[1]) > -1 && - decrypted.IndexOf(commonWords[2]) > -1 && - decrypted.IndexOf(commonWords[3]) > -1 && - decrypted.IndexOf(commonWords[4]) > -1) + ReadOnlySpan span = decrypted; + + if (span.Contains("Euler", StringComparison.Ordinal)) { int sum = 0; - for (int k = 0; k < decrypted.Length; k++) + for (int j = 0; j < span.Length; j++) { - sum += decrypted[k]; + sum += span[j]; } Answer = sum; From 35fecfb454d9a7db01b9402af290d763149731cc Mon Sep 17 00:00:00 2001 From: martincostello Date: Sat, 14 Sep 2024 15:19:45 +0100 Subject: [PATCH 18/22] Use Split() Use the `ReadOnlySpan.Split(char)` method to see if that's better than manual coding. --- src/ProjectEuler/Puzzles/Puzzle059.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/ProjectEuler/Puzzles/Puzzle059.cs b/src/ProjectEuler/Puzzles/Puzzle059.cs index e0b3bff5..71528abd 100644 --- a/src/ProjectEuler/Puzzles/Puzzle059.cs +++ b/src/ProjectEuler/Puzzles/Puzzle059.cs @@ -82,21 +82,14 @@ private ReadOnlySpan LoadText() return string.Create(text.Length, text, (buffer, value) => { - int comma; int index = 0; - while ((comma = value.IndexOf(',')) > -1) + foreach (var range in value.Split(',')) { - buffer[index++] = ParseChar(value[..comma]); - value = value[(comma + 1)..]; - length++; + buffer[index++] = ParseChar(value[range]); } - if (value.Length > 0) - { - buffer[index] = ParseChar(value); - length++; - } + length = index; static char ParseChar(ReadOnlySpan span) => (char)byte.Parse(span, CultureInfo.InvariantCulture); From ecf511b32d54bf0c09149f94a7cd6702f0d1e322 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sat, 14 Sep 2024 15:31:40 +0100 Subject: [PATCH 19/22] Simplify loop - Remove local method. - Use a single variable. --- src/ProjectEuler/Puzzles/Puzzle059.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/ProjectEuler/Puzzles/Puzzle059.cs b/src/ProjectEuler/Puzzles/Puzzle059.cs index 71528abd..745fef1c 100644 --- a/src/ProjectEuler/Puzzles/Puzzle059.cs +++ b/src/ProjectEuler/Puzzles/Puzzle059.cs @@ -82,17 +82,10 @@ private ReadOnlySpan LoadText() return string.Create(text.Length, text, (buffer, value) => { - int index = 0; - foreach (var range in value.Split(',')) { - buffer[index++] = ParseChar(value[range]); + buffer[length++] = (char)byte.Parse(value[range], CultureInfo.InvariantCulture); } - - length = index; - - static char ParseChar(ReadOnlySpan span) - => (char)byte.Parse(span, CultureInfo.InvariantCulture); }).AsSpan()[..length]; } } From 79a89199ee40afb0d975f39c6a9014b6e381b5dd Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Sun, 15 Sep 2024 14:30:33 +0100 Subject: [PATCH 20/22] Use ReadOnlySpan.Split() (#557) - Treat some strings as spans and use their `Split()` method. - Use `string.Join(char)`. - Rename variable to theta symbol. --- src/ProjectEuler/Puzzles/Puzzle042.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/ProjectEuler/Puzzles/Puzzle042.cs b/src/ProjectEuler/Puzzles/Puzzle042.cs index ddf984fc..58fe7474 100644 --- a/src/ProjectEuler/Puzzles/Puzzle042.cs +++ b/src/ProjectEuler/Puzzles/Puzzle042.cs @@ -51,17 +51,16 @@ internal IList ReadWords() using var stream = ReadResource(); using var reader = new StreamReader(stream); - string rawWords = reader.ReadToEnd(); + var text = reader.ReadToEnd().AsSpan(); + var words = new List(); - string[] split = rawWords.Split(','); - - var words = new List(split.Length); - - foreach (string word in split) + foreach (var word in text.Split(',')) { - words.Add(word.Trim('\"')); + words.Add(text[word].Trim('\"').ToString()); } + words.TrimExcess(); + return words; } From be413b3726e15d8d14111af98a888e874d39bf18 Mon Sep 17 00:00:00 2001 From: costellobot <102549341+costellobot@users.noreply.github.com> Date: Tue, 8 Oct 2024 18:39:26 +0100 Subject: [PATCH 21/22] Update .NET SDK (#573) Update .NET SDK to version 9.0.100-rc.2.24474.11. --- updated-dependencies: - dependency-name: Microsoft.NET.Sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: costellobot <102549341+costellobot@users.noreply.github.com> --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 809fc626..6b97ddb7 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100-rc.1.24452.12", + "version": "9.0.100-rc.2.24474.11", "allowPrerelease": false, "rollForward": "latestMajor" } From 9663131aee6f4dddc91def5615ce04a4fd779766 Mon Sep 17 00:00:00 2001 From: costellobot <102549341+costellobot@users.noreply.github.com> Date: Tue, 12 Nov 2024 21:48:02 +0000 Subject: [PATCH 22/22] Update .NET SDK (#585) Update .NET SDK to version 9.0.100. --- updated-dependencies: - dependency-name: Microsoft.NET.Sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: costellobot <102549341+costellobot@users.noreply.github.com> --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 6b97ddb7..217f7c9f 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100-rc.2.24474.11", + "version": "9.0.100", "allowPrerelease": false, "rollForward": "latestMajor" }