Created
February 4, 2013 05:50
-
-
Save zerowidth/4705219 to your computer and use it in GitHub Desktop.
My solutions for adventure.cueup.com, written in Haskell as an exercise. I first solved this puzzle using hacked-together ruby, but the algorithms here are essentially the same. The search in particular is not optimal, as it's a depth-first search rather than using any sort of cost heuristic to search the best paths first, but it works, and I go…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Grid where | |
import Control.Monad | |
type Pos = Int | |
type Cost = Int | |
type Path = [Pos] | |
type Grid = [Cost] | |
type GridSize = Int | |
type CostFn = (Grid -> Path -> Cost) | |
readGrid :: [String] -> Grid | |
readGrid ls = map read $ words $ unlines ls | |
basicCost :: Grid -> Path -> Cost | |
basicCost grid path = sum $ map ((!!) grid) path | |
incrementingCost :: Grid -> Path -> Cost | |
incrementingCost grid path = extra + total | |
where | |
-- ignore first and last squares, they cost no extra | |
extra = sum $ take (length path - 2) [0..] | |
total = basicCost grid path | |
nextAvailable :: Int -> Pos -> [Pos] | |
nextAvailable gridSize n = | |
filter (validMove gridSize n) $ map (+ n) [1, -1, gridSize, -gridSize] | |
validMove :: GridSize -> Pos -> Pos -> Bool | |
validMove gridSize from to = | |
to `elem` [0..(gridSize ^ 2 - 1)] && (dx == 0 || dy == 0) | |
where dx = (to `mod` gridSize) - (from `mod` gridSize) | |
dy = (to `div` gridSize) - (from `div` gridSize) | |
search :: Pos -> Pos -> Cost -> CostFn -> [String] -> Maybe [Int] | |
search from to targetCost costFn textGrid = | |
search' [from] | |
where | |
grid = readGrid textGrid | |
size = floor . sqrt $ fromIntegral $ length grid | |
cost = costFn grid | |
search' path | |
| head path == to && cost path == targetCost = Just $ reverse path | |
| cost path > targetCost = Nothing | |
| otherwise = | |
msum [search' (n:path) | n <- nextAvailable size $ head path] | |
formatPath :: Maybe Path -> [String] | |
formatPath Nothing = [] | |
formatPath (Just path) = zipWith direction path (drop 1 path) | |
direction :: Int -> Int -> String | |
direction a b = tr (b - a) where | |
tr n | n == 1 = "east" | |
| n == -1 = "west" | |
| n < 1 = "north" | |
| n > 1 = "south" | |
tr _ = "???" | |
smallGrid = [ "8 8 4 4 5", | |
"4 9 6 4 8", | |
"8 6 4 1 2", | |
"4 8 2 6 3", | |
"0 6 8 8 4" ] | |
largeGrid = [ "0 8 1 7 8 8 5 2 9 5 9 5", | |
"8 5 1 1 5 6 9 4 4 5 2 1", | |
"7 2 3 5 2 9 2 6 9 3 9 4", | |
"9 2 5 9 8 9 5 7 7 5 9 6", | |
"2 4 6 7 1 4 2 6 6 2 5 8", | |
"2 8 1 5 3 8 4 9 7 5 2 3", | |
"2 9 3 5 6 7 2 4 9 4 2 5", | |
"6 3 1 7 8 2 3 3 6 7 9 3", | |
"2 5 7 4 2 7 8 5 5 3 5 8", | |
"5 2 9 8 3 6 1 4 9 5 6 3", | |
"4 6 9 8 5 4 9 7 6 4 6 8", | |
"2 7 7 1 9 9 7 3 7 2 2 5" ] | |
main = do | |
print $ formatPath $ search 20 4 35 basicCost smallGrid | |
print $ formatPath $ search 0 143 444 incrementingCost largeGrid |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Parens where | |
import Data.Maybe (fromMaybe) | |
main = putStrLn $ "error at position " ++ (show $ findError code) | |
code :: String | |
code = unlines [ | |
"{{[{{{{}}{{}}}[]}[][{}][({[((", | |
"{{[][()()]}}{[{{{}}}]}))][()]", | |
"{[[{((()))({}(())[][])}][]()]", | |
"}{()[()]}]})][]]}{{}[]}}" ] | |
findError :: String -> Maybe Int | |
findError = search [] 0 | |
search :: [Char] -> Int -> String -> Maybe Int | |
search stack pos [] | |
| null stack = Nothing | |
| otherwise = Just pos | |
search stack pos (c:cs) | |
| c `notElem` "(){}[]" = search stack pos cs | |
| c `elem` "({[" = search (c:stack) (pos + 1) cs | |
| pairMatches c $ head stack = search (tail stack) (pos + 1) cs | |
| otherwise = Just pos | |
pairMatches :: Char -> Char -> Bool | |
pairMatches a b = lookup a pairs == Just b | |
pairs :: [(Char, Char)] | |
pairs = zip ")]}" "([{" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Vax where | |
import Data.List (isPrefixOf) | |
vax :: Int -> Int | |
vax s = ((69069 * s) + 1) `mod` 2 ^ 32 | |
randoms :: Int -> [Int] | |
randoms seed = map (`mod` 36) $ takeWhile (/= 0) $ iterate vax seed | |
nextN :: Int -> [Int] -> [Int] -> [Int] | |
nextN n needle haystack@(_:hs) = | |
if needle `isPrefixOf` haystack | |
then | |
take n $ drop (length needle) haystack | |
else | |
nextN n needle hs | |
nextN _ _ [] = [] | |
main = do | |
putStrLn $ "first game: " ++ (show $ nextN 2 [6,19,16] $ randoms 6) | |
putStrLn $ "second game: " ++ (show $ nextN 3 [34, 27, 16, 1, 34, 31, 24, 17, 34, 35, 16, 13] $ randoms 34) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment