-

Haskell part 1

Kind of messy and verbose, but good enough

import Data.List

-- Note, for the sake of definition, the center point is a 1D ring

-- Given a ring index, returns the max value in that ring
getRingMax :: Int -> Int
getRingMax = (^ 2) . (1 +) . (2 *)

-- Given a ring index, returns the min value in that ring
getRingMin :: Int -> Int
getRingMin 0 = 1
getRingMin n = 1 + (getRingMax $ n - 1)

-- Given a value, returns the distance from its ring's midpoints to the center
getNormalDistance :: Int -> Int
getNormalDistance n = dist
  where mins = map getRingMin [0..]
        next = findIndex (\y -> y > n) mins
        dist = case next of
          Just a  -> a - 1 -- a represents the next rings index, and we want this rings index
          Nothing -> error "Oh geeze how did you mess up this bad? This shouldn't be possible"

-- Given a value, returns the midpoints of its ring
getRingMidpoints :: Int -> [Int]
getRingMidpoints n = [bottom, left, top, right]
  where dist       = getNormalDistance n
        maxRingVal = getRingMax dist
        sideLength = 2 * dist + 1
        subtrahend = sideLength - 1
        bottom     = (-) maxRingVal $ div subtrahend 2
        left       = (-) bottom subtrahend
        top        = (-) left subtrahend
        right      = (-) top subtrahend

-- Given a value, returns the distance to its ring's nearest midpoint
getTangentDistance n = minDist
  where midpoints = getRingMidpoints n
        distances = map (abs . (-) n) midpoints
        minDist   = minimum distances

-- Given a value, returns the manhattan distance to the center
getDistance :: Int -> Int
getDistance n = getTangentDistance n + getNormalDistance n

main = do
  contents <- readFile "../input.txt"
  let value = read contents :: Int
  putStrLn $ "Solution 1:" ++ (show $ getDistance value)
  putStrLn $ "Solution 2:" ++ "TODO"

Haskell part 2

No thanks I spent enough time on part 1

/r/adventofcode Thread