Faster parts 1-6 and part 7 skeleton

This commit is contained in:
Smaug123
2023-12-06 21:29:57 +00:00
parent 786a7eba8e
commit 148ea496c8
9 changed files with 213 additions and 49 deletions

View File

@@ -5,21 +5,13 @@ open System
[<RequireQualifiedAccess>]
module Day1 =
let firstDigit (s : ReadOnlySpan<char>) =
let mutable pos = 0
while '0' > s.[pos] || s.[pos] > '9' do
pos <- pos + 1
let inline firstDigit (s : ReadOnlySpan<char>) =
let pos = s.IndexOfAnyInRange ('0', '9')
byte s.[pos] - byte '0'
// No surrogate pairs please!
let lastDigit (s : ReadOnlySpan<char>) =
let mutable pos = s.Length - 1
while '0' > s.[pos] || s.[pos] > '9' do
pos <- pos - 1
let inline lastDigit (s : ReadOnlySpan<char>) =
let pos = s.LastIndexOfAnyInRange ('0', '9')
byte s.[pos] - byte '0'
let part1 (s : string) =
@@ -35,35 +27,66 @@ module Day1 =
total
let table =
[|
"one", 1uy
"two", 2uy
"three", 3uy
"four", 4uy
"five", 5uy
"six", 6uy
"seven", 7uy
"eight", 8uy
"nine", 9uy
|]
let isDigitSpelled (s : ReadOnlySpan<char>) (pos : int) (answer : byref<byte>) =
// Can't be bothered to write a jump-table compiler
if s.[pos] >= '0' && s.[pos] <= '9' then
answer <- byte s.[pos] - byte '0'
else if s.[pos] = 'o' then
if pos + 2 < s.Length && s.[pos + 1] = 'n' && s.[pos + 2] = 'e' then
answer <- 1uy
elif s.[pos] = 't' then
if pos + 2 < s.Length && s.[pos + 1] = 'w' && s.[pos + 2] = 'o' then
answer <- 2uy
elif
pos + 4 < s.Length
&& s.[pos + 1] = 'h'
&& s.[pos + 2] = 'r'
&& s.[pos + 3] = 'e'
&& s.[pos + 4] = 'e'
then
answer <- 3uy
elif s.[pos] = 'f' then
if pos + 3 < s.Length then
if s.[pos + 1] = 'o' && s.[pos + 2] = 'u' && s.[pos + 3] = 'r' then
answer <- 4uy
elif s.[pos + 1] = 'i' && s.[pos + 2] = 'v' && s.[pos + 3] = 'e' then
answer <- 5uy
elif s.[pos] = 's' then
if pos + 2 < s.Length && s.[pos + 1] = 'i' && s.[pos + 2] = 'x' then
answer <- 6uy
elif
pos + 4 < s.Length
&& s.[pos + 1] = 'e'
&& s.[pos + 2] = 'v'
&& s.[pos + 3] = 'e'
&& s.[pos + 4] = 'n'
then
answer <- 7uy
elif s.[pos] = 'e' then
if
pos + 4 < s.Length
&& s.[pos + 1] = 'i'
&& s.[pos + 2] = 'g'
&& s.[pos + 3] = 'h'
&& s.[pos + 4] = 't'
then
answer <- 8uy
elif s.[pos] = 'n' then
if
pos + 3 < s.Length
&& s.[pos + 1] = 'i'
&& s.[pos + 2] = 'n'
&& s.[pos + 3] = 'e'
then
answer <- 9uy
let firstDigitIncSpelled (s : ReadOnlySpan<char>) =
let mutable pos = 0
let mutable answer = 255uy
while answer = 255uy do
if s.[pos] >= '0' && s.[pos] <= '9' then
answer <- byte s.[pos] - byte '0'
else
for i, value in table do
if
pos + i.Length < s.Length
&& MemoryExtensions.SequenceEqual (s.Slice (pos, i.Length), i)
then
answer <- value
pos <- pos + 1
isDigitSpelled s pos &answer
pos <- pos + 1
answer
@@ -72,17 +95,8 @@ module Day1 =
let mutable answer = 255uy
while answer = 255uy do
if s.[pos] >= '0' && s.[pos] <= '9' then
answer <- byte s.[pos] - byte '0'
else
for i, value in table do
if
pos - i.Length + 1 >= 0
&& MemoryExtensions.SequenceEqual (s.Slice (pos - i.Length + 1, i.Length), i)
then
answer <- value
pos <- pos - 1
isDigitSpelled s pos &answer
pos <- pos - 1
answer