- some enhancements

- started graph module
This commit is contained in:
weiss
2020-04-14 10:54:42 +02:00
parent a8e94c0bf6
commit 9c39c1c0d5
6 changed files with 156 additions and 40 deletions

View File

@@ -6,7 +6,7 @@
{ {
"label": "build_purescript", "label": "build_purescript",
"type": "shell", "type": "shell",
"command": "spago bundle-app", "command": "spago bundle-app && uglifyjs index.js --mangle --output index.min.js",
"presentation": { "presentation": {
"echo": true, "echo": true,
"focus": true, "focus": true,

View File

@@ -4,7 +4,14 @@ You can edit this file as you like.
-} -}
{ name = "code_royal" { name = "code_royal"
, dependencies = , dependencies =
[ "arrays", "console", "effect", "integers", "js-date", "math", "random" ] [ "arrays"
, "console"
, "effect"
, "integers"
, "js-date"
, "math"
, "ordered-collections"
]
, packages = ./packages.dhall , packages = ./packages.dhall
, sources = [ "src/**/*.purs", "test/**/*.purs" ] , sources = [ "src/**/*.purs", "test/**/*.purs" ]
} }

54
code_royal/src/Graph.purs Normal file
View File

@@ -0,0 +1,54 @@
module Graph where
import Prelude
import Data.List (List(..), drop, head, reverse, (:), fromFoldable, (\\))
import Data.Map as M
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Set as S
import Data.Tuple (Tuple(..), fst, snd)
newtype Graph v = Graph (M.Map v (List v))
empty :: forall v. Graph v
empty = Graph M.empty
addNode :: forall v. Ord v => Graph v -> v -> Graph v
addNode (Graph m) v = Graph $ M.insert v Nil m
infixl 5 addNode as <+>
-- adds an Edge from Node "from" to Node "to"
-- returns the graph unmodified if "to" does not exist
addEdge :: forall v. Ord v => Graph v -> v -> v -> Graph v
addEdge g@(Graph m) from to = Graph $ M.update updateVal from m
where
updateVal :: List v -> Maybe (List v)
updateVal nodes
| g `contains` to = Just $ to : nodes
| otherwise = Just nodes
toMap :: forall v. Graph v -> M.Map v (List v)
toMap (Graph m) = m
adjacentEdges :: forall v. Ord v => Graph v -> v -> List v
adjacentEdges (Graph m) nodeId = fromMaybe Nil $ M.lookup nodeId m
contains :: forall v. Ord v => Graph v -> v -> Boolean
contains (Graph m) key = case M.lookup key m of
Just _ -> true
Nothing -> false
shortestPath :: forall v. Ord v => Graph v -> v -> v -> List v
shortestPath g@(Graph m) from to = reverse $ shortestPath' (Tuple from Nil) Nil S.empty
where
shortestPath' :: (Tuple v (List v)) -> List (Tuple v (List v)) -> S.Set v-> List v
shortestPath' from queue visited
| fst from == to = snd from
| otherwise = case head $ newQueue of
Just n -> shortestPath' n newQueue (S.insert (fst from) visited)
Nothing -> Nil
where
adjacent :: S.Set v
adjacent = S.fromFoldable $ adjacentEdges g (fst from)
newQueue :: List (Tuple v (List v))
newQueue = drop 1 queue <> ( map (\x -> Tuple x $ fst from : snd from) (fromFoldable $ S.difference adjacent visited) )

View File

@@ -8,15 +8,14 @@ module Main where
import Prelude import Prelude
import Control.Monad.State (State, gets, modify_, runState) import Control.Monad.State (State, gets, modify_, runState)
import Control.MonadZero (guard) import Control.MonadZero (empty, guard)
import Data.Array (any, filter, foldl, head, length, reverse, sort, sortBy) import Data.Array (any, concatMap, filter, foldl, head, length, sort, sortBy, (..))
import Data.DateTime (time)
import Data.Foldable (sum)
import Data.Maybe (Maybe(..), fromJust) import Data.Maybe (Maybe(..), fromJust)
import Data.Tuple (fst, snd) import Data.Tuple (fst, snd)
import Effect (Effect) import Effect (Effect)
import Effect.Console (error, log) import Effect.Console (error, log)
import GameInput (Minion, Site, SiteInfo, ProtoSite, parseInitInput, parseInput) import GameInput (Minion, Site, SiteInfo, ProtoSite, parseInitInput, parseInput)
import Graph as G
import Lib (dist) import Lib (dist)
import Partial.Unsafe (unsafePartial) import Partial.Unsafe (unsafePartial)
@@ -32,12 +31,27 @@ type GameState =
main :: Effect Unit main :: Effect Unit
main = do main = do
initInput <- parseInitInput initInput <- parseInitInput
nextRound initInput.numSites initInput.sites Nothing --error $ show $ concatMap nodeConnections nodes
nextRound initInput.numSites initInput.sites Nothing G.empty
where
-- graph :: G.Graph String
-- graph = unsafePartial $ fromJust $ foldl G.addNode graph' [ ["[1,1]", "[2,2]"], ["[3,4]", "[4,4]"], ["[2,2]", "[4,4]"] ]
graph' = foldl G.addNode G.empty sNodes
sNodes :: Array String
sNodes = map (\n -> show n) nodes
nodes = do
x <- (1..4)
y <- (1..4)
pure $ [x, y]
nodeConnections :: Array Int -> Array (Array String)
nodeConnections [x, y] = [ [o, show [x-1,y]], [o, show [x+1,y]], [o, show [x,y-1]], [o, show [x,y+1]] ]
where o = show [x, y]
nodeConnections _ = []
nextRound :: Int -> Array SiteInfo -> Maybe GameState -> Effect Unit nextRound :: Int -> Array SiteInfo -> Maybe GameState -> G.Graph String -> Effect Unit
nextRound numSites siteInfo gameState = do nextRound numSites siteInfo gameState graph = do
input <- parseInput numSites input <- parseInput numSites
error $ show input -- error $ show $ G.shortestPath "[4,4]" "[1,1]" graph
-- do we start on the left side of the map? -- do we start on the left side of the map?
let leftSide' = case gameState of let leftSide' = case gameState of
@@ -57,7 +71,7 @@ nextRound numSites siteInfo gameState = do
let state = snd res let state = snd res
let val = fst res let val = fst res
log $ val log $ val
nextRound state.numSites (toSiteInfo <$> state.sites) (Just state) nextRound state.numSites (toSiteInfo <$> state.sites) (Just state) graph
where where
-- combine sites with siteInfo and old state -- combine sites with siteInfo and old state

View File

@@ -5,7 +5,7 @@ exports.readline = readline
exports.parseInitInput = function() { exports.parseInitInput = function() {
var sites = [] var sites = []
var numSites = parseInt(readline()); var numSites = parseInt(readline());
for (let i = 0; i < numSites; i++) { for (var i = 0; i < numSites; i++) {
var inputs = readline().split(' '); var inputs = readline().split(' ');
var siteId = parseInt(inputs[0]); var siteId = parseInt(inputs[0]);
var x = parseInt(inputs[1]); var x = parseInt(inputs[1]);
@@ -13,13 +13,14 @@ exports.parseInitInput = function() {
var radius = parseInt(inputs[3]); var radius = parseInt(inputs[3]);
sites.push({ sites.push({
id: siteId, id: siteId,
x, y, x: x,
radius, y: y,
radius: radius,
}) })
} }
return { return {
numSites, numSites: numSites,
sites, sites: sites,
} }
}; };
@@ -29,7 +30,7 @@ exports.parseInput = function(numSites) {
var gold = parseInt(inputs[0]); var gold = parseInt(inputs[0]);
var touchedSite = parseInt(inputs[1]); // -1 if none var touchedSite = parseInt(inputs[1]); // -1 if none
var sites = [] var sites = []
for (let i = 0; i < numSites; i++) { for (var i = 0; i < numSites; i++) {
var inputs = readline().split(' '); var inputs = readline().split(' ');
var siteId = parseInt(inputs[0]); var siteId = parseInt(inputs[0]);
var mineGold = parseInt(inputs[1]); // The total number of gold remaining to be mined from this site (-1 if unknown) var mineGold = parseInt(inputs[1]); // The total number of gold remaining to be mined from this site (-1 if unknown)
@@ -41,16 +42,16 @@ exports.parseInput = function(numSites) {
sites.push({ sites.push({
id: siteId, id: siteId,
gold: mineGold, gold: mineGold,
maxMineSize, maxMineSize: maxMineSize,
structureType, structureType: structureType,
owner, owner: owner,
param1, param1: param1,
param2, param2: param2,
}) })
} }
var numUnits = parseInt(readline()); var numUnits = parseInt(readline());
var units = [] var units = []
for (let i = 0; i < numUnits; i++) { for (var i = 0; i < numUnits; i++) {
var inputs = readline().split(' '); var inputs = readline().split(' ');
var x = parseInt(inputs[0]); var x = parseInt(inputs[0]);
var y = parseInt(inputs[1]); var y = parseInt(inputs[1]);
@@ -58,18 +59,19 @@ exports.parseInput = function(numSites) {
var unitType = parseInt(inputs[3]); // -1 = QUEEN, 0 = KNIGHT, 1 = ARCHER var unitType = parseInt(inputs[3]); // -1 = QUEEN, 0 = KNIGHT, 1 = ARCHER
var health = parseInt(inputs[4]); var health = parseInt(inputs[4]);
units.push({ units.push({
x, y, x: x,
owner, y: y,
unitType, owner: owner,
health unitType: unitType,
health: health
}) })
} }
return { return {
gold, gold: gold,
touchedSite, touchedSite: touchedSite,
sites, sites: sites,
units, units: units
} }
} }
}; };

View File

@@ -2,18 +2,57 @@ module Test.Main where
import Prelude import Prelude
import Data.Array (concatMap, (..))
import Data.Foldable (foldl)
import Data.Int (fromNumber)
import Data.JSDate (getTime, now)
import Data.List (List)
import Data.Map (Map, showTree)
import Data.Maybe (fromJust)
import Effect (Effect) import Effect (Effect)
import Effect.Console (log) import Effect.Console (log)
import Graph (Graph(..), addEdge, addNode, empty, shortestPath, toMap, (<+>))
import Partial.Unsafe (unsafePartial)
main :: Effect Unit main :: Effect Unit
main = do main = do
let input = { test "graph" testCreateGraph
x: 20, let f2 = log $ show $ shortestPath graph "[1,1]" "[8,8]"
y: 20, test "search" f2
width: 100,
height: 100, --testCreateGraph :: forall v. Effect (Map v (List v))
turns: 50 testCreateGraph = pure $ toMap $ graph
}
-- loop input $ calcWindows input test :: forall a. String -> Effect a -> Effect Unit
log "hi" test tName fn = do
d0 <- now
let t0 = getTime d0
_ <- fn
d1 <- now
log $ "execution time of " <> tName <> ": " <> (show $ unsafePartial $ fromJust $ fromNumber $ getTime d1 - t0) <> "ms"
graph :: Graph String
-- graph = foldl addEdge' graph' [ ["[1,1]", "[2,2]"], ["[3,4]", "[4,4]"], ["[2,2]", "[4,4]"] ]
graph = foldl addEdge' graph' $ concatMap nodeConnections nodes
addEdge' :: forall v. Ord v => Graph v -> Array v -> Graph v
addEdge' g v = unsafePartial $ addEdge'' v
where
addEdge'' :: Partial => Array v -> Graph v
addEdge'' [a,b] = addEdge g a b
graph' = foldl addNode empty sNodes
sNodes :: Array String
sNodes = map (\n -> show n) nodes
nodes = do
x <- (1..360)
y <- (1..250)
pure $ [x, y]
nodeConnections :: Array Int -> Array (Array String)
nodeConnections [x, y] = [ [o, show [x-1,y]], [o, show [x+1,y]], [o, show [x,y-1]], [o, show [x,y+1]] ]
where o = show [x, y]
nodeConnections _ = []