A "high-level" language for the Gameboy
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
2.4 KiB

  1. export type Graph<V> = {
  2. vertices: {
  3. [v: string]: V
  4. },
  5. edges: {
  6. [v: string]: Set<string>
  7. }
  8. }
  9. export type AddVertex<V> = (name: string, v: V) => void
  10. export type AddEdge = (source: string, dest: string) => void
  11. export const createGraph = <V>(cons: (v: AddVertex<V>, e: AddEdge) => void): Graph<V> => {
  12. const g: Graph<V> = { vertices: {}, edges: {} }
  13. const addVertex = (name: string, v: V) => {
  14. g.vertices[name] = v
  15. g.edges[name] = new Set()
  16. }
  17. const addEdge = (source: string, dest: string) => {
  18. if (typeof g.vertices[source] === "undefined") {
  19. throw new Error(`vertex \`${source}' does not exist in graph`)
  20. } else if (typeof g.vertices[dest] === "undefined") {
  21. throw new Error(`vertex \`${dest}' does not exist in graph`)
  22. }
  23. g.edges[source].add(dest)
  24. g.edges[dest].add(source)
  25. }
  26. cons(addVertex, addEdge)
  27. return g
  28. }
  29. export const neighbors = <V>(g: Graph<V>, name: string): Set<string> => {
  30. if (typeof g.vertices[name] === "undefined") {
  31. throw new Error(`vertex \`${name}' does not exist in graph`)
  32. }
  33. return g.edges[name]
  34. }
  35. export const vertices = <V>(g: Graph<V>): Set<string> => new Set(Object.keys(g.vertices))
  36. export const maxCardinalitySearch = <V>(g: Graph<V>): Array<string> => {
  37. const weights: { [s: string]: number } = {}
  38. const ordering: Array<string> = []
  39. const W = vertices(g)
  40. const numVertices = W.size
  41. for (let i = 0; i < numVertices; ++i) {
  42. const v = findMaxWeight(weights, W)
  43. ordering.push(v)
  44. setIntersect(W, neighbors(g, v)).forEach(x =>
  45. weights[x] = (weights[x] || 0) + 1
  46. )
  47. W.delete(v)
  48. }
  49. return ordering
  50. }
  51. const findMaxWeight = (weights: { [s: string]: number }, W: Set<string>): string => {
  52. let maxV = null
  53. let maxWeight = -Infinity
  54. W.forEach(v => {
  55. const vWeight = weights[v] || 0
  56. if (vWeight > maxWeight) {
  57. maxV = v
  58. maxWeight = vWeight
  59. }
  60. })
  61. if (maxV === null) {
  62. throw new Error(`remaining vertex set is empty`)
  63. }
  64. return maxV
  65. }
  66. const setIntersect = <A>(xs: Set<A>, ys: Set<A>): Set<A> => {
  67. const intersection: Set<A> = new Set()
  68. xs.forEach(x => {
  69. if (ys.has(x)) {
  70. intersection.add(x)
  71. }
  72. })
  73. return intersection
  74. }