USING: accessors arrays ascii combinators formatting generalizations io.directories io.encodings.utf8 io.files io.files.private io.pathnames kernel literals math math.parser math.text.english namespaces present prettyprint regexp sequences source-files splitting strings tools.time ; IN: aoc2023.day1 CONSTANT: numbers1 R/ \d|one|two|three|four|five|six|seven|eight|nine/ CONSTANT: numbers2 R/ \d|eno|owt|eerht|ruof|evif|xis|neves|thgie|enin/ : day1-part1 ( seq -- sum ) [ [ digit? ] [ find nip ] [ find-last nip ] 2bi [ 48 - ] 2 napply swap 10 * + ] map sum ; : first-number ( str -- n ) numbers1 first-match >string { { "one" [ 1 ] } { "two" [ 2 ] } { "three" [ 3 ] } { "four" [ 4 ] } { "five" [ 5 ] } { "six" [ 6 ] } { "seven" [ 7 ] } { "eight" [ 8 ] } { "nine" [ 9 ] } [ string>number ] } case ; : last-number ( str -- n ) reverse numbers2 first-match >string { { "eno" [ 1 ] } { "owt" [ 2 ] } { "eerht" [ 3 ] } { "ruof" [ 4 ] } { "evif" [ 5 ] } { "xis" [ 6 ] } { "neves" [ 7 ] } { "thgie" [ 8 ] } { "enin" [ 9 ] } [ string>number ] } case ; : day1-part2 ( seq -- sum ) [ [ first-number ] [ last-number ] bi swap 10 * + ] map sum ; : day1-main ( -- ) $[ current-source-file get path>> parent-directory ] [ "input.txt" utf8 file-contents ] with-directory split-lines [ [ day1-part1 ] benchmark "part1. answer: %d, time: %d ns.\n" printf ] [ [ day1-part2 ] benchmark "part2. answer: %d, time: %d ns.\n" printf ] bi ; MAIN: day1-main