diff --git a/day 15/day_15_sebastian_part1.hs b/day 15/day_15_sebastian_part1.hs
new file mode 100644
index 0000000000000000000000000000000000000000..9469c00d3582b8ef8916d5dfb34e64dcdf40ab95
--- /dev/null
+++ b/day 15/day_15_sebastian_part1.hs	
@@ -0,0 +1,90 @@
+module Main where
+
+import Data.Array
+import Data.Array.ST
+import Data.List (transpose)
+import Control.Monad (forM_, when, unless)
+import Data.STRef
+
+data Direction = U | D | L | R deriving Show
+data Tile = Wall | Box | Robot | Free deriving (Show, Eq)
+newtype Board = Board (Array (Int, Int) Tile)
+
+instance Show Board where
+  show (Board m) = unlines ([]:map (map (tile2Char . (m !))) is) where
+    is = [[(i, j) | i <- [x0 .. x1]] | j <- [y0 .. y1]]
+    ((x0, y0), (x1, y1)) = bounds m
+
+main :: IO ()
+main = interact solve
+
+solve :: String -> String
+solve s = unlines ["Part 1: " ++ part1 s, "Part 2: " ++ part2 s]
+
+part1 :: String -> String
+part1 = show . totalGPS . simulate . readInput
+
+totalGPS :: Board -> Int
+totalGPS (Board b) = sum $ map gps $ filter ((== Box) . (b !)) (indices b)
+
+gps :: (Int, Int) -> Int
+gps (x, y) = x + 100 * y
+
+part2 :: String -> String
+part2 = const ""
+
+lookTowards :: Direction -> (Int, Int) -> [(Int, Int)]
+lookTowards d (x, y) = goTowards d (x, y) : lookTowards d (goTowards d (x, y))
+
+goTowards :: Direction -> (Int, Int) -> (Int, Int)
+goTowards U (x, y) = (x, y - 1)
+goTowards D (x, y) = (x, y + 1)
+goTowards L (x, y) = (x - 1, y)
+goTowards R (x, y) = (x + 1, y)
+
+simulate :: (Board, [Direction], (Int, Int)) -> Board
+simulate (Board m, ds, pos) = Board $ runSTArray $ do
+    m' <- thaw m
+    pos' <- newSTRef pos
+    writeArray m' pos Free
+    forM_ ds $ \d -> do
+      p <- readSTRef pos'
+      bds <- getBounds m'
+      let nextPos = takeWhile (inRange bds) (lookTowards d p)
+      nextTiles <- mapM (readArray m') nextPos
+      let (posAfterBoxes, tileAfterBoxes) = head $ dropWhile ((== Box) . snd) (zip nextPos nextTiles)
+      unless (tileAfterBoxes == Wall) (modifySTRef pos' (goTowards d))
+      when (tileAfterBoxes /= Wall && posAfterBoxes /= goTowards d p) (writeArray m' posAfterBoxes Box >> writeArray m' (goTowards d p) Free)
+    lastPos <- readSTRef pos'
+    writeArray m' lastPos Robot
+    return m'
+
+readInput :: String -> (Board, [Direction], (Int, Int))
+readInput s = (Board floorMap, directions, robotPos) where
+  ls = lines s
+  (mapTransposed, dirChars) = span (/= []) ls
+  w = length mapTransposed
+  h = length (head mapTransposed)
+  floorMap = listArray ((0, 0), (w - 1, h - 1)) (map char2Tile $ concat (transpose mapTransposed))
+  directions = map char2Dir (concat dirChars)
+  robotPos = head $ filter (\i -> floorMap ! i == Robot) (indices floorMap)
+
+char2Dir :: Char -> Direction
+char2Dir '>' = R
+char2Dir '<' = L
+char2Dir '^' = U
+char2Dir 'v' = D
+char2Dir _ = undefined
+
+char2Tile :: Char -> Tile
+char2Tile 'O' = Box
+char2Tile '.' = Free
+char2Tile '#' = Wall
+char2Tile '@' = Robot
+char2Tile _ = undefined
+
+tile2Char :: Tile -> Char
+tile2Char Box = 'O'
+tile2Char Free = '.'
+tile2Char Wall = '#'
+tile2Char Robot = '@'
diff --git a/day 9/day_9_sebastian_part1.hs b/day 9/day_9_sebastian_part1.hs
new file mode 100644
index 0000000000000000000000000000000000000000..231dfd957545d2dbd47fcc5df1cd3ca594f46630
--- /dev/null
+++ b/day 9/day_9_sebastian_part1.hs	
@@ -0,0 +1,44 @@
+module Main where
+
+import Data.Char (isDigit)
+import Data.Array
+
+data Memtype = Free | Occupied Int deriving (Show, Eq)
+
+main :: IO ()
+main = interact solve
+
+solve :: String -> String
+solve s = unlines ["Part 1: " ++ part1 s, "Part 2: " ++ part2 s]
+
+part1 :: String -> String
+part1 = show . checksum . getMap . getInput . filter isDigit
+
+part2 :: String -> String
+part2 = const ""
+
+getInput :: String -> [(Memtype, Int)]
+getInput = getBlock 0
+
+getBlock :: Int -> String -> [(Memtype, Int)]
+getBlock _ [] = []
+getBlock i (h:t) = (Occupied i, read [h]):getFree (i + 1) t
+
+getFree :: Int -> String -> [(Memtype, Int)]
+getFree _ [] = []
+getFree i (h:t) = (Free, read [h]):getBlock i t
+
+getMap :: [(Memtype, Int)] -> Array Int Memtype
+getMap l = listArray (0, len - 1) (unRle l) where
+  len = sum $ map snd l
+
+unRle :: [(a, Int)] -> [a]
+unRle [] = []
+unRle ((c, n):t) = replicate n c ++ unRle t
+
+checksum :: Array Int Memtype -> Int
+checksum a = checksumAux 0 (bounds a) where
+  checksumAux acc (l, r) = if l > r then acc else case (a ! l, a ! r) of
+     (Free, Free) -> checksumAux acc (l, r - 1)
+     (Free, Occupied ir) -> checksumAux (acc + l * ir) (l + 1, r - 1)
+     (Occupied il, _) -> checksumAux (acc + l * il) (l + 1, r)