Skip to content

Instantly share code, notes, and snippets.

@zerowidth
Created February 4, 2013 05:50
Show Gist options
  • Save zerowidth/4705219 to your computer and use it in GitHub Desktop.
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…
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
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 ")]}" "([{"
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