Quest 5: Fishbone Order

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

Link to participate: https://everybody.codes/

you are viewing a single comment's thread
view the rest of the comments
[โ€“] 3 points 1 year ago

I forgot that "weekdays" for a US website means something different for me here in UTC+9.

This was surprisingly fiddly, but I think I managed to do it reasonably neatly.

import Control.Arrow  
import Data.Foldable  
import Data.List (sortBy)  
import Data.List.Split  
import Data.Maybe  
import Data.Ord  

data Fishbone  
  = Fishbone (Maybe Int) Int (Maybe Int) Fishbone  
  | Empty  
  deriving (Eq)  

instance Ord Fishbone where  
  compare = comparing numbers  

readInput :: String -> [(Int, Fishbone)]  
readInput = map readSword . lines  
  where  
    readSword = (read *** build) . break (== ':')  
    build = foldl' insert Empty . map read . splitOn "," . tail  

insert bone x =  
  case bone of  
    (Fishbone l c r next)  
      | isNothing l && x < c -> Fishbone (Just x) c r next  
      | isNothing r && x > c -> Fishbone l c (Just x) next  
      | otherwise -> Fishbone l c r $ insert next x  
    Empty -> Fishbone Nothing x Nothing Empty  

spine (Fishbone _ c _ next) = c : spine next  
spine Empty = []  

numbers :: Fishbone -> [Int]  
numbers (Fishbone l c r next) =  
  (read $ concatMap show $ catMaybes [l, Just c, r])  
    : numbers next  
numbers Empty = []  

quality :: Fishbone -> Int  
quality = read . concatMap show . spine  

part1, part2, part3 :: [(Int, Fishbone)] -> Int  
part1 = quality . snd . head  
part2 = uncurry (-) . (maximum &&& minimum) . map (quality . snd)  
part3 = sum . zipWith (*) [1 ..] . map fst . sortBy (flip compareSwords)  
  where  
    compareSwords =  
      comparing (quality . snd)  
        <> comparing snd  
        <> comparing fst  

main =  
  forM_  
    [ ("everybody_codes_e2025_q05_p1.txt", part1),  
      ("everybody_codes_e2025_q05_p2.txt", part2),  
      ("everybody_codes_e2025_q05_p3.txt", part3)  
    ]  
    $ \(input, solve) -> readFile input >>= print . solve . readInput  
  • source