├── 2015 ├── 1a.sh ├── 1b.sh ├── 4a.py ├── A10a.hs ├── A11a.hs ├── A12a.hs ├── A12a.py ├── A12b.hs ├── A12b.py ├── A13a.hs ├── A13b.hs ├── A14a.hs ├── A14b.hs ├── A15a.hs ├── A15b.hs ├── A16a.hs ├── A16b.hs ├── A17a.hs ├── A17b.hs ├── A18a.py ├── A18b.py ├── A19a.hs ├── A19b.hs ├── A19balt.hs ├── A20a.c ├── A20a.hs ├── A20b.c ├── A21a.hs ├── A21b.hs ├── A22a.hs ├── A22b.hs ├── A23a.py ├── A24a.c ├── A24a.hs ├── A24b.hs ├── A25a.py ├── A2a.hs ├── A2b.hs ├── A3a.hs ├── A3b.hs ├── A5a.hs ├── A5b.hs ├── A6a.py ├── A6b.py ├── A7a.hs ├── A7b.hs ├── A8a.hs ├── A8a.py ├── A8b.py ├── A9a.hs └── A9b.hs ├── 2016 ├── 1a.py ├── 1b.py ├── 2a.py ├── 2b.py ├── 3a.py ├── 3b.py ├── A10a.py ├── A11a.hs ├── A12a.py ├── A12b.py ├── A13a.hs ├── A13b.hs ├── A14a.hs ├── A14b.hs ├── A15a.hs ├── A16.hs ├── A17.hs ├── A18.hs ├── A19b.hs ├── A19b_stock.hs ├── A20a.hs ├── A20b.hs ├── A21a.py ├── A21b.py ├── A22a.hs ├── A22b.hs ├── A23a.py ├── A23b.py ├── A24.hs ├── A25.py ├── A3a.hs ├── A3b.hs ├── A4a.py ├── A4b.py ├── A5a.py ├── A5b.hs ├── A5b.py ├── A6a.py ├── A6b.py ├── A7a.hs ├── A7b.hs ├── A8a.py ├── A9a.hs ├── A9b.hs ├── A9b_Seq.hs └── Template.hs ├── 2017 ├── 1.py ├── 10a.py ├── 10b.py ├── 11.py ├── 12.py ├── 13a.py ├── 13b.py ├── 14.py ├── 15a.py ├── 15b.py ├── 16.py ├── 16alt.py ├── 17a.py ├── 17b.py ├── 18a.py ├── 18b.py ├── 19.py ├── 2.py ├── 21.py ├── 22a.py ├── 22b.py ├── 23a.py ├── 23b.c ├── 23b.py ├── 23b2.c ├── 23bgen.c ├── 24a.py ├── 24b.py ├── 25.py ├── 3a.py ├── 3b.py ├── 4.py ├── 5a.py ├── 5b.py ├── 6.py ├── 7.py ├── A1.hs ├── A2.hs ├── A20.hs ├── A4.hs ├── A8a.hs ├── A8b.hs ├── A9a.hs ├── A9b.hs └── Template.hs ├── 2018 ├── 10.py ├── 11a.py ├── 11b.py ├── 12a.py ├── 12b.py ├── 12bhash.py ├── 12pretty.py ├── 13a.py ├── 13b.py ├── 14a.py ├── 14b.py ├── 15a.py ├── 15b.py ├── 17.py ├── 18a.py ├── 18b.py ├── 19.input.annotated ├── 19b.py ├── 1a.py ├── 1b.py ├── 20a.py ├── 20b.py ├── 21bhelper.py ├── 22a.py ├── 22b.1.py ├── 22b.py ├── 23a.py ├── 23b.py ├── 23balt.py ├── 24a.py ├── 24b.py ├── 25a.py ├── 2a.py ├── 2b.py ├── 3a.py ├── 3b.py ├── 4.py ├── 5a.py ├── 5b.py ├── 5balt.py ├── 7a.py ├── 7b.py ├── 8a.py ├── 8b.py ├── A16a.hs ├── A16b.hs ├── A19a.hs ├── A21a.hs ├── A21b.hs ├── A6a.hs ├── A6b.hs ├── A9a.hs ├── A9b.hs ├── a5btyped.py └── rule.py ├── 2019 ├── .gitignore ├── 10.py ├── 11a.py ├── 11b.py ├── 12a.py ├── 12b.py ├── 13.py ├── 14.py ├── 15.py ├── 16a.py ├── 16b.alt.py ├── 16b.c ├── 16b.py ├── 17.py ├── 18a.py ├── 18abits.py ├── 18b.py ├── 18good.py ├── 19.py ├── 1a.py ├── 1b.py ├── 20a.py ├── 20b.py ├── 21a.py ├── 21b.py ├── 22a.2.py ├── 22a.py ├── 22b.py ├── 23a.py ├── 23b.py ├── 24a.py ├── 24b.py ├── 25.py ├── 25auto.py ├── 2a.py ├── 2b.py ├── 3a.py ├── 3b.py ├── 4a.py ├── 4b.py ├── 5a.py ├── 5b.py ├── 6.py ├── 7a.py ├── 7b.py ├── 7basync.py ├── 8.py ├── 9.py ├── _intcode.c ├── fib.intcode ├── intcode.py ├── run_intcode.py └── setup.py ├── 2020 ├── 1.py ├── 10a.py ├── 10b.py ├── 11a.py ├── 11b.py ├── 12a.py ├── 12b.py ├── 13a.py ├── 13b.py ├── 14a.py ├── 14b-bdd.py ├── 14b-bdd2.py ├── 14b.py ├── 15a.py ├── 15b.py ├── 16a.py ├── 16b.py ├── 17a.py ├── 17b.py ├── 18a.py ├── 18b.py ├── 19a.py ├── 19b.py ├── 20a.py ├── 20b.py ├── 21a.py ├── 21b.py ├── 22a.py ├── 22b.py ├── 23a.py ├── 23b.py ├── 24a.py ├── 24b.py ├── 25.py ├── 2a.py ├── 2b.py ├── 3a.py ├── 3b.py ├── 4a.py ├── 4b.py ├── 5a.py ├── 5b.alt.py ├── 5b.py ├── 6a.py ├── 6b.py ├── 7a.py ├── 7b.py ├── 8a.py ├── 8b.py ├── 9a.py ├── 9b.py └── template.py ├── 2021 ├── 10b.py ├── 11a.py ├── 11b.py ├── 12a.py ├── 12b.py ├── 13a.py ├── 13b.py ├── 14a.py ├── 14b.py ├── 14balt.py ├── 15a.py ├── 15b.py ├── 16b.py ├── 17.py ├── 18.py ├── 19.py ├── 1a.py ├── 1b.py ├── 20a.py ├── 20b.py ├── 21a.py ├── 21b.py ├── 22a.py ├── 22b.py ├── 23b.py ├── 24-honest.py ├── 24-honest2.py ├── 24.py ├── 25.py ├── 2a.py ├── 2b.py ├── 3a.py ├── 3b.py ├── 4a.py ├── 4b.py ├── 5a.py ├── 5b.py ├── 6a.py ├── 6b.py ├── 6balt.py ├── 7a.py ├── 7b.py ├── 8a.py ├── 8b.py ├── 8balt.py ├── 9a.py └── 9b.py ├── 2022 ├── 10a.py ├── 10b.py ├── 11a.py ├── 11b.py ├── 12a.py ├── 12b.py ├── 13a.py ├── 13b.py ├── 14a.py ├── 14b.py ├── 15a.py ├── 15b.py ├── 15bz3.py ├── 16a.py ├── 16b.py ├── 17a.py ├── 17b.py ├── 18b.py ├── 19a.py ├── 19b.py ├── 1a.py ├── 1b.py ├── 20-ante.py ├── 20a.py ├── 20b.py ├── 21a.py ├── 21b-honest.py ├── 21b.py ├── 22a.py ├── 22b.py ├── 23.py ├── 24a.py ├── 24b.py ├── 25.py ├── 2a.py ├── 2b.py ├── 3a.py ├── 3b.py ├── 4a.py ├── 4b.py ├── 5a.py ├── 5b.py ├── 6a.py ├── 6b.py ├── 7a.py ├── 7b.py ├── 8a.py ├── 8b.py ├── 9a.py └── 9b.py ├── 2023 ├── 10b.py ├── 11a.py ├── 11b.py ├── 12a.py ├── 12b.py ├── 13a.py ├── 13b.py ├── 14a.py ├── 14b.py ├── 15a.py ├── 15b.py ├── 16a.py ├── 16b.py ├── 17a.py ├── 17b.py ├── 18a.py ├── 18b.py ├── 19a.py ├── 19b.py ├── 1a.py ├── 1b.py ├── 2.py ├── 20a.py ├── 20b.py ├── 20bgv.py ├── 21a.py ├── 21b.py ├── 22a.py ├── 22b.py ├── 23a.py ├── 23b.py ├── 24a.py ├── 24b.py ├── 25.py ├── 3.py ├── 4.py ├── 5a.py ├── 5b.py ├── 6a.py ├── 6b.py ├── 7a.py ├── 7b.py ├── 8a.py ├── 8b.py ├── 9a.py └── 9b.py ├── 2024 ├── .gitignore ├── 1.py ├── 10a.py ├── 10b.py ├── 11a.py ├── 11b.py ├── 12.py ├── 13a.py ├── 13b-np.py ├── 13b-z3.py ├── 13b.py ├── 14a.py ├── 14b.py ├── 15a.py ├── 15b.py ├── 16-alt.py ├── 16.py ├── 17.py ├── 18-alt.py ├── 18-altb.py ├── 18.py ├── 19.py ├── 20a.py ├── 20b.py ├── 21a.py ├── 21b.py ├── 22a.py ├── 22b.py ├── 23a.py ├── 23b-bk.py ├── 23b.py ├── 24a.py ├── 24b.py ├── 25.py ├── 2a.py ├── 2b.py ├── 3a.py ├── 3b.py ├── 4a.py ├── 4b.py ├── 5.py ├── 6a.py ├── 6b.py ├── 7a.py ├── 7b.py ├── 8a.py ├── 8b.py ├── 9a.py └── 9b.py ├── .gitignore ├── LICENSE.md ├── README.md ├── best-of ├── snippets.py └── template.py /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.test* 3 | *.input* 4 | *.realinput 5 | *.o 6 | *.hi 7 | .mypy_cache 8 | *.pyc 9 | *.so 10 | -------------------------------------------------------------------------------- /2015/1a.sh: -------------------------------------------------------------------------------- 1 | expr $(cat 1.input | tr -dc '(' | wc -c) - $(cat 1.input | tr -dc ')' | wc -c) 2 | -------------------------------------------------------------------------------- /2015/1b.sh: -------------------------------------------------------------------------------- 1 | (for I in `seq 1 5000`; do printf "%d: " $I; head -c$I 1.realinput > 1.input; sh 1.sh; done) | grep -- -1 | head -n1 2 | -------------------------------------------------------------------------------- /2015/4a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import hashlib 4 | 5 | sekrit='bgvyzdsv' 6 | 7 | for i in range(1000000000): 8 | s=hashlib.md5((sekrit+str(i)).encode()) 9 | if s.hexdigest().startswith("000000"): 10 | print(i) 11 | break 12 | -------------------------------------------------------------------------------- /2015/A10a.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Map as Map 5 | 6 | 7 | looksay l = concatMap cleanup $ group l 8 | where cleanup a = [length a, head a] 9 | 10 | -- Without the type annotation, this gets inferred as [Integer], and 11 | -- then answer doesn't typecheck. Turning off the monomorphism 12 | -- restriction would also fix this. Grumble. Grumble grumble. 13 | input :: [Int] 14 | input = [3,1,1,3,3,2,2,1,1,3] 15 | 16 | -- When actually running this I definitely didn't have it as a program 17 | -- like this, and just ran this at ghci... 18 | answer = length $ iterate looksay input !! 40 19 | 20 | main = putStrLn $ show answer 21 | -------------------------------------------------------------------------------- /2015/A11a.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.Char 3 | 4 | incletter c i = chr (ord c + i) 5 | letter = incletter 'a' 6 | 7 | doubles = [ [c, c] | i <- [0..25], let c = letter i ] 8 | runs = [ [letter i, letter (i+1), letter (i+2)] | i <- [0..23] ] 9 | noneof = ["i", "o", "l"] 10 | 11 | increv ('z' : xs) = 'a' : increv xs 12 | increv (c : xs) = incletter c 1 : xs 13 | 14 | inc = reverse . increv . reverse 15 | 16 | matches s = hasDoubles && hasRun && notBad 17 | where hasDoubles = length (filter (`isInfixOf` s) doubles) >= 2 18 | hasRun = any (`isInfixOf` s) runs 19 | notBad = not $ any (`isInfixOf` s) noneof 20 | 21 | -- Again, I actually just ran this in ghci. Outputs both of the answers. 22 | input = "hepxcrrq" 23 | main = putStrLn $ show $ take 2 $ filter matches $ iterate inc input 24 | -------------------------------------------------------------------------------- /2015/A12a.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | import Text.JSON 4 | 5 | -- I wrote the python one first but wanted to see how nice doing it in 6 | -- haskell would have been. 7 | -- need to: cabal install json 8 | 9 | process :: JSValue -> Int 10 | process (JSRational _ i) = ceiling i 11 | process (JSArray ls) = sum $ map process ls 12 | process (JSObject ls) = sum $ map process $ map snd $ fromJSObject ls 13 | process _ = 0 14 | 15 | solve :: String -> Int 16 | solve input = process res 17 | where Ok res = decode input 18 | 19 | answer f = interact $ (++"\n") . show . f 20 | main = answer solve 21 | -------------------------------------------------------------------------------- /2015/A12a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys, json 4 | 5 | def crawl(obj): 6 | if isinstance(obj, int) or isinstance(obj, float): 7 | return obj 8 | 9 | sum = 0 10 | if isinstance(obj, list): 11 | for a in obj: 12 | sum += crawl(a) 13 | if isinstance(obj, dict): 14 | for a in obj.values(): 15 | sum += crawl(a) 16 | return sum 17 | 18 | def main(args): 19 | shit = "\n".join([s.strip() for s in sys.stdin]) 20 | js = json.loads(shit) 21 | 22 | print(crawl(js)) 23 | 24 | if __name__ == '__main__': 25 | sys.exit(main(sys.argv)) 26 | -------------------------------------------------------------------------------- /2015/A12b.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | import Text.JSON 4 | 5 | -- I wrote the python one first but wanted to see how nice doing it in 6 | -- haskell would have been. 7 | -- need to: cabal install json 8 | 9 | process :: JSValue -> Int 10 | process (JSRational _ i) = ceiling i 11 | process (JSArray ls) = sum $ map process ls 12 | process (JSObject ls) = 13 | if any (\ (_, v) -> encode v == encode "red") alist then 0 else 14 | sum $ map process $ map snd alist 15 | 16 | where alist = fromJSObject ls 17 | process _ = 0 18 | 19 | solve :: String -> Int 20 | solve input = process res 21 | where Ok res = decode input 22 | 23 | answer f = interact $ (++"\n") . show . f 24 | main = answer solve 25 | -------------------------------------------------------------------------------- /2015/A12b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys, json 4 | 5 | def crawl(obj): 6 | if isinstance(obj, int) or isinstance(obj, float): 7 | return obj 8 | 9 | sum = 0 10 | if isinstance(obj, list): 11 | for a in obj: 12 | sum += crawl(a) 13 | if isinstance(obj, dict): 14 | for a in obj.values(): 15 | if a == "red": 16 | return 0 17 | sum += crawl(a) 18 | return sum 19 | 20 | def main(args): 21 | shit = "\n".join([s.strip() for s in sys.stdin]) 22 | js = json.loads(shit) 23 | 24 | print(crawl(js)) 25 | 26 | if __name__ == '__main__': 27 | sys.exit(main(sys.argv)) 28 | -------------------------------------------------------------------------------- /2015/A13a.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Map as Map 5 | 6 | type Distances = Map.Map (String, String) Int 7 | 8 | parseLine :: String -> [((String, String), Int)] 9 | parseLine s = 10 | let [loc1, "would", dir, num, _, _, _, _, _, _, loc2] = words $ filter (/='.') s 11 | mult = if dir == "gain" then 1 else -1 12 | dist = read num * mult 13 | in 14 | [((loc1, loc2), dist)] 15 | 16 | makeMap :: [String] -> Distances 17 | makeMap = Map.fromList . concatMap parseLine 18 | 19 | adjPairs :: [a] -> [(a, a)] 20 | adjPairs (a1 : a2 : as) = (a1, a2) : adjPairs (a2 : as) 21 | adjPairs _ = [] 22 | 23 | lolpairs xs = (last xs, head xs) : adjPairs xs 24 | 25 | findShortest :: Distances -> Int 26 | findShortest ds = maximum costs 27 | where cities = nub $ map fst $ Map.keys ds 28 | lists = map lolpairs $ permutations cities 29 | get (k1, k2) = (fromJust $ Map.lookup (k1, k2) ds) + 30 | (fromJust $ Map.lookup (k2, k1) ds) 31 | listcost l = sum $ map get l 32 | costs = map listcost lists 33 | 34 | solve :: String -> Int 35 | solve = findShortest . makeMap . lines 36 | 37 | answer f = interact $ (++"\n") . show . f 38 | main = answer solve 39 | -------------------------------------------------------------------------------- /2015/A14a.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Map as Map 5 | 6 | 7 | parseLine :: String -> [Int] 8 | parseLine s = 9 | let [name, _, _, speed, "km/s", _, endurance, "seconds,", 10 | _, _, _, _, _, rest, "seconds."] = words s 11 | in 12 | concat $ repeat $ replicate (read endurance) (read speed) ++ replicate (read rest) 0 13 | 14 | allDistances :: [String] -> [[Int]] 15 | allDistances = map parseLine 16 | 17 | totalDistance :: Int -> [Int] -> Int 18 | totalDistance time thingus = sum $ take time thingus 19 | 20 | 21 | time = 2503 22 | furthest :: [[Int]] -> Int 23 | furthest dists = maximum $ map (totalDistance time) dists 24 | 25 | 26 | solve :: String -> Int 27 | solve = furthest . allDistances . lines 28 | 29 | answer f = interact $ (++"\n") . show . f 30 | main = answer solve 31 | -------------------------------------------------------------------------------- /2015/A14b.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Map as Map 5 | 6 | 7 | parseLine :: String -> [Int] 8 | parseLine s = 9 | let [name, _, _, speed, "km/s", _, endurance, "seconds,", 10 | _, _, _, _, _, rest, "seconds."] = words s 11 | in 12 | concat $ repeat $ replicate (read endurance) (read speed) ++ replicate (read rest) 0 13 | 14 | allDistances :: [String] -> [[Int]] 15 | allDistances = map parseLine 16 | 17 | totalDistance :: [Int] -> [Int] 18 | totalDistance = tail . scanl (+) 0 19 | 20 | leadingDistance :: [[Int]] -> [Int] 21 | leadingDistance = map maximum . transpose 22 | 23 | currentScore :: [Int] -> [Int] -> [Int] 24 | currentScore = 25 | zipWith (\lead x -> if lead == x then 1 else 0) 26 | 27 | time = 2503 28 | furthest :: [[Int]] -> Int 29 | furthest speeds = maximum $ map (sum . take time) scores 30 | 31 | where leader = leadingDistance totals 32 | totals = map totalDistance speeds 33 | scores = map (currentScore leader) totals 34 | 35 | 36 | 37 | solve :: String -> Int 38 | solve = furthest . allDistances . lines 39 | 40 | answer f = interact $ (++"\n") . show . f 41 | main = answer solve 42 | -------------------------------------------------------------------------------- /2015/A15a.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Char 5 | import qualified Data.Map as Map 6 | 7 | -- This is the first time I used monads for advent of code! 8 | 9 | -- Input hardcoded because there are only 4 lines of it 10 | ingredients = [[2, 0, -2, 0, 3], 11 | [0, 5, -3, 0, 3], 12 | [0, 0, 5, -1, 8], 13 | [0, -1, 0, 5, 8]] 14 | 15 | -- partitions target n returns a list of all lists 16 | -- [k_1, ..., k_n] s.t. k_1 + ... + k_n = target 17 | partitions :: Int -> Int -> [[Int]] 18 | partitions count 1 = [[count]] 19 | partitions count n = 20 | do k <- [0..count] 21 | l <- partitions (count-k) (n-1) 22 | return (k : l) 23 | 24 | scale k l = map (* k) l 25 | 26 | scores = 27 | do coefs <- partitions 100 (length ingredients) 28 | let scaled = zipWith scale coefs ingredients 29 | final = map sum $ transpose scaled 30 | guard $ not (any (<0) final) 31 | return $ product $ take 4 final 32 | 33 | main = putStrLn $ show $ maximum scores 34 | -------------------------------------------------------------------------------- /2015/A15b.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Char 5 | import qualified Data.Map as Map 6 | 7 | -- This is the first time I used monads for advent of code! 8 | 9 | -- Input hardcoded because there are only 4 lines of it 10 | ingredients = [[2, 0, -2, 0, 3], 11 | [0, 5, -3, 0, 3], 12 | [0, 0, 5, -1, 8], 13 | [0, -1, 0, 5, 8]] 14 | 15 | -- partitions target n returns a list of all lists 16 | -- [k_1, ..., k_n] s.t. k_1 + ... + k_n = target 17 | partitions :: Int -> Int -> [[Int]] 18 | partitions count 1 = [[count]] 19 | partitions count n = 20 | do k <- [0..count] 21 | l <- partitions (count-k) (n-1) 22 | return (k : l) 23 | 24 | scale k l = map (* k) l 25 | 26 | scores = 27 | do coefs <- partitions 100 (length ingredients) 28 | let scaled = zipWith scale coefs ingredients 29 | final = map sum $ transpose scaled 30 | calories = last final 31 | guard $ not (any (<0) final) 32 | guard $ calories == 500 33 | return $ product $ take 4 final 34 | 35 | main = putStrLn $ show $ maximum scores 36 | -------------------------------------------------------------------------------- /2015/A16a.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Char 5 | import qualified Data.Map as Map 6 | 7 | splitOn1 a b = fromJust $ stripInfix a b 8 | 9 | type Data = Map.Map String Int 10 | 11 | input = "Sue 0: children: 3, cats: 7, samoyeds: 2, pomeranians: 3, akitas: 0, vizslas: 0, goldfish: 5, trees: 3, cars: 2, perfumes: 1" 12 | 13 | target = snd $ readSue input 14 | 15 | readSue :: String -> (Int, Data) 16 | readSue s = 17 | let (prefix, body) = splitOn1 ": " s 18 | fragments = splitOn ", " body 19 | parsePart frag = 20 | let (key, count) = splitOn1 ": " frag in 21 | (key, read count) 22 | ["Sue", num] = words prefix 23 | in (read num, Map.fromList $ map parsePart fragments) 24 | 25 | matches :: (Int, Data) -> Bool 26 | matches (i, d) = all present $ Map.toList d 27 | where present (k, v) = Map.lookup k target == Just v 28 | 29 | solve :: String -> Int 30 | solve = fst . head . filter matches . map readSue . lines 31 | 32 | answer f = interact $ (++"\n") . show . f 33 | main = answer solve 34 | -------------------------------------------------------------------------------- /2015/A17a.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Map as Map 5 | 6 | solve :: String -> Int 7 | solve = length . filter (\x -> sum x == 150) . subsequences . map read . lines 8 | 9 | answer f = interact $ (++"\n") . show . f 10 | main = answer solve 11 | -------------------------------------------------------------------------------- /2015/A17b.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Map as Map 5 | 6 | countMinConfigs l = 7 | let min = minimum $ map length l 8 | in length $ filter (\z -> length z == min) l 9 | 10 | solve :: String -> Int 11 | solve = countMinConfigs . filter ((==150) . sum) . subsequences . 12 | map read . lines 13 | 14 | answer f = interact $ (++"\n") . show . f 15 | main = answer solve 16 | -------------------------------------------------------------------------------- /2015/A19a.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Char 5 | import qualified Data.Map as Map 6 | 7 | splitOn1 a b = fromJust $ stripInfix a b 8 | 9 | --type Data = Map.Map String Int 10 | type Mappings = [(String, String)] 11 | 12 | getMappings :: String -> Mappings -> [String] 13 | getMappings s = map snd . filter (\(x, _) -> x == s) 14 | 15 | getMap s = (from, to) 16 | where [from, "=>", to] = words s 17 | 18 | checkMatch :: String -> (String, String) -> Maybe (String, String) 19 | checkMatch s (from, to) = 20 | case stripPrefix from s of 21 | Nothing -> Nothing 22 | Just post -> Just (to, post) 23 | 24 | getNuses mapping [] = [] 25 | getNuses mapping (x:xs) = 26 | map (x:) (getNuses mapping xs) ++ 27 | do (to, post) <- mapMaybe (checkMatch (x:xs)) mapping 28 | return $ to++post 29 | 30 | 31 | solve input = length $ nub $ getNuses mappings molecule 32 | where molecule : "" : smappings = reverse $ lines input 33 | mappings = map getMap smappings 34 | 35 | answer f = interact $ (++"\n") . show . f 36 | main = answer solve 37 | -------------------------------------------------------------------------------- /2015/A20a.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define N 5000000 4 | int nus[N]; 5 | 6 | int main() { 7 | for (int i = 1; i < N; i++) { 8 | for (int j = i; j < N; j += i) { 9 | nus[j] += i*10; 10 | } 11 | } 12 | for (int i = 1; i < N; i++) { 13 | if (nus[i] >= 29000000) { 14 | printf("%d %d\n", i, nus[i]); 15 | break; 16 | } 17 | } 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /2015/A20a.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | 5 | elf n = e 6 | where e = n*10 : replicate (n-1) 0 ++ e 7 | elves n = 8 | zipWith (+) (elf n) (0 : elves (n+1)) 9 | 10 | presents n = 11 | sum [if n `mod` i == 0 then i*10 else 0 | i <- [1..n `div` 2]] + (n*10) 12 | 13 | -- This is vastly too slow. 14 | -------------------------------------------------------------------------------- /2015/A20b.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define N 5000000 4 | int nus[N]; 5 | 6 | int main() { 7 | for (int i = 1; i < N; i++) { 8 | for (int j = i, k = 0; j < N && k < 50; j += i, k++) { 9 | nus[j] += i*11; 10 | } 11 | } 12 | for (int i = 1; i < N; i++) { 13 | if (nus[i] >= 29000000) { 14 | printf("%d %d\n", i, nus[i]); 15 | break; 16 | } 17 | } 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /2015/A23a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys, json 4 | 5 | 6 | def step(cmd, state): 7 | cmd = cmd.replace(",", "") 8 | parts = cmd.split(" ") 9 | # print(parts) 10 | op = parts[0] 11 | reg = parts[1] 12 | 13 | if op == "hlf": 14 | state[reg] = int(state[reg] / 2) 15 | elif op == "tpl": 16 | state[reg] *= 3 17 | elif op == "inc": 18 | state[reg] += 1 19 | elif op == "jmp": 20 | return int(parts[1]) 21 | elif op == "jie": 22 | if state[reg] % 2 == 0: 23 | return int(parts[2]) 24 | elif op == "jio": 25 | # asdf. jump if *one* 26 | if state[reg] == 1: 27 | return int(parts[2]) 28 | 29 | return 1 30 | 31 | 32 | def main(args): 33 | prog = [s.strip() for s in sys.stdin] 34 | state = {"a": 1, "b": 0} 35 | ip = 0 36 | 37 | while ip >= 0 and ip < len(prog): 38 | ip += step(prog[ip], state) 39 | # print(ip, state) 40 | 41 | print(state) 42 | 43 | if __name__ == '__main__': 44 | sys.exit(main(sys.argv)) 45 | -------------------------------------------------------------------------------- /2015/A24a.c: -------------------------------------------------------------------------------- 1 | //meh 2 | 3 | #include 4 | 5 | int checkrest(long *rest, int count, long tgt) { 6 | for (int mask = 0; mask < 1 << count; mask++) { 7 | long sum = 0; 8 | for (int i = 0, j = 0; i < count; i++) { 9 | if (mask & (1 << i)) { 10 | sum += rest[i]; 11 | } 12 | } 13 | if (sum != total) continue; 14 | 15 | 16 | } 17 | 18 | void solve(long *nums, int count) { 19 | long total = 0; 20 | for (int i = 0; i < count; i++) { 21 | total += nums[i]; 22 | } 23 | total /= 3; 24 | 25 | long min_count = 10000000000; 26 | long min_q = 1 << 63; 27 | 28 | for (int mask = 0; mask < 1 << count; mask++) { 29 | int pop = __builtin_popcount(mask); 30 | if (pop > min_count) continue; 31 | 32 | long sum = 0; 33 | long rest[50]; 34 | for (int i = 0, j = 0; i < count; i++) { 35 | if (mask & (1 << i)) { 36 | sum += nums[i]; 37 | } else { 38 | rest[j++] = nums[i]; 39 | } 40 | } 41 | if (sum != total) continue; 42 | 43 | int main() { 44 | char buf[1000]; 45 | long nums[50]; 46 | int i = 0; 47 | while (fgets(buf, sizeof(buf), stdin)) { 48 | nums[i++] = strtol(buf, NULL, 0); 49 | } 50 | solve(nums, i); 51 | } 52 | -------------------------------------------------------------------------------- /2015/A25a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys, json 4 | 5 | def calc(cnt): 6 | v = 20151125 7 | for i in range(cnt-1): 8 | v = (v * 252533) % 33554393 9 | return v 10 | 11 | 12 | def main(args): 13 | N = 6100 14 | board = [[0]*N for i in range(N)] 15 | n = 1 16 | for i in range(N): 17 | for j in range(i): 18 | board[i-j-1][j] = n 19 | n += 1 20 | 21 | cnt = board[2978-1][3083-1] 22 | 23 | print(calc(1)) 24 | print(calc(2)) 25 | print(calc(3)) 26 | print(calc(cnt)) 27 | 28 | # print(board) 29 | 30 | if __name__ == '__main__': 31 | sys.exit(main(sys.argv)) 32 | 33 | 34 | # 0, 0 35 | # 1, 0 36 | # 0, 1 37 | # 2, 0 38 | # 1, 1 39 | # 0, 2 40 | -------------------------------------------------------------------------------- /2015/A2a.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | 4 | type Box = (Int, Int, Int) 5 | 6 | readBox :: String -> Box 7 | readBox s = 8 | let [a, b, c] = map read $ wordsBy (=='x') s 9 | in (a, b, c) 10 | 11 | calcBox :: Box -> Int 12 | calcBox (l, w, h) = 13 | let sides = sort [l*w, l*h, w*h] 14 | in 2*sum sides + head sides 15 | 16 | answer f = interact $ (++"\n") . show . f 17 | main = answer $ sum . map (calcBox . readBox) . lines 18 | -------------------------------------------------------------------------------- /2015/A2b.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | 4 | type Box = (Int, Int, Int) 5 | 6 | readBox :: String -> Box 7 | readBox s = 8 | let [a, b, c] = map read $ wordsBy (=='x') s 9 | in (a, b, c) 10 | 11 | calcBox :: Box -> Int 12 | calcBox (l, w, h) = 13 | let halfperims = sort [l+w, l+h, w+h] 14 | in 2*head halfperims + l*w*h 15 | 16 | main = interact $ (++"\n") . show . sum . map (calcBox . readBox) . lines 17 | -------------------------------------------------------------------------------- /2015/A3a.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | 4 | coord :: Char -> (Int, Int) 5 | coord '^' = (0, 1) 6 | coord 'v' = (0, -1) 7 | coord '>' = ( 1, 0) 8 | coord '<' = (-1, 0) 9 | coord _ = (0, 0) 10 | 11 | plusc (a, b) (c, d) = (a+c, b+d) 12 | 13 | answer f = interact $ (++"\n") . show . f 14 | main = answer $ length . group . sort . scanl plusc (0, 0) . map coord 15 | -------------------------------------------------------------------------------- /2015/A3b.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | 4 | coord :: Char -> (Int, Int) 5 | coord '^' = (0, 1) 6 | coord 'v' = (0, -1) 7 | coord '>' = ( 1, 0) 8 | coord '<' = (-1, 0) 9 | coord _ = (0, 0) 10 | 11 | plusc (a, b) (c, d) = (a+c, b+d) 12 | 13 | uninterleave [] = ([], []) 14 | uninterleave [x] = ([x], []) 15 | uninterleave (a : b : l) = (a : as, b : bs) 16 | where (as, bs) = uninterleave l 17 | 18 | nus = scanl plusc (0, 0) . map coord 19 | doit l = nus as ++ nus bs 20 | where (as, bs) = uninterleave l 21 | 22 | 23 | answer f = interact $ (++"\n") . show . f 24 | main = answer $ length . group . sort . doit 25 | -------------------------------------------------------------------------------- /2015/A5a.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.Char 3 | 4 | 5 | vowels = "aeiou" 6 | doubles = [ [c, c] | i <- [0..25], let c = chr (ord 'a' + i) ] 7 | bad = ["ab", "cd", "pq", "xy"] 8 | 9 | good s = hasVowels && hasDoubles && notBad 10 | where hasVowels = length (filter (`elem` vowels) s) >= 3 11 | hasDoubles = any (`isInfixOf` s) doubles 12 | notBad = not $ any (`isInfixOf` s) bad 13 | 14 | answer f = interact $ (++"\n") . show . f 15 | main = answer $ length . filter good . lines 16 | -------------------------------------------------------------------------------- /2015/A5b.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.Char 3 | 4 | 5 | isRepeatThing (c1 : c2 : rest) = [c1, c2] `isInfixOf` rest 6 | isRepeatThing _ = False 7 | 8 | isSandwichThing (c1 : _ : c2 : _) = c1 == c2 9 | isSandwichThing _ = False 10 | 11 | good s = hasRepeat && hasSandwich 12 | where hasRepeat = any isRepeatThing (tails s) 13 | hasSandwich = any isSandwichThing (tails s) 14 | 15 | answer f = interact $ (++"\n") . show . f 16 | main = answer $ length . filter good . lines 17 | -------------------------------------------------------------------------------- /2015/A6a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def process(cmd, lights): 6 | cmd = cmd.replace("turn ", "") 7 | cmd, c1, _, c2 = cmd.split(" ") 8 | x1, y1 = (int(x) for x in c1.split(",")) 9 | x2, y2 = (int(x) for x in c2.split(",")) 10 | 11 | # print(x1, y1, x2, y2) 12 | for x in range(x1, x2+1): 13 | for y in range(y1, y2+1): 14 | if cmd == "on": 15 | lights[x][y] = True 16 | elif cmd == "off": 17 | lights[x][y] = False 18 | elif cmd == "toggle": 19 | lights[x][y] = not lights[x][y] 20 | 21 | 22 | def main(args): 23 | cmds = [s.strip() for s in sys.stdin] 24 | 25 | lights = [[False for i in range(1000)] for j in range(1000)] 26 | 27 | for c in cmds: 28 | process(c, lights) 29 | 30 | count = 0 31 | for row in lights: 32 | for light in row: 33 | if light: count += 1 34 | 35 | print(count) 36 | 37 | if __name__ == '__main__': 38 | sys.exit(main(sys.argv)) 39 | -------------------------------------------------------------------------------- /2015/A6b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def process(cmd, lights): 6 | cmd = cmd.replace("turn ", "") 7 | cmd, c1, _, c2 = cmd.split(" ") 8 | x1, y1 = (int(x) for x in c1.split(",")) 9 | x2, y2 = (int(x) for x in c2.split(",")) 10 | 11 | # print(x1, y1, x2, y2) 12 | for x in range(x1, x2+1): 13 | for y in range(y1, y2+1): 14 | if cmd == "on": 15 | lights[x][y] += 1 16 | elif cmd == "off": 17 | if lights[x][y] > 0: 18 | lights[x][y] -= 1 19 | elif cmd == "toggle": 20 | lights[x][y] += 2 21 | 22 | 23 | def main(args): 24 | cmds = [s.strip() for s in sys.stdin] 25 | 26 | lights = [[0 for i in range(1000)] for j in range(1000)] 27 | 28 | for c in cmds: 29 | process(c, lights) 30 | 31 | count = 0 32 | for row in lights: 33 | for light in row: 34 | count += light 35 | 36 | print(count) 37 | 38 | if __name__ == '__main__': 39 | sys.exit(main(sys.argv)) 40 | -------------------------------------------------------------------------------- /2015/A8a.hs: -------------------------------------------------------------------------------- 1 | -- XXX: doesn't work because unicode 2 | 3 | import Data.List 4 | import Data.List.Extra 5 | 6 | 7 | nus :: String -> String 8 | nus = read 9 | 10 | lol s = show $ length s - length (nus s) 11 | --lol s = length (show s) - length s 12 | 13 | answer f = interact $ (++"\n") . show . f 14 | --main = answer $ sum . map lol . lines 15 | main = interact $ unlines . map lol . lines 16 | -------------------------------------------------------------------------------- /2015/A8a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | cmds = [s.strip() for s in sys.stdin] 7 | 8 | sum = 0 9 | for i in cmds: 10 | diff = len(i) - len(eval(i)) 11 | sum += diff 12 | print(sum) 13 | 14 | if __name__ == '__main__': 15 | sys.exit(main(sys.argv)) 16 | -------------------------------------------------------------------------------- /2015/A8b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | cmds = [s.strip() for s in sys.stdin] 7 | 8 | sum = 0 9 | for i in cmds: 10 | a = i 11 | a = a.replace('\\', '\\\\') 12 | a = a.replace("\"", '\\"') 13 | a = '"' + a + '"' 14 | sum += len(a) - len(i) 15 | print(sum) 16 | 17 | if __name__ == '__main__': 18 | sys.exit(main(sys.argv)) 19 | -------------------------------------------------------------------------------- /2015/A9a.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Map as Map 5 | 6 | type Distances = Map.Map (String, String) Int 7 | 8 | parseLine :: String -> [((String, String), Int)] 9 | parseLine s = 10 | let [loc1, "to", loc2, "=", num] = words s 11 | dist = read num 12 | in 13 | [((loc1, loc2), dist), ((loc2, loc1), dist)] 14 | 15 | makeMap :: [String] -> Distances 16 | makeMap = Map.fromList . concatMap parseLine 17 | 18 | adjPairs :: [a] -> [(a, a)] 19 | adjPairs xs = zip xs (tail xs) 20 | 21 | findShortest :: Distances -> Int 22 | findShortest ds = minimum $ map pathCost $ permutations cities 23 | where cities = nub $ map fst $ Map.keys ds 24 | get k = fromJust $ Map.lookup k ds 25 | pathCost l = sum $ map get $ adjPairs l 26 | 27 | solve :: String -> Int 28 | solve = findShortest . makeMap . lines 29 | 30 | answer f = interact $ (++"\n") . show . f 31 | main = answer solve 32 | -------------------------------------------------------------------------------- /2015/A9b.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Map as Map 5 | 6 | type Distances = Map.Map (String, String) Int 7 | 8 | parseLine :: String -> [((String, String), Int)] 9 | parseLine s = 10 | let [loc1, "to", loc2, "=", num] = words s 11 | dist = read num 12 | in 13 | [((loc1, loc2), dist), ((loc2, loc1), dist)] 14 | 15 | makeMap :: [String] -> Distances 16 | makeMap = Map.fromList . concatMap parseLine 17 | 18 | adjPairs :: [a] -> [(a, a)] 19 | adjPairs xs = zip xs (tail xs) 20 | 21 | findLongest :: Distances -> Int 22 | findLongest ds = maximum $ map pathCost $ permutations cities 23 | where cities = nub $ map fst $ Map.keys ds 24 | get k = fromJust $ Map.lookup k ds 25 | pathCost l = sum $ map get $ adjPairs l 26 | 27 | solve :: String -> Int 28 | solve = findLongest . makeMap . lines 29 | 30 | answer f = interact $ (++"\n") . show . f 31 | main = answer solve 32 | -------------------------------------------------------------------------------- /2016/1a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | DIRS = [(0,1), (1,0), (0,-1), (-1,0)] 6 | 7 | def main(args): 8 | s = input() 9 | cmds = s.split(", ") 10 | 11 | d = 0 12 | x = 0 13 | y = 0 14 | 15 | for a in cmds: 16 | turn = a[0] 17 | amt = int(a[1:]) 18 | if turn == 'R': d += 1 19 | else: d -= 1 20 | d %= 4 21 | x += amt * DIRS[d][0] 22 | y += amt * DIRS[d][1] 23 | 24 | print(abs(x)+abs(y)) 25 | 26 | if __name__ == '__main__': 27 | sys.exit(main(sys.argv)) 28 | -------------------------------------------------------------------------------- /2016/1b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | DIRS = [(0,1), (1,0), (0,-1), (-1,0)] 6 | 7 | def main(args): 8 | s = input() 9 | cmds = s.split(", ") 10 | visited = set() 11 | visited.add((0,0)) 12 | 13 | d = 0 14 | x = 0 15 | y = 0 16 | 17 | for a in cmds: 18 | turn = a[0] 19 | amt = int(a[1:]) 20 | if turn == 'R': d += 1 21 | else: d -= 1 22 | d %= 4 23 | 24 | for i in range(amt): 25 | x += DIRS[d][0] 26 | y += DIRS[d][1] 27 | # print((x,y)) 28 | if (x,y) in visited: 29 | print(abs(x)+abs(y)) 30 | return 31 | visited.add((x,y)) 32 | 33 | if __name__ == '__main__': 34 | sys.exit(main(sys.argv)) 35 | -------------------------------------------------------------------------------- /2016/2a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | DIRS = {"U": (0,-1), "D": (0,1), "L": (-1,0), "R": (1,0)} 6 | ass = ["123", "456", "789"] 7 | 8 | def main(args): 9 | nubs = [s.strip() for s in sys.stdin] 10 | 11 | x = 1 12 | y = 1 13 | 14 | for nub in nubs: 15 | for c in nub: 16 | x += DIRS[c][0] 17 | y += DIRS[c][1] 18 | if x < 0: x = 0 19 | if x > 2: x = 2 20 | if y < 0: y = 0 21 | if y > 2: y = 2 22 | # print(c, x,y, ass[y][x]) 23 | # print(": ", ass[y][x]) 24 | print(ass[y][x], end="") 25 | print() 26 | if __name__ == '__main__': 27 | sys.exit(main(sys.argv)) 28 | -------------------------------------------------------------------------------- /2016/2b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | DIRS = {"U": (0,-1), "D": (0,1), "L": (-1,0), "R": (1,0)} 6 | ass = [ 7 | " 1 ", 8 | " 234 ", 9 | "56789", 10 | " ABC ", 11 | " D "] 12 | 13 | def main(args): 14 | nubs = [s.strip() for s in sys.stdin] 15 | 16 | x = 0 17 | y = 2 18 | # print(ass[y][x]) 19 | for nub in nubs: 20 | for c in nub: 21 | old = x,y 22 | x += DIRS[c][0] 23 | y += DIRS[c][1] 24 | try: 25 | if ass[y][x] == " ": raise 5 26 | if x < 0 or y < 0: raise 2 27 | except: 28 | x, y = old 29 | # print(c, x,y, ass[y][x]) 30 | # print(": ", ass[y][x]) 31 | print(ass[y][x], end="") 32 | print() 33 | if __name__ == '__main__': 34 | sys.exit(main(sys.argv)) 35 | -------------------------------------------------------------------------------- /2016/3a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | 6 | def main(args): 7 | nubs = [s.strip() for s in sys.stdin] 8 | for i in range(len(nubs)): 9 | for j in range(10): 10 | nubs[i] = nubs[i].replace(" ", " ") 11 | 12 | 13 | wrong = 0 14 | 15 | for nub in nubs: 16 | butts = nub.split(" ") 17 | butts = [int(x) for x in butts] 18 | # print(butts) 19 | lol = sum(butts) 20 | for x in butts: 21 | other = lol - x 22 | # print(other, x) 23 | if other <= x: 24 | wrong += 1 25 | break 26 | print(len(nubs) - wrong) 27 | 28 | if __name__ == '__main__': 29 | sys.exit(main(sys.argv)) 30 | -------------------------------------------------------------------------------- /2016/3b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | 6 | def main(args): 7 | nubs = [s.strip() for s in sys.stdin] 8 | for i in range(len(nubs)): 9 | for j in range(10): 10 | nubs[i] = nubs[i].replace(" ", " ") 11 | nubs[i] = nubs[i].split(" ") 12 | nubs[i] = [int(x) for x in nubs[i]] 13 | print(nubs) 14 | 15 | 16 | wrong = 0 17 | 18 | fuckup = [] 19 | i = 0 20 | while i < len(nubs): 21 | fuckup += [[nubs[i][0], nubs[i+1][0], nubs[i+2][0]]] 22 | fuckup += [[nubs[i][1], nubs[i+1][1], nubs[i+2][1]]] 23 | fuckup += [[nubs[i][2], nubs[i+1][2], nubs[i+2][2]]] 24 | i += 3 25 | 26 | 27 | for butts in fuckup: 28 | lol = sum(butts) 29 | for x in butts: 30 | other = lol - x 31 | # print(other, x) 32 | if other <= x: 33 | wrong += 1 34 | break 35 | print(len(nubs) - wrong) 36 | 37 | if __name__ == '__main__': 38 | sys.exit(main(sys.argv)) 39 | -------------------------------------------------------------------------------- /2016/A12a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys, json 4 | from collections import defaultdict 5 | 6 | def val(regs, x): 7 | if x in regs: 8 | return regs[x] 9 | else: 10 | return int(x) 11 | 12 | 13 | def main(args): 14 | program = [s.strip().split(" ") for s in sys.stdin] 15 | regs = {c: 0 for c in "abcd"} 16 | 17 | pc = 0 18 | 19 | while pc < len(program): 20 | cmd = program[pc] 21 | if cmd[0] == "cpy": 22 | regs[cmd[2]] = val(regs, cmd[1]) 23 | elif cmd[0] == "inc": 24 | regs[cmd[1]] += 1 25 | elif cmd[0] == "dec": 26 | regs[cmd[1]] -= 1 27 | elif cmd[0] == "jnz": 28 | if val(regs, cmd[1]) != 0: 29 | pc += int(cmd[2]) - 1 30 | pc += 1 31 | 32 | print(regs["a"]) 33 | 34 | 35 | if __name__ == '__main__': 36 | sys.exit(main(sys.argv)) 37 | -------------------------------------------------------------------------------- /2016/A12b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys, json 4 | from collections import defaultdict 5 | 6 | def val(regs, x): 7 | if x in regs: 8 | return regs[x] 9 | else: 10 | return int(x) 11 | 12 | 13 | def main(args): 14 | program = [s.strip().split(" ") for s in sys.stdin] 15 | regs = {c: 0 for c in "abcd"} 16 | regs["c"] = 1 17 | 18 | pc = 0 19 | 20 | while pc < len(program): 21 | cmd = program[pc] 22 | if cmd[0] == "cpy": 23 | regs[cmd[2]] = val(regs, cmd[1]) 24 | elif cmd[0] == "inc": 25 | regs[cmd[1]] += 1 26 | elif cmd[0] == "dec": 27 | regs[cmd[1]] -= 1 28 | elif cmd[0] == "jnz": 29 | if val(regs, cmd[1]) != 0: 30 | pc += int(cmd[2]) - 1 31 | pc += 1 32 | 33 | print(regs["a"]) 34 | 35 | 36 | if __name__ == '__main__': 37 | sys.exit(main(sys.argv)) 38 | -------------------------------------------------------------------------------- /2016/A13a.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Char as C 5 | import qualified Data.Map as Map 6 | 7 | import Debug.Trace 8 | 9 | faveNum = 1362 10 | goal = (31,39) 11 | --faveNum = 10 12 | --goal = (7,4) 13 | 14 | 15 | countOnes 0 = 0 16 | countOnes n = n `mod` 2 + countOnes (n `div` 2) 17 | 18 | isOpen (x, y) = countOnes ((x*x + 3*x + 2*x*y + y + y*y) + faveNum) `mod` 2 == 0 19 | 20 | 21 | 22 | search seen ((k, c@(x,y)) : rest) = 23 | if c == goal then k else 24 | search (Map.insert c () seen) $ rest ++ 25 | do (i,j) <- [(-1,0), (1,0), (0,-1), (0,1)] 26 | let c'@(x',y') = (x+i, y+j) 27 | guard $ x' >= 0 && y' >= 0 28 | guard $ isOpen c' 29 | guard $ Map.notMember c' seen 30 | return (k+1, c') 31 | 32 | -------- 33 | main = putStrLn $ show $ search Map.empty [(0, (1,1))] 34 | -------------------------------------------------------------------------------- /2016/A13b.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Char as C 5 | import qualified Data.Map as Map 6 | 7 | import Debug.Trace 8 | 9 | faveNum = 1362 10 | goal = (31,39) 11 | --faveNum = 10 12 | --goal = (7,4) 13 | 14 | 15 | countOnes 0 = 0 16 | countOnes n = n `mod` 2 + countOnes (n `div` 2) 17 | 18 | isOpen (x, y) = countOnes ((x*x + 3*x + 2*x*y + y + y*y) + faveNum) `mod` 2 == 0 19 | 20 | 21 | 22 | search seen [] = Map.size seen 23 | search seen ((k, c@(x,y)) : rest) = 24 | search (Map.insert c () seen) $ rest ++ 25 | do (i,j) <- [(-1,0), (1,0), (0,-1), (0,1)] 26 | let c'@(x',y') = (x+i, y+j) 27 | guard $ x' >= 0 && y' >= 0 28 | guard $ isOpen c' 29 | guard $ Map.notMember c' seen 30 | guard $ k < 50 31 | return (k+1, c') 32 | 33 | -------- 34 | main = putStrLn $ show $ search Map.empty [(0, (1,1))] 35 | -------------------------------------------------------------------------------- /2016/A14a.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.Maybe 3 | import Data.Hash.MD5 4 | import Debug.Trace 5 | 6 | key = "yjdafjpo" 7 | 8 | stream = map (\i -> (i, md5s $ Str $ key ++ show i)) [0..] 9 | 10 | getTrip (a : rest@(b : c : _)) | a == b && b == c = Just a 11 | getTrip (_ : rest) = getTrip rest 12 | getTrip _ = Nothing 13 | 14 | isKey ((i, x) : rest) = case getTrip x of 15 | Nothing -> False 16 | Just c -> any (isInfixOf (replicate 5 c) . snd) (take 1000 rest) 17 | 18 | main = putStrLn $ show $ (map head $ filter isKey (tails stream)) !! 63 19 | -------------------------------------------------------------------------------- /2016/A14b.hs: -------------------------------------------------------------------------------- 1 | -- ASDF. Data.Hash.MD5 appeared to suck. 2 | 3 | import Data.List 4 | import qualified Crypto.Hash.MD5 as MD5 5 | import qualified Data.ByteString.Char8 as BS 6 | import qualified Data.ByteString.Base16 as B16 7 | import Debug.Trace 8 | 9 | 10 | key = "yjdafjpo" 11 | --key = "abc" 12 | 13 | md5' = B16.encode . MD5.hash 14 | smd5 s = trace s (loop 2017 (BS.pack s)) 15 | where loop 0 s = BS.unpack s 16 | loop k s = loop (k-1) (md5' s) 17 | 18 | stream = map (\i -> (i, smd5 $ key ++ show i)) [0..] 19 | 20 | getTrip (a : rest@(b : c : _)) | a == b && b == c = Just a 21 | getTrip (_ : rest) = getTrip rest 22 | getTrip _ = Nothing 23 | 24 | isKey ((i, x) : rest) = case getTrip x of 25 | Nothing -> False 26 | Just c -> any (isInfixOf (replicate 5 c) . snd) (take 1000 rest) 27 | 28 | main = putStrLn $ show $ (map head $ filter isKey (tails stream)) !! 63 29 | -------------------------------------------------------------------------------- /2016/A15a.hs: -------------------------------------------------------------------------------- 1 | -- This is a hilariously dumb solution. 2 | 3 | -- It didn't occur to me to use modular arithmetic until I had already 4 | -- finished. The first thing that popped into my head was to simulate 5 | -- the circular disks using infinite lists. And I made the leaderboard 6 | -- sooooooooo lol. 7 | 8 | -- both parts 9 | 10 | import Data.List.Extra 11 | 12 | stuff = map make [ 13 | (13, 11), 14 | (5, 0), 15 | (17, 11), 16 | (3, 0), 17 | (7, 2), 18 | (19, 17) 19 | ] 20 | stuff_b = stuff ++ [make (11, 0)] 21 | stuff' = map make [ 22 | (5, 4), 23 | (2, 1) 24 | ] 25 | 26 | make (cnt, start) = drop start $ cycle (True : replicate (cnt-1) False) 27 | 28 | step = map tail 29 | 30 | ready state = all (\i -> (state' !! i) !! i) [0..length state-1] 31 | where state' = step state 32 | 33 | search i state = 34 | if ready state then i else 35 | search (i+1) (step state) 36 | 37 | -- when actually doing it I just poked at things in ghci though 38 | main = putStrLn $ show $ (search 0 stuff, search 0 stuff_b) 39 | -------------------------------------------------------------------------------- /2016/A16.hs: -------------------------------------------------------------------------------- 1 | -- both parts 2 | 3 | import Data.List.Extra 4 | import Data.Char 5 | 6 | input = map digitToInt "01111001100111011" 7 | 8 | step a = 9 | let b = map (1-) $ reverse a 10 | in a ++ [0] ++ b 11 | 12 | make a len = until ((len <=) . length) step a 13 | 14 | cksum' [] = [] 15 | cksum' (x:y:xs) = c : cksum' xs 16 | where c = if x == y then '1' else '0' 17 | 18 | cksum = until (odd . length) cksum' . cksum' 19 | 20 | -- when actually doing it I just poked at things in ghci though 21 | solve len = cksum $ take len $ make input len 22 | main = putStrLn $ show $ (solve 272, solve 35651584) 23 | -------------------------------------------------------------------------------- /2016/A18.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Char as C 5 | import qualified Data.Map as Map 6 | 7 | -------- 8 | 9 | input = "...^^^^^..^...^...^^^^^^...^.^^^.^.^.^^.^^^.....^.^^^...^^^^^^.....^.^^...^^^^^...^.^^^.^^......^^^^" 10 | 11 | one "^^." = '^' 12 | one ".^^" = '^' 13 | one "^.." = '^' 14 | one "..^" = '^' 15 | one _ = '.' 16 | 17 | step s = map one $ filter ((==3) . length) $ map (take 3) $ tails ('.' : s ++ ".") 18 | 19 | -- this stuff actually done in ghci 20 | solve n = length $ filter (=='.') $ concat $ take n $ iterate step input 21 | main = do print $ solve 40 22 | print $ solve 400000 23 | -------------------------------------------------------------------------------- /2016/A19b.hs: -------------------------------------------------------------------------------- 1 | -- for part 1 I just looked up the closed form for the Josephus 2 | -- problem on wikipedia <_< 3 | 4 | import Control.Monad 5 | import Data.List.Extra 6 | import Data.Maybe 7 | import qualified Data.Char as C 8 | import qualified Data.Map as Map 9 | import qualified Data.Sequence as S 10 | import Data.Sequence ((<|), (|>), (><), ViewL(..)) 11 | 12 | -------- 13 | num = 3005290 14 | 15 | makeSeq n = S.fromList [1..n] 16 | 17 | step s = 18 | let (keep, s') = S.splitAt 1 s 19 | s'' = S.deleteAt ((S.length s' - 1) `div` 2) s' 20 | in s'' >< keep 21 | 22 | -- done at repl 23 | solve n = (`S.index` 0) $ until ((==1) . S.length) step $ makeSeq num 24 | main = print $ solve num 25 | -------------------------------------------------------------------------------- /2016/A20a.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Char as C 5 | import qualified Data.Map as Map 6 | import qualified Data.Set as Set 7 | import Control.Arrow 8 | 9 | ------ 10 | answer :: (Show a) => (String -> a) -> IO () 11 | answer f = interact $ (++"\n") . show . f 12 | 13 | splitOn1 a b = fromJust $ stripInfix a b 14 | 15 | -------- 16 | 17 | matches k (lo,hi) = k >= lo && k <= hi 18 | allowed ls k = not $ any (matches k) ls 19 | solve rules = filter (allowed rules) candidates 20 | where candidates = sort $ map ((+1) . snd) rules 21 | 22 | main = answer $ head . solve . map ((read *** read) . splitOn1 "-") . lines 23 | -------------------------------------------------------------------------------- /2016/A20b.hs: -------------------------------------------------------------------------------- 1 | -- OK so this version actually works. 2 | -- But I actually somewhat accidentally originally solved this problem by 3 | -- taking the length of the list that I produced in part 1... 4 | -- None of the gaps are longer than 1 element! 5 | 6 | -- This code could also produce the part 1 solution more efficient 7 | -- than part 1, though it doesn't seem to matter. 8 | 9 | import Control.Monad 10 | import Data.List.Extra 11 | import Data.Maybe 12 | import qualified Data.Char as C 13 | import qualified Data.Map as Map 14 | import qualified Data.Set as Set 15 | import Control.Arrow 16 | 17 | ------ 18 | answer :: (Show a) => (String -> a) -> IO () 19 | answer f = interact $ (++"\n") . show . f 20 | 21 | splitOn1 a b = fromJust $ stripInfix a b 22 | 23 | -------- 24 | maxNum = 4294967295 25 | 26 | rmerge (lo,hi) ((lo',hi'):rest) = 27 | if lo' <= hi+1 then rmerge (lo,max hi hi') rest 28 | else (lo,hi) : rmerge (lo',hi') rest 29 | rmerge (lo,hi) [] = [(lo,hi)] 30 | 31 | canonify l = rmerge (-1,-1) $ sort $ (maxNum,maxNum):l 32 | 33 | gap (_,hi) (lo,_) = lo-hi-1 34 | 35 | solve l = sum $ zipWith gap l (tail l) 36 | 37 | main = answer $ solve . canonify . map ((read *** read) . splitOn1 "-") . lines 38 | -------------------------------------------------------------------------------- /2016/A3a.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | 4 | -- Originally done in python but I redid it in haskell to get back in 5 | -- the feel of writing haskell (which I don't think I've done since 6 | -- last year's AoC). 7 | 8 | iread :: String -> Int 9 | iread = read 10 | 11 | check :: [Int] -> Bool 12 | check x = let [a,b,c] = sort x 13 | in a+b > c 14 | 15 | load = map iread . words 16 | 17 | answer f = interact $ (++"\n") . show . f 18 | main = answer $ length . filter check . map load . lines 19 | -------------------------------------------------------------------------------- /2016/A3b.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.List.Extra 3 | 4 | -- Originally done in python but I redid it in haskell to get back in 5 | -- the feel of writing haskell (which I don't think I've done since 6 | -- last year's AoC). 7 | 8 | iread :: String -> Int 9 | iread = read 10 | 11 | check :: [Int] -> Bool 12 | check x = let [a,b,c] = sort x 13 | in a+b > c 14 | 15 | load = map iread . words 16 | 17 | fux = concat . map transpose . chunksOf 3 18 | 19 | answer f = interact $ (++"\n") . show . f 20 | main = answer $ length . filter check . fux . map load . lines 21 | -------------------------------------------------------------------------------- /2016/A4a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import Counter 5 | FUCK = 0 6 | 7 | def thing(s): 8 | global FUCK 9 | thing, cksum = s.split("[") 10 | cksum = cksum.replace("]", "") 11 | stuff, sector = thing.rsplit("-", 1) 12 | stuff = stuff.replace("-", "") 13 | nus = Counter() 14 | for c in stuff: 15 | nus[c] += 1 16 | 17 | def key(x): return (-nus[x], x) 18 | things = list(nus.keys()) 19 | thingss = list(sorted(things, key=key)) 20 | 21 | s = "".join(thingss[0:5]) 22 | print(s, cksum) 23 | if s == cksum[0:5]: FUCK += int(sector) 24 | 25 | print(nus) 26 | 27 | 28 | print(stuff, sector) 29 | 30 | def main(args): 31 | names = [s.strip() for s in sys.stdin] 32 | for x in names: 33 | thing(x) 34 | 35 | print(FUCK) 36 | 37 | if __name__ == '__main__': 38 | sys.exit(main(sys.argv)) 39 | -------------------------------------------------------------------------------- /2016/A4b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # I wasn't sure what 4 | 5 | import sys 6 | from collections import Counter 7 | FUCK = 0 8 | 9 | def add(c, n): 10 | if c == "-": return " " 11 | i = ord(c) - ord('a') 12 | i = (i + n) % 26 13 | return chr(i + ord('a')) 14 | 15 | def thing(s): 16 | global FUCK 17 | thing, cksum = s.split("[") 18 | cksum = cksum.replace("]", "") 19 | stuff, sector = thing.rsplit("-", 1) 20 | butt = stuff 21 | stuff = stuff.replace("-", "") 22 | nus = Counter() 23 | for c in stuff: 24 | nus[c] += 1 25 | 26 | def key(x): return (-nus[x], x) 27 | things = list(nus.keys()) 28 | thingss = list(sorted(things, key=key)) 29 | 30 | s = "".join(thingss[0:5]) 31 | if s == cksum[0:5]: FUCK += int(sector) 32 | else: return 33 | 34 | s = "".join(add(c, int(sector)) for c in butt) 35 | print(s, sector) 36 | 37 | def main(args): 38 | names = [s.strip() for s in sys.stdin] 39 | for x in names: 40 | thing(x) 41 | 42 | print(FUCK) 43 | 44 | if __name__ == '__main__': 45 | sys.exit(main(sys.argv)) 46 | -------------------------------------------------------------------------------- /2016/A5a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import hashlib 5 | 6 | sekrit='reyedfim' 7 | #sekrit='abc' 8 | 9 | 10 | def main(args): 11 | pas = "" 12 | for i in range(1000000000): 13 | s = hashlib.md5((sekrit+str(i)).encode()) 14 | ss = s.hexdigest() 15 | if ss.startswith("00000"): 16 | pas += ss[5] 17 | print(len(pas), i, pas, ss) 18 | if len(pas) == 8: break 19 | print(pas) 20 | 21 | if __name__ == '__main__': 22 | sys.exit(main(sys.argv)) 23 | -------------------------------------------------------------------------------- /2016/A5b.hs: -------------------------------------------------------------------------------- 1 | import Data.List 2 | import Data.Maybe 3 | import Data.Hash.MD5 4 | import Debug.Trace 5 | 6 | key = "reyedfim" 7 | 8 | traceSelf x = traceShow x x 9 | 10 | result = map (fromJust . flip lookup stuff . show) [0..7] 11 | where stuff = map (\s -> traceSelf ([s !! 5], s !! 6)) $ filter (isPrefixOf "00000") $ map (\i -> md5s $ Str $ key ++ show i) [1..] 12 | 13 | main = putStrLn $ show result 14 | -------------------------------------------------------------------------------- /2016/A5b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import hashlib 5 | 6 | sekrit='reyedfim' 7 | #sekrit='abc' 8 | 9 | 10 | def main(args): 11 | pas = ["*"]*8 12 | for i in range(1000000000): 13 | s = hashlib.md5((sekrit+str(i)).encode()) 14 | ss = s.hexdigest() 15 | if ss.startswith("00000"): 16 | j = int(ss[5], 16) 17 | if j < 8 and pas[j] == "*": pas[int(ss[5])] = ss[6] 18 | print(i, "".join(pas), ss) 19 | if "*" not in pas: break 20 | print("".join(pas)) 21 | 22 | if __name__ == '__main__': 23 | sys.exit(main(sys.argv)) 24 | -------------------------------------------------------------------------------- /2016/A6a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import Counter 5 | 6 | def main(args): 7 | names = [s.strip() for s in sys.stdin] 8 | n = len(names[0]) 9 | spots = [Counter() for x in range(n)] 10 | for name in names: 11 | for i in range(n): 12 | spots[i][name[i]] += 1 13 | 14 | print("".join(x.most_common()[0][0] for x in spots)) 15 | 16 | if __name__ == '__main__': 17 | sys.exit(main(sys.argv)) 18 | -------------------------------------------------------------------------------- /2016/A6b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import Counter 5 | 6 | def main(args): 7 | names = [s.strip() for s in sys.stdin] 8 | n = len(names[0]) 9 | spots = [Counter() for x in range(n)] 10 | for name in names: 11 | for i in range(n): 12 | spots[i][name[i]] += 1 13 | 14 | print("".join(x.most_common()[-1][0] for x in spots)) 15 | 16 | if __name__ == '__main__': 17 | sys.exit(main(sys.argv)) 18 | -------------------------------------------------------------------------------- /2016/A7a.hs: -------------------------------------------------------------------------------- 1 | import Data.List.Extra 2 | 3 | answer :: (Show a) => (String -> a) -> IO () 4 | answer f = interact $ (++"\n") . show . f 5 | 6 | check nus ('[':xs) = check (not nus) xs 7 | check nus (']':xs) = check (not nus) xs 8 | check nus (a:b:c:d:xs) | nus && a == d && b == c && not (a == b) = True 9 | | otherwise = check nus (b:c:d:xs) 10 | check nus _ = False 11 | 12 | check' xs = check True xs && not (check False xs) 13 | 14 | main = answer $ length . filter check' . lines 15 | -------------------------------------------------------------------------------- /2016/A7b.hs: -------------------------------------------------------------------------------- 1 | import Data.List.Extra 2 | 3 | answer :: (Show a) => (String -> a) -> IO () 4 | answer f = interact $ (++"\n") . show . f 5 | 6 | nus [] = ([], []) 7 | nus xs = let (as, bscs) = break (== '[') xs 8 | (bs, cs) = break (== ']') bscs 9 | (ys, zs) = nus cs 10 | in (as ++ ys, bs ++ zs) 11 | 12 | 13 | check (a:b:c:xs) lol = if a == c && not (a == b) && [b,a,b] `isInfixOf` lol then True 14 | else check (b:c:xs) lol 15 | check _ _ = False 16 | 17 | check' xs = let (a, b) = nus xs in check a b 18 | 19 | main = answer $ length . filter check' . lines 20 | -------------------------------------------------------------------------------- /2016/A9a.hs: -------------------------------------------------------------------------------- 1 | import Data.List.Extra 2 | import Data.Maybe 3 | 4 | ------ 5 | answer :: (Show a) => (String -> a) -> IO () 6 | answer f = interact $ (++"\n") . show . f 7 | splitOn1 a b = fromJust $ stripInfix a b 8 | -------- 9 | 10 | decompress ('(':xs) = 11 | let (lol, ys) = splitOn1 ")" xs 12 | [n, m] = map read $ splitOn "x" lol 13 | rep = take n ys 14 | in concat (replicate m rep) ++ decompress (drop n ys) 15 | decompress (x:xs) = x : decompress xs 16 | decompress [] = [] 17 | 18 | main = answer $ length . decompress . trim 19 | -------------------------------------------------------------------------------- /2016/A9b.hs: -------------------------------------------------------------------------------- 1 | import Data.List.Extra 2 | import Data.Maybe 3 | 4 | ------ 5 | -- Routines I reuse for a lot of problems 6 | answer :: (Show a) => (String -> a) -> IO () 7 | answer f = interact $ (++"\n") . show . f 8 | splitOn1 a b = fromJust $ stripInfix a b 9 | -------- 10 | 11 | decompress ('(':xs) = 12 | let (lol, ys) = splitOn1 ")" xs 13 | [n, m] = map read $ splitOn "x" lol 14 | (rep, rest) = splitAt n ys 15 | in (m * (decompress rep)) + decompress rest 16 | decompress (x:xs) = 1 + (decompress xs) 17 | decompress [] = 0 18 | 19 | main = answer $ decompress . trim 20 | -------------------------------------------------------------------------------- /2016/A9b_Seq.hs: -------------------------------------------------------------------------------- 1 | import Data.List.Extra 2 | import Data.Maybe 3 | import Control.Monad 4 | import qualified Data.Sequence as S 5 | import Data.Sequence ((<|), (><)) 6 | 7 | -- This is a version of 9 part two that actually *does* kind of 8 | -- construct the string. It does it using a Data.Sequence which can 9 | -- efficiently operate on big lazy things. 10 | 11 | -- It is structured exactly like producing the list would be except it 12 | -- calls equivalent Sequence functions. It runs basically instantly 13 | -- and can be made to generate text. You can ask it for the expansion 14 | -- at basically any point in the string and it will return data very 15 | -- quickly! 16 | 17 | ------ 18 | answer :: (Show a) => (String -> a) -> IO () 19 | answer f = interact $ (++"\n") . show . f 20 | splitOn1 a b = fromJust $ stripInfix a b 21 | -------- 22 | 23 | decompress ('(':xs) = 24 | let (lol, ys) = splitOn1 ")" xs 25 | [n, m] = map read $ splitOn "x" lol 26 | (rep, rest) = splitAt n ys 27 | in join (S.replicate m (decompress rep)) >< decompress rest 28 | decompress (x: xs) = x <| decompress xs 29 | decompress [] = S.empty 30 | 31 | -- You can do things like this! 32 | --main = answer $ S.drop 9000000000 . decompress . trim 33 | main = answer $ S.length . decompress . trim 34 | -------------------------------------------------------------------------------- /2016/Template.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Char as C 5 | import qualified Data.Map as Map 6 | import qualified Data.Set as Set 7 | 8 | ------ 9 | iread :: String -> Int 10 | iread = read 11 | 12 | answer :: (Show a) => (String -> a) -> IO () 13 | answer f = interact $ (++"\n") . show . f 14 | 15 | ord0 c = C.ord c - C.ord 'a' 16 | chr0 i = C.chr (i + C.ord 'a') 17 | incletter c i = chr0 ((ord0 c + i) `mod` 26) 18 | 19 | splitOn1 a b = fromJust $ stripInfix a b 20 | rsplitOn1 a b = fromJust $ stripInfixEnd a b 21 | 22 | -- pull out every part of a String that can be read in 23 | -- for some Read a and ignore the rest 24 | readOut :: Read a => String -> [a] 25 | readOut "" = [] 26 | readOut s = case reads s of 27 | [] -> readOut $ tail s 28 | [(x, s')] -> x : readOut s' 29 | _ -> error "ambiguous parse" 30 | ireadOut :: String -> [Int] 31 | ireadOut = readOut 32 | 33 | -------- 34 | 35 | 36 | 37 | main = answer $ map ireadOut . lines 38 | -------------------------------------------------------------------------------- /2017/1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | nub = [s.strip() for s in sys.stdin][0] 7 | nub2 = nub + nub[0] 8 | n = 0 9 | 10 | for i in range(len(nub)): 11 | if nub2[i] == nub2[i+1]: 12 | n += int(nub2[i]) 13 | 14 | print(n) 15 | 16 | n = 0 17 | l = len(nub) 18 | h = l//2 19 | for i in range(l): 20 | if nub[i] == nub[(i+h) % l]: 21 | n += int(nub[i]) 22 | 23 | print(n) 24 | 25 | 26 | if __name__ == '__main__': 27 | sys.exit(main(sys.argv)) 28 | -------------------------------------------------------------------------------- /2017/10a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [s.strip() for s in sys.stdin] 7 | lens = map(int, data[0].split(",")) 8 | 9 | l = list(range(256)) 10 | cur = 0 11 | skip = 0 12 | 13 | for ln in lens: 14 | lurr = l+l 15 | sub = list(reversed(lurr[cur:cur+ln])) 16 | for i in range(ln): 17 | l[(cur+i)%len(l)] = sub[i] 18 | cur = (cur + ln + skip) % len(l) 19 | skip += 1 20 | 21 | print(l[0]*l[1]) 22 | 23 | 24 | if __name__ == '__main__': 25 | sys.exit(main(sys.argv)) 26 | -------------------------------------------------------------------------------- /2017/10b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def hash(lens): 6 | l = list(range(256)) 7 | cur = 0 8 | skip = 0 9 | 10 | for i in range(64): 11 | for ln in lens: 12 | lurr = l+l 13 | sub = list(reversed(lurr[cur:cur+ln])) 14 | for i in range(ln): 15 | l[(cur+i)%len(l)] = sub[i] 16 | cur = (cur + ln + skip) % len(l) 17 | skip += 1 18 | 19 | return l 20 | 21 | def main(args): 22 | data = [s.strip() for s in sys.stdin] 23 | lens = list(map(ord, data[0]))+[17, 31, 73, 47, 23] 24 | 25 | h = hash(lens) 26 | sparse = [] 27 | for i in range(16): 28 | x = 0 29 | for j in range(16): 30 | x ^= h[i*16+j] 31 | sparse += [x] 32 | 33 | print("".join("%02x" % x for x in sparse)) 34 | 35 | if __name__ == '__main__': 36 | sys.exit(main(sys.argv)) 37 | -------------------------------------------------------------------------------- /2017/11.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | dirs = { 6 | 'n': (0, 1, -1), 7 | 's': (0, -1, 1), 8 | 'ne': (1, 0, -1), 9 | 'nw': (-1, 1, 0), 10 | 'se': (1, -1, 0), 11 | 'sw': (-1, 0, 1), 12 | } 13 | 14 | def main(args): 15 | data = [s.strip() for s in sys.stdin] 16 | moves = data[0].split(",") 17 | 18 | x,y,z = 0,0,0 19 | farthest = 0 20 | for move in moves: 21 | dx,dy,dz = dirs[move] 22 | x+=dx 23 | y+=dy 24 | z+=dz 25 | 26 | farthest = max(farthest, max(map(abs,(x,y,z)))) 27 | 28 | print(max(map(abs,(x,y,z)))) 29 | print(farthest) 30 | 31 | if __name__ == '__main__': 32 | sys.exit(main(sys.argv)) 33 | -------------------------------------------------------------------------------- /2017/12.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def dfs(graph, seen, nobe): 6 | if nobe in seen: return 7 | seen.add(nobe) 8 | for child in graph[nobe]: 9 | dfs(graph, seen, child) 10 | 11 | def main(args): 12 | data = [s.strip() for s in sys.stdin] 13 | graph = {} 14 | for line in data: 15 | k, vs = line.split(" <-> ") 16 | vs = vs.split(", ") 17 | graph[k] = set(vs) 18 | 19 | seen = set() 20 | dfs(graph, seen, "0") 21 | print(len(seen)) 22 | 23 | num = 1 24 | for k in graph.keys(): 25 | if k not in seen: num += 1 26 | dfs(graph, seen, k) 27 | print(num) 28 | 29 | 30 | if __name__ == '__main__': 31 | sys.exit(main(sys.argv)) 32 | -------------------------------------------------------------------------------- /2017/13a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def step(depths, pos, dir): 6 | for k in depths.keys(): 7 | if pos[k] == depths[k]-1: 8 | dir[k] = -1 9 | if pos[k] == 0: 10 | dir[k] = 1 11 | pos[k] += dir[k] 12 | 13 | def main(args): 14 | data = [s.strip() for s in sys.stdin] 15 | 16 | depths = {} 17 | for line in data: 18 | k, v = map(int, line.split(": ")) 19 | depths[k] = v 20 | 21 | positions = {k: 0 for k in depths.keys()} 22 | dirs = {k: 1 for k in depths.keys()} 23 | 24 | 25 | print(depths) 26 | print(positions) 27 | 28 | cost = 0 29 | for i in range(max(depths.keys())+1): 30 | if i in positions and positions[i] == 0: 31 | print(i, depths[i]) 32 | cost += i*depths[i] 33 | step(depths, positions, dirs) 34 | 35 | print(cost) 36 | 37 | 38 | 39 | if __name__ == '__main__': 40 | sys.exit(main(sys.argv)) 41 | -------------------------------------------------------------------------------- /2017/13b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def seq_list(l): 6 | a = list(range(l)) 7 | return a + list(reversed(a))[1:-1] 8 | 9 | def position(seqs, i, k): 10 | ass = seqs[i] 11 | return ass[k % len(ass)] 12 | 13 | def go(depths, seqs, wait): 14 | for i in range(max(depths.keys())+1): 15 | if i in depths and position(seqs, i, wait+i) == 0: 16 | return False 17 | 18 | return True 19 | 20 | def main(args): 21 | data = [s.strip() for s in sys.stdin] 22 | 23 | depths = {} 24 | for line in data: 25 | k, v = map(int, line.split(": ")) 26 | depths[k] = v 27 | 28 | seqs = {k: seq_list(depths[k]) for k in depths.keys()} 29 | 30 | wait = 1 31 | while not go(depths, seqs, wait): 32 | wait += 1 33 | print(wait) 34 | 35 | 36 | 37 | 38 | if __name__ == '__main__': 39 | sys.exit(main(sys.argv)) 40 | -------------------------------------------------------------------------------- /2017/15a.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def main(args): 4 | a, b = 873, 583 5 | 6 | count = 0 7 | for i in range(40 * 1000000): 8 | a = (a * 16807) % 2147483647 9 | b = (b * 48271) % 2147483647 10 | if (a & 0xffff) == (b & 0xffff): 11 | count += 1 12 | 13 | print(count) 14 | 15 | return 0 16 | 17 | if __name__ == '__main__': 18 | sys.exit(main(sys.argv)) 19 | -------------------------------------------------------------------------------- /2017/15b.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def main(args): 4 | a, b = 873, 583 5 | 6 | count = 0 7 | for i in range(5 * 1000000): 8 | while True: 9 | a = (a * 16807) % 2147483647 10 | if a % 4 == 0: break 11 | while True: 12 | b = (b * 48271) % 2147483647 13 | if b % 8 == 0: break 14 | 15 | if (a & 0xffff) == (b & 0xffff): 16 | count += 1 17 | print(count) 18 | 19 | return 0 20 | 21 | if __name__ == '__main__': 22 | sys.exit(main(sys.argv)) 23 | -------------------------------------------------------------------------------- /2017/16.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def round(things, data): 6 | for move in data: 7 | if move[0] == 's': 8 | amt = int(move[1:]) 9 | things = things[-amt:] + things[:-amt] 10 | elif move[0] == 'x': 11 | a,b = map(int, move[1:].split("/")) 12 | things[a], things[b] = things[b], things[a] 13 | else: 14 | x, y = move[1], move[3] 15 | a = things.index(x) 16 | b = things.index(y) 17 | things[a], things[b] = things[b], things[a] 18 | return things 19 | 20 | 21 | def main(args): 22 | data = [s.strip() for s in sys.stdin] 23 | data = data[0].split(",") 24 | 25 | seen = {} 26 | things = [chr(ord('a')+i) for i in range(16)] 27 | 28 | print(''.join(round(list(things), data))) 29 | 30 | n = 0 31 | while True: 32 | s = ''.join(things) 33 | if s in seen: break 34 | seen[s] = n 35 | things = round(things, data) 36 | n += 1 37 | 38 | # fun fact: round is injective so the first element is always on the cycle 39 | k = (1000000000) % n 40 | print([k2 for k2,v in seen.items() if k == v][0]) 41 | 42 | 43 | if __name__ == '__main__': 44 | sys.exit(main(sys.argv)) 45 | -------------------------------------------------------------------------------- /2017/17a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | cnt = 2017 7 | n = 3 8 | n = 345 9 | buf = [0] 10 | pos = 0 11 | 12 | for i in range(cnt): 13 | #for j in range(n): 14 | # pos = (pos + 1) % len(buf) 15 | pos = (pos + n) % len(buf) 16 | #print(pos) 17 | buf = buf[:pos+1] + [i+1] + buf[pos+1:] 18 | pos += 1 19 | 20 | print(buf[buf.index(2017)+1]) 21 | 22 | 23 | if __name__ == '__main__': 24 | sys.exit(main(sys.argv)) 25 | -------------------------------------------------------------------------------- /2017/17b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | #cnt = 2017 7 | cnt = 50000000 8 | n = 3 9 | n = 345 10 | size = 0 11 | buf = [0] 12 | pos = 0 13 | 14 | at_1 = None 15 | 16 | for i in range(cnt): 17 | pos = (pos + n) % (i+1) 18 | if pos == 0: 19 | at_1 = i+1 20 | pos += 1 21 | 22 | print(at_1) 23 | 24 | if __name__ == '__main__': 25 | sys.exit(main(sys.argv)) 26 | -------------------------------------------------------------------------------- /2017/19.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict 5 | def flip(s): return "|" if s == "-" else "-" 6 | 7 | 8 | def look(grid, y, x): 9 | if x < 0 or y < 0: return ' ' 10 | if y >= len(grid): return ' ' 11 | if y >= len(grid[y]): return ' ' 12 | return grid[y][x] 13 | 14 | def main(args): 15 | grid = [s[:-1] for s in sys.stdin] 16 | 17 | y = 0 18 | x = grid[0].index('|') 19 | 20 | dx,dy = (0,1) 21 | char = '|' 22 | 23 | g = grid 24 | 25 | path = [] 26 | i = 0 27 | while True: 28 | i += 1 29 | if look(g, y, x) == ' ': 30 | break 31 | if look(g, y, x).isalpha(): 32 | path.append(look(g, y, x)) 33 | if look(g, y, x) == '+': 34 | ndx,ndy = dy,dx 35 | char = flip(char) 36 | if look(g, y+ndy, x+ndx) != ' ': 37 | dx,dy = ndx,ndy 38 | elif look(g, y-ndy, x-ndx) != ' ': 39 | dx,dy = -ndx,-ndy 40 | else: 41 | break 42 | x += dx 43 | y += dy 44 | 45 | print("".join(path)) 46 | print(i-1) 47 | 48 | 49 | if __name__ == '__main__': 50 | sys.exit(main(sys.argv)) 51 | -------------------------------------------------------------------------------- /2017/2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | nubs = [s.strip() for s in sys.stdin] 7 | n = 0 8 | m = 0 9 | 10 | for line in nubs: 11 | parts = line.split("\t") 12 | nums = [int(s) for s in parts if s] 13 | for x in nums: 14 | for y in nums: 15 | if x % y == 0 and x != y: 16 | m += (x // y) 17 | 18 | n += (max(nums) - min(nums)) 19 | print(n) 20 | print(m) 21 | 22 | 23 | if __name__ == '__main__': 24 | sys.exit(main(sys.argv)) 25 | -------------------------------------------------------------------------------- /2017/22a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict 5 | 6 | def left(dx,dy): 7 | if (dx,dy) == (1,0): 8 | return (0,-1) 9 | elif (dx,dy) == (0,-1): 10 | return (-1,0) 11 | elif (dx,dy) == (-1,0): 12 | return (0,1) 13 | else: 14 | return (1,0) 15 | 16 | def right(dx,dy): 17 | return left(*left(*left(dx,dy))) 18 | 19 | def main(args): 20 | nubs = [s.strip() for s in sys.stdin] 21 | 22 | grid = defaultdict(bool) 23 | for y in range(len(nubs)): 24 | for x in range(len(nubs[0])): 25 | if nubs[y][x] == '#': 26 | grid[(x,y)] = True 27 | 28 | mid = len(nubs)//2 29 | 30 | dx, dy = 0, -1 31 | x, y = mid, mid 32 | 33 | made = 0 34 | for i in range(10000): 35 | if grid[(x,y)]: 36 | dx, dy = right(dx, dy) 37 | grid[(x,y)] = False 38 | else: 39 | dx, dy = left(dx, dy) 40 | made += 1 41 | grid[(x,y)] = True 42 | x += dx 43 | y += dy 44 | 45 | print(made) 46 | 47 | 48 | if __name__ == '__main__': 49 | sys.exit(main(sys.argv)) 50 | -------------------------------------------------------------------------------- /2017/23b2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "23bgen.c" 4 | 5 | int main() { 6 | long h = func(0); 7 | printf("cnt: %ld\n", mul_count); 8 | } 9 | -------------------------------------------------------------------------------- /2017/23bgen.c: -------------------------------------------------------------------------------- 1 | long mul_count; 2 | long func(long a) { 3 | long b, c, d, e, f, g, h; 4 | b = c = d = e = f = g = h = 0; 5 | mul_count = 0; 6 | 7 | b = 99; 8 | c = b; 9 | if (a) goto L0; 10 | goto L1; 11 | 12 | L0: 13 | b *= 100; mul_count++; 14 | b += 100000; 15 | c = b; 16 | c += 17000; 17 | 18 | L1: 19 | f = 1; 20 | d = 2; 21 | 22 | L2: 23 | e = 2; 24 | 25 | L3: 26 | g = d; 27 | g *= e; mul_count++; 28 | g -= b; 29 | if (g) goto L4; 30 | f = 0; 31 | 32 | L4: 33 | e += 1; 34 | g = e; 35 | g -= b; 36 | if (g) goto L3; 37 | d += 1; 38 | g = d; 39 | g -= b; 40 | if (g) goto L2; 41 | if (f) goto L5; 42 | h += 1; 43 | 44 | L5: 45 | g = b; 46 | g -= c; 47 | if (g) goto L6; 48 | goto L7; 49 | 50 | L6: 51 | b += 17; 52 | goto L1; 53 | 54 | L7: 55 | return h; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /2017/24a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict 5 | 6 | def other(pair, x): return pair[0] if x == pair[1] else pair[1] 7 | 8 | def search(m, avail, cur): 9 | top = 0 10 | for choice in m[cur]: 11 | if choice not in avail: continue 12 | avail.remove(choice) 13 | val = search(m, avail, other(choice, cur)) + choice[0] + choice[1] 14 | top = max(top, val) 15 | avail.add(choice) 16 | return top 17 | 18 | def main(args): 19 | data = [tuple(map(int, s.strip().split("/"))) for s in sys.stdin] 20 | print(len(data), len(set(data))) 21 | 22 | avail = set(data) 23 | m = defaultdict(list) 24 | for a in avail: 25 | m[a[0]] += [a] 26 | m[a[1]] += [a] 27 | 28 | print(search(m, avail, 0)) 29 | 30 | 31 | 32 | if __name__ == '__main__': 33 | sys.exit(main(sys.argv)) 34 | -------------------------------------------------------------------------------- /2017/24b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict 5 | 6 | def other(pair, x): return pair[0] if x == pair[1] else pair[1] 7 | 8 | def search(m, avail, cur): 9 | top = 0, 0 10 | for choice in m[cur]: 11 | if choice not in avail: continue 12 | avail.remove(choice) 13 | l, v = search(m, avail, other(choice, cur)) 14 | l += 1 15 | v += choice[0] + choice[1] 16 | top = max(top, (l, v)) 17 | avail.add(choice) 18 | return top 19 | 20 | def main(args): 21 | data = [tuple(map(int, s.strip().split("/"))) for s in sys.stdin] 22 | print(len(data), len(set(data))) 23 | 24 | avail = set(data) 25 | m = defaultdict(list) 26 | for a in avail: 27 | m[a[0]] += [a] 28 | m[a[1]] += [a] 29 | 30 | print(search(m, avail, 0)) 31 | 32 | 33 | 34 | if __name__ == '__main__': 35 | sys.exit(main(sys.argv)) 36 | -------------------------------------------------------------------------------- /2017/3a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def left(dx,dy): 6 | if (dx,dy) == (1,0): 7 | return (0,1) 8 | elif (dx,dy) == (0,1): 9 | return (-1,0) 10 | elif (dx,dy) == (-1,0): 11 | return (0,-1) 12 | else: 13 | return (1,0) 14 | 15 | def main(args): 16 | # nubs = [s.strip() for s in sys.stdin] 17 | 18 | x = 0 19 | y = 0 20 | n = 1 21 | 22 | dx, dy = 1, 0 23 | # last = 0 24 | size = 0 25 | 26 | # num = int(args[1]) 27 | num = 312051 28 | # num = 12 29 | while True: 30 | #print(n, x, y, size) 31 | if n == num: break 32 | if max(abs(x+dx), abs(y+dy)) > size: 33 | if x == size and y == -size: 34 | size += 1 35 | else: 36 | dx, dy = left(dx, dy) 37 | x += dx 38 | y += dy 39 | n += 1 40 | print(abs(x) + abs(y)) 41 | 42 | 43 | if __name__ == '__main__': 44 | sys.exit(main(sys.argv)) 45 | -------------------------------------------------------------------------------- /2017/3b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def left(dx,dy): 6 | if (dx,dy) == (1,0): 7 | return (0,1) 8 | elif (dx,dy) == (0,1): 9 | return (-1,0) 10 | elif (dx,dy) == (-1,0): 11 | return (0,-1) 12 | else: 13 | return (1,0) 14 | 15 | def main(args): 16 | x = 0 17 | y = 0 18 | n = 1 19 | 20 | dx, dy = 1, 0 21 | # last = 0 22 | size = 0 23 | 24 | num = 312051 25 | 26 | 27 | vals = {(0,0): 1} 28 | while True: 29 | #print(n, x, y, size) 30 | if max(abs(x+dx), abs(y+dy)) > size: 31 | if x == size and y == -size: 32 | size += 1 33 | else: 34 | dx, dy = left(dx, dy) 35 | x += dx 36 | y += dy 37 | n += 1 38 | 39 | val = 0 40 | for ix in [-1,0,1]: 41 | for iy in [-1,0,1]: 42 | if ix == 0 and iy == 0: continue 43 | val += vals.get((x+ix, y+iy), 0) 44 | vals[(x,y)] = val 45 | 46 | if val >= num: break 47 | print(val) 48 | 49 | 50 | if __name__ == '__main__': 51 | sys.exit(main(sys.argv)) 52 | -------------------------------------------------------------------------------- /2017/4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | nubs = [s.strip() for s in sys.stdin] 7 | valid = 0 8 | 9 | for nub in nubs: 10 | words = nub.split(" ") 11 | swords = set(words) 12 | if len(words) == len(swords): valid +=1 13 | 14 | print(valid) 15 | 16 | valid = 0 17 | for nub in nubs: 18 | words = nub.split(" ") 19 | words = [tuple(sorted(w)) for w in words] 20 | swords = set(words) 21 | if len(words) == len(swords): valid +=1 22 | print(valid) 23 | 24 | if __name__ == '__main__': 25 | sys.exit(main(sys.argv)) 26 | -------------------------------------------------------------------------------- /2017/5a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | offs = [int(s.strip()) for s in sys.stdin] 7 | 8 | j = 0 9 | i = 0 10 | while i >= 0 and i < len(offs): 11 | off = offs[i] 12 | offs[i] += 1 13 | i += off 14 | j +=1 15 | print(j) 16 | 17 | if __name__ == '__main__': 18 | sys.exit(main(sys.argv)) 19 | -------------------------------------------------------------------------------- /2017/5b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | offs = [int(s.strip()) for s in sys.stdin] 7 | 8 | j = 0 9 | i = 0 10 | while i >= 0 and i < len(offs): 11 | off = offs[i] 12 | if off >= 3: 13 | offs[i] -= 1 14 | else: 15 | offs[i] += 1 16 | i += off 17 | j+=1 18 | print(j) 19 | 20 | if __name__ == '__main__': 21 | sys.exit(main(sys.argv)) 22 | -------------------------------------------------------------------------------- /2017/6.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | offs = [s.strip() for s in sys.stdin] 7 | banks = list(map(int, offs[0].split("\t"))) 8 | seen = set() 9 | 10 | n = 0 11 | while True: 12 | if tuple(banks) in seen: 13 | break 14 | seen.add(tuple(banks)) 15 | 16 | m = max(banks) 17 | i = banks.index(m) 18 | banks[i] = 0 19 | for j in range(m): 20 | banks[(i+1+j) % len(banks)] += 1 21 | n += 1 22 | 23 | print(n) 24 | 25 | start = tuple(banks) 26 | n = 0 27 | while True: 28 | m = max(banks) 29 | i = banks.index(m) 30 | banks[i] = 0 31 | for j in range(m): 32 | banks[(i+1+j) % len(banks)] += 1 33 | n += 1 34 | if tuple(banks) == start: 35 | break 36 | print(n) 37 | 38 | 39 | if __name__ == '__main__': 40 | sys.exit(main(sys.argv)) 41 | -------------------------------------------------------------------------------- /2017/A1.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Char as C 5 | import qualified Data.Map as Map 6 | import qualified Data.Set as Set 7 | 8 | ------ 9 | iread :: String -> Int 10 | iread = read 11 | 12 | answer :: (Show a) => (String -> a) -> IO () 13 | answer f = interact $ (++"\n") . show . f 14 | 15 | ord0 c = C.ord c - C.ord 'a' 16 | chr0 i = C.chr (i + C.ord 'a') 17 | incletter c i = chr0 ((ord0 c + i) `mod` 26) 18 | 19 | splitOn1 a b = fromJust $ stripInfix a b 20 | rsplitOn1 a b = fromJust $ stripInfixEnd a b 21 | 22 | -- pull out every part of a String that can be read in 23 | -- for some Read a and ignore the rest 24 | readOut :: Read a => String -> [a] 25 | readOut "" = [] 26 | readOut s = case reads s of 27 | [] -> readOut $ tail s 28 | [(x, s')] -> x : readOut s' 29 | _ -> error "ambiguous parse" 30 | ireadOut :: String -> [Int] 31 | ireadOut = readOut 32 | 33 | -------- 34 | 35 | ckfilter (x:xs) (y:ys) = if x == y then x : rest else rest 36 | where rest = ckfilter xs ys 37 | ckfilter _ _ = [] 38 | 39 | cksum l = (sum $ ckfilter l (tail (l ++ [head l])), 40 | sum $ ckfilter l (drop (length l `div` 2) (cycle l))) 41 | 42 | main = answer $ cksum . map (read . (:[])) . head . lines 43 | -------------------------------------------------------------------------------- /2017/A2.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Char as C 5 | import qualified Data.Map as Map 6 | import qualified Data.Set as Set 7 | 8 | ------ 9 | iread :: String -> Int 10 | iread = read 11 | 12 | do2 f g x = (f x, g x) 13 | 14 | answer :: (Show a) => (String -> a) -> IO () 15 | answer f = interact $ (++"\n") . show . f 16 | 17 | ord0 c = C.ord c - C.ord 'a' 18 | chr0 i = C.chr (i + C.ord 'a') 19 | incletter c i = chr0 ((ord0 c + i) `mod` 26) 20 | 21 | splitOn1 a b = fromJust $ stripInfix a b 22 | rsplitOn1 a b = fromJust $ stripInfixEnd a b 23 | 24 | -- pull out every part of a String that can be read in 25 | -- for some Read a and ignore the rest 26 | readOut :: Read a => String -> [a] 27 | readOut "" = [] 28 | readOut s = case reads s of 29 | [] -> readOut $ tail s 30 | [(x, s')] -> x : readOut s' 31 | _ -> error "ambiguous parse" 32 | ireadOut :: String -> [Int] 33 | ireadOut = readOut 34 | 35 | -------- 36 | 37 | cksum l = sum $ map lcksum l 38 | where lcksum l' = maximum l' - minimum l'c 39 | cksum2 l = sum $ concatMap nus l 40 | where nus z = [x `div` y | x <- z, y <- z, x /= y && x `mod` y == 0] 41 | 42 | 43 | main = answer $ do2 cksum cksum2 . map ireadOut . lines 44 | -------------------------------------------------------------------------------- /2017/A4.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Char as C 5 | import qualified Data.Map as Map 6 | import qualified Data.Set as Set 7 | 8 | ------ 9 | iread :: String -> Int 10 | iread = read 11 | 12 | do2 f g x = (f x, g x) 13 | 14 | answer :: (Show a) => (String -> a) -> IO () 15 | answer f = interact $ (++"\n") . show . f 16 | 17 | ord0 c = C.ord c - C.ord 'a' 18 | chr0 i = C.chr (i + C.ord 'a') 19 | incletter c i = chr0 ((ord0 c + i) `mod` 26) 20 | 21 | splitOn1 a b = fromJust $ stripInfix a b 22 | rsplitOn1 a b = fromJust $ stripInfixEnd a b 23 | 24 | -- pull out every part of a String that can be read in 25 | -- for some Read a and ignore the rest 26 | readOut :: Read a => String -> [a] 27 | readOut "" = [] 28 | readOut s = case reads s of 29 | [] -> readOut $ tail s 30 | [(x, s')] -> x : readOut s' 31 | _ -> error "ambiguous parse" 32 | ireadOut :: String -> [Int] 33 | ireadOut = readOut 34 | 35 | -------- 36 | 37 | part1 ls = length (filter (\l -> length l == length (nub l)) ls) 38 | part2 ls = length (filter (\l -> length l == length (nub (map sort l))) ls) 39 | 40 | main = answer $ do2 part1 part2 . map words . lines 41 | -------------------------------------------------------------------------------- /2017/Template.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import Data.List.Extra 3 | import Data.Maybe 4 | import qualified Data.Char as C 5 | import qualified Data.Map as Map 6 | import qualified Data.Set as Set 7 | 8 | ------ 9 | iread :: String -> Int 10 | iread = read 11 | 12 | do2 f g x = (f x, g x) 13 | 14 | answer :: (Show a) => (String -> a) -> IO () 15 | answer f = interact $ (++"\n") . show . f 16 | 17 | ord0 c = C.ord c - C.ord 'a' 18 | chr0 i = C.chr (i + C.ord 'a') 19 | incletter c i = chr0 ((ord0 c + i) `mod` 26) 20 | 21 | splitOn1 a b = fromJust $ stripInfix a b 22 | rsplitOn1 a b = fromJust $ stripInfixEnd a b 23 | 24 | -- pull out every part of a String that can be read in 25 | -- for some Read a and ignore the rest 26 | readOut :: Read a => String -> [a] 27 | readOut "" = [] 28 | readOut s = case reads s of 29 | [] -> readOut $ tail s 30 | [(x, s')] -> x : readOut s' 31 | _ -> error "ambiguous parse" 32 | ireadOut :: String -> [Int] 33 | ireadOut = readOut 34 | 35 | -------- 36 | 37 | 38 | 39 | main = answer $ map ireadOut . lines 40 | -------------------------------------------------------------------------------- /2018/11a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict, deque 5 | 6 | input = 2694 7 | #input = 18 8 | 9 | def eval(x, y, input): 10 | power = ((x + 10) * y + input) * (x + 10) 11 | power = (power % 1000) // 100 12 | power -= 5 13 | return power 14 | 15 | 16 | def main(args): 17 | vals = {} 18 | for x in range(1, 301): 19 | for y in range(1, 301): 20 | vals[(x,y)] = eval(x, y, input) 21 | 22 | things = [] 23 | for x in range(1, 299): 24 | for y in range(1, 299): 25 | lol = [(x+i,y+j) for i in range(3) for j in range(3)] 26 | val = sum(vals.get(z) for z in lol) 27 | things += [(val, (x, y))] 28 | print(max(things)) 29 | 30 | if __name__ == '__main__': 31 | sys.exit(main(sys.argv)) 32 | -------------------------------------------------------------------------------- /2018/12a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict, deque 5 | #from dataclasses import dataclass 6 | 7 | def main(args): 8 | size = 20 9 | if args[1:]: 10 | size = int(args[1]) 11 | 12 | data = [s.strip() for s in sys.stdin] 13 | 14 | initial = data[0].split(" ")[2] 15 | stuff = [x.split(' ') for x in data[2:]] 16 | stuff = dict([(x, z) for x, _, z in stuff]) 17 | 18 | plants = defaultdict(lambda: '.') 19 | for i, x in enumerate(initial): 20 | plants[i] = x 21 | 22 | for i in range(size): 23 | new = defaultdict(lambda: '.') 24 | bottom = min(plants.keys()) 25 | top = max(plants.keys()) 26 | for j in range(bottom-3, top+3): 27 | key = "".join(plants[k] for k in range(j-2, j+3)) 28 | assert len(key) == 5 29 | new[j] = stuff[key] 30 | plants = new 31 | 32 | # print([k for k, v in stuff.items() if v == '#']) 33 | print(sum(k for k, v in plants.items() if v == '#')) 34 | 35 | # print(initial) 36 | # print(stuff) 37 | 38 | if __name__ == '__main__': 39 | sys.exit(main(sys.argv)) 40 | -------------------------------------------------------------------------------- /2018/14a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict, deque 5 | #from dataclasses import dataclass 6 | 7 | def main(args): 8 | num = 598701 9 | things = [3, 7] 10 | n1 = 0 11 | n2 = 1 12 | while len(things) < num + 10: 13 | things += list(map(int, str(things[n1] + things[n2]))) 14 | n1 = (n1 + 1 + things[n1]) % len(things) 15 | n2 = (n2 + 1 + things[n2]) % len(things) 16 | 17 | print(''.join(str(i) for i in things[num:num+10])) 18 | 19 | 20 | 21 | 22 | if __name__ == '__main__': 23 | sys.exit(main(sys.argv)) 24 | -------------------------------------------------------------------------------- /2018/14b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | seen = list(map(int, '598701')) 7 | things = [3, 7] 8 | n1 = 0 9 | n2 = 1 10 | i = 2 11 | while True: 12 | new = str(things[n1] + things[n2]) 13 | for cc in new: 14 | c = int(cc) 15 | i += 1 16 | things.append(c) 17 | if i % 10000 == 0: 18 | print(i) 19 | if things[-len(seen):] == seen: 20 | print(i - len(seen)) 21 | return 22 | n1 = (n1 + 1 + things[n1]) % len(things) 23 | n2 = (n2 + 1 + things[n2]) % len(things) 24 | 25 | 26 | if __name__ == '__main__': 27 | sys.exit(main(sys.argv)) 28 | -------------------------------------------------------------------------------- /2018/19b.py: -------------------------------------------------------------------------------- 1 | from functools import reduce 2 | from itertools import chain, combinations 3 | import operator 4 | 5 | def powerset(iterable): 6 | "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)" 7 | s = list(iterable) 8 | return chain.from_iterable(combinations(s, r) for r in range(len(s)+1)) 9 | 10 | 11 | # N = 996 12 | N = 10685796 13 | 14 | def brute(N): 15 | x = 0 16 | for i in range(1,N+1): 17 | for j in range(1,N+1): 18 | if i*j == N: 19 | x += i 20 | return x 21 | 22 | def factors(facs): 23 | x = 0 24 | for thing in set(powerset(facs)): 25 | prod = reduce(operator.mul, thing, 1) 26 | x += prod 27 | return x 28 | 29 | print(brute(996)) 30 | # Factors pulled found by `factors` program 31 | print(factors([2, 2, 3, 83])) 32 | print(factors([2, 2, 3, 879283])) 33 | -------------------------------------------------------------------------------- /2018/1a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [s.strip() for s in sys.stdin] 7 | print(sum(int(x) for x in data)) 8 | 9 | if __name__ == '__main__': 10 | sys.exit(main(sys.argv)) 11 | -------------------------------------------------------------------------------- /2018/1b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [s.strip() for s in sys.stdin] 7 | f = 0 8 | seen = set([0]) 9 | while True: 10 | for x in data: 11 | f += int(x) 12 | if f in seen: 13 | print(f) 14 | sys.exit(0) 15 | seen.add(f) 16 | 17 | if __name__ == '__main__': 18 | sys.exit(main(sys.argv)) 19 | -------------------------------------------------------------------------------- /2018/21bhelper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'-?\d+', s)] 8 | 9 | def main(args): 10 | data = [extract(s.strip())[0] for s in sys.stdin] 11 | seen = set() 12 | for i in range(len(data)): 13 | if data[i] in seen: 14 | print(data[i-1]) 15 | return 16 | seen.add(data[i]) 17 | 18 | if __name__ == '__main__': 19 | sys.exit(main(sys.argv)) 20 | -------------------------------------------------------------------------------- /2018/22a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from collections import defaultdict, deque 4 | import sys 5 | import re 6 | import time 7 | from functools import lru_cache 8 | #from dataclasses import dataclass 9 | 10 | @lru_cache(None) 11 | def index(target, depth, x, y): 12 | if x == 0 and y == 0: 13 | return 0 14 | if (x, y) == target: 15 | return 0 16 | if y == 0: 17 | return x * 16807 18 | if x == 0: 19 | return y * 48271 20 | return erosion(target, depth, x-1, y) * erosion(target, depth, x, y-1) 21 | 22 | @lru_cache(None) 23 | def erosion(target, depth, x, y): 24 | return (index(target, depth, x, y) + depth) % 20183 25 | 26 | def go(depth, target): 27 | tx, ty = target 28 | 29 | risk = 0 30 | for x in range(tx+1): 31 | for y in range(ty+1): 32 | e = erosion(target, depth, x, y) 33 | print(x, y, e, e%3, index(target, depth, x, y)) 34 | risk += e%3 35 | 36 | print(risk) 37 | 38 | 39 | def main(args): 40 | go(11739, (11, 718)) 41 | #go(510, (10, 10)) 42 | if __name__ == '__main__': 43 | sys.exit(main(sys.argv)) 44 | -------------------------------------------------------------------------------- /2018/23a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from collections import defaultdict, deque 4 | import sys 5 | import re 6 | #from dataclasses import dataclass 7 | 8 | def extract(s): 9 | return [int(x) for x in re.findall(r'-?\d+', s)] 10 | 11 | def dist(x, y): 12 | return abs(x[0] - y[0]) + abs(x[1] - y[1]) + abs(x[2] - y[2]) 13 | 14 | def main(args): 15 | data = [extract(s.strip()) for s in sys.stdin] 16 | data = [(x[3], tuple(x[:-1])) for x in data] 17 | m = max(data) 18 | in_range = [x for x in data if dist(x[1], m[1]) <= m[0]] 19 | print(len(in_range)) 20 | 21 | 22 | if __name__ == '__main__': 23 | sys.exit(main(sys.argv)) 24 | -------------------------------------------------------------------------------- /2018/25a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from collections import defaultdict, deque 4 | import sys 5 | import re 6 | #from dataclasses import dataclass 7 | 8 | def extract(s): 9 | return [int(x) for x in re.findall(r'-?\d+', s)] 10 | 11 | def dist(x, y): 12 | return abs(x[0] - y[0]) + abs(x[1] - y[1]) + abs(x[2] - y[2]) + abs(x[3] - y[3]) 13 | 14 | def main(args): 15 | data = [extract(s.strip()) for s in sys.stdin] 16 | 17 | constos = [] 18 | 19 | for line in data: 20 | match = None 21 | for i in range(len(constos)): 22 | consto = constos[i] 23 | if consto and any(dist(x, line) <= 3 for x in consto): 24 | if match is None: 25 | match = consto 26 | match.append(line) 27 | else: 28 | match.extend(consto) 29 | constos[i] = None 30 | if match is None: 31 | constos.append([line]) 32 | 33 | print(len([x for x in constos if x])) 34 | 35 | if __name__ == '__main__': 36 | sys.exit(main(sys.argv)) 37 | -------------------------------------------------------------------------------- /2018/2a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict 5 | 6 | def count(s, k): 7 | x = defaultdict(int) 8 | for c in s: 9 | x[c] += 1 10 | return len([a for a in x.values() if a == k]) 11 | 12 | 13 | def main(args): 14 | data = [s.strip() for s in sys.stdin] 15 | a = len([x for x in data if count(x, 2)]) 16 | b = len([x for x in data if count(x, 3)]) 17 | print(a, b, a*b) 18 | 19 | if __name__ == '__main__': 20 | sys.exit(main(sys.argv)) 21 | -------------------------------------------------------------------------------- /2018/2b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict 5 | 6 | def count(s1, s2): 7 | return len([0 for x1, x2 in zip(s1, s2) if x1 != x2]) == 1 8 | 9 | def main(args): 10 | data = [s.strip() for s in sys.stdin] 11 | for x in data: 12 | for y in data: 13 | if count(x, y): 14 | print("".join([x1 for x1, x2 in zip(x, y) if x1 == x2])) 15 | print(x, y) 16 | return 17 | 18 | if __name__ == '__main__': 19 | sys.exit(main(sys.argv)) 20 | -------------------------------------------------------------------------------- /2018/3a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from collections import defaultdict 4 | import sys 5 | import re 6 | 7 | def extract(s): 8 | return [int(x) for x in re.findall(r'-?\d+', s)] 9 | 10 | def main(args): 11 | data = [extract(s.strip()) for s in sys.stdin] 12 | map = defaultdict(int) 13 | doubled = 0 14 | 15 | for _, x, y, l, w in data: 16 | for i in range(l): 17 | for j in range(w): 18 | c = x + i, y + j 19 | if map[c] == 1: doubled += 1 20 | map[c] += 1 21 | print(doubled) 22 | 23 | 24 | 25 | 26 | if __name__ == '__main__': 27 | sys.exit(main(sys.argv)) 28 | -------------------------------------------------------------------------------- /2018/3b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from collections import defaultdict 4 | import sys 5 | import re 6 | 7 | def extract(s): 8 | return [int(x) for x in re.findall(r'-?\d+', s)] 9 | 10 | def main(args): 11 | data = [extract(s.strip()) for s in sys.stdin] 12 | map = defaultdict(set) 13 | doubled = 0 14 | 15 | ok = set(x[0] for x in data) 16 | for id, x, y, l, w in data: 17 | for i in range(l): 18 | for j in range(w): 19 | c = x + i, y + j 20 | map[c].add(id) 21 | if len(map[c]) > 1: 22 | ok -= map[c] 23 | print(list(ok)[0]) 24 | 25 | 26 | 27 | 28 | if __name__ == '__main__': 29 | sys.exit(main(sys.argv)) 30 | -------------------------------------------------------------------------------- /2018/4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from collections import defaultdict 4 | import sys 5 | import re 6 | 7 | def extract(s): 8 | return [int(x) for x in re.findall(r'\d+', s)] 9 | 10 | def main(args): 11 | data = sorted([extract(s) for s in sys.stdin]) 12 | i = 0 13 | 14 | sleep_time = defaultdict(int) 15 | most_common = defaultdict(lambda: defaultdict(int)) 16 | 17 | while i < len(data): 18 | times = data[i] 19 | guard = times[-1] 20 | i += 1 21 | while True: 22 | if i >= len(data) or len(data[i]) == 6: 23 | break 24 | 25 | start = data[i][4] 26 | stop = data[i+1][4] 27 | sleep_time[guard] += (stop - start) 28 | for j in range(start, stop): 29 | most_common[guard][j] += 1 30 | i += 2 31 | 32 | amount, sleepy = max(((v, k) for k, v in sleep_time.items())) 33 | amount, minute = max(((v, k) for k, v in most_common[sleepy].items())) 34 | print(minute * sleepy) 35 | 36 | amount, sleepy, minute = max((v, guard, minute) for guard, d in most_common.items() for minute, v in d.items()) 37 | print(minute * sleepy) 38 | 39 | 40 | if __name__ == '__main__': 41 | sys.exit(main(sys.argv)) 42 | -------------------------------------------------------------------------------- /2018/5a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = list([s.strip() for s in sys.stdin][0]) 7 | print(data) 8 | 9 | changed = True 10 | while changed: 11 | changed = False 12 | new = [] 13 | i = 0 14 | while i < len(data): 15 | if i + 1 < len(data) and data[i] != data[i+1] and data[i].upper() == data[i+1].upper(): 16 | changed = True 17 | i += 2 18 | else: 19 | new.append(data[i]) 20 | i += 1 21 | data = new 22 | 23 | print(len(data)) 24 | 25 | if __name__ == '__main__': 26 | sys.exit(main(sys.argv)) 27 | -------------------------------------------------------------------------------- /2018/5balt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def doit(data): 6 | out = [] 7 | for c in data: 8 | if out and c != out[-1] and c.upper() == out[-1].upper(): 9 | out.pop() 10 | else: 11 | out.append(c) 12 | 13 | return len(out) 14 | 15 | def main(data): 16 | data = [s.strip() for s in sys.stdin][0] 17 | 18 | lol = [] 19 | for i in range(26): 20 | c = chr(ord('a') + i) 21 | n = list(data.replace(c, '').replace(c.upper(), '')) 22 | a = doit(n) 23 | lol.append(a) 24 | print(min(lol)) 25 | 26 | 27 | if __name__ == '__main__': 28 | sys.exit(main(sys.argv)) 29 | -------------------------------------------------------------------------------- /2018/7a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict 5 | 6 | def build_rgraph(graph): 7 | rgraph = {k: set() for k in graph.keys()} 8 | for u in graph.keys(): 9 | for v in graph[u]: 10 | rgraph[v].add(u) 11 | return rgraph 12 | 13 | def main(args): 14 | data = list([s.strip().split(' ') for s in sys.stdin]) 15 | asdf = [(x[1], x[-3]) for x in data] 16 | 17 | xs, ys = zip(*asdf) 18 | all = set(xs + ys) 19 | graph = {x: set() for x in all} 20 | for a, b in asdf: 21 | graph[a].add(b) 22 | rgraph = build_rgraph(graph) 23 | 24 | seen = set() 25 | avail = list(all - set(ys)) 26 | order = [] 27 | while avail: 28 | avail.sort() 29 | x = avail.pop(0) 30 | order.append(x) 31 | seen.add(x) 32 | for y in graph[x]: 33 | rgraph[y].discard(x) 34 | if not rgraph[y] and y not in seen: 35 | seen.add(y) 36 | avail.append(y) 37 | print(''.join(order)) 38 | 39 | if __name__ == '__main__': 40 | sys.exit(main(sys.argv)) 41 | -------------------------------------------------------------------------------- /2018/8a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict, deque 5 | from dataclasses import dataclass 6 | 7 | @dataclass 8 | class Nobe: 9 | children: object 10 | metadata: object 11 | 12 | argh = 0 13 | 14 | def parse(data): 15 | global argh 16 | children = data.popleft() 17 | metadata = data.popleft() 18 | print(children, metadata) 19 | nobe = Nobe([], []) 20 | for x in range(children): 21 | nobe.children.append(parse(data)) 22 | for x in range(metadata): 23 | argh += data.popleft() 24 | 25 | def main(args): 26 | data = [s.strip() for s in sys.stdin][0] 27 | data = deque([int(x) for x in data.split(' ')]) 28 | 29 | print(data) 30 | print(len(data)) 31 | parse(data) 32 | print(argh) 33 | 34 | 35 | 36 | if __name__ == '__main__': 37 | sys.exit(main(sys.argv)) 38 | -------------------------------------------------------------------------------- /2018/8b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict, deque 5 | from dataclasses import dataclass 6 | 7 | @dataclass 8 | class Nobe: 9 | children: object 10 | metadata: object 11 | 12 | argh = 0 13 | 14 | def parse(data): 15 | global argh 16 | children = data.popleft() 17 | metadata = data.popleft() 18 | nobe = Nobe([], []) 19 | for x in range(children): 20 | nobe.children.append(parse(data)) 21 | for x in range(metadata): 22 | y = data.popleft() 23 | nobe.metadata.append(y) 24 | argh += y 25 | 26 | return nobe 27 | 28 | def eval(nobe): 29 | if not nobe.children: 30 | return sum(nobe.metadata) 31 | 32 | children_values = [eval(x) for x in nobe.children] 33 | z = 0 34 | for x in nobe.metadata: 35 | if x != 0 and x - 1 < len(children_values): 36 | #z += children_values[x - 1] 37 | z += eval(nobe.children[x - 1]) 38 | return z 39 | 40 | def main(args): 41 | data = [s.strip() for s in sys.stdin][0] 42 | data = deque([int(x) for x in data.split(' ')]) 43 | 44 | print(eval(parse(data))) 45 | 46 | if __name__ == '__main__': 47 | sys.exit(main(sys.argv)) 48 | -------------------------------------------------------------------------------- /2018/rule.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def bit(n, i): 6 | return (n >> i) & 1 7 | 8 | def rule(n): 9 | d = {} 10 | states = '.#' 11 | for i in range(8): 12 | s = ''.join(states[bit(i, j)] for j in range(2, -1, -1)) 13 | for l in states: 14 | for r in states: 15 | d[l+s+r] = states[bit(n, i)] 16 | 17 | return d 18 | 19 | def main(args): 20 | d = rule(int(args[1])) 21 | for k, v in d.items(): 22 | print('{} => {}'.format(k, v)) 23 | 24 | if __name__ == '__main__': 25 | sys.exit(main(sys.argv)) 26 | -------------------------------------------------------------------------------- /2019/.gitignore: -------------------------------------------------------------------------------- 1 | 25.saves 2 | -------------------------------------------------------------------------------- /2019/12a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | import time 6 | from typing import Set 7 | 8 | 9 | def extract(s): 10 | return [int(x) for x in re.findall(r'-?\d+', s)] 11 | 12 | def add(v1, v2): 13 | return tuple(x + y for x, y in zip(v1, v2)) 14 | 15 | def gravity(r1, r2): 16 | return tuple( 17 | 1 if x < y else 0 if x == y else -1 18 | for x, y in zip(r1, r2) 19 | ) 20 | 21 | def energy(r): 22 | return sum(abs(x) for x in r) 23 | 24 | 25 | def main(args): 26 | data = [s.strip() for s in sys.stdin] 27 | xs = [tuple(extract(s)) for s in data] 28 | vs = [(0, 0, 0) for _ in xs] 29 | 30 | for i in range(1000): 31 | print(xs) 32 | for i in range(len(xs)): 33 | for j in range(len(xs)): 34 | vs[i] = add(vs[i], gravity(xs[i], xs[j])) 35 | 36 | for i in range(len(xs)): 37 | xs[i] = add(xs[i], vs[i]) 38 | 39 | print(sum(energy(x)*energy(v) for x, v in zip(xs, vs))) 40 | 41 | 42 | 43 | if __name__ == '__main__': 44 | main(sys.argv) 45 | -------------------------------------------------------------------------------- /2019/16a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import time 5 | import math 6 | 7 | def go(l, n): 8 | pattern = [] 9 | for x in [0, 1, 0, -1]: 10 | pattern += [x] * n 11 | 12 | val = 0 13 | for i, v in enumerate(l): 14 | val += v * pattern[(i+1) % len(pattern)] 15 | 16 | return int(str(val)[-1]) 17 | 18 | def fft(l): 19 | """Fucked Fourier Transform""" 20 | x = [] 21 | for i, y in enumerate(l): 22 | x.append(go(l, i+1)) 23 | return x 24 | 25 | 26 | def main(args): 27 | data = [int(x) for x in [s.strip() for s in sys.stdin][0]] 28 | 29 | for i in range(100): 30 | data = fft(data) 31 | 32 | print(''.join(str(x) for x in data)) 33 | 34 | 35 | if __name__ == '__main__': 36 | main(sys.argv) 37 | -------------------------------------------------------------------------------- /2019/16b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import time 5 | import math 6 | 7 | 8 | def go(l, n, partials): 9 | return (partials[-1] - partials[n]) % 10 10 | 11 | 12 | def fft(l): 13 | """Fucked Fourier Transform""" 14 | partials = [0] 15 | sum = 0 16 | for v in l: 17 | sum += v 18 | partials.append(sum) 19 | 20 | x = [] 21 | for i, y in enumerate(l): 22 | x.append(go(l, i, partials)) 23 | return x 24 | 25 | 26 | def main(args): 27 | orig_data = [int(x) for x in [s.strip() for s in sys.stdin][0]] 28 | data = orig_data * 10000 29 | 30 | offset = int(''.join(str(x) for x in data[:7])) 31 | assert offset*2 > len(data) 32 | data = data[offset:] 33 | 34 | 35 | for i in range(100): 36 | data = fft(data) 37 | 38 | print(''.join(str(x) for x in data[:8])) 39 | 40 | 41 | if __name__ == '__main__': 42 | main(sys.argv) 43 | -------------------------------------------------------------------------------- /2019/1a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [int(s.strip()) for s in sys.stdin] 7 | total = 0 8 | for x in data: 9 | total += (x // 3) - 2 10 | 11 | print(total) 12 | 13 | 14 | if __name__ == '__main__': 15 | sys.exit(main(sys.argv)) 16 | -------------------------------------------------------------------------------- /2019/1b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [int(s.strip()) for s in sys.stdin] 7 | total = 0 8 | for x in data: 9 | while x: 10 | x = max((x // 3) - 2, 0) 11 | total += x 12 | 13 | print(total) 14 | 15 | 16 | if __name__ == '__main__': 17 | sys.exit(main(sys.argv)) 18 | -------------------------------------------------------------------------------- /2019/21a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import copy 4 | import sys 5 | import time 6 | from collections import defaultdict, deque 7 | from intcode import IntCode 8 | 9 | # !(b&c) = 10 | 11 | # (!b and d) | (!a) 12 | # ! (!(!b and d) & a) 13 | 14 | 15 | PROGRAM = """ 16 | NOT B T 17 | NOT T T 18 | AND C T 19 | NOT T J 20 | AND D J 21 | NOT J J 22 | AND A J 23 | NOT J J 24 | WALK 25 | """.lstrip() 26 | 27 | 28 | def main(args): 29 | data = [s.strip() for s in sys.stdin] 30 | p = [int(x) for x in data[0].split(",")] 31 | board = defaultdict(lambda: " ") 32 | 33 | # Part 1 34 | interp = IntCode(p) 35 | out = interp.run([ord(c) for c in PROGRAM]) 36 | 37 | answer = None 38 | if out[-1] > 255: 39 | answer = out.pop() 40 | 41 | s = "".join(chr(x) for x in out) 42 | print(s) 43 | m = s.split("\n") 44 | print(answer) 45 | 46 | 47 | if __name__ == '__main__': 48 | sys.exit(main(sys.argv)) 49 | -------------------------------------------------------------------------------- /2019/21b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import copy 4 | import sys 5 | import time 6 | from collections import defaultdict, deque 7 | from intcode import IntCode 8 | 9 | # !(b&c) = 10 | # ! (!(!b and d) & a) 11 | 12 | 13 | PROGRAM = """ 14 | NOT B T 15 | NOT T T 16 | AND C T 17 | NOT T J 18 | AND D J 19 | 20 | AND H J 21 | 22 | NOT J J 23 | 24 | AND A J 25 | NOT J J 26 | RUN 27 | """.replace("\n\n", "\n").lstrip() 28 | 29 | 30 | def main(args): 31 | data = [s.strip() for s in sys.stdin] 32 | p = [int(x) for x in data[0].split(",")] 33 | board = defaultdict(lambda: " ") 34 | 35 | # Part 1 36 | interp = IntCode(p) 37 | out = interp.run([ord(c) for c in PROGRAM]) 38 | 39 | answer = None 40 | if out[-1] > 255: 41 | answer = out.pop() 42 | 43 | s = "".join(chr(x) for x in out) 44 | print(s) 45 | m = s.split("\n") 46 | print(answer) 47 | 48 | 49 | if __name__ == '__main__': 50 | sys.exit(main(sys.argv)) 51 | -------------------------------------------------------------------------------- /2019/22a.2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from __future__ import print_function 4 | 5 | from collections import defaultdict, deque 6 | import sys 7 | import time 8 | import math 9 | import re 10 | 11 | def extract(s): 12 | return [int(x) for x in re.findall(r'-?\d+', s)] 13 | 14 | DIRS = [(0, -1), (1, 0), (0, 1), (-1, 0)] 15 | 16 | def add(v1, v2): 17 | return tuple(x + y for x, y in zip(v1, v2)) 18 | 19 | def deal(l): 20 | l.reverse() 21 | 22 | N = 10007 23 | #N = 10 24 | 25 | def main(args): 26 | data = [s.strip() for s in sys.stdin] 27 | 28 | cards = list(range(N)) 29 | 30 | 31 | pos = 2019 32 | for s in data: 33 | if s == "deal into new stack": 34 | pos = N - 1 - pos 35 | elif s.startswith("deal with"): 36 | (increment,) = extract(s) 37 | pos = (pos * increment) % N 38 | else: 39 | (cut,) = extract(s) 40 | pos = (pos - cut) % N 41 | 42 | print(pos) 43 | 44 | if __name__ == '__main__': 45 | main(sys.argv) 46 | -------------------------------------------------------------------------------- /2019/2a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [s.strip() for s in sys.stdin] 7 | program = [int(x) for x in data[0].split(",")] 8 | 9 | program[1] = 12 10 | program[2] = 2 11 | 12 | ip = 0 13 | while True: 14 | instr = program[ip] 15 | if instr == 1: 16 | program[program[ip+3]] = program[program[ip+1]] + program[program[ip+2]] 17 | elif instr == 2: 18 | program[program[ip+3]] = program[program[ip+1]] * program[program[ip+2]] 19 | elif instr == 99: 20 | break 21 | 22 | ip += 4 23 | 24 | print(program[0]) 25 | 26 | if __name__ == '__main__': 27 | sys.exit(main(sys.argv)) 28 | -------------------------------------------------------------------------------- /2019/2b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def run(p): 6 | ip = 0 7 | while True: 8 | instr = p[ip] 9 | if instr == 1: 10 | p[p[ip+3]] = p[p[ip+1]] + p[p[ip+2]] 11 | ip += 4 12 | elif instr == 2: 13 | p[p[ip+3]] = p[p[ip+1]] * p[p[ip+2]] 14 | ip += 4 15 | elif instr == 99: 16 | break 17 | 18 | 19 | def main(args): 20 | data = [s.strip() for s in sys.stdin] 21 | p = [int(x) for x in data[0].split(",")] 22 | op = list(p) 23 | 24 | for n in range(100): 25 | for v in range(100): 26 | p = list(op) 27 | p[1] = n 28 | p[2] = v 29 | run(p) 30 | if p[0] == 19690720: 31 | print(100*n + v) 32 | return 33 | 34 | if __name__ == '__main__': 35 | sys.exit(main(sys.argv)) 36 | -------------------------------------------------------------------------------- /2019/3a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | DIRS = {"R": (1, 0), "L": (-1, 0), "U": (0, 1), "D": (0, -1)} 6 | 7 | def trace(wire): 8 | x, y = 0, 0 9 | for s in wire: 10 | d = s[0] 11 | n = int(s[1:]) 12 | dx, dy = DIRS[d] 13 | for i in range(n): 14 | x += dx 15 | y += dy 16 | yield x, y 17 | 18 | def main(args): 19 | data = [s.strip() for s in sys.stdin] 20 | wire1 = [x for x in data[0].split(",")] 21 | wire2 = [x for x in data[1].split(",")] 22 | 23 | spots = set(trace(wire1)) & set(trace(wire2)) 24 | print(min([abs(x)+abs(y) for x, y in spots])) 25 | 26 | if __name__ == '__main__': 27 | sys.exit(main(sys.argv)) 28 | -------------------------------------------------------------------------------- /2019/3b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | DIRS = {"R": (1, 0), "L": (-1, 0), "U": (0, 1), "D": (0, -1)} 6 | 7 | def trace(wire): 8 | x, y = 0, 0 9 | num = 0 10 | for s in wire: 11 | d = s[0] 12 | n = int(s[1:]) 13 | dx, dy = DIRS[d] 14 | for i in range(n): 15 | x += dx 16 | y += dy 17 | num += 1 18 | yield (x, y), num 19 | 20 | def main(args): 21 | data = [s.strip() for s in sys.stdin] 22 | wire1 = [x for x in data[0].split(",")] 23 | wire2 = [x for x in data[1].split(",")] 24 | 25 | trace1 = dict(trace(wire1)) 26 | trace2 = dict(trace(wire2)) 27 | 28 | spots = trace1.keys() & trace2.keys() 29 | print(min([trace1[xy]+trace2[xy] for xy in spots])) 30 | 31 | if __name__ == '__main__': 32 | sys.exit(main(sys.argv)) 33 | -------------------------------------------------------------------------------- /2019/4a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def extract(s): 6 | import re 7 | return [int(x) for x in re.findall(r'\d+', s)] 8 | 9 | def go(input): 10 | lo, hi = extract(input) 11 | count = 0 12 | for i in range(lo, hi+1): 13 | s = str(i) 14 | if sorted(s) != list(s): continue 15 | if not any(s[j] == s[j+1] for j in range(5)): continue 16 | count += 1 17 | print(count) 18 | 19 | def main(args): 20 | go("256310-732736") 21 | 22 | if __name__ == '__main__': 23 | sys.exit(main(sys.argv)) 24 | -------------------------------------------------------------------------------- /2019/4b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def extract(s): 6 | import re 7 | return [int(x) for x in re.findall(r'\d+', s)] 8 | 9 | def matches(i): 10 | s = str(i) 11 | if sorted(s) != list(s): return False 12 | if not any(s[j] == s[j+1] and (j == 4 or s[j] != s[j+2]) 13 | and (j == 0 or s[j] != s[j-1]) for j in range(5)): return False 14 | return True 15 | 16 | def go(input): 17 | lo, hi = extract(input) 18 | count = 0 19 | for i in range(lo, hi+1): 20 | #if not any(s[j] == s[j+1] == s[j+2] for j in range(4)): continue 21 | if matches(i): 22 | count += 1 23 | print(count) 24 | 25 | def main(args): 26 | go("256310-732736") 27 | 28 | if __name__ == '__main__': 29 | sys.exit(main(sys.argv)) 30 | -------------------------------------------------------------------------------- /2019/5a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def run(p, input): 6 | ip = 0 7 | output = [] 8 | while True: 9 | instr = p[ip] 10 | 11 | def read(i): 12 | mode = (instr // (10**(1+i))) % 10 13 | return p[p[ip+i]] if mode == 0 else p[ip+i] 14 | 15 | if instr % 100 == 1: 16 | p[p[ip+3]] = read(1) + read(2) 17 | ip += 4 18 | elif instr % 100 == 2: 19 | p[p[ip+3]] = read(1) * read(2) 20 | ip += 4 21 | elif instr % 100 == 3: 22 | p[p[ip+1]] = input.pop(0) 23 | ip += 2 24 | elif instr % 100 == 4: 25 | output.append(read(1)) 26 | ip += 2 27 | elif instr % 100 == 99: 28 | break 29 | 30 | print(output) 31 | 32 | 33 | def main(args): 34 | data = [s.strip() for s in sys.stdin] 35 | p = [int(x) for x in data[0].split(",")] 36 | op = list(p) 37 | run(p, [1]) 38 | 39 | if __name__ == '__main__': 40 | sys.exit(main(sys.argv)) 41 | -------------------------------------------------------------------------------- /2019/6.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | import time 6 | from typing import Set 7 | 8 | 9 | def extract(s): 10 | return [int(x) for x in re.findall(r'\d+', s)] 11 | 12 | 13 | 14 | def main(args): 15 | data = [tuple(s.strip().split(")")) for s in sys.stdin] 16 | m = {k: v for v, k in data} 17 | s = set(m.items()) 18 | for k in list(m.keys()): 19 | p = k 20 | while p in m: 21 | s.add((k, p)) 22 | p = m[p] 23 | 24 | print(len(s) - 1) 25 | 26 | cnt = 0 27 | p = m["YOU"] 28 | while True: 29 | if ("SAN", p) in s: 30 | break 31 | p = m[p] 32 | cnt += 1 33 | pp = p 34 | p = m["SAN"] 35 | while p != pp: 36 | p = m[p] 37 | cnt += 1 38 | 39 | print(cnt) 40 | 41 | 42 | if __name__ == '__main__': 43 | sys.exit(main(sys.argv)) 44 | -------------------------------------------------------------------------------- /2019/8.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import time 5 | import math 6 | 7 | HEIGHT=6 8 | WIDTH=25 9 | 10 | 11 | def main(args): 12 | data = [s.strip() for s in sys.stdin][0] 13 | layers = [] 14 | i = 0 15 | while i < len(data): 16 | layers.append(data[i:i+HEIGHT*WIDTH]) 17 | i += HEIGHT*WIDTH 18 | 19 | # Part 1 20 | m = min(x.count('0') for x in layers) 21 | layer = next(x for x in layers if x.count('0') == m) 22 | print(layer.count('1') * layer.count('2')) 23 | 24 | # Part 2 25 | image = [] 26 | for i in range(len(layers[0])): 27 | cur = '2' 28 | for layer in layers: 29 | if cur == '2': 30 | cur = layer[i] 31 | image.append(cur) 32 | 33 | i = 0 34 | while i < len(image): 35 | print(''.join(image[i:i+WIDTH]).replace('0', ' ')) 36 | i += WIDTH 37 | 38 | 39 | if __name__ == '__main__': 40 | main(sys.argv) 41 | -------------------------------------------------------------------------------- /2019/fib.intcode: -------------------------------------------------------------------------------- 1 | # from https://github.com/emmericp/aoc19-intcode-jit 2 | 1101,0,0,0, 3 | 1101,0,0,0, 4 | 3,0, 5 | 1007,0,3,5, 6 | 1006,5,20, 7 | 104,1,99, 8 | 1101,0,1,1, 9 | 1101,0,1,2, 10 | 1101,0,1,3, 11 | 1101,0,2,4, 12 | 8,4,0,5, 13 | 1006,5,46, 14 | 4,3,99, 15 | 1,1,2,3, 16 | 1001,2,0,1, 17 | 1001,3,0,2, 18 | 1001,4,1,4, 19 | 1106,0,36 20 | -------------------------------------------------------------------------------- /2019/run_intcode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from intcode import IntCode 5 | 6 | def main(args): 7 | data = ''.join([s.strip() for s in open(args[1]) if not s.startswith('#')]) 8 | p = [int(x) for x in data.split(",")] 9 | 10 | inp = [int(x) for x in args[2:]] 11 | 12 | interp = IntCode(p) 13 | print(interp.run(inp)) 14 | 15 | if __name__ == '__main__': 16 | sys.exit(main(sys.argv)) 17 | -------------------------------------------------------------------------------- /2019/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup, Extension 2 | 3 | setup(name = '_intcode', 4 | version = '0.1', 5 | ext_modules = [Extension('_intcode', sources = ['_intcode.c'])]) 6 | -------------------------------------------------------------------------------- /2020/1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def p1(data): 6 | for x in data: 7 | for y in data: 8 | if x + y == 2020: 9 | print(x*y) 10 | return 11 | 12 | 13 | def p2(data): 14 | for x in data: 15 | for y in data: 16 | for z in data: 17 | if x + y +z == 2020: 18 | print(x*y*z) 19 | return 20 | 21 | 22 | def main(args): 23 | data = [s.strip() for s in sys.stdin] 24 | data = [int(x) for x in data] 25 | p1(data) 26 | p2(data) 27 | 28 | 29 | if __name__ == '__main__': 30 | sys.exit(main(sys.argv)) 31 | -------------------------------------------------------------------------------- /2020/10b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | import functools 6 | 7 | def extract(s): 8 | return [int(x) for x in re.findall(r'-?\d+', s)] 9 | 10 | 11 | def edges(jolts, v): 12 | # return [v+i for i in [-3,-2,-1,1,2,3] if v+i in jolts] 13 | return [v+i for i in [1,2,3] if v+i in jolts] 14 | 15 | @functools.lru_cache() 16 | def search(jolts, v, tgt): 17 | if v == tgt: 18 | return 1 19 | x = 0 20 | for e in edges(jolts, v): 21 | x += search(jolts, e, tgt) 22 | return x 23 | 24 | def main(args): 25 | # data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 26 | data = set(int(s.strip()) for s in sys.stdin) 27 | tgt = max(data) + 3 28 | data.add(tgt) 29 | data = frozenset(data) 30 | 31 | x = search(data, 0, tgt) 32 | print(x) 33 | 34 | 35 | if __name__ == '__main__': 36 | sys.exit(main(sys.argv)) 37 | -------------------------------------------------------------------------------- /2020/13a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'-?\d+', s)] 8 | 9 | 10 | def main(args): 11 | # data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 12 | data = [s.strip() for s in sys.stdin] 13 | early = int(data[0]) 14 | stamps = [int(x) if x != "x" else None for x in data[1].split(",")] 15 | 16 | i = early 17 | while True: 18 | matches = [x for x in stamps if x and i % x == 0] 19 | print("a", matches) 20 | if matches: 21 | break 22 | i += 1 23 | 24 | print(matches[0]) 25 | print((i - early) * matches[0]) 26 | 27 | if __name__ == '__main__': 28 | sys.exit(main(sys.argv)) 29 | -------------------------------------------------------------------------------- /2020/13b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | # From https://rosettacode.org/wiki/Chinese_remainder_theorem#Python_3.6 6 | # But tweaked to use python3.8 pow 7 | from functools import reduce 8 | def chinese_remainder(n, a): 9 | sum = 0 10 | prod = reduce(lambda a, b: a*b, n) 11 | for n_i, a_i in zip(n, a): 12 | p = prod // n_i 13 | sum += a_i * pow(p, -1, n_i) * p 14 | return sum % prod 15 | 16 | 17 | def main(args): 18 | data = [s.strip() for s in sys.stdin] 19 | early = int(data[0]) 20 | stamps = [int(x) if x != "x" else None for x in data[1].split(",")] 21 | 22 | i = early 23 | while True: 24 | matches = [x for x in stamps if x and i % x == 0] 25 | if matches: 26 | break 27 | i += 1 28 | 29 | print((i - early) * matches[0]) 30 | 31 | bcrap = [(x,((x-i)%x)) for i,x in enumerate(stamps) if x] 32 | ns, bs = zip(*bcrap) 33 | # print(bs, ns) 34 | crt = chinese_remainder(ns, bs) 35 | print(crt) 36 | 37 | 38 | if __name__ == '__main__': 39 | sys.exit(main(sys.argv)) 40 | -------------------------------------------------------------------------------- /2020/14a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from collections import defaultdict 4 | import sys 5 | import re 6 | 7 | def extract(s): 8 | return [int(x) for x in re.findall(r'-?\d+', s)] 9 | 10 | 11 | def main(args): 12 | # data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 13 | data = [s.strip() for s in sys.stdin] 14 | 15 | mem = defaultdict(int) 16 | 17 | for line in data: 18 | if "mask" in line: 19 | smask = line.split(" = ")[1] 20 | mmask = int(smask.replace("1", "0").replace("X", "1"), 2) 21 | mval = int(smask.replace("X", "0"), 2) 22 | print(hex(mmask), hex(mval)) 23 | else: 24 | addr, val = extract(line) 25 | print(addr, val) 26 | write = val & mmask 27 | new = write | mval 28 | print("write", addr, new) 29 | mem[addr] = new 30 | 31 | print(mem) 32 | print(sum(mem.values())) 33 | 34 | 35 | 36 | # print(data) 37 | 38 | if __name__ == '__main__': 39 | sys.exit(main(sys.argv)) 40 | -------------------------------------------------------------------------------- /2020/15a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | from collections import defaultdict 5 | import sys 6 | import re 7 | 8 | def extract(s): 9 | return [int(x) for x in re.findall(r'-?\d+', s)] 10 | 11 | 12 | def main(args): 13 | # data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 14 | data = [s.strip() for s in sys.stdin] 15 | data = [int(x) for x in data[0].split(",")] 16 | 17 | times = {} 18 | counts = defaultdict(list) 19 | t = 0 20 | nums = [] 21 | for x in data: 22 | times[x] = t 23 | counts[x] += [t] 24 | 25 | nums += [x] 26 | t += 1 27 | 28 | print(nums) 29 | print(times) 30 | while t < 2020: 31 | last = nums[-1] 32 | ls = counts[last] 33 | if len(ls) == 1: 34 | num = 0 35 | else: 36 | num = ls[-1] - ls[-2] 37 | counts[num] += [t] 38 | times[num]=t 39 | nums += [num] 40 | t += 1 41 | 42 | print(nums) 43 | print(nums[-1]) 44 | 45 | if __name__ == '__main__': 46 | sys.exit(main(sys.argv)) 47 | -------------------------------------------------------------------------------- /2020/15b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | from collections import defaultdict 5 | import sys 6 | import re 7 | 8 | def extract(s): 9 | return [int(x) for x in re.findall(r'-?\d+', s)] 10 | 11 | 12 | def main(args): 13 | # data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 14 | data = [s.strip() for s in sys.stdin] 15 | data = [int(x) for x in data[0].split(",")] 16 | 17 | counts = defaultdict(list) 18 | t = 0 19 | for x in data: 20 | counts[x] += [t] 21 | 22 | last = x 23 | t += 1 24 | 25 | while t < 30000000: 26 | if t % 1000 == 0: print(t) 27 | ls = counts[last] 28 | if len(ls) == 1: 29 | num = 0 30 | else: 31 | num = ls[-1] - ls[-2] 32 | counts[num] += [t] 33 | counts[num] = counts[num][-2:] 34 | last = num 35 | t += 1 36 | 37 | # print(nums) 38 | print(last) 39 | 40 | if __name__ == '__main__': 41 | sys.exit(main(sys.argv)) 42 | -------------------------------------------------------------------------------- /2020/16a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'\d+', s)] 8 | 9 | 10 | def valid(n, r): 11 | (a,b),(c,d) = r 12 | return (a <= n <= b) or (c <= n <= d) 13 | 14 | def main(args): 15 | # data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 16 | data = [s.strip() for s in sys.stdin] 17 | 18 | fields = {} 19 | for i,x in enumerate(data): 20 | if x == "": break 21 | thing = x.split(":")[0] 22 | a,b,c,d = extract(x) 23 | fields[thing] = ((a,b),(c,d)) 24 | 25 | print(fields) 26 | tickets = [] 27 | for x in data[i:]: 28 | if ',' not in x: continue 29 | z = [int(y) for y in x.split(',')] 30 | tickets.append(z) 31 | 32 | my_ticket = tickets[0] 33 | tickets = tickets[1:] 34 | 35 | print(tickets) 36 | cnt = 0 37 | fucked = [] 38 | for t in tickets: 39 | fucked += [ 40 | v 41 | for v in t 42 | if all(not valid(v, r) for r in fields.values()) 43 | ] 44 | 45 | print(sum(fucked)) 46 | 47 | 48 | # print(data) 49 | 50 | if __name__ == '__main__': 51 | sys.exit(main(sys.argv)) 52 | -------------------------------------------------------------------------------- /2020/22a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'-?\d+', s)] 8 | 9 | 10 | def main(args): 11 | data = [x.strip().split('\n') for x in sys.stdin.read().split('\n\n')] 12 | # data = [s.strip() for s in sys.stdin] 13 | d1 = [int(x) for x in data[0][1:]] 14 | d2 = [int(x) for x in data[1][1:]] 15 | 16 | while d1 and d2: 17 | x1 = d1.pop(0) 18 | x2 = d2.pop(0) 19 | if x1 > x2: 20 | d1.append(x1) 21 | d1.append(x2) 22 | else: 23 | d2.append(x2) 24 | d2.append(x1) 25 | 26 | print(d1, d2) 27 | xs = list(reversed(d1 + d2)) 28 | s = 0 29 | for i, x in enumerate(xs): 30 | s += (i+1)*x 31 | 32 | print(s) 33 | 34 | if __name__ == '__main__': 35 | sys.exit(main(sys.argv)) 36 | -------------------------------------------------------------------------------- /2020/22b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def game(d1, d2): 7 | seen = set() 8 | 9 | while d1 and d2: 10 | if (d1, d2) in seen: 11 | return True, d1, d2 12 | seen.add((d1, d2)) 13 | 14 | x1, d1 = d1[0], d1[1:] 15 | x2, d2 = d2[0], d2[1:] 16 | 17 | if len(d1) >= x1 and len(d2) >= x2: 18 | p1w, _, _ = game(d1[:x1], d2[:x2]) 19 | else: 20 | p1w = x1 > x2 21 | 22 | if p1w: 23 | d1 = d1 + (x1, x2) 24 | else: 25 | d2 = d2 + (x2, x1) 26 | 27 | return bool(d1), d1, d2 28 | 29 | 30 | def main(args): 31 | data = [x.strip().split('\n') for x in sys.stdin.read().split('\n\n')] 32 | d1 = tuple([int(x) for x in data[0][1:]]) 33 | d2 = tuple([int(x) for x in data[1][1:]]) 34 | 35 | p1w, d1, d2 = game(d1, d2) 36 | 37 | print(d1, d2) 38 | xs = list(reversed(d1 + d2)) 39 | s = 0 40 | for i, x in enumerate(xs): 41 | s += (i+1)*x 42 | 43 | print(s) 44 | 45 | if __name__ == '__main__': 46 | sys.exit(main(sys.argv)) 47 | -------------------------------------------------------------------------------- /2020/23a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'-?\d+', s)] 8 | 9 | def go(l): 10 | N = len(l) 11 | up = l[1:4] 12 | l = [l[0]] + l[4:] 13 | dest = l[0] - 1 14 | if dest == 0: 15 | dest = N 16 | while dest in up: 17 | dest -= 1 18 | if dest == 0: 19 | dest = N 20 | 21 | idx = l.index(dest) 22 | l = l[:idx+1] + up + l[idx+1:] 23 | l = l[1:] + [l[0]] 24 | 25 | return l 26 | 27 | 28 | def main(args): 29 | # data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 30 | data = [s.strip() for s in sys.stdin] 31 | cups = [int(x) for x in data[0]] 32 | 33 | for i in range(100): 34 | cups = go(cups) 35 | 36 | print(cups) 37 | idx = cups.index(1) 38 | print(idx) 39 | cups = cups[idx:] + cups[:idx] 40 | print(cups) 41 | print(''.join(str(x) for x in cups)[1:]) 42 | 43 | 44 | 45 | if __name__ == '__main__': 46 | sys.exit(main(sys.argv)) 47 | -------------------------------------------------------------------------------- /2020/24a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from collections import defaultdict 4 | 5 | import sys 6 | import re 7 | 8 | def add(v1, v2): 9 | return tuple(x + y for x, y in zip(v1, v2)) 10 | 11 | def extract(s): 12 | return [int(x) for x in re.findall(r'-?\d+', s)] 13 | 14 | dirs = { 15 | 'e': (1, -1, 0), 16 | 'w': (-1, 1, 0), 17 | 'ne': (1, 0, -1), 18 | 'nw': (0, 1, -1), 19 | 'se': (0, -1, 1), 20 | 'sw': (-1, 0, 1), 21 | } 22 | 23 | def split(x): 24 | i = 0 25 | while i < len(x): 26 | if x[i] in 'ns': 27 | yield x[i:i+2] 28 | i += 2 29 | else: 30 | yield x[i] 31 | i += 1 32 | 33 | def main(args): 34 | # data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 35 | data = [list(split(s.strip())) for s in sys.stdin] 36 | 37 | # white is false 38 | map = defaultdict(bool) 39 | for path in data: 40 | coord = 0, 0, 0 41 | for step in path: 42 | coord = add(coord, dirs[step]) 43 | map[coord] = not map[coord] 44 | 45 | print(map) 46 | print(len([x for x in map.values() if x])) 47 | 48 | # print(data) 49 | 50 | if __name__ == '__main__': 51 | sys.exit(main(sys.argv)) 52 | -------------------------------------------------------------------------------- /2020/25.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'-?\d+', s)] 8 | 9 | def xform(loop, subject): 10 | return pow(subject, loop, 20201227) 11 | 12 | def main(args): 13 | data = [s.strip() for s in sys.stdin] 14 | 15 | d1 = int(data[0]) 16 | d2 = int(data[1]) 17 | 18 | for i in range(1000000000): 19 | if xform(i, 7) == d2: 20 | print(i) 21 | break 22 | else: 23 | print("fuck") 24 | 25 | p2 = i 26 | 27 | print(xform(p2, d1)) 28 | 29 | 30 | 31 | if __name__ == '__main__': 32 | sys.exit(main(sys.argv)) 33 | -------------------------------------------------------------------------------- /2020/2a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [s.strip() for s in sys.stdin] 7 | data = [x.split(" ") for x in data] 8 | data = [(x.split('-'), y[0], z) for x,y,z in data] 9 | 10 | cnt = 0 11 | for (lo, hi), l, s in data: 12 | n = s.count(l) 13 | if int(lo) <= n <= int(hi): 14 | cnt += 1 15 | 16 | print(cnt) 17 | 18 | 19 | 20 | 21 | if __name__ == '__main__': 22 | sys.exit(main(sys.argv)) 23 | -------------------------------------------------------------------------------- /2020/2b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [s.strip() for s in sys.stdin] 7 | data = [x.split(" ") for x in data] 8 | data = [(x.split('-'), y[0], z) for x,y,z in data] 9 | 10 | cnt = 0 11 | for (lo, hi), l, s in data: 12 | x = 0 13 | if s[int(lo)-1] == l: x += 1 14 | if s[int(hi)-1] == l: x += 1 15 | if x == 1: 16 | cnt += 1 17 | 18 | print(cnt) 19 | 20 | 21 | 22 | 23 | if __name__ == '__main__': 24 | sys.exit(main(sys.argv)) 25 | -------------------------------------------------------------------------------- /2020/3a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [s.strip() for s in sys.stdin] 7 | 8 | x = 0 9 | y = 0 10 | n = len(data[0]) 11 | ts = 0 12 | while y < len(data): 13 | if data[y][x % n] == '#': 14 | ts += 1 15 | x += 3 16 | y += 1 17 | 18 | print(ts) 19 | 20 | 21 | if __name__ == '__main__': 22 | sys.exit(main(sys.argv)) 23 | -------------------------------------------------------------------------------- /2020/3b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [s.strip() for s in sys.stdin] 7 | 8 | things = [(1,1), (3,1), (5,1), (7,1), (1,2)] 9 | 10 | res = 1 11 | for dx, dy in things: 12 | x = 0 13 | y = 0 14 | n = len(data[0]) 15 | ts = 0 16 | while y < len(data): 17 | if data[y][x % n] == '#': 18 | ts += 1 19 | x += dx 20 | y += dy 21 | 22 | res *= ts 23 | 24 | print(res) 25 | 26 | 27 | if __name__ == '__main__': 28 | sys.exit(main(sys.argv)) 29 | -------------------------------------------------------------------------------- /2020/4a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'-?\d+', s)] 8 | 9 | bs = ["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid", "cid"] 10 | bs2 = ["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"] 11 | 12 | def main(args): 13 | data = [s.strip() for s in sys.stdin] 14 | data.append('') 15 | 16 | crap = [] 17 | cur = [] 18 | for x in data: 19 | if not x: 20 | crap.append(list(cur)) 21 | cur = [] 22 | else: 23 | cur.extend(x.split(" ")) 24 | 25 | valid = 0 26 | for pp in crap: 27 | things = [x.split(":")[0] for x in pp] 28 | assert all(x in bs for x in things) 29 | print(things) 30 | if all(x in things for x in bs2): 31 | valid += 1 32 | 33 | 34 | 35 | print(crap) 36 | print(valid) 37 | 38 | if __name__ == '__main__': 39 | sys.exit(main(sys.argv)) 40 | -------------------------------------------------------------------------------- /2020/5a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [s.strip() for s in sys.stdin] 7 | 8 | maxseen = 0 9 | seen = set() 10 | for row in data: 11 | lo, hi = 0, 128 12 | for c in row[:7]: 13 | mid = (lo+hi)//2 14 | if c == 'F': 15 | hi = mid 16 | else: 17 | lo = mid 18 | rown = lo 19 | 20 | lo, hi = 0, 8 21 | for c in row[7:]: 22 | mid = (lo+hi)//2 23 | if c == 'L': 24 | hi = mid 25 | else: 26 | lo = mid 27 | 28 | seat = lo 29 | id = rown*8+seat 30 | maxseen = max(maxseen, id) 31 | seen.add(id) 32 | 33 | print(maxseen) 34 | 35 | 36 | # print(data) 37 | 38 | if __name__ == '__main__': 39 | sys.exit(main(sys.argv)) 40 | -------------------------------------------------------------------------------- /2020/5b.alt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Obviously this is how I should have done it but did not. 4 | 5 | import sys 6 | 7 | 8 | def main(args): 9 | data = [s.strip() for s in sys.stdin] 10 | 11 | seen = set() 12 | for row in data: 13 | row = row.replace("F", "0").replace("B", "1") 14 | row = row.replace("L", "0").replace("R", "1") 15 | id = int(row, 2) 16 | seen.add(id) 17 | 18 | print(max(seen)) 19 | for x in range(max(seen)): 20 | if x not in seen and x+1 in seen and x-1 in seen: 21 | print(x) 22 | 23 | # print(data) 24 | 25 | if __name__ == '__main__': 26 | sys.exit(main(sys.argv)) 27 | -------------------------------------------------------------------------------- /2020/6a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'-?\d+', s)] 8 | 9 | 10 | def main(args): 11 | data = [s.strip() for s in sys.stdin] 12 | data.append('') 13 | 14 | crap = [] 15 | cur = [] 16 | for x in data: 17 | if not x: 18 | crap.append(list(cur)) 19 | cur = [] 20 | else: 21 | cur.extend(x.split(" ")) 22 | 23 | data = crap 24 | 25 | total = 0 26 | for group in data: 27 | seen = set() 28 | for person in group: 29 | seen.update(person) 30 | 31 | total += len(seen) 32 | 33 | print(total) 34 | 35 | if __name__ == '__main__': 36 | sys.exit(main(sys.argv)) 37 | -------------------------------------------------------------------------------- /2020/6b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'-?\d+', s)] 8 | 9 | 10 | def main(args): 11 | data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 12 | # data = [s.strip() for s in sys.stdin] 13 | 14 | total = 0 15 | letters = "abcdefghijklmnopqrstuvwxyz" 16 | 17 | for group in data: 18 | seen = set(letters) 19 | for person in group: 20 | seen = seen & set(person) 21 | 22 | total += len(seen) 23 | 24 | print(total) 25 | 26 | if __name__ == '__main__': 27 | sys.exit(main(sys.argv)) 28 | -------------------------------------------------------------------------------- /2020/7a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'-?\d+', s)] 8 | 9 | 10 | def search(bags, x): 11 | if x == 'shiny gold': 12 | return True 13 | # print("A", x, bags[x][1]) 14 | return any(search(bags, y[1]) 15 | for y in bags[x]) 16 | 17 | 18 | def main(args): 19 | data = [s.strip() for s in sys.stdin] 20 | # data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 21 | 22 | bags = {} 23 | for line in data: 24 | bx,y = line.split(" bags contain ") 25 | # print(x, y) 26 | y = y.replace("bags", "").replace("bag", "").replace(".", "") 27 | ys = y.split(", ") 28 | nys = [] 29 | for y in ys: 30 | x = y.strip().split(" ") 31 | if x[0] == 'no': break 32 | nys.append((int(x[0]), " ".join(x[1:]))) 33 | 34 | print((bx, nys)) 35 | bags[bx] = nys 36 | 37 | 38 | print(bags) 39 | n = 0 40 | for k in bags: 41 | if search(bags, k) and k != 'shiny gold': 42 | n += 1 43 | 44 | print(len(bags)) 45 | print(n) 46 | 47 | # print(data) 48 | 49 | if __name__ == '__main__': 50 | sys.exit(main(sys.argv)) 51 | -------------------------------------------------------------------------------- /2020/7b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def search(bags, x): 6 | if x == 'shiny gold': 7 | return True 8 | return any(search(bags, y[1]) 9 | for y in bags[x]) 10 | 11 | def collect(bags, x): 12 | return 1+sum(k*collect(bags, y) 13 | for k,y in bags[x]) 14 | 15 | 16 | def main(args): 17 | data = [s.strip() for s in sys.stdin] 18 | 19 | bags = {} 20 | for line in data: 21 | bx,y = line.split(" bags contain ") 22 | y = y.replace("bags", "").replace("bag", "").replace(".", "") 23 | ys = y.split(", ") 24 | nys = [] 25 | for y in ys: 26 | x = y.strip().split(" ") 27 | if x[0] == 'no': break 28 | nys.append((int(x[0]), " ".join(x[1:]))) 29 | 30 | bags[bx] = nys 31 | 32 | 33 | n = 0 34 | for k in bags: 35 | if search(bags, k) and k != 'shiny gold': 36 | n += 1 37 | 38 | print(n) 39 | print(collect(bags, 'shiny gold')-1) 40 | 41 | if __name__ == '__main__': 42 | sys.exit(main(sys.argv)) 43 | -------------------------------------------------------------------------------- /2020/8a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'-?\d+', s)] 8 | 9 | 10 | def main(args): 11 | # data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 12 | data = [s.strip() for s in sys.stdin] 13 | 14 | prog = data 15 | acc = 0 16 | ip = 0 17 | 18 | seen = set() 19 | while True: 20 | print(ip) 21 | if ip in seen: 22 | break 23 | 24 | seen.add(ip) 25 | 26 | instr = prog[ip].split(" ") 27 | if instr[0] == "acc": 28 | acc += int(instr[1]) 29 | elif instr[0] == "jmp": 30 | ip += int(instr[1]) - 1 31 | elif instr[0] == "nop": 32 | pass 33 | 34 | ip += 1 35 | 36 | 37 | print(acc) 38 | 39 | if __name__ == '__main__': 40 | sys.exit(main(sys.argv)) 41 | -------------------------------------------------------------------------------- /2020/8b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def run(prog): 6 | loop = False 7 | seen = set() 8 | acc = 0 9 | ip = 0 10 | 11 | while ip < len(prog): 12 | if ip in seen: 13 | loop = True 14 | break 15 | seen.add(ip) 16 | 17 | instr = prog[ip].split(" ") 18 | if instr[0] == "acc": 19 | acc += int(instr[1]) 20 | elif instr[0] == "jmp": 21 | ip += int(instr[1]) - 1 22 | elif instr[0] == "nop": 23 | pass 24 | 25 | ip += 1 26 | 27 | return loop, acc 28 | 29 | 30 | def main(args): 31 | data = [s.strip() for s in sys.stdin] 32 | 33 | prog = data 34 | 35 | print(run(prog)[1]) 36 | 37 | for i in range(len(data)): 38 | prog2 = list(prog) 39 | if "nop" in prog2[i]: 40 | prog2[i] = prog2[i].replace("nop", "jmp") 41 | else: 42 | prog2[i] = prog2[i].replace("jmp", "nop") 43 | loop, acc = run(prog2) 44 | if not loop: 45 | break 46 | print(acc) 47 | 48 | if __name__ == '__main__': 49 | sys.exit(main(sys.argv)) 50 | -------------------------------------------------------------------------------- /2020/9a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'-?\d+', s)] 8 | 9 | def match(pre, n): 10 | for x in pre: 11 | for y in pre: 12 | if x != y and x + y == n: 13 | return (x, y) 14 | return None 15 | 16 | 17 | 18 | def main(args): 19 | # data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 20 | data = [int(s.strip()) for s in sys.stdin] 21 | 22 | N = 25 23 | last = data[:N] 24 | rest = data[N:] 25 | 26 | prev = None 27 | for num in rest: 28 | if not match(last, num): 29 | break 30 | last = last[1:] + [num] 31 | prev = num 32 | 33 | print(num) 34 | 35 | if __name__ == '__main__': 36 | sys.exit(main(sys.argv)) 37 | -------------------------------------------------------------------------------- /2020/9b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def match(pre, n): 6 | for x in pre: 7 | for y in pre: 8 | if x != y and x + y == n: 9 | return (x, y) 10 | return None 11 | 12 | def main(args): 13 | # data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 14 | data = [int(s.strip()) for s in sys.stdin] 15 | 16 | N = 25 17 | last = data[:N] 18 | rest = data[N:] 19 | 20 | prev = None 21 | for num in rest: 22 | if not match(last, num): 23 | break 24 | last = last[1:] + [num] 25 | prev = num 26 | 27 | print(num) 28 | part1 = num 29 | 30 | for i in range(len(data)): 31 | for j in range(len(data)): 32 | if sum(data[i:j]) == part1: 33 | print(min(data[i:j]) + max(data[i:j])) 34 | return 35 | 36 | if __name__ == '__main__': 37 | sys.exit(main(sys.argv)) 38 | -------------------------------------------------------------------------------- /2020/template.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'-?\d+', s)] 8 | 9 | 10 | def main(args): 11 | # data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 12 | data = [s.strip() for s in sys.stdin] 13 | 14 | 15 | print(data) 16 | 17 | if __name__ == '__main__': 18 | sys.exit(main(sys.argv)) 19 | -------------------------------------------------------------------------------- /2021/10b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | 6 | def main(args): 7 | data = [s.strip() for s in sys.stdin] 8 | 9 | LS = "([{<" 10 | RS = ")]}>" 11 | m = {k: v for k, v in zip(LS, RS)} 12 | 13 | scores = [3, 57, 1197, 25137] 14 | 15 | incomplete = [] 16 | score = 0 17 | score2 = [] 18 | for line in data: 19 | stack = [] 20 | busted = False 21 | for i, c in enumerate(line): 22 | if c in LS: 23 | stack.append(c) 24 | else: 25 | l = stack.pop() 26 | if m[l] != c: 27 | busted = True 28 | break 29 | if busted: 30 | score += scores[RS.index(c)] 31 | else: 32 | lscore = 0 33 | for c in reversed(stack): 34 | lscore *= 5 35 | r = RS.index(m[c]) + 1 36 | lscore += r 37 | score2 += [lscore] 38 | 39 | 40 | print(score) 41 | print(score2[len(score2)//2]) 42 | 43 | if __name__ == '__main__': 44 | main(sys.argv) 45 | -------------------------------------------------------------------------------- /2021/11a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def vadd(v1, v2): 6 | return tuple(x + y for x, y in zip(v1, v2)) 7 | 8 | ADIRS = [(x,y) for x in [-1,0,1] for y in [-1,0,1] if not x == y == 0] 9 | 10 | def step(m): 11 | for k in list(m): 12 | m[k] += 1 13 | 14 | togo = [k for k, v in m.items() if v > 9] 15 | flashes = 0 16 | while togo: 17 | flashes += 1 18 | v = togo.pop() 19 | for d in ADIRS: 20 | n = vadd(v, d) 21 | if n in m: 22 | m[n] += 1 23 | if m[n] == 10: 24 | togo.append(n) 25 | 26 | for k in list(m): 27 | if m[k] > 9: 28 | m[k] = 0 29 | 30 | return flashes 31 | 32 | 33 | def main(args): 34 | data = [s.strip() for s in sys.stdin] 35 | data = [[int(x) for x in l] for l in data] 36 | 37 | m = {(i, j): v for i, l in enumerate(data) for j, v in enumerate(l)} 38 | 39 | flashes = 0 40 | for i in range(100): 41 | flashes += step(m) 42 | 43 | print(flashes) 44 | 45 | if __name__ == '__main__': 46 | main(sys.argv) 47 | -------------------------------------------------------------------------------- /2021/11b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | 6 | def vadd(v1, v2): 7 | return tuple(x + y for x, y in zip(v1, v2)) 8 | 9 | 10 | ADIRS = [(x,y) for x in [-1,0,1] for y in [-1,0,1] if not x == y == 0] 11 | 12 | 13 | def step(m): 14 | for k in list(m): 15 | m[k] += 1 16 | 17 | togo = [k for k, v in m.items() if v > 9] 18 | flashes = 0 19 | while togo: 20 | flashes += 1 21 | v = togo.pop() 22 | for d in ADIRS: 23 | n = vadd(v, d) 24 | if n in m: 25 | m[n] += 1 26 | if m[n] == 10: 27 | togo.append(n) 28 | 29 | for k in list(m): 30 | if m[k] > 9: 31 | m[k] = 0 32 | 33 | return flashes 34 | 35 | 36 | def main(args): 37 | data = [s.strip() for s in sys.stdin] 38 | data = [[int(x) for x in l] for l in data] 39 | 40 | m = {(i, j): v for i, l in enumerate(data) for j, v in enumerate(l)} 41 | 42 | n = 0 43 | while True: 44 | flashes = step(m) 45 | n += 1 46 | if flashes == len(m): 47 | break 48 | 49 | print(n) 50 | 51 | if __name__ == '__main__': 52 | main(sys.argv) 53 | -------------------------------------------------------------------------------- /2021/12a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from collections import defaultdict 6 | 7 | def go(m, paths, path, u): 8 | if path in paths: 9 | return 10 | paths.add(path) 11 | if u == 'end': 12 | return 13 | 14 | for v in m[u]: 15 | if v.islower() and v in path: 16 | continue 17 | go(m, paths, path + (v,), v) 18 | 19 | 20 | def main(args): 21 | data = [s.strip() for s in sys.stdin] 22 | 23 | m = defaultdict(set) 24 | for line in data: 25 | u, v = line.split('-') 26 | m[u].add(v) 27 | m[v].add(u) 28 | 29 | paths = set() 30 | 31 | go(m, paths, ('start',), 'start') 32 | rpaths = {x for x in paths if x and x[-1] == 'end'} 33 | 34 | print(len(rpaths)) 35 | 36 | 37 | if __name__ == '__main__': 38 | main(sys.argv) 39 | -------------------------------------------------------------------------------- /2021/12b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict 5 | 6 | def go(m, paths, path, doubled, u): 7 | if path in paths: 8 | return 9 | paths.add(path) 10 | if u == 'end': 11 | return 12 | 13 | for v in m[u]: 14 | d = doubled 15 | if v.islower() and v in path: 16 | if v == 'start': 17 | continue 18 | if doubled: 19 | continue 20 | d = True 21 | go(m, paths, path + (v,), d, v) 22 | 23 | 24 | def main(args): 25 | data = [s.strip() for s in sys.stdin] 26 | 27 | m = defaultdict(set) 28 | for line in data: 29 | u, v = line.split('-') 30 | m[u].add(v) 31 | m[v].add(u) 32 | 33 | paths = set() 34 | go(m, paths, ('start',), False, 'start') 35 | rpaths = {x for x in paths if x and x[-1] == 'end'} 36 | 37 | print(len(rpaths)) 38 | 39 | 40 | if __name__ == '__main__': 41 | main(sys.argv) 42 | -------------------------------------------------------------------------------- /2021/13a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | import re 6 | 7 | def extract(s): 8 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 9 | def fold_x(dot, x): 10 | if dot[0] > x: 11 | diff = dot[0] - x 12 | return (x - diff, dot[1]) 13 | return dot 14 | 15 | def main(args): 16 | p1, p2 = sys.stdin.read().split("\n\n") 17 | 18 | dots = [tuple(extract(l)) for l in p1.split("\n")] 19 | instrs = p2.split("\n") 20 | 21 | i1 = extract(instrs[0])[0] 22 | # does assuming x always work?? 23 | new = {fold_x(dot, i1) for dot in dots} 24 | print(len(new)) 25 | 26 | 27 | if __name__ == '__main__': 28 | main(sys.argv) 29 | -------------------------------------------------------------------------------- /2021/13b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | import re 6 | 7 | BLOCK = "█" 8 | 9 | def extract(s): 10 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 11 | 12 | def fold(dot, dir, x): 13 | if 'x' in dir and dot[0] > x: 14 | diff = dot[0] - x 15 | return (x - diff, dot[1]) 16 | if 'y' in dir and dot[1] > x: 17 | diff = dot[1] - x 18 | return (dot[0], x - diff) 19 | return dot 20 | 21 | def fold_y(dot, y): 22 | return dot 23 | 24 | def main(args): 25 | p1, p2 = sys.stdin.read().split("\n\n") 26 | 27 | dots = [tuple(extract(l)) for l in p1.split("\n")] 28 | instrs = p2.strip().split("\n") 29 | 30 | i1 = extract(instrs[0])[0] 31 | new = {fold(dot, instrs[0], i1) for dot in dots} 32 | print(len(new)) 33 | 34 | for instr in instrs: 35 | i1 = extract(instr)[0] 36 | dots = {fold(dot, instr, i1) for dot in dots} 37 | 38 | max_x = max(x for x, y in dots) 39 | max_y = max(y for x, y in dots) 40 | 41 | for y in range(max_y+1): 42 | l = "" 43 | for x in range(max_x+1): 44 | c = BLOCK if (x, y) in dots else " " 45 | l += c 46 | print(l) 47 | 48 | 49 | if __name__ == '__main__': 50 | main(sys.argv) 51 | -------------------------------------------------------------------------------- /2021/14a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from collections import Counter 6 | 7 | def step(s, rules): 8 | out = "" 9 | for i in range(len(s)): 10 | out += s[i] 11 | k = s[i:i+2] 12 | if k in rules: 13 | out += rules[k] 14 | return out 15 | 16 | def main(args): 17 | data = [s.strip() for s in sys.stdin] 18 | target = data[0] 19 | rules = [x.split(" -> ") for x in data[2:]] 20 | rules = {k: v for k, v in rules} 21 | 22 | s = target 23 | for _ in range(10): 24 | s = step(s, rules) 25 | 26 | cnt = Counter(s) 27 | print(max(cnt.values()) - min(cnt.values())) 28 | 29 | 30 | 31 | if __name__ == '__main__': 32 | main(sys.argv) 33 | -------------------------------------------------------------------------------- /2021/14b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from collections import Counter 6 | 7 | 8 | def step(cnt, rules): 9 | ncnt = Counter() 10 | for k, v in cnt.items(): 11 | if k in rules: 12 | c = rules[k] 13 | ncnt[k[0] + c] += v 14 | ncnt[c + k[1]] += v 15 | else: 16 | ncnt[k] += v 17 | return ncnt 18 | 19 | 20 | def main(args): 21 | data = [s.strip() for s in sys.stdin] 22 | s = data[0] 23 | rules = dict(x.split(" -> ") for x in data[2:]) 24 | 25 | cnt = Counter(s[i:i+2] for i in range(len(s)-1)) 26 | for _ in range(40): 27 | cnt = step(cnt, rules) 28 | 29 | lcnt = Counter(s[0]) 30 | for k, v in cnt.items(): 31 | lcnt[k[1]] += v 32 | 33 | print(max(lcnt.values()) - min(lcnt.values())) 34 | 35 | 36 | if __name__ == '__main__': 37 | main(sys.argv) 38 | -------------------------------------------------------------------------------- /2021/15a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from collections import defaultdict, Counter, deque 6 | 7 | def vadd(v1, v2): 8 | return tuple(x + y for x, y in zip(v1, v2)) 9 | 10 | UP, RIGHT, DOWN, LEFT = VDIRS = (0, -1), (1, 0), (0, 1), (-1, 0), 11 | 12 | 13 | def edges(m, v): 14 | l = [vadd(v, e) for e in VDIRS] 15 | return [x for x in l if x in m] 16 | 17 | def main(args): 18 | data = [s.strip() for s in sys.stdin] 19 | data = [[int(x) for x in l] for l in data] 20 | 21 | m = {(i, j): v for i, l in enumerate(data) for j, v in enumerate(l)} 22 | 23 | start = (0, 0) 24 | cost = {start: 0} 25 | todo = deque([start]) 26 | cost[start] = 0 27 | target = (len(data[0])-1, len(data)-1) 28 | 29 | while todo: 30 | # really this should be a PQ but oh well... 31 | cur = min(todo, key=lambda x: cost[x]) 32 | todo.remove(cur) 33 | for nbr in edges(m, cur): 34 | ncost = cost[cur] + m[nbr] 35 | if nbr not in cost or cost[nbr] > ncost: 36 | todo.append(nbr) 37 | cost[nbr] = ncost 38 | 39 | print(cost[target]) 40 | 41 | if __name__ == '__main__': 42 | main(sys.argv) 43 | -------------------------------------------------------------------------------- /2021/1a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [int(s.strip()) for s in sys.stdin] 7 | 8 | cnt = 0 9 | last = data[0] 10 | for cur in data[1:]: 11 | if cur > last: 12 | cnt += 1 13 | last = cur 14 | 15 | print(cnt) 16 | 17 | if __name__ == '__main__': 18 | sys.exit(main(sys.argv)) 19 | -------------------------------------------------------------------------------- /2021/1b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [int(s.strip()) for s in sys.stdin] 7 | 8 | cnt = 0 9 | last = sum(data[0:2]) 10 | for i in range(1, len(data)): 11 | cur = sum(data[i:i+3]) 12 | if cur > last: 13 | cnt += 1 14 | last = cur 15 | 16 | print(cnt) 17 | 18 | if __name__ == '__main__': 19 | sys.exit(main(sys.argv)) 20 | -------------------------------------------------------------------------------- /2021/22a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict 5 | import re 6 | 7 | def extract(s): 8 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 9 | 10 | 11 | def main(args): 12 | data = [s.strip() for s in sys.stdin] 13 | 14 | cmds = [(s.split(" ")[0], extract(s)) for s in data] 15 | cmds = [(s, ((x[0], x[2], x[4]), (x[1], x[3], x[5]))) for s, x in cmds] 16 | 17 | grids = defaultdict(bool) 18 | i = 0 19 | for cmd, ((xmin, ymin, zmin), (xmax, ymax, zmax)) in cmds: 20 | flag = cmd == "on" 21 | for x in range(max(xmin, -50), min(xmax, 50)+1): 22 | for y in range(max(ymin, -50), min(ymax, 50)+1): 23 | for z in range(max(zmin, -50), min(zmax, 50)+1): 24 | grids[x,y,z] = flag 25 | print(i, sum(grids.values())) 26 | 27 | i += 1 28 | 29 | print(sum(grids.values())) 30 | 31 | if __name__ == '__main__': 32 | main(sys.argv) 33 | -------------------------------------------------------------------------------- /2021/2a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | import re 6 | 7 | def extract(s, pos=False): 8 | p = '' if pos else '-?' 9 | return [int(x) for x in re.findall(fr'{p}\d+', s)] 10 | 11 | def main(args): 12 | data = [s.strip() for s in sys.stdin] 13 | 14 | x, y = 0, 0 15 | for line in data: 16 | num = extract(line)[0] 17 | if line.startswith('forward'): 18 | x += num 19 | elif line.startswith('down'): 20 | y += num 21 | else: 22 | y -= num 23 | 24 | print(x*y) 25 | 26 | if __name__ == '__main__': 27 | sys.exit(main(sys.argv)) 28 | -------------------------------------------------------------------------------- /2021/2b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from parse import parse 5 | import re 6 | 7 | 8 | def extract(s, pos=False): 9 | p = '' if pos else '-?' 10 | return [int(x) for x in re.findall(fr'{p}\d+', s)] 11 | 12 | def main(args): 13 | data = [s.strip() for s in sys.stdin] 14 | 15 | x, y = 0, 0 16 | aim = 0 17 | for line in data: 18 | cmd, num = parse('{} {:d}', line) 19 | if cmd == 'forward': 20 | x += num 21 | y += aim*num 22 | elif cmd == 'down': 23 | aim += num 24 | else: 25 | aim -= num 26 | 27 | print(x*y) 28 | 29 | if __name__ == '__main__': 30 | sys.exit(main(sys.argv)) 31 | -------------------------------------------------------------------------------- /2021/3a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from collections import defaultdict, Counter 6 | 7 | def main(args): 8 | data = [s.strip() for s in sys.stdin] 9 | 10 | cs = Counter() 11 | for line in data: 12 | for i in range(len(line)): 13 | if line[i] == "1": 14 | cs[i] += 1 15 | 16 | n = len(data) 17 | zs = ["1" if cs[i]/n > 0.5 else "0" for i in range(len(line))] 18 | ys = ["0" if cs[i]/n > 0.5 else "1" for i in range(len(line))] 19 | gamma = int("".join(zs), 2) 20 | eps = int("".join(ys), 2) 21 | print(gamma*eps) 22 | 23 | if __name__ == '__main__': 24 | sys.exit(main(sys.argv)) 25 | -------------------------------------------------------------------------------- /2021/5a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict 5 | import re 6 | 7 | def extract(s, pos=False): 8 | p = '' if pos else '-?' 9 | return [int(x) for x in re.findall(fr'{p}\d+', s)] 10 | 11 | def main(args): 12 | data = [extract(s.strip()) for s in sys.stdin] 13 | 14 | grid = defaultdict(int) 15 | for x1,y1,x2,y2 in data: 16 | x1, x2 = min(x1, x2), max(x1, x2) 17 | y1, y2 = min(y1, y2), max(y1, y2) 18 | assert x1 <= x2 19 | assert y1 <= y2, (y1, y2) 20 | 21 | if x1 == x2: 22 | for y in range(y1, y2+1): 23 | grid[x1,y] += 1 24 | elif y1 == y2: 25 | for x in range(x1, x2+1): 26 | grid[x,y1] += 1 27 | 28 | num = 0 29 | for val in grid.values(): 30 | if val > 1: 31 | num += 1 32 | print(grid) 33 | 34 | print(num) 35 | 36 | if __name__ == '__main__': 37 | sys.exit(main(sys.argv)) 38 | -------------------------------------------------------------------------------- /2021/6a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from collections import Counter 6 | import re 7 | 8 | def extract(s, pos=False): 9 | p = '' if pos else '-?' 10 | return [int(x) for x in re.findall(fr'{p}\d+', s)] 11 | 12 | 13 | def main(args): 14 | data = [s.strip() for s in sys.stdin] 15 | data = extract(data[0]) 16 | 17 | for _ in range(80): 18 | print(len(data)) 19 | for i in range(len(data)): 20 | if data[i] == 0: 21 | data[i] = 6 22 | data.append(8) 23 | else: 24 | data[i] -= 1 25 | 26 | print(len(data)) 27 | 28 | if __name__ == '__main__': 29 | sys.exit(main(sys.argv)) 30 | -------------------------------------------------------------------------------- /2021/6b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from collections import Counter 6 | import re 7 | 8 | def extract(s, pos=False): 9 | p = '' if pos else '-?' 10 | return [int(x) for x in re.findall(fr'{p}\d+', s)] 11 | 12 | 13 | def main(args): 14 | data = [s.strip() for s in sys.stdin] 15 | data = extract(data[0]) 16 | 17 | cs = Counter(data) 18 | 19 | for n in range(256): 20 | ncs = Counter() 21 | for i in range(9): 22 | if i == 0: 23 | ncs[6] += cs[i] 24 | ncs[8] += cs[i] 25 | else: 26 | ncs[i-1] += cs[i] 27 | cs = ncs 28 | if n == 79: 29 | print(sum(cs.values())) # part A 30 | 31 | print(sum(cs.values())) 32 | 33 | if __name__ == '__main__': 34 | sys.exit(main(sys.argv)) 35 | -------------------------------------------------------------------------------- /2021/6balt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import Counter 5 | import re 6 | import numpy as np 7 | 8 | 9 | def extract(s, pos=False): 10 | p = '' if pos else '-?' 11 | return [int(x) for x in re.findall(fr'{p}\d+', s)] 12 | 13 | 14 | def main(args): 15 | # Make a transformation matrix 16 | mat = np.zeros((9,9), dtype=int) 17 | for i in range(8): 18 | mat[i+1,i] = 1 19 | mat[0,8] = 1 20 | mat[0,6] = 1 21 | print(mat) 22 | 23 | cs = Counter(extract(sys.stdin.read())) 24 | fish = np.array([cs[i] for i in range(9)]) 25 | 26 | print(sum(fish @ np.linalg.matrix_power(mat, 80))) 27 | print(sum(fish @ np.linalg.matrix_power(mat, 256))) 28 | 29 | if __name__ == '__main__': 30 | sys.exit(main(sys.argv)) 31 | -------------------------------------------------------------------------------- /2021/7a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s, pos=False): 7 | p = '' if pos else '-?' 8 | return [int(x) for x in re.findall(fr'{p}\d+', s)] 9 | 10 | def main(args): 11 | data = extract(sys.stdin.read()) 12 | 13 | spots = {} 14 | for i in range(0, max(data)+1): 15 | x = 0 16 | for d in data: 17 | x += abs(i - d) 18 | spots[i] = x 19 | 20 | print(min(spots.values())) 21 | 22 | if __name__ == '__main__': 23 | main(sys.argv) 24 | -------------------------------------------------------------------------------- /2021/7b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s, pos=False): 7 | p = '' if pos else '-?' 8 | return [int(x) for x in re.findall(fr'{p}\d+', s)] 9 | 10 | def main(args): 11 | data = extract(sys.stdin.read()) 12 | 13 | spots = {} 14 | for i in range(0, max(data)+1): 15 | x = 0 16 | for d in data: 17 | di = abs(i - d) 18 | z = di*(di+1)//2 19 | x += z 20 | spots[i] = x 21 | 22 | print(min(spots.values())) 23 | 24 | if __name__ == '__main__': 25 | main(sys.argv) 26 | -------------------------------------------------------------------------------- /2021/8balt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | import itertools 6 | 7 | 8 | CS = [ 9 | "abcefg", "cf", "acdeg", "acdfg", "bcdf", 10 | "abdfg", "abdefg", "acf", "abcdefg", "abcdfg", 11 | ] 12 | MCS = {frozenset(k): i for i, k in enumerate(CS)} 13 | 14 | def solve(codes, nums): 15 | LETS = "abcdefg" 16 | for perm in itertools.permutations(LETS): 17 | m = {k: v for k, v in zip(perm, LETS)} 18 | pcodes = [frozenset([m[c] for c in code]) for code in codes] 19 | matches = {MCS.get(pcode) for pcode in pcodes} 20 | if len(matches) == 10 and None not in matches: 21 | break 22 | else: 23 | raise ValueError 24 | 25 | snum = "" 26 | for num in nums: 27 | numk = frozenset(m[c] for c in num) 28 | snum += str(MCS[numk]) 29 | print(snum) 30 | return int(snum) 31 | 32 | 33 | def main(args): 34 | data = [s.strip() for s in sys.stdin] 35 | data = [x.split(" | ") for x in data] 36 | data = [(x.split(" "), y.split(" ")) for x, y in data] 37 | 38 | # solve(*data[0]) 39 | print(sum(solve(*ent) for ent in data)) 40 | 41 | if __name__ == '__main__': 42 | main(sys.argv) 43 | -------------------------------------------------------------------------------- /2021/9a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | import re 6 | 7 | def vadd(v1, v2): 8 | return tuple(x + y for x, y in zip(v1, v2)) 9 | 10 | UP, RIGHT, DOWN, LEFT = VDIRS = (0, -1), (1, 0), (0, 1), (-1, 0), 11 | 12 | def main(args): 13 | data = [s.strip() for s in sys.stdin] 14 | data = [[int(x) for x in l] for l in data] 15 | 16 | m = {} 17 | for i in range(len(data)): 18 | for j in range(len(data[0])): 19 | m[i,j] = data[i][j] 20 | 21 | lows = set() 22 | for spot, val in m.items(): 23 | z = 0 24 | for dir in VDIRS: 25 | nbr = vadd(spot, dir) 26 | if nbr not in m or m[nbr] > val: 27 | z += 1 28 | if z == 4: 29 | lows.add(spot) 30 | 31 | 32 | print(sum(m[lo] for lo in lows) + len(lows)) 33 | 34 | if __name__ == '__main__': 35 | main(sys.argv) 36 | -------------------------------------------------------------------------------- /2022/10a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 8 | 9 | def main(args): 10 | data = [s.rstrip('\n') for s in sys.stdin] 11 | 12 | ns = [20, 60, 100, 140, 180, 220] 13 | X = 1 14 | last = None 15 | strength = 0 16 | cycle = 1 17 | for i, line in enumerate(data): 18 | if cycle in ns: 19 | strength += cycle * X 20 | cycle += 1 21 | 22 | if not line.startswith('addx'): 23 | continue 24 | 25 | if cycle in ns: 26 | strength += cycle * X 27 | cycle += 1 28 | 29 | n = extract(line)[0] 30 | X += n 31 | 32 | 33 | print(strength) 34 | 35 | if __name__ == '__main__': 36 | main(sys.argv) 37 | -------------------------------------------------------------------------------- /2022/10b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 8 | 9 | def main(args): 10 | data = [s.rstrip('\n') for s in sys.stdin] 11 | 12 | ns = [20, 60, 100, 140, 180, 220] 13 | X = 1 14 | last = None 15 | strength = 0 16 | cycle = 1 17 | 18 | m = list('.' * (40*6)) 19 | 20 | for i, line in enumerate(data): 21 | pos = (cycle-1)%40 22 | if abs(pos-X) <= 1: 23 | m[cycle-1] = '#' 24 | 25 | if cycle in ns: 26 | strength += cycle * X 27 | z = ns.index(cycle) 28 | 29 | 30 | cycle += 1 31 | 32 | if not line.startswith('addx'): 33 | continue 34 | 35 | pos = (cycle-1)%40 36 | if abs(pos-X) <= 1: 37 | m[cycle-1] = '#' 38 | 39 | if cycle in ns: 40 | strength += cycle * X 41 | cycle += 1 42 | 43 | n = extract(line)[0] 44 | X += n 45 | 46 | for r in range(6): 47 | for c in range(40): 48 | print(m[r*40+c], end='') 49 | print() 50 | 51 | print(strength) 52 | 53 | if __name__ == '__main__': 54 | main(sys.argv) 55 | -------------------------------------------------------------------------------- /2022/12a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import deque 5 | 6 | def vadd(v1, v2): 7 | return tuple(x + y for x, y in zip(v1, v2)) 8 | 9 | def iord(c): 10 | return ord(c.lower()) - ord('a') 11 | 12 | UP, RIGHT, DOWN, LEFT = VDIRS = (0, -1), (1, 0), (0, 1), (-1, 0), 13 | 14 | def main(args): 15 | data = [s.rstrip('\n') for s in sys.stdin] 16 | 17 | m = {} 18 | for r in range(len(data)): 19 | for c in range(len(data[0])): 20 | if data[r][c] == 'S': 21 | start = (r, c) 22 | if data[r][c] == 'E': 23 | end = (r, c) 24 | x = data[r][c] 25 | m[r,c] = 0 if x == 'S' else 25 if x == 'E' else iord(x) 26 | 27 | wl = deque([(start, 0)]) 28 | seen = set() 29 | while wl: 30 | node, dist = wl.popleft() 31 | if node in seen: 32 | continue 33 | seen.add(node) 34 | if node == end: 35 | break 36 | for dir in VDIRS: 37 | nbr = vadd(dir, node) 38 | if nbr in m and m[nbr] <= m[node]+1: 39 | wl.append((nbr, dist+1)) 40 | 41 | print(dist) 42 | 43 | if __name__ == '__main__': 44 | main(sys.argv) 45 | -------------------------------------------------------------------------------- /2022/12b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import deque 5 | 6 | def iord(c): 7 | return ord(c.lower()) - ord('a') 8 | 9 | def vadd(v1, v2): 10 | return tuple(x + y for x, y in zip(v1, v2)) 11 | 12 | UP, RIGHT, DOWN, LEFT = VDIRS = (0, -1), (1, 0), (0, 1), (-1, 0), 13 | 14 | def main(args): 15 | data = [s.rstrip('\n') for s in sys.stdin] 16 | 17 | m = {} 18 | for r in range(len(data)): 19 | for c in range(len(data[0])): 20 | if data[r][c] == 'S': 21 | start = (r, c) 22 | if data[r][c] == 'E': 23 | end = (r, c) 24 | x = data[r][c] 25 | m[r,c] = 0 if x == 'S' else 25 if x == 'E' else iord(x) 26 | 27 | wl = deque([(end, 0)]) 28 | seen = set() 29 | while wl: 30 | node, dist = wl.popleft() 31 | if node in seen: 32 | continue 33 | seen.add(node) 34 | if m[node] == 0: 35 | break 36 | for dir in VDIRS: 37 | nbr = vadd(dir, node) 38 | if nbr in m and m[node] <= m[nbr]+1: 39 | wl.append((nbr, dist+1)) 40 | 41 | print(dist) 42 | 43 | if __name__ == '__main__': 44 | main(sys.argv) 45 | -------------------------------------------------------------------------------- /2022/13a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import ast 5 | 6 | def cmp(x1, x2): 7 | if isinstance(x1, int) and isinstance(x2, int): 8 | return x1 - x2 9 | elif isinstance(x1, list) and isinstance(x2, list): 10 | for y1, y2 in zip(x1, x2): 11 | n = cmp(y1, y2) 12 | if n != 0: 13 | return n 14 | return len(x1) - len(x2) 15 | elif isinstance(x1, int): 16 | return cmp([x1], x2) 17 | else: 18 | return cmp(x1, [x2]) 19 | 20 | 21 | def main(args): 22 | data = [x.rstrip('\n').split('\n') for x in sys.stdin.read().split('\n\n')] 23 | 24 | score = 0 25 | for i, (l1, l2) in enumerate(data): 26 | l1 = ast.literal_eval(l1) 27 | l2 = ast.literal_eval(l2) 28 | n = cmp(l1, l2) 29 | if n < 0: 30 | score += (i + 1) 31 | 32 | print(score) 33 | 34 | if __name__ == '__main__': 35 | main(sys.argv) 36 | -------------------------------------------------------------------------------- /2022/1a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [x.strip().split('\n') for x in sys.stdin.read().split('\n\n')] 7 | ys = [sum(int(y) for y in x) for x in data] 8 | print(max(ys)) 9 | 10 | if __name__ == '__main__': 11 | main(sys.argv) 12 | -------------------------------------------------------------------------------- /2022/1b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [x.split('\n') for x in sys.stdin.read().split('\n\n')] 7 | ys = [sum(int(y) for y in x if y) for x in data] 8 | ys.sort() 9 | print(sum(ys[-3:])) 10 | 11 | if __name__ == '__main__': 12 | main(sys.argv) 13 | -------------------------------------------------------------------------------- /2022/20a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | file = open(args[1]) if len(args) > 1 else sys.stdin 7 | data = [int(s.rstrip('\n')) for s in file] 8 | idx0 = data.index(0) 9 | data = list(enumerate(data)) 10 | order = list(data) 11 | 12 | N = len(data) 13 | for pos, i in order: 14 | j = data.index((pos, i)) 15 | del data[j] 16 | idx = (j+i) % len(data) 17 | data[idx:idx] = [(pos, i)] 18 | 19 | nidx0 = data.index((idx0, 0)) 20 | print(sum(data[(nidx0+k)%N][1] for k in (1000, 2000, 3000))) 21 | 22 | 23 | if __name__ == '__main__': 24 | main(sys.argv) 25 | -------------------------------------------------------------------------------- /2022/20b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | K = 811589153 6 | 7 | def main(args): 8 | file = open(args[1]) if len(args) > 1 else sys.stdin 9 | data = [K*int(s.rstrip('\n')) for s in file] 10 | idx0 = data.index(0) 11 | data = list(enumerate(data)) 12 | order = list(data) 13 | 14 | N = len(data) 15 | for _ in range(10): 16 | for pos, i in order: 17 | j = data.index((pos, i)) 18 | del data[j] 19 | idx = (j+i) % (N-1) 20 | data[idx:idx] = [(pos, i)] 21 | 22 | nidx0 = data.index((idx0, 0)) 23 | print(sum(data[(nidx0+k)%N][1] for k in (1000, 2000, 3000))) 24 | 25 | 26 | if __name__ == '__main__': 27 | main(sys.argv) 28 | -------------------------------------------------------------------------------- /2022/25.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | DIGITS = "=-012" 6 | 7 | def num(s): 8 | return DIGITS.index(s) - 2 9 | 10 | def to_dec(s): 11 | v = 0 12 | for i, c in enumerate(reversed(s)): 13 | v += num(c) * 5**i 14 | return v 15 | 16 | def to_snafu(n): 17 | # adapated from https://rosettacode.org/wiki/Balanced_ternary#Python 18 | if n == 0: return '' 19 | if (n % 5) == 0: return to_snafu(n // 5) + '0' 20 | if (n % 5) == 1: return to_snafu(n // 5) + '1' 21 | if (n % 5) == 2: return to_snafu(n // 5) + '2' 22 | if (n % 5) == 3: return to_snafu((n+2) // 5) + '=' 23 | if (n % 5) == 4: return to_snafu((n+1) // 5) + '-' 24 | 25 | def main(args): 26 | file = open(args[1]) if len(args) > 1 else sys.stdin 27 | data = [s.rstrip('\n') for s in file] 28 | 29 | x = 0 30 | for s in data: 31 | x += to_dec(s) 32 | 33 | print(x) 34 | print(to_snafu(x)) 35 | 36 | if __name__ == '__main__': 37 | main(sys.argv) 38 | -------------------------------------------------------------------------------- /2022/2a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [s.strip().split(' ') for s in sys.stdin] 7 | 8 | # This... was not a good way to do this, but I decided to 9 | # prioritize typing over thinking. 10 | results = { 11 | "AX": 3, 12 | "AY": 6, 13 | "AZ": 0, 14 | "BX": 0, 15 | "BY": 3, 16 | "BZ": 6, 17 | "CX": 6, 18 | "CY": 0, 19 | "CZ": 3, 20 | } 21 | 22 | score = 0 23 | for a, b in data: 24 | me = "XYZ".index(b) + 1 25 | res = results[a+b] 26 | score += me + res 27 | 28 | print(score) 29 | 30 | if __name__ == '__main__': 31 | main(sys.argv) 32 | -------------------------------------------------------------------------------- /2022/2b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [s.strip().split(' ') for s in sys.stdin] 7 | 8 | # This... was not a good way to do this, but I decided to 9 | # prioritize typing over thinking. 10 | results = { 11 | "AX": 3, 12 | "AY": 6, 13 | "AZ": 0, 14 | "BX": 0, 15 | "BY": 3, 16 | "BZ": 6, 17 | "CX": 6, 18 | "CY": 0, 19 | "CZ": 3, 20 | } 21 | 22 | score = 0 23 | for a, b in data: 24 | key = {"X": 0, "Y": 3, "Z": 6} 25 | need = key[b] 26 | for c in "XYZ": 27 | if results[a+c] == need: 28 | break 29 | 30 | me = "XYZ".index(c) + 1 31 | res = results[a+c] 32 | score += me + res 33 | 34 | print(score) 35 | 36 | if __name__ == '__main__': 37 | main(sys.argv) 38 | -------------------------------------------------------------------------------- /2022/3a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def iord(c): 6 | return ord(c.lower()) - ord('a') 7 | 8 | 9 | def main(args): 10 | data = [s.strip() for s in sys.stdin] 11 | 12 | cnt = 0 13 | for line in data: 14 | mid = len(line)//2 15 | a, b = line[:mid], line[mid:] 16 | same = list(set(a) & set(b))[0] 17 | if same.islower(): 18 | val = 1 + iord(same) 19 | else: 20 | val = 27 + iord(same) 21 | 22 | cnt += val 23 | 24 | print(cnt) 25 | 26 | if __name__ == '__main__': 27 | main(sys.argv) 28 | -------------------------------------------------------------------------------- /2022/3b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def iord(c): 6 | return ord(c.lower()) - ord('a') 7 | 8 | def main(args): 9 | data = [s.strip() for s in sys.stdin] 10 | 11 | cnt = 0 12 | for i in range(0, len(data), 3): 13 | parts = data[i:i+3] 14 | same = set(parts[0]) & set(parts[1]) & set(parts[2]) 15 | same = list(same)[0] 16 | if same.islower(): 17 | val = 1 + iord(same) 18 | else: 19 | val = 27 + iord(same) 20 | 21 | cnt += val 22 | 23 | print(cnt) 24 | 25 | if __name__ == '__main__': 26 | main(sys.argv) 27 | -------------------------------------------------------------------------------- /2022/4a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 8 | 9 | def main(args): 10 | data = [s.strip() for s in sys.stdin] 11 | 12 | cnt = 0 13 | for line in data: 14 | a1, a2, b1, b2 = extract(line) 15 | if a1 <= b1 <= b2 <= a2: 16 | cnt += 1 17 | elif b1 <= a1 <= a2 <= b2: 18 | cnt += 1 19 | 20 | print(cnt) 21 | 22 | if __name__ == '__main__': 23 | main(sys.argv) 24 | -------------------------------------------------------------------------------- /2022/4b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def main(args): 7 | data = [s.strip() for s in sys.stdin] 8 | 9 | cnt = 0 10 | for line in data: 11 | a1, a2, b1, b2 = extract(line) 12 | 13 | if a1 <= b1 and b1 <= a2: 14 | cnt += 1 15 | elif b1 <= a1 and a1 <= b2: 16 | cnt += 1 17 | 18 | print(cnt) 19 | 20 | if __name__ == '__main__': 21 | main(sys.argv) 22 | -------------------------------------------------------------------------------- /2022/5a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 8 | 9 | def main(args): 10 | m, cmds = [x.strip().split('\n') for x in sys.stdin.read().split('\n\n')] 11 | 12 | N = extract(m[-1])[-1] 13 | stacks = [[] for _ in range(N)] 14 | for line in list(reversed(m))[1:]: 15 | for i in range(N): 16 | j = 1+i*4 17 | if line[j:j+1] not in (" ", ""): 18 | stacks[i].append(line[j]) 19 | 20 | for cmd in cmds: 21 | cnt, from_, to = extract(cmd) 22 | for _ in range(cnt): 23 | c = stacks[from_-1].pop() 24 | stacks[to-1].append(c) 25 | 26 | s = "".join([s[-1] for s in stacks]) 27 | print(s) 28 | 29 | if __name__ == '__main__': 30 | main(sys.argv) 31 | -------------------------------------------------------------------------------- /2022/5b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 8 | 9 | def main(args): 10 | m, cmds = [x.strip().split('\n') for x in sys.stdin.read().split('\n\n')] 11 | 12 | N = extract(m[-1])[-1] 13 | stacks = [[] for _ in range(N)] 14 | for line in list(reversed(m))[1:]: 15 | for i in range(N): 16 | j = 1+i*4 17 | if line[j:j+1] not in (" ", ""): 18 | stacks[i].append(line[j]) 19 | 20 | for cmd in cmds: 21 | cnt, from_, to = extract(cmd) 22 | moved = stacks[from_-1][-cnt:] 23 | del stacks[from_-1][-cnt:] 24 | stacks[to-1].extend(moved) 25 | 26 | s = "".join([s[-1] for s in stacks]) 27 | print(s) 28 | 29 | if __name__ == '__main__': 30 | main(sys.argv) 31 | -------------------------------------------------------------------------------- /2022/6a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [s.rstrip('\n') for s in sys.stdin][0] 7 | 8 | for i in range(len(data)): 9 | if len(set(data[i:i+4])) == 4: 10 | print(i+4) 11 | break 12 | 13 | if __name__ == '__main__': 14 | main(sys.argv) 15 | -------------------------------------------------------------------------------- /2022/6b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [s.rstrip('\n') for s in sys.stdin][0] 7 | 8 | for i in range(len(data)): 9 | if len(set(data[i:i+14])) == 14: 10 | print(i+14) 11 | break 12 | 13 | if __name__ == '__main__': 14 | main(sys.argv) 15 | -------------------------------------------------------------------------------- /2022/8a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [[int(c) for c in s.rstrip('\n')] for s in sys.stdin] 7 | 8 | N = len(data) 9 | M = len(data[0]) 10 | 11 | num = 0 12 | for i in range(N): 13 | for j in range(M): 14 | h = data[i][j] 15 | x = 0 16 | if ( 17 | h > max([-1] + data[i][:j]) 18 | or h > max([-1] + (data[i][j+1:])) 19 | or h > max([-1] + [data[k][j] for k in range(0, i)]) 20 | or h > max([-1] + [data[k][j] for k in range(i+1, N)]) 21 | ): 22 | x = 1 23 | num += 1 24 | 25 | print(num) 26 | 27 | if __name__ == '__main__': 28 | main(sys.argv) 29 | -------------------------------------------------------------------------------- /2022/8b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | data = [[int(c) for c in s.rstrip('\n')] for s in sys.stdin] 7 | 8 | N = len(data) 9 | M = len(data[0]) 10 | 11 | scs = [] 12 | num = 0 13 | for i in range(N): 14 | for j in range(M): 15 | 16 | h = data[i][j] 17 | x = 0 18 | 19 | a = [(i+(x!=10),x) for i, x in enumerate(reversed([10] + data[i][:j])) if x >= h] 20 | b = [(i+(x!=10),x) for i, x in enumerate(((data[i][j+1:] + [10]))) if x >= h] 21 | 22 | up = [data[k][j] for k in range(0, i)] 23 | down = [data[k][j] for k in range(i+1, N)] 24 | 25 | c = [(i+(x!=10),x) for i, x in enumerate(reversed([10] + up)) if x >= h] 26 | d = [(i+(x!=10),x) for i, x in enumerate(((down + [10]))) if x >= h] 27 | # print(a, b, c, d) 28 | score = a[0][0]*b[0][0]*c[0][0]*d[0][0] 29 | scs.append(score) 30 | 31 | print(max(scs)) 32 | 33 | 34 | if __name__ == '__main__': 35 | main(sys.argv) 36 | -------------------------------------------------------------------------------- /2023/11b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def solve(data, N): 6 | cols = set() 7 | rows = set() 8 | 9 | for y, l in enumerate(data): 10 | for x, c in enumerate(l): 11 | if c == '#': 12 | rows.add(y) 13 | cols.add(x) 14 | 15 | galaxies = [] 16 | yreal = 0 17 | for y, r in enumerate(data): 18 | row = "" 19 | if y not in rows: 20 | yreal += N-1 21 | xreal = 0 22 | for x, c in enumerate(r): 23 | if x not in cols: 24 | xreal += N-1 25 | if c == '#': 26 | galaxies.append((xreal, yreal)) 27 | xreal += 1 28 | yreal += 1 29 | 30 | sum = 0 31 | for i, (x1, y1) in enumerate(galaxies): 32 | for j, (x2, y2) in enumerate(galaxies[i+1:]): 33 | dst = abs(y2-y1) + abs(x2-x1) 34 | sum += dst 35 | 36 | return sum 37 | 38 | 39 | def main(args): 40 | file = open(args[1]) if len(args) > 1 else sys.stdin 41 | data = [s.rstrip('\n') for s in file] 42 | 43 | p1 = solve(data, 1) 44 | p2 = solve(data, 1000000) 45 | 46 | print(p1) 47 | print(p2) 48 | 49 | if __name__ == '__main__': 50 | main(sys.argv) 51 | -------------------------------------------------------------------------------- /2023/12a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 8 | 9 | def check(line, cnts): 10 | if '?' not in line: 11 | ls = [len(x) for x in line.split('.') if '.' not in x and len(x)] 12 | return ls == cnts 13 | 14 | return ( 15 | check(line.replace('?', '.', 1), cnts) 16 | + check(line.replace('?', '#', 1), cnts) 17 | ) 18 | 19 | def main(args): 20 | file = open(args[1]) if len(args) > 1 else sys.stdin 21 | data = [s.rstrip('\n') for s in file] 22 | 23 | sum = 0 24 | for l in data: 25 | l, nums = l.split(' ') 26 | nums = extract(nums) 27 | sum += check(l, nums) 28 | 29 | print(sum) 30 | 31 | if __name__ == '__main__': 32 | main(sys.argv) 33 | -------------------------------------------------------------------------------- /2023/13a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def lcheck(x): 6 | for i in range(1, len(x)): 7 | start = x[:i] 8 | end = x[i:] 9 | if len(start) < len(end): 10 | if start == end[:len(start)][::-1]: 11 | return i 12 | else: 13 | if start[-len(end):] == end[::-1]: 14 | return i 15 | 16 | 17 | def check(x): 18 | # horiz 19 | if n := lcheck(x): 20 | return n * 100 21 | 22 | x = [list(c) for c in zip(*x)] 23 | if n := lcheck(x): 24 | return n 25 | 26 | 27 | def main(args): 28 | file = open(args[1]) if len(args) > 1 else sys.stdin 29 | data = [x.rstrip('\n').split('\n') for x in file.read().split('\n\n')] 30 | 31 | sum = 0 32 | for x in data: 33 | v = check(x) 34 | # print('\n'.join(x)) 35 | # print(v) 36 | sum += v 37 | 38 | 39 | print(sum) 40 | 41 | if __name__ == '__main__': 42 | main(sys.argv) 43 | -------------------------------------------------------------------------------- /2023/14a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import copy 5 | 6 | def slide(l): 7 | l = copy.deepcopy(l) 8 | for i in range(len(l)-1): 9 | for j in range(len(l[0])): 10 | if l[i][j] == '.' and l[i+1][j] == 'O': 11 | l[i][j] = 'O' 12 | l[i+1][j] = '.' 13 | 14 | return l 15 | 16 | def main(args): 17 | file = open(args[1]) if len(args) > 1 else sys.stdin 18 | data = [s.rstrip('\n') for s in file] 19 | 20 | m = [list(s) for s in data] 21 | 22 | i = 0 23 | while True: 24 | nl = slide(m) 25 | if nl == m: 26 | break 27 | print(i, nl) 28 | print(nl) 29 | print(m) 30 | print([x == y for x, y in zip(nl, m)]) 31 | print(nl[0]) 32 | print(m[0]) 33 | m = nl 34 | 35 | i+= 1 36 | 37 | sum = 0 38 | for i, row in enumerate(m): 39 | i = len(m)-i 40 | for c in row: 41 | if c == 'O': 42 | sum += i 43 | 44 | print(sum) 45 | 46 | if __name__ == '__main__': 47 | main(sys.argv) 48 | -------------------------------------------------------------------------------- /2023/15a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | file = open(args[1]) if len(args) > 1 else sys.stdin 7 | data = file.read().replace('\n', '').split(',') 8 | 9 | sum = 0 10 | for node in data: 11 | val = 0 12 | for c in node: 13 | val += ord(c) 14 | val *= 17 15 | val %= 256 16 | print(node, val) 17 | sum += val 18 | 19 | print(sum) 20 | 21 | if __name__ == '__main__': 22 | main(sys.argv) 23 | -------------------------------------------------------------------------------- /2023/15b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def hash(s): 6 | val = 0 7 | for c in s: 8 | val += ord(c) 9 | val *= 17 10 | val %= 256 11 | return val 12 | 13 | 14 | def main(args): 15 | file = open(args[1]) if len(args) > 1 else sys.stdin 16 | data = file.read().replace('\n', '').split(',') 17 | 18 | boxes = [{} for _ in range(256)] 19 | 20 | for node in data: 21 | if '-' in node: 22 | s = node[:-1] 23 | box = hash(s) 24 | boxes[box].pop(s, None) 25 | else: 26 | s, n = node.split('=') 27 | box = hash(s) 28 | n = int(n) 29 | # don't try this on python3.5 or earlier ;) 30 | boxes[box][s] = n 31 | 32 | sum = 0 33 | for i, box in enumerate(boxes): 34 | i += 1 35 | for j, val in enumerate(box.values()): 36 | j += 1 37 | sum += i*j*val 38 | 39 | print(sum) 40 | 41 | if __name__ == '__main__': 42 | main(sys.argv) 43 | -------------------------------------------------------------------------------- /2023/18b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | 6 | def vadd(v1, v2, n=1): 7 | return tuple([x + n*y for x, y in zip(v1, v2)]) 8 | 9 | UP, RIGHT, DOWN, LEFT = VDIRS = (0, -1), (1, 0), (0, 1), (-1, 0), 10 | DIRS = {'U': UP, 'R': RIGHT, 'D': DOWN, 'L': LEFT } 11 | ALL_DIRS = [(x, y) for x in [-1,0,1] for y in [-1,0,1] if not x == y == 0] 12 | 13 | # Lol: https://stackoverflow.com/questions/451426/how-do-i-calculate-the-area-of-a-2d-polygon 14 | def area(p): 15 | return abs(sum(x0*y1 - x1*y0 for ((x0, y0), (x1, y1)) in segments(p))) // 2 16 | 17 | def segments(p): 18 | return zip(p, p[1:] + [p[0]]) 19 | 20 | def main(args): 21 | file = open(args[1]) if len(args) > 1 else sys.stdin 22 | data = [s.rstrip('\n') for s in file] 23 | 24 | pos = (0, 0) 25 | poses = [pos] 26 | perim = 0 27 | for line in data: 28 | d, n, x = line.split(' ') 29 | # n = int(n) 30 | n = int(x[2:-2], 16) 31 | d = 'RDLU'[int(x[-2])] 32 | 33 | pos = vadd(pos, DIRS[d], n) 34 | poses.append(pos) 35 | perim += n 36 | 37 | print(int(area(poses)) + perim//2 + 1) 38 | 39 | 40 | if __name__ == '__main__': 41 | main(sys.argv) 42 | -------------------------------------------------------------------------------- /2023/1a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict, Counter, deque 5 | from parse import parse 6 | import re 7 | import math 8 | 9 | 10 | def main(args): 11 | file = open(args[1]) if len(args) > 1 else sys.stdin 12 | data = [s.rstrip('\n') for s in file] 13 | 14 | v = 0 15 | for line in data: 16 | s = ''.join(x for x in line if x.isdigit()) 17 | print(s) 18 | num = int(s[0] + s[-1]) 19 | print(line, num) 20 | v += num 21 | 22 | 23 | print(v) 24 | 25 | if __name__ == '__main__': 26 | main(sys.argv) 27 | -------------------------------------------------------------------------------- /2023/1b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict, Counter, deque 5 | from parse import parse 6 | import re 7 | import math 8 | 9 | 10 | asdf = ['----', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'] 11 | 12 | def main(args): 13 | file = open(args[1]) if len(args) > 1 else sys.stdin 14 | data = [s.rstrip('\n') for s in file] 15 | 16 | v = 0 17 | for line in data: 18 | first = None 19 | last = None 20 | for i in range(len(line)): 21 | if line[i].isdigit(): 22 | last = int(line[i]) 23 | if not first: first = last 24 | else: 25 | for j, k in enumerate(asdf): 26 | if line[i:].startswith(k): 27 | last = j 28 | if not first: first = last 29 | break 30 | 31 | num = int(first*10 + last) 32 | print(line, num) 33 | v += num 34 | 35 | 36 | print(v) 37 | 38 | if __name__ == '__main__': 39 | main(sys.argv) 40 | -------------------------------------------------------------------------------- /2023/2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 8 | 9 | def main(args): 10 | file = open(args[1]) if len(args) > 1 else sys.stdin 11 | data = [s.rstrip('\n') for s in file] 12 | 13 | cap = {'red': 12, 'green': 13, 'blue': 14} 14 | 15 | p1sum = 0 16 | p2sum = 0 17 | for line in data: 18 | game, rest = line.split(": ") 19 | parts = [[y.split(' ') for y in x.split(', ')] for x in rest.split('; ')] 20 | ds = [{k: int(v) for v, k in part} for part in parts] 21 | 22 | ok = all( 23 | all(v <= cap[k] for k, v in d.items()) 24 | for d in ds 25 | ) 26 | if ok: 27 | p1sum += extract(game)[0] 28 | 29 | pwr = 1 30 | for c in cap: 31 | pwr *= max(d.get(c, 0) for d in ds) 32 | p2sum += pwr 33 | 34 | print(p1sum) 35 | print(p2sum) 36 | 37 | if __name__ == '__main__': 38 | main(sys.argv) 39 | -------------------------------------------------------------------------------- /2023/20bgv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict, deque 5 | import math 6 | import itertools 7 | 8 | # I didn't actually use this when solving but maybe I should have! 9 | 10 | def main(args): 11 | file = open(args[1]) if len(args) > 1 else sys.stdin 12 | data = [s.rstrip('\n') for s in file] 13 | 14 | 15 | inputs = defaultdict(list) 16 | nodes = {} 17 | 18 | for line in data: 19 | l, r = line.split(' -> ') 20 | outs = r.split(', ') 21 | 22 | c, n = l[0], l[1:] 23 | nodes[n] = (c, outs) 24 | for out in outs: 25 | inputs[out].append(n) 26 | 27 | print('digraph nodes {') 28 | print('rankdir="LR"') 29 | for node, (typ, _) in nodes.items(): 30 | print(f'{node} [label="{typ}{node}"]') 31 | 32 | for node, (typ, outs) in nodes.items(): 33 | for out in outs: 34 | print(f'{node} -> {out}') 35 | 36 | print('}') 37 | 38 | if __name__ == '__main__': 39 | main(sys.argv) 40 | -------------------------------------------------------------------------------- /2023/4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 8 | 9 | 10 | def main(args): 11 | file = open(args[1]) if len(args) > 1 else sys.stdin 12 | data = [s.rstrip('\n') for s in file] 13 | 14 | copies = [1 for _ in data] 15 | tscore = 0 16 | tot = 0 17 | 18 | for i, line in enumerate(data): 19 | n, r = line.split(':') 20 | win, have = r.split('|') 21 | 22 | win = extract(win) 23 | have = extract(have) 24 | 25 | score = cnt = 0 26 | for n in have: 27 | if n in win: 28 | cnt += 1 29 | 30 | if score == 0: 31 | score = 1 32 | else: 33 | score *= 2 34 | 35 | 36 | for j in range(i + 1, i + 1 + cnt): 37 | copies[j] += copies[i] 38 | 39 | tscore += score 40 | tot += copies[i] 41 | 42 | print(tscore) 43 | print(tot) 44 | 45 | 46 | if __name__ == '__main__': 47 | main(sys.argv) 48 | -------------------------------------------------------------------------------- /2023/5a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 8 | 9 | def lookup(m, i): 10 | for d, s, n in m: 11 | if s <= i < s + n: 12 | return d + (i - s) 13 | return i 14 | 15 | def main(args): 16 | file = open(args[1]) if len(args) > 1 else sys.stdin 17 | data = [x.rstrip('\n').split('\n') for x in file.read().split('\n\n')] 18 | 19 | seeds = extract(data[0][0]) 20 | maps = [] 21 | for lines in data[1:]: 22 | print(lines) 23 | m = [extract(s) for s in lines[1:] if s] 24 | maps.append(m) 25 | 26 | nums = [] 27 | for seed in seeds: 28 | for m in maps: 29 | n = seed 30 | seed = lookup(m, seed) 31 | print(n, "->", seed) 32 | print(m) 33 | nums.append(seed) 34 | 35 | print(nums) 36 | print(min(nums)) 37 | 38 | if __name__ == '__main__': 39 | main(sys.argv) 40 | -------------------------------------------------------------------------------- /2023/6a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 8 | 9 | 10 | def main(args): 11 | file = open(args[1]) if len(args) > 1 else sys.stdin 12 | data = [s.rstrip('\n') for s in file] 13 | 14 | # How I should have done part 2 15 | # data[0] = data[0].replace(' ', '') 16 | # data[1] = data[1].replace(' ', '') 17 | 18 | times = extract(data[0]) 19 | dists = extract(data[1]) 20 | 21 | ans = 1 22 | for time, dist in zip(times, dists): 23 | n = 0 24 | for i in range(time-1): 25 | traved = i * (time-i) 26 | if traved > dist: 27 | n += 1 28 | ans *= n 29 | 30 | print(ans) 31 | 32 | if __name__ == '__main__': 33 | main(sys.argv) 34 | -------------------------------------------------------------------------------- /2023/7a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import Counter 5 | 6 | ORDERS = reversed('AKQJT98765432') 7 | ORDER = {v: k for k, v in enumerate(ORDERS)} 8 | 9 | def characterize(s): 10 | cnts = Counter(s) 11 | vals = sorted(cnts.values()) 12 | if vals[-1] == 5: 13 | return 10 14 | elif vals[-1] == 4: 15 | return 9 16 | elif vals == [2, 3]: 17 | return 8 18 | elif vals == [1, 1, 3]: 19 | return 7 20 | elif vals == [1, 2, 2]: 21 | return 6 22 | elif vals == [1, 1, 1, 2]: 23 | return 5 24 | elif vals == [1, 1, 1, 2]: 25 | return 4 26 | else: 27 | return 3 28 | 29 | def key(s): 30 | return (characterize(s), tuple(ORDER[c] for c in s)) 31 | 32 | def main(args): 33 | file = open(args[1]) if len(args) > 1 else sys.stdin 34 | data = [s.rstrip('\n') for s in file] 35 | 36 | data = [x.split(' ') for x in data] 37 | data = [(s, int(x)) for s, x in data] 38 | 39 | data2 = sorted(data, key=lambda k: key(k[0])) 40 | 41 | sum = 0 42 | for i, (_, k) in enumerate(data2): 43 | sum += (i+1)*k 44 | print(sum) 45 | 46 | if __name__ == '__main__': 47 | main(sys.argv) 48 | -------------------------------------------------------------------------------- /2023/8a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | file = open(args[1]) if len(args) > 1 else sys.stdin 7 | data = [s.rstrip('\n') for s in file] 8 | 9 | dirs = data[0] 10 | d = {} 11 | for line in data[2:]: 12 | x, yz = line.split(" = (") 13 | y, z = yz.split(", ") 14 | z = z.replace(")", "") 15 | d[x] = (y, z) 16 | 17 | steps = 0 18 | node = 'AAA' 19 | while node != 'ZZZ': 20 | s = dirs[steps % len(dirs)] 21 | r = s == 'R' 22 | node = d[node][r] 23 | steps += 1 24 | 25 | print(steps) 26 | 27 | if __name__ == '__main__': 28 | main(sys.argv) 29 | -------------------------------------------------------------------------------- /2023/8b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import math 5 | 6 | def main(args): 7 | file = open(args[1]) if len(args) > 1 else sys.stdin 8 | data = [s.rstrip('\n') for s in file] 9 | 10 | dirs = data[0] 11 | d = {} 12 | for line in data[2:]: 13 | x, yz = line.split(" = (") 14 | y, z = yz.split(", ") 15 | z = z.replace(")", "") 16 | d[x] = (y, z) 17 | 18 | nodes = {s for s in d if s[-1] == 'A'} 19 | repeat = set() 20 | 21 | snodes = sorted(nodes) 22 | 23 | stops = [] 24 | for node in nodes: 25 | steps = 0 26 | while True: 27 | if node[-1] == 'Z': 28 | break 29 | s = dirs[steps % len(dirs)] 30 | r = s == 'R' 31 | node = d[node][r] 32 | steps += 1 33 | stops.append(steps) 34 | 35 | prod = 1 36 | for x in stops: 37 | prod *= x 38 | print(math.lcm(*stops)) 39 | 40 | 41 | if __name__ == '__main__': 42 | main(sys.argv) 43 | -------------------------------------------------------------------------------- /2024/.gitignore: -------------------------------------------------------------------------------- 1 | day14 2 | -------------------------------------------------------------------------------- /2024/1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | from collections import Counter 6 | 7 | def extract(s): 8 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 9 | 10 | 11 | def main(args): 12 | file = open(args[1]) if len(args) > 1 else sys.stdin 13 | data = [extract(s.rstrip('\n')) for s in file] 14 | 15 | # ... I couldn't remember the unzip trick 16 | # xs, ys = [], [] 17 | # for x, y in data: 18 | # xs.append(x) 19 | # ys.append(y) 20 | xs, ys = zip(*data) 21 | 22 | xs = sorted(xs) 23 | ys = sorted(ys) 24 | 25 | asdf = Counter(ys) 26 | 27 | print(sum(abs(x-y) for x, y in zip(xs, ys))) 28 | print(sum(x * asdf[x] for x in xs)) 29 | 30 | 31 | if __name__ == '__main__': 32 | main(sys.argv) 33 | -------------------------------------------------------------------------------- /2024/11b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict 5 | import re 6 | 7 | def extract(s): 8 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 9 | 10 | 11 | def main(args): 12 | file = open(args[1]) if len(args) > 1 else sys.stdin 13 | data = [s.rstrip('\n') for s in file] 14 | 15 | l = extract(data[0]) 16 | 17 | m = defaultdict(int) 18 | for x in l: 19 | m[x] += 1 20 | 21 | for i in range(75): 22 | nm = defaultdict(int) 23 | for x, cnt in m.items(): 24 | sx = str(x) 25 | if x == 0: 26 | nm[1] += cnt 27 | elif len(sx) % 2 == 0: 28 | nm[int(sx[:len(sx)//2])] += cnt 29 | nm[int(sx[len(sx)//2:])] += cnt 30 | else: 31 | nm[x*2024] += cnt 32 | 33 | m = nm 34 | if i == 25-1: 35 | p1 = sum(m.values()) 36 | 37 | print(p1) 38 | print(sum(m.values())) 39 | 40 | if __name__ == '__main__': 41 | main(sys.argv) 42 | -------------------------------------------------------------------------------- /2024/13b-z3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | from z3 import Int, Optimize, sat 6 | 7 | def extract(s): 8 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 9 | 10 | def main(args): 11 | file = open(args[1]) if len(args) > 1 else sys.stdin 12 | data = [x.rstrip('\n').split('\n') for x in file.read().split('\n\n')] 13 | 14 | ans = 0 15 | for group in data: 16 | xa, ya = extract(group[0]) 17 | xb, yb = extract(group[1]) 18 | xt, yt = extract(group[2]) 19 | xt += 10000000000000 20 | yt += 10000000000000 21 | 22 | opt = Optimize() # ?? 23 | A, B = Int('A'), Int('B') 24 | opt.add(A*xa + B*xb == xt) 25 | opt.add(A*ya + B*yb == yt) 26 | opt.add(A >= 0) 27 | opt.add(B >= 0) 28 | opt.minimize(A*3 + B) 29 | 30 | if opt.check() != sat: 31 | continue 32 | model = opt.model() 33 | print(model) 34 | ans += model[A].as_long()*3 + model[B].as_long() 35 | 36 | print(ans) 37 | 38 | 39 | 40 | if __name__ == '__main__': 41 | main(sys.argv) 42 | -------------------------------------------------------------------------------- /2024/19.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import functools 5 | 6 | 7 | def main(args): 8 | file = open(args[1]) if len(args) > 1 else sys.stdin 9 | data = [x.rstrip('\n').split('\n') for x in file.read().split('\n\n')] 10 | 11 | patterns = data[0][0].split(', ') 12 | lines = data[1] 13 | 14 | @functools.cache 15 | def pos(s, i): 16 | if i == len(s): 17 | return 1 18 | n = 0 19 | for pat in patterns: 20 | if pat == s[i:i+len(pat)] : 21 | n += pos(s, i+len(pat)) 22 | return n 23 | 24 | vals = [pos(s, 0) for s in lines] 25 | 26 | print(sum(v > 0 for v in vals)) 27 | print(sum(vals)) 28 | 29 | 30 | if __name__ == '__main__': 31 | main(sys.argv) 32 | -------------------------------------------------------------------------------- /2024/22a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import numpy as np 5 | import time 6 | 7 | def compute(n, i): 8 | mask = 16777216 - 1 9 | for _ in range(i): 10 | n = (n ^ (n << 6)) & mask 11 | n = (n ^ (n >> 5)) & mask 12 | n = (n ^ (n << 11)) & mask 13 | return n 14 | 15 | 16 | def main(args): 17 | t0 = time.monotonic() 18 | file = open(args[1]) if len(args) > 1 else sys.stdin 19 | data = [int(s.rstrip('\n')) for s in file] 20 | 21 | # val = sum(compute(n, 2000) for n in data) 22 | 23 | ns = np.array(data, dtype=np.int64) 24 | val = sum(compute(ns, 2000)) 25 | 26 | t1 = time.monotonic() 27 | print(f'{t1-t0:0.3f}s') 28 | print(val) 29 | 30 | 31 | 32 | if __name__ == '__main__': 33 | main(sys.argv) 34 | -------------------------------------------------------------------------------- /2024/23b-bk.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict, Counter, deque 5 | 6 | def bron_kerbosch(r, p, x, n, out): 7 | if not p and not x: 8 | out.append(frozenset(r)) 9 | 10 | for v in list(p): 11 | bron_kerbosch(r | {v}, p & n[v], x & n[v], n, out) 12 | p.discard(v) 13 | x.add(v) 14 | # p = p - {v} 15 | # x = x | {v} 16 | 17 | 18 | def main(args): 19 | file = open(args[1]) if len(args) > 1 else sys.stdin 20 | data = [s.rstrip('\n') for s in file] 21 | 22 | m = defaultdict(set) 23 | 24 | for line in data: 25 | x, y = line.split('-') 26 | m[x].add(y) 27 | m[y].add(x) 28 | 29 | 30 | cliques = [] 31 | bron_kerbosch(set(), set(m), set(), m, cliques) 32 | 33 | x = ','.join(sorted(list(cliques)[0])) 34 | print(x) 35 | 36 | if __name__ == '__main__': 37 | main(sys.argv) 38 | -------------------------------------------------------------------------------- /2024/23b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict, Counter, deque 5 | 6 | 7 | def main(args): 8 | file = open(args[1]) if len(args) > 1 else sys.stdin 9 | data = [s.rstrip('\n') for s in file] 10 | 11 | m = defaultdict(set) 12 | 13 | for line in data: 14 | x, y = line.split('-') 15 | m[x].add(y) 16 | m[y].add(x) 17 | 18 | 19 | cliques = {frozenset([c]) for c in m} 20 | while len(cliques) > 1: 21 | print(len(list(cliques)[0]), len(cliques)) 22 | ncliques = set() 23 | for c1 in cliques: 24 | x = next(iter(c1)) 25 | for n in m[x]: 26 | if n not in c1: 27 | ns = m[n] 28 | if all(c in ns for c in c1): 29 | ncliques.add(c1 | {n}) 30 | 31 | cliques = ncliques 32 | 33 | x = ','.join(sorted(list(cliques)[0])) 34 | print(x) 35 | 36 | if __name__ == '__main__': 37 | main(sys.argv) 38 | -------------------------------------------------------------------------------- /2024/25.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | def main(args): 6 | file = open(args[1]) if len(args) > 1 else sys.stdin 7 | data = [x.rstrip('\n').split('\n') for x in file.read().split('\n\n')] 8 | 9 | locks = [] 10 | keys = [] 11 | for obj in data: 12 | trans = list(map(list, zip(*obj))) 13 | key = tuple(sum(c == '#' for c in l)-1 for l in trans) 14 | 15 | if '#' in obj[0]: 16 | locks.append(key) 17 | else: 18 | keys.append(key) 19 | 20 | n = 0 21 | for key in keys: 22 | for lock in locks: 23 | if all(x + y <= 5 for x, y in zip(key, lock)): 24 | n += 1 25 | 26 | print(n) 27 | 28 | if __name__ == '__main__': 29 | main(sys.argv) 30 | -------------------------------------------------------------------------------- /2024/2b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 8 | 9 | 10 | def main(args): 11 | file = open(args[1]) if len(args) > 1 else sys.stdin 12 | # data = [x.rstrip('\n').split('\n') for x in file.read().split('\n\n')] 13 | # data = [int(s.rstrip('\n')) for s in file] 14 | data = [extract(s.rstrip('\n')) for s in file] 15 | 16 | n = 0 17 | for x in data: 18 | asdfs = [list(x)] 19 | for i in range(len(x)): 20 | xx = list(x) 21 | xx.pop(i) 22 | asdfs.append(xx) 23 | 24 | ook = False 25 | 26 | for x in asdfs: 27 | ok = True 28 | if x != sorted(x) and x != list(reversed(sorted(x))): 29 | ok = False 30 | for a, b in zip(x, x[1:]): 31 | if abs(a-b) < 1 or abs(a-b) > 3: 32 | ok = False 33 | 34 | ook |= ok 35 | 36 | if ook: 37 | n += 1 38 | 39 | print(n) 40 | 41 | 42 | if __name__ == '__main__': 43 | main(sys.argv) 44 | -------------------------------------------------------------------------------- /2024/4a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict, Counter, deque 5 | 6 | 7 | def vadd(v1, v2): 8 | return tuple([x + y for x, y in zip(v1, v2)]) 9 | 10 | ALL_DIRS = [(x, y) for x in [-1,0,1] for y in [-1,0,1] if not x == y == 0] 11 | 12 | ############################## 13 | 14 | def main(args): 15 | file = open(args[1]) if len(args) > 1 else sys.stdin 16 | data = [s.rstrip('\n') for s in file] 17 | 18 | m = defaultdict(lambda: '.') 19 | for y, l in enumerate(data): 20 | for x, c in enumerate(l): 21 | m[x, y] = c 22 | 23 | n = 0 24 | for y in range(len(data)): 25 | for x in range(len(data[0])): 26 | for dir in ALL_DIRS: 27 | v = [(x, y)] 28 | for i in range(3): 29 | v.append(vadd(dir, v[-1])) 30 | s = ''.join(m[a] for a in v) 31 | if s == 'XMAS': 32 | n += 1 33 | 34 | 35 | print(n) 36 | 37 | if __name__ == '__main__': 38 | main(sys.argv) 39 | -------------------------------------------------------------------------------- /2024/4b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import defaultdict, Counter, deque 5 | 6 | def main(args): 7 | file = open(args[1]) if len(args) > 1 else sys.stdin 8 | # data = [x.rstrip('\n').split('\n') for x in file.read().split('\n\n')] 9 | # data = [int(s.rstrip('\n')) for s in file] 10 | data = [s.rstrip('\n') for s in file] 11 | 12 | m = defaultdict(lambda: '.') 13 | for y, l in enumerate(data): 14 | for x, c in enumerate(l): 15 | m[x, y] = c 16 | 17 | n = 0 18 | 19 | for y in range(len(data)): 20 | for x in range(len(data[0])): 21 | if ( 22 | m[x,y] == 'A' 23 | and ( 24 | (m[x-1,y-1] == 'M' and m[x+1,y+1] == 'S') 25 | or (m[x-1,y-1] == 'S' and m[x+1,y+1] == 'M') 26 | ) 27 | and ( 28 | (m[x-1,y+1] == 'M' and m[x+1,y-1] == 'S') 29 | or (m[x-1,y+1] == 'S' and m[x+1,y-1] == 'M') 30 | ) 31 | ): 32 | n += 1 33 | 34 | print(n) 35 | 36 | if __name__ == '__main__': 37 | main(sys.argv) 38 | -------------------------------------------------------------------------------- /2024/7a.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | 6 | def extract(s): 7 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 8 | 9 | 10 | def test(mask, vals, tgt): 11 | v = vals[0] 12 | for j, n in enumerate(vals[1:]): 13 | if mask & (1 << j) != 0: 14 | v += n 15 | else: 16 | v *= n 17 | if v > tgt: 18 | return False 19 | return v == tgt 20 | 21 | 22 | def main(args): 23 | file = open(args[1]) if len(args) > 1 else sys.stdin 24 | data = [s.rstrip('\n') for s in file] 25 | 26 | score = 0 27 | for line in data: 28 | tgt, *vals = extract(line) 29 | n = len(vals) - 1 30 | cnt = 0 31 | for i in range(1 << n): 32 | if test(i, vals, tgt): 33 | print(vals, tgt) 34 | score += tgt 35 | break 36 | 37 | print(score) 38 | 39 | if __name__ == '__main__': 40 | main(sys.argv) 41 | -------------------------------------------------------------------------------- /2024/7b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import re 5 | import itertools 6 | 7 | def extract(s): 8 | return [int(x) for x in re.findall(r'(-?\d+).?', s)] 9 | 10 | def test(mask, vals, tgt): 11 | v = vals[0] 12 | for j, n in enumerate(vals[1:]): 13 | if mask[j] == '+': 14 | v += n 15 | elif mask[j] == '*': 16 | v *= n 17 | else: 18 | v = int(str(v) + str(n)) 19 | if v > tgt: 20 | return False 21 | return v == tgt 22 | 23 | 24 | def main(args): 25 | file = open(args[1]) if len(args) > 1 else sys.stdin 26 | data = [s.rstrip('\n') for s in file] 27 | 28 | score = 0 29 | for i, line in enumerate(data): 30 | print(i, line) 31 | tgt, *vals = extract(line) 32 | n = len(vals) - 1 33 | cnt = 0 34 | for asdf in itertools.product(*['+*|'] * n): 35 | if test(asdf, vals, tgt): 36 | score += tgt 37 | break 38 | 39 | print(score) 40 | 41 | if __name__ == '__main__': 42 | main(sys.argv) 43 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Michael J. Sullivan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # advent-of-code 2 | My hacky advent of code solutions. Generally not good code. 3 | 4 | Many of these were originally written very fast, to try to make the 5 | leaderboard. In the early years, I was somewhat surprised that I wound 6 | up instinctively reaching for Haskell so often. These days my Haskell 7 | has grown rusty, so it seems to be always Python now. 8 | 9 | I'm somewhat inconsistent about whether the files here represent the 10 | very first original code that I wrote to solve the problem, or 11 | something somewhat cleaned up. I think what I am going to try to do is 12 | commit my first versions without change, so it is available in the 13 | history, and then if I feel like it, commit a cleaned up version with 14 | generally the same approach. 15 | --------------------------------------------------------------------------------