Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 'use strict'
- const filter = pred => function* (iterable) {
- for(let x of iterable) {
- if(pred(x)){
- yield x
- }
- }
- }
- const collect = iterable => {
- const arr = []
- for(let x of iterable) {
- arr.push(x)
- }
- return arr
- }
- const update = (obj, ups) => {
- let res = {}
- for(let key in obj) {
- res[key] = ups[key] || obj[key]
- }
- return res
- }
- const findIf = (array, first, last, pred) => {
- for(; first < last && !pred(array[first]); ++ first){}
- return first
- }
- // private
- const shiftLeft = (array, first, last, n) => {
- for(; first + n < last; ++first) {
- array[first] = array[first + n]
- }
- }
- const removeIf = (array, pred) => {
- if(array.length === 0) return 0
- let first = 0
- let p = 0
- let n = 0
- let last = array.length
- const notPred = x => !pred(x)
- //
- while(n < last) {
- p = findIf(array, first, last, notPred)
- n = findIf(array, p, last, pred)
- shiftLeft(array, first, n, p - first)
- first = first + (n - p)
- }
- array.splice(first)
- }
- /*
- no error cheking in this version, see comments for preconditions
- */
- const DirectedGraph = function () {
- const _nodes = []
- const _edges = []
- //
- this.node = name => _nodes.find(n => n.name === name)
- this.edge = (from, to) => _edges.find(e => e.from === from && e.to === to)
- //
- this.nodes = function* () {
- for(let node of _nodes){
- yield node
- }
- }
- this.edges = function* () {
- for(let edge of _edges){
- yield edge
- }
- }
- // edges that lead from nothing into nodes (into the graph)
- this.inEdges = function* () {
- for(let edge of _edges) {
- if(!edge.from) {
- yield edge
- }
- }
- }
- // edges that lead from nodes to nothing (out of the graph)
- this.outEdges = function* () {
- for(let edge of _edges) {
- if(!edge.to) {
- yield edge
- }
- }
- }
- // name :: string
- // data :: any; user data
- this.addOrUpdateNode = (name, data) => {
- let node = _nodes.find(n => n.name === name)
- if(node){
- node.data = update(node.data, data)
- } else {
- _nodes.push({name:name, data:data})
- }
- }
- // from :: string or null; has to be name of a node
- // to :: string or null; has to be name of a node
- // data :: any; user data
- // only one of `from` and `to` can be null
- this.addOrUpdateEdge = (from, to, data) => {
- let edge = _edges.find( e => e.from === from && e.to === to)
- if(edge) {
- edge.data = update(edge.data, data)
- } else {
- _edges.push({
- from: from,
- to: to,
- data: data
- })
- }
- }
- this.removeNode = name => {
- removeIf(_nodes, n => n.name === name)
- for(let edge of _edges){
- if(edge.from === name) {
- edge.from = null
- }
- if(edge.to === name) {
- edge.to = null
- }
- }
- removeIf(_edges, e => e.from === null && e.to === null)
- }
- this.removeEdge =(from, to) => removeIf(_edges, e => e.from === from && e.to === to )
- //
- // `inEdges` and `outEdges` must be subset of `this.inEdges()` and `this.outEdges()`, respectively
- //
- // `namePrefix` is optional and is appended to names of nodes in `graph` before they are inserted
- // into `this` graph. `graph` is not modified
- //
- // number of `inEdges` must be same as number of `graph.outEdges()` (same for `outEdges` and
- // `graph.inEdges()`)
- //
- this.splice = (inEdges, outEdges, graph, namePrefix) => {
- let gInEdges = collect(graph.inEdges())
- let gOutEdges = collect(graph.outEdges())
- }
- }
- //
- //
- //
- let graph = new DirectedGraph()
- graph.addOrUpdateNode('start', {})
- graph.addOrUpdateNode('first', {})
- graph.addOrUpdateNode('second', {})
- graph.addOrUpdateNode('end', {})
- graph.addOrUpdateEdge('start', 'first', {})
- graph.addOrUpdateEdge('first', 'first', {})
- graph.addOrUpdateEdge('first', 'second', {})
- graph.addOrUpdateEdge('second', 'first', {})
- graph.addOrUpdateEdge('second', 'end', {})
- graph.addOrUpdateEdge(null, 'start', {})
- graph.addOrUpdateEdge('end', null, {})
- graph.removeNode('first')
- console.log("Nodes: ")
- for(let node of graph.nodes()){
- console.log(node)
- }
- console.log("Edges: ")
- for(let edge of graph.edges()){
- console.log(edge)
- }
- console.log("Edges (from and to 'second'): ")
- for(let edge of filter(e => e.from === 'second' || e.to === 'second')(graph.edges())){
- console.log(edge)
- }
- console.log("In edges: ")
- for(let node of graph.inEdges()){
- console.log(node)
- }
- console.log("Out edges: ")
- for(let edge of graph.outEdges()){
- console.log(edge)
- }
- console.log("\ninsert test\n")
- let outerGraph = new DirectedGraph()
- let inEdges = []
- let outEdges = []
- let innerGraph = new DirectedGraph()
- outerGraph.splice(inEdges, outEdges, innerGraph, 'inner.')
- console.log("Nodes: ")
- for(let node of outerGraph.nodes()){
- console.log(node)
- }
- console.log("Edges: ")
- for(let edge of outerGraph.edges()){
- console.log(edge)
- }
- console.log("In edges: ")
- for(let node of outerGraph.inEdges()){
- console.log(node)
- }
- console.log("Out edges: ")
- for(let edge of outerGraph.outEdges()){
- console.log(edge)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement