I'm not really happy with the repetition I have, but here's my Factor solution:
Here it is on GitHub with comments and imports.
: part1 ( -- )
"vocab:aoc-2023/day01/input.txt" utf8 file-lines
[
[ [ digit? ] find nip ]
[ [ digit? ] find-last nip ] bi
2array string>number
] map-sum .
;
MEMO: digit-words ( -- name-char-assoc )
[ "123456789" [ dup char>name "-" split1 nip ,, ] each ] H{ } make
;
: first-digit-char ( str -- num-char/f i/f )
[ digit? ] find swap
;
: last-digit-char ( str -- num-char/f i/f )
[ digit? ] find-last swap
;
: first-digit-word ( str -- num-char/f )
[
digit-words keys [
2dup subseq-index
dup [
[ digit-words at ] dip
,,
] [ 2drop ] if
] each drop !
] H{ } make
[ f ] [
sort-keys first last
] if-assoc-empty
;
: last-digit-word ( str -- num-char/f )
reverse
[
digit-words keys [
reverse
2dup subseq-index
dup [
[ reverse digit-words at ] dip
,,
] [ 2drop ] if
] each drop !
] H{ } make
[ f ] [
sort-keys first last
] if-assoc-empty
;
: first-digit ( str -- num-char )
dup first-digit-char dup [
pick 2dup swap head nip
first-digit-word dup [
[ 2drop ] dip
] [ 2drop ] if
nip
] [
2drop first-digit-word
] if
;
: last-digit ( str -- num-char )
dup last-digit-char dup [
pick 2dup swap 1 + tail nip
last-digit-word dup [
[ 2drop ] dip
] [ 2drop ] if
nip
] [
2drop last-digit-word
] if
;
: part2 ( -- )
"vocab:aoc-2023/day01/input.txt" utf8 file-lines
[ [ first-digit ] [ last-digit ] bi 2array string>number ] map-sum .
;