🏡 index : ~doyle/aoc.git

author Jordan Doyle <jordan@doyle.la> 2023-12-06 0:54:51.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2023-12-06 1:29:08.0 +00:00:00
commit
bd66e14d3d10d863e19fc767f9d1c612d6b5f8ed [patch]
tree
017bb72814439f30c37c4109b7c74cb2a9f0cdaa
download
bd66e14d3d10d863e19fc767f9d1c612d6b5f8ed.tar.gz

Add day 1



Diff

 1.hs | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/1.hs b/1.hs
new file mode 100755
index 0000000..1676ab4 100755
--- /dev/null
+++ a/1.hs
@@ -1,0 +1,68 @@
#!/usr/bin/env nix-shell
#!nix-shell -i runghc -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ])"
import Data.List (find, isInfixOf)
import Data.Maybe (catMaybes)

{- https://adventofcode.com/2023/day/1 -}

main = print =<< run 0

-- recursively read each line from stdin, concatenating first and last digits and folding the result into a sum
run :: Int -> IO Int
run acc = do
  line <- getLine
  if null line
    then return acc
    else do
      let x = concatFirstLastDigitsInString line
      run $ acc + x

-- read first and last digit in a string and concatenate the two together
concatFirstLastDigitsInString :: String -> Int
concatFirstLastDigitsInString s =

  case catMaybes [findDigitFromLeft "" s, findDigitFromRight "" s] of
    [x, y] -> x * 10 + y
    [x] -> x * 11
    _ -> 0

-- find the first digit in the string, searching from the left hand side
findDigitFromLeft :: String -> String -> Maybe Int
findDigitFromLeft acc "" = findDigit acc
findDigitFromLeft acc (x : xs) = case findDigit acc of
  Just v -> Just v
  Nothing -> findDigitFromLeft (acc ++ [x]) xs

-- find the last digit in the string, searching from the right hand side
findDigitFromRight :: String -> String -> Maybe Int
findDigitFromRight acc "" = findDigit acc
findDigitFromRight acc xs = case findDigit acc of
  Just v -> Just v
  Nothing -> findDigitFromRight (last xs : acc) (init xs)

-- finds a digit in either textual or numeric form and returns it as an int
findDigit :: String -> Maybe Int
findDigit s = case find (`isInfixOf` s) digitAsText of
  Just textual -> lookup textual digitMap
  Nothing -> Nothing
  where
    digitMap =

      [ ("eight", 8),
        ("seven", 7),
        ("three", 3),
        ("nine", 9),
        ("four", 4),
        ("five", 5),
        ("two", 2),
        ("one", 1),
        ("six", 6),
        ("1", 1),
        ("2", 2),
        ("3", 3),
        ("4", 4),
        ("5", 5),
        ("6", 6),
        ("7", 7),
        ("8", 8),
        ("9", 9)
      ]
    digitAsText = map fst digitMap