Advertisement
Guest User

Untitled

a guest
Dec 14th, 2021
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.     import Data.Text (splitOn, unpack, pack, strip)
  2.     import Data.List(inits, tails)
  3.     import System.Environment (getArgs)
  4.     import Data.Set (fromList, toList)
  5.  
  6.  
  7.     main = do
  8.     lns <- getLines
  9.  
  10.     let seed = head lns
  11.     let instructions = map (splitOnStr "->") (filter (contains "->") lns)
  12.  
  13.     args <- getArgs
  14.     let desiredRounds = ((read::String->Int).head) (args)
  15.  
  16.     -- -- Part 1 - Naive
  17.     -- putStrLn "Part 1"
  18.  
  19.     -- let polymer = growPolymer desiredRounds seed instructions
  20.     -- let alphabet = fromList polymer
  21.     -- let occurrences = map (\a->
  22.     --                          (a, length (filter (\x->x==a) polymer))
  23.     --                          ) (toList alphabet)
  24.     -- let leastCommon = filter (\(_,y) -> y == (minimum (map (snd) occurrences))) occurrences
  25.     -- let mostCommon = filter (\(_,y) -> y == (maximum (map (snd) occurrences))) occurrences
  26.  
  27.     -- print occurrences
  28.     -- print $ (snd (head mostCommon)) - (snd (head leastCommon))
  29.  
  30.     -- Part 1 & 2 - Not so naive
  31.     let emptyCounts = map (\i->(head i,0)) instructions
  32.     let productions = map (\i-> (head i,[[head (head i)] ++ last i, last i ++[last (head i)]])) instructions
  33.     let seedCounts = map (\(pair, count)-> if contains pair seed then (pair, count+containsCount pair seed) else (pair, 0)) emptyCounts
  34.  
  35.     let finalCounts = growCounts desiredRounds seedCounts productions
  36.  
  37.     let letterCounts = occurrences finalCounts seed
  38.     let leastCommon = filter (\(_,y) -> y == (minimum (map (snd) letterCounts))) letterCounts
  39.     let mostCommon = filter (\(_,y) -> y == (maximum (map (snd) letterCounts))) letterCounts
  40.  
  41.     putStrLn "Part 1 & 2"
  42.     print mostCommon
  43.     print leastCommon
  44.     print $ (snd (head mostCommon)) - (snd (head leastCommon))
  45.  
  46.  
  47.     growCounts :: Int -> [(String,Int)] -> [(String,[String])]-> [(String,Int)]
  48.     growCounts rounds counts productions
  49.     | (rounds == 0) = counts
  50.     | otherwise =
  51.         growCounts (rounds - 1) (updateCounts counts productions) productions
  52.  
  53.     updateCounts :: [(String,Int)] -> [(String,[String])] -> [(String,Int)]
  54.     updateCounts counts productions =
  55.     foldl (\newcounts paircount ->
  56.             let pair = fst paircount
  57.                 increase = snd paircount
  58.                 producedPairs = snd $ head $ filter (\(x,y)->x==pair) productions
  59.                 withAdded = map (\(p,count)->
  60.                             if p `elem` producedPairs then (p, count + increase)
  61.                                 else (p,count)
  62.                             ) newcounts
  63.                 in map (\(p,count)->
  64.                             if p == pair then (pair, count - increase)
  65.                                 else (p,count)
  66.                             ) withAdded
  67.             ) counts counts
  68.  
  69.     occurrences :: [(String,Int)] -> String -> [(Char,Int)]
  70.     occurrences pairCounts seed = foldl (updateOccurrences) [(last seed,1)] pairCounts
  71.  
  72.     updateOccurrences :: [(Char, Int)] -> (String,Int) -> [(Char,Int)]
  73.     updateOccurrences charCounts pairCount =
  74.     let p = fst pairCount
  75.         c = snd pairCount
  76.         withFst = if (head p) `elem` (map fst charCounts) then
  77.                         (map (\(x,y)->if x == (head p) then (x,y+c) else (x,y)) charCounts)
  78.                     else charCounts ++ [(head p, c)]
  79.     in withFst
  80.  
  81.  
  82.     growPolymer :: Int -> String -> [[String]] -> String
  83.     growPolymer rounds seed instructions
  84.     | (rounds == 0) = seed
  85.     | otherwise = growPolymer (rounds  - 1) (applyInstructions seed instructions) instructions
  86.  
  87.     applyInstructions :: String -> [[String]] -> String
  88.     applyInstructions seed instructions =
  89.     let pairs = charPairs seed
  90.     in foldl (\x y-> if (x /= "") && (y /= "") then (x) ++ (tail y) else x ++ y) "" $ map (\x ->
  91.                 let instruction = head (filter ((==x).head) instructions)
  92.                 in if (length instruction) > 0 then [head x] ++ (last instruction) ++ [last x] else ""
  93.                 ) pairs
  94.  
  95.     splitOnStr :: String -> String -> [String]
  96.     splitOnStr d s = map (unpack.strip) $ splitOn (pack d) (pack s)
  97.  
  98.     substrings :: String -> [String]
  99.     substrings s = foldl (++) [] (map inits (tails s))
  100.  
  101.     charPairs :: String -> [String]
  102.     charPairs s = [x | g <- tails s, length g > 1, let x = take 2 g]
  103.  
  104.     contains :: String -> String -> Bool
  105.     contains needle haystack =
  106.     let matches = map (== needle) (substrings haystack)
  107.     in foldl (||) False matches
  108.  
  109.     containsCount :: String -> String -> Int
  110.     containsCount needle haystack =
  111.     let matches = map (\x-> if x == needle then 1 else 0) (substrings haystack)
  112.     in foldl (+) 0 matches
  113.  
  114.     getLines::IO([String])
  115.     getLines = do
  116.     s <- getContents
  117.     pure(lines s)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement