Advent of Code 2019 Repository
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

61 lines
2.3KB

  1. import System.Environment
  2. import Data.Set as Set
  3. import Data.List as List
  4. import Data.List.Split
  5. import Data.Maybe as Maybe
  6. parse :: [String] -> [[String]]
  7. parse = List.map (splitOn ",")
  8. -- Calculate given a direction, whether the length should be added or subtracted
  9. getDir :: Char -> Int
  10. getDir dir = if dir == 'L' || dir == 'D' then -1 else 1
  11. -- Calculate an array of points in a single step of the wire
  12. getPoints :: Char -> Int -> [[Int]] -> [[Int]]
  13. getPoints dir len points = points ++ [if dir == 'L' || dir == 'R' then [x + point, y] else [x, y + point]
  14. | point <- Prelude.map ((getDir dir)*) [1..len]]
  15. where [x,y] = last points
  16. -- Calculate all the points for all the steps
  17. getAllPoints :: [String] -> [[Int]] -> [[Int]]
  18. getAllPoints [] points = points
  19. getAllPoints (d:ds) points = getAllPoints ds (getPoints (head d) (read (tail d)::Int) points)
  20. -- Convert two wire array of points to sets, and find where they cross
  21. getIntersectionSet :: [[Int]] -> [[Int]] -> Set [Int]
  22. getIntersectionSet a b = (fromList a) `Set.intersection` (fromList b)
  23. -- Calculate Manhattan distance of point to (0,0)
  24. getDis :: [Int] -> Int
  25. getDis [x,y] = (abs x) + (abs y)
  26. -- Calculate Manhattan distance for all the intersection points, and return the smallest that isn't 0
  27. getMinManhattan :: Set [Int] -> Int
  28. getMinManhattan points = elemAt 1 $ Set.map getDis points
  29. -- Calculate number of steps needed to get to a given intersection point
  30. getPointStep :: [[Int]] -> [[Int]] -> [Int] -> Int
  31. getPointStep a b point = (fromMaybe 0 $ List.elemIndex point a) + (fromMaybe 0 $ List.elemIndex point b)
  32. -- Calculate steps for all the intersection points, and return the smallest that isn't 0
  33. getMinSteps :: [[Int]] -> [[Int]] -> Set [Int] -> Int
  34. getMinSteps a b points = elemAt 1 $ Set.map (getPointStep a b) points
  35. main = do
  36. input <- getArgs
  37. let x = parse input
  38. -- Get all the points for wires a and b
  39. let pointsA = getAllPoints (x!!0) [[0,0]]
  40. let pointsB = getAllPoints (x!!1) [[0,0]]
  41. -- Find all the points where the wires cross
  42. let intersection = pointsA `getIntersectionSet` pointsB
  43. -- Print the minimum Manhattan distance of an intersection
  44. print $ getMinManhattan intersection
  45. -- Print the minimum steps needed to get to an intersection
  46. print $ getMinSteps pointsA pointsB intersection