I'm almost there with this code the only difference is instead to adding n1 to the graph, I have to add the edges of n1 to the graph but I can't seem to figure out how.
Question: The file includes a function named insertEdge of type Eq a =>
(NodeID,NodeID) -> Graph a -> Maybe (Graph a) that inserts an
edge from the Node with the given NodeID in the first part of the tuple
to the Node with the given NodeID in the second part of the tuple.
If the edge already exists, it should NOT introduce a duplicate. If
the nodes corresponding to either of the given NodeIDs do not already
exist, the function should return Nothing.
`insertEdge :: Eq a => (NodeID,NodeID) -> Graph a -> Maybe (Graph a)
insertEdge _ (Graph []) = Nothing
insertEdge (n1,n2) g#(Graph graph)
| not containsBothNodes = Nothing
| otherwise = Just(Graph(insertE (n1,n2) graph))
where
containsBothNodes :: Bool
containsBothNodes = case(lookupNode n1 g) of
(Just _)->True
_ -> False
insertE (n1,n2) ((n0,es):graph)=
if (getNodeID n0)==n2
then
if es/=[]
then (n0,es):graph
**else (n0,es++[n1]):graph**
else (n0,es):insertE (n1,n2)graph
Description of the graph
newtype Graph a = Graph [(Node a,[NodeID])]
deriving (Show,Eq)
type NodeID = Int
data Node a = Node { getNodeID :: NodeID,
getNodeVal :: a }
deriving (Show,Eq,Ord)
nodeA,nodeB,nodeC :: Node Char
nodeA = Node 0 'A'
nodeB = Node 1 'B'
nodeC = Node 2 'C'
exGraph :: Graph Char
exGraph = Graph [(nodeA,[1,2])
,(nodeB,[])
,(nodeC,[1,2])]
`
I highlighted the part that I cannot figure out. Instead of adding n1, it should add the edges of n1
Related
I'm trying to insert a node to a graph. I already have a function to find the maximum nodeID so the new nodeID is 1 greater than it but I'm having trouble getting the output as a graph.
newID :: Maybe NodeID -> NodeID
newID Nothing = 1
newID (Just x) = x+1
insertNode :: a -> Graph a -> Graph a
insertNode v (Graph node_list)=
let newNode=Node(newID(maxNodeID (Graph node_list))) v
in (node_list): [[(newNode,[])]]
Description for the graph is:
newtype Graph a = Graph [(Node a,[NodeID])]
deriving (Show,Eq)
type NodeID = Int
data Node a = Node { getNodeID :: NodeID,
getNodeVal :: a }
deriving (Show,Eq,Ord)
nodeA,nodeB,nodeC :: Node Char
nodeA = Node 0 'A'
nodeB = Node 1 'B'
nodeC = Node 2 'C'
exGraph :: Graph Char
exGraph = Graph [(nodeA,[1,2])
,(nodeB,[])
,(nodeC,[1,2])]
I've been stuck for this for 2 hours now. I just want to insert the new node at the end of the graph.
You're almost there, the only things you have to change are:
Use (++) :: [a] -> [a] -> [a] instead of (:) :: a -> [a] -> [a]. The : operator is for inserting things at the front, for adding to the end of a list the simplest way is to use the form xs ++ [x].
Wrap the result in a Graph constructor.
So a working version is:
insertNode :: a -> Graph a -> Graph a
insertNode v (Graph node_list)=
let newNode=Node(newID(maxNodeID (Graph node_list))) v
in Graph (node_list ++ [(newNode,[])])
I am trying to add an edge to a graph in Haskell where the graph data type is defined as:
data Graph a = Graph [(a, [a])]
deriving (Show)
Effectively, my data type is defined as: A Graph is a list of nodes stored as tuples, where the first element is the node value and the second element is a list of its edges (i.e., which other nodes it is connected to).
When inserting an edge between two nodes (u,v), you first have to check that both nodes exist and that the edge does not already exist. That is, that (u, [a,b...n]) and (v,[a,b...n]) their respective lists of edges does not contain u or v. Thus, I have two functions that performs this check. If this check passes and due to that my data type is defined as above mentioned, I must insert u and v in respective node's lists. After this, I must return a new Graph.
addEdge :: Eq a => Graph a -> (a, a) -> Graph a
addEdge g (u, v)
| (existsNode u g) && (existsNode v g) && (not (existsEdge (u, v) g)) = undefined
| otherwise = g
-- Check if an edge between two nodes exists
existsEdge :: Eq a => (a, a) -> Graph a -> Bool
existsEdge (u, v) g = elem u (getEdges (u, v) g) && elem v (getEdges (u, v) g)
getEdges :: Eq a => (a, a) -> Graph a -> [a]
getEdges (u, v) g =
let rightNeighbours = getNodeNeighbours (getNode u g)
leftNeihbours = getNodeNeighbours (getNode v g)
in rightNeighbours ++ leftNeihbours
-- Get a node given its node id
getNode :: Eq a => a -> Graph a -> (a, [a])
getNode y (Graph []) = (y, [])
getNode y (Graph (x : xs))
| y == fst x = x
| otherwise = getNode y (Graph xs)
I need a way to fill the part where undefined is now with something that takes each node u and v, and appends v to u's neighbors list (u,[v]) and vice versa (v, [u]), that results in returning a Graph.
For example, if we have that:
g = (Graph [(1,[2]),(2,[1]), (3,[2])])
And we want to add an edge between nodes 3 and 1. We first see that both nodes exist, and that an edge does not already exist -->
g = (Graph [(1,[2,3]),(2,[1]), (3,[2,1])])
Is there a way to do this in Haskell?
This is a nice example for a common rule of thumb:
Avoid boolean checks and then conditionally doing something. Instead write functions that attempt doing something, and fail if it's not possible.
Your task can be broken down to:
Pick out both of the nodes between which you want the edge (if they exist). You should do this in a way that allows also tweaking them, not just reading out.
Modify the edges-list of one of the nodes, inserting the new edge (if it doesn't exist).
The failure cases should be associated with a Maybe type: if an operation isn't possible, it's typically a bad idea to have it silently fail, instead you should make it clear that the update wasn't applied and then leave it to the caller to ignore it or do something else.
addEdge :: Eq a => Graph a -> (a, a) -> Maybe (Graph a)
Now, what do I mean by “do this in a way that allows also tweaking [the nodes]”? It means that you should return a view into the old version, as well as a function that, given a modified value of the node, reconstructs the corresponding modified version of the entire graph. Specifically, you want to modify the outgoing edges. (Modifying the node's key would require also updating all other nodes that may point to it; we don't need that.)
getNode :: Eq a => a -> Graph a -> Maybe ((a, [a]), [a] -> Graph a)
This signature looks a bit daunting; let's introduce some type synonyms to make it easier:
type Node a = (a, [a])
type NodeView a = (Node a, [a] -> Graph a)
getNode :: Eq a => a -> Graph a -> Maybe (NodeView a)
The main change in implementation is that you need to “remember” the nodes in the list that were skipped because they didn't match. I would do this with an auxiliary function
getNode' :: Eq a => a -> Graph a
-> [Node a] -- ^ The nodes that need to be prepended in the reconstructed graph
-> Maybe (NodeView a)
getNode' _ _ (Graph []) = Nothing -- Node was not found
getNode' y prep (Graph ((x,es):ns))
| x==y -- Node was found, now create a view to it:
= Just ( (x,es)
, \es' -> Graph $ prep ++ (x,es') : xs )
| otherwise -- Not found yet, but maybe later. Add currently tried node to the prep-list.
= getNode' y ((x,es):prep) (Graph ns)
Obs: the above makes a change to the reconstructed graph that may or may not matter for you. Can you spot what it is?
In practice, you shouldn't use getNode' directly, but always call it with empty prep list. In fact you should probably make it a local “loop body” function:
getNode :: Eq a => a -> Graph a -> Maybe (NodeView a)
getNode y = go y []
where go _ _ (Graph []) = Nothing
go y prep (Graph ((x,es):ns)) = ...
For the rest of the task, you can use the NodeView given by this function as a helper to create the whole updated graph.
I have a custom data type Point Int Int and I need to compare it to another Point Int Int (with elem function).
Could you please tell me how to write Eq instance for this data type? Thanks.
type Result = [String]
data Point = Point Int Int
-- missing Eq instance
data Line = Line Point Point
drawField :: [Point] -> (Int, Int) -> Result
drawField positions (width, height) = let
check coordinates | elem coordinates positions = '#'
| otherwise = '.'
in [[check (Point rows cols) | cols <- [0..width-1]] | rows <- [0..height-1]]
If two Points are equal if all parameters are elementwise equal, then you can let Haskell derive the Eq instance with:
data Point = Point Int Int deriving Eq
If the points are equivalent if a more sophisticated test succeeds, you can define your own instance of Eq with:
instance Eq Point where
Point xa ya == Point xb yb = …
where … is an expression with Bool as type.
I am trying to get my feet wet with Haskell and I have found a few workshop which asks to create a graph data structure. I followed along and created a Binary Tree using map which felt much simpler. I have the following data types given
type Graph a = [(Node a, Edges)]
type Edges = [NodeID]
type NodeID = Int
data Node a = Node
{ getNodeID :: NodeID,
getNodeVal :: a
}
deriving (Show, Eq)
and example node would be as follows
nodeA = Node 0 'A'
and an example graph connected both ways would be
graphA = [(nodeA, [1]), nodeB, [0]]
Now in order to do any kind of insert or remove operation, I would first have to find out what the max NodeID at the moment is. So I am trying to write a maxNodeID as follows
maxNodeID :: Graph a -> Maybe NodeID
maxNodeID [] = Nothing --base case
But I am having a real hard coming up with the next case for this function.
My type definition for insertNode function is as follows
insertNode :: a -> Graph a -> Graph a
-- This is my idea for a base case but I get a parse error at 0
insertNode v [] = [a, []] where a = Node {0, v}
Any help with this and creating a insertNode function would be much appreciated as it would really help me set myself in the right path.
Rather than rolling my own, I would use the maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a functrion from Data.List.
maxNodeID :: Graph a -> Maybe NodeID
maxNodeID [] = Nothing --base case
maxNodeID xs = Just $ maximumBy (\a b -> compare (getID a) (getID b)) xs
where getID = getNodeID . fst
For your insertNode function you need
insertNode v [] = [(a, [])] where a = Node 0 v
-- or --
insertNode v [] = [(a, [])] where a = Node {getNodeID = 0, getNodeVal= v}
Edited to add:
If you are not comfortable with type classes yet, you can read the type of maximumBy specialized for Lists as :: (a -> a -> Ordering) -> [a] -> a.
Assume I have a binary tree:
data Bst a = Empty | Node (Bst a) a (Bst a)
I have to write a function that searches for a value and returns the number of its children. If there is no node with this value, it returns -1. I was trying to write both BFS and DFS, and I failed with both.
Pattern matching is your friend. Your Bst can either be Empty or a Node, so at the toplevel, your search function will be
search Empty = ...
search (Node left x right) = ...
Can an Empty tree possibly contain the target value? With a Node the target value, if present, will be either the node value (x above), in the left subtree, in the right subtree—or perhaps some combination of these.
By “return[ing] the number of its children,” I assume you mean the total number of descendants of the Bst rooted at a Node whose value is the target, which is an interesting combination of problems. You will want another function, say numChildren, whose definition uses pattern matching as above. Considerations:
How many descendants does an Empty tree have?
In the Node case, x doesn’t count because you want descendants. If only you had a function to count the number of children in the left and right subtrees …
Here is a way to do this. Breath-first search can actually be a bit tricky to implement and this solution (findBFS) has aweful complexity (appending to the list is O(n)) but you'll get the gist.
First I have decided to split out the finding functions to return the tree where the node element matches. That simplifies splitting out the counting function. Also, it is easier to return the number of elements than the number of descendants and return -1 in case not found, so the numDesc functions rely on the numElements function.
data Tree a = Empty
| Node a (Tree a) (Tree a)
numElements :: Tree a -> Int
numElements Empty = 0
numElements (Node _ l r) = 1 + numElements l + numElements r
findDFS :: Eq a => a -> Tree a -> Tree a
findDFS _ Empty = Empty
findDFS x node#(Node y l r) | x == y = node
| otherwise = case findDFS x l of
node'#(Node _ _ _) -> node'
Empty -> findDFS x r
findBFS :: Eq a => a -> [Tree a] -> Tree a
findBFS x [] = Empty
findBFS x ((Empty):ts) = findBFS x ts
findBFS x (node#(Node y _ _):ts) | x == y = node
findBFS x ((Node _ l r):ts) = findBFS x (ts ++ [l,r])
numDescDFS :: Eq a => a -> Tree a -> Int
numDescDFS x t = numElements (findDFS x t) - 1
numDescBFS :: Eq a => a -> Tree a -> Int
numDescBFS x t = numElements (findBFS x [t]) - 1