This documentation is automatically generated by online-judge-tools/verification-helper

:warning: spec/graph_spec.cr

Depends on

Code

require "spec"
require "../src/graph"

describe DiGraph do
  it ".weighted?, .directed?" do
    DiGraph.weighted?.should be_true
    DiGraph.directed?.should be_true
  end

  it ".new(size)" do
    g = DiGraph(Int32).new(5)
    g.size.should eq 5
    g.to_a.should eq [] of WeightedEdge2(Int32)
    expect_raises(ArgumentError) { DiGraph(Int32).new(-2) }
  end

  it ".new(n, edges)" do
    edges = [WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(1, 0, 11)]

    g = DiGraph.new 2, edges
    g.to_a.should eq edges

    g = DiGraph.new 2, edges.values_at(0, 1)
    g.to_a.should eq edges

    g = DiGraph.new 2, [{0, 1, 10}, {1, 0, 11}]
    g.to_a.should eq edges

    expect_raises(IndexError) { DiGraph.new 1, [WeightedEdge2.new(0, 1, 10)] }
  end

  it "#<<, #add_edges" do
    g = DiGraph(Int32).new(5)
    edges = [
      WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(0, 1, 11), WeightedEdge2.new(1, 2, 12),
      WeightedEdge2.new(2, 3, 13), WeightedEdge2.new(3, 4, 14),
    ]
    (g << edges[0]).should be g
    g << {0, 1, 11}
    g << {1, 2, 12}
    g.add_edges(edges[3..4]).should be g
    expect_raises(IndexError) { g << {4, 5, -1} }

    g[0].should eq [WeightedEdge.new(1, 10), WeightedEdge.new(1, 11)]
    g[1].should eq [WeightedEdge.new(2, 12)]
    g.to_a.should eq edges
  end

  it "#reverse" do
    edges = [
      WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(0, 1, 11), WeightedEdge2.new(1, 2, 12),
      WeightedEdge2.new(2, 3, 13), WeightedEdge2.new(3, 4, 14),
    ]
    g = DiGraph(Int32).new(5, edges)
    g.reverse.to_a.should eq edges.map(&.reverse)
  end

  it "#to_undirected" do
    edges = [
      WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(0, 1, 11), WeightedEdge2.new(1, 2, 12),
      WeightedEdge2.new(2, 3, 13), WeightedEdge2.new(3, 4, 14),
    ]
    g = DiGraph(Int32).new(5, edges)
    g.to_undirected.to_set.should eq edges.flat_map { |e| [e, e.reverse] }.to_set
  end
end

describe UnGraph do
  it ".weighted?, .directed?" do
    UnGraph.weighted?.should be_true
    UnGraph.directed?.should be_false
  end

  it "#.new(size)" do
    g = UnGraph(Int32).new(5)
    g.size.should eq 5
    g.to_a.should eq [] of WeightedEdge2(Int32)
    expect_raises(ArgumentError) { UnGraph(Int32).new(-2) }
  end

  it ".new(n, edges)" do
    edges = [WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(0, 1, 11), WeightedEdge2.new(1, 0, 10), WeightedEdge2.new(1, 0, 11)]
    g = UnGraph.new 2, [edges[0], edges[3]]
    g.to_a.should eq edges

    g = UnGraph.new 2, edges.values_at(0, 3)
    g.to_a.should eq edges

    g = UnGraph.new 2, [{0, 1, 10}, {1, 0, 11}]
    g.to_a.should eq edges

    expect_raises(IndexError) { UnGraph.new 1, [WeightedEdge2.new(0, 1, 10)] }
  end

  it "#<<, #add_edges" do
    edges = [
      [WeightedEdge.new(1, 10)],
      [WeightedEdge.new(0, 10), WeightedEdge.new(2, 11)],
      [WeightedEdge.new(1, 11), WeightedEdge.new(3, 12)],
      [WeightedEdge.new(2, 12)],
    ]
    all_edges = [
      WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(1, 0, 10),
      WeightedEdge2.new(1, 2, 11), WeightedEdge2.new(2, 1, 11),
      WeightedEdge2.new(2, 3, 12), WeightedEdge2.new(3, 2, 12),
    ]

    g = UnGraph(Int32).new(4)
    (g << {0, 1, 10}).should be g
    g << {1, 2, 11}
    g << WeightedEdge2.new(2, 3, 12)
    g[0].should eq edges[0]
    g[1].should eq edges[1]
    g[2].should eq edges[2]
    g[3].should eq edges[3]
    g.to_a.should eq all_edges

    g = UnGraph(Int32).new(4)
    g.add_edges([{0, 1, 10}]).should be g
    g.add_edges({WeightedEdge2.new(1, 2, 11), WeightedEdge2.new(2, 3, 12)})
    g[0].should eq edges[0]
    g[1].should eq edges[1]
    g[2].should eq edges[2]
    g[3].should eq edges[3]
    g.to_a.should eq all_edges
  end

  it "#reverse" do
    all_edges = [
      WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(1, 0, 10),
      WeightedEdge2.new(1, 2, 11), WeightedEdge2.new(2, 1, 11),
      WeightedEdge2.new(2, 3, 12), WeightedEdge2.new(3, 2, 12),
    ]

    g = UnGraph(Int32).new(4)
    g << {0, 1, 10} << {1, 2, 11} << {2, 3, 12}
    g.reverse.to_set.should eq all_edges.map(&.reverse).to_set
  end

  it "#to_undirected" do
    all_edges = [
      WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(1, 0, 10),
      WeightedEdge2.new(1, 2, 11), WeightedEdge2.new(2, 1, 11),
      WeightedEdge2.new(2, 3, 12), WeightedEdge2.new(3, 2, 12),
    ]

    g = UnGraph(Int32).new(4)
    g << {0, 1, 10} << {1, 2, 11} << {2, 3, 12}
    g.to_undirected.to_set.should eq all_edges.map(&.reverse).to_set
  end

  it "#each_child" do
    g = UnGraph(Int32).new(6)
    g << {0, 1, 1} << {0, 2, 2} << {0, 3, 3} << {3, 4, 4} << {3, 5, 5}
    v = [] of Int32
    g.each_child(0, nil) { |e| v << e.to }
    v.should eq [1, 2, 3]
    v.clear
    g.each_child(3, nil) { |e| v << e.to }
    v.should eq [0, 4, 5]
    v.clear
    g.each_child(3, 0) { |e| v << e.to }
    v.should eq [4, 5]
    g.each_child(0, nil).map(&.to).to_a.should eq [1, 2, 3]
    g.each_child(3, nil).map(&.to).to_a.should eq [0, 4, 5]
    g.each_child(3, 0).map(&.to).to_a.should eq [4, 5]
  end
end

describe UnweightedDiGraph do
  it ".weighted?, .directed?" do
    UnweightedDiGraph.weighted?.should be_false
    UnweightedDiGraph.directed?.should be_true
  end

  it ".new(size)" do
    g = UnweightedDiGraph.new(5)
    g.size.should eq 5
    g.to_a.should eq [] of UnweightedEdge2
    expect_raises(ArgumentError) { UnweightedDiGraph.new(-2) }
  end

  it ".new(n, edges)" do
    edges = [UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 0)]

    g = UnweightedDiGraph.new 2, edges
    g.to_a.should eq edges

    g = UnweightedDiGraph.new 2, edges.values_at(0, 1)
    g.to_a.should eq edges

    g = UnweightedDiGraph.new 2, [{0, 1}, {1, 0}]
    g.to_a.should eq edges

    expect_raises(IndexError) { UnweightedDiGraph.new 1, [UnweightedEdge2.new(0, 1)] }
  end

  it "#<<, #add_edges" do
    g = UnweightedDiGraph.new(5)
    edges = [
      UnweightedEdge2.new(0, 1), UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 2),
      UnweightedEdge2.new(2, 3), UnweightedEdge2.new(3, 4),
    ]
    (g << edges[0]).should be g
    g << {0, 1}
    g << {1, 2}
    g.add_edges(edges[3..4]).should be g
    expect_raises(IndexError) { g << {4, 5} }

    g[0].should eq [UnweightedEdge.new(1), UnweightedEdge.new(1)]
    g[1].should eq [UnweightedEdge.new(2)]
    g.to_a.should eq edges
  end

  it "#reverse" do
    edges = [
      UnweightedEdge2.new(0, 1), UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 2),
      UnweightedEdge2.new(2, 3), UnweightedEdge2.new(3, 4),
    ]
    g = UnweightedDiGraph.new(5, edges)
    g.reverse.to_a.should eq edges.map(&.reverse)
  end

  it "#to_undirected" do
    edges = [
      UnweightedEdge2.new(0, 1), UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 2),
      UnweightedEdge2.new(2, 3), UnweightedEdge2.new(3, 4),
    ]
    g = UnweightedDiGraph.new(5, edges)
    g.to_undirected.to_set.should eq edges.flat_map { |e| [e, e.reverse] }.to_set
  end
end

describe UnweightedUnGraph do
  it ".weighted?, .directed?" do
    UnweightedUnGraph.weighted?.should be_false
    UnweightedUnGraph.directed?.should be_false
  end

  it "#.new(size)" do
    g = UnweightedUnGraph.new(5)
    g.size.should eq 5
    g.to_a.should eq [] of UnweightedEdge2
    expect_raises(ArgumentError) { UnweightedUnGraph.new(-2) }
  end

  it ".new(n, edges)" do
    edges = [UnweightedEdge2.new(0, 1), UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 0), UnweightedEdge2.new(1, 0)]
    g = UnweightedUnGraph.new 2, [edges[0], edges[3]]
    g.to_a.should eq edges

    g = UnweightedUnGraph.new 2, edges.values_at(0, 3)
    g.to_a.should eq edges

    g = UnweightedUnGraph.new 2, [{0, 1}, {1, 0}]
    g.to_a.should eq edges

    expect_raises(IndexError) { UnweightedUnGraph.new 1, [UnweightedEdge2.new(0, 1)] }
  end

  it "#<<, #add_edges" do
    edges = [
      [UnweightedEdge.new(1)],
      [UnweightedEdge.new(0), UnweightedEdge.new(2)],
      [UnweightedEdge.new(1), UnweightedEdge.new(3)],
      [UnweightedEdge.new(2)],
    ]
    all_edges = [
      UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 0),
      UnweightedEdge2.new(1, 2), UnweightedEdge2.new(2, 1),
      UnweightedEdge2.new(2, 3), UnweightedEdge2.new(3, 2),
    ]

    g = UnweightedUnGraph.new(4)
    (g << {0, 1}).should be g
    g << {1, 2}
    g << UnweightedEdge2.new(2, 3)
    g[0].should eq edges[0]
    g[1].should eq edges[1]
    g[2].should eq edges[2]
    g[3].should eq edges[3]
    g.to_a.should eq all_edges

    g = UnweightedUnGraph.new(4)
    g.add_edges([{0, 1}]).should be g
    g.add_edges({UnweightedEdge2.new(1, 2), UnweightedEdge2.new(2, 3)})
    g[0].should eq edges[0]
    g[1].should eq edges[1]
    g[2].should eq edges[2]
    g[3].should eq edges[3]
    g.to_a.should eq all_edges
  end

  it "#reverse" do
    all_edges = [
      UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 0),
      UnweightedEdge2.new(1, 2), UnweightedEdge2.new(2, 1),
      UnweightedEdge2.new(2, 3), UnweightedEdge2.new(3, 2),
    ]

    g = UnweightedUnGraph.new(4)
    g << {0, 1} << {1, 2} << {2, 3}
    g.reverse.to_set.should eq all_edges.to_set
  end

  it "#to_undirected" do
    all_edges = [
      UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 0),
      UnweightedEdge2.new(1, 2), UnweightedEdge2.new(2, 1),
      UnweightedEdge2.new(2, 3), UnweightedEdge2.new(3, 2),
    ]

    g = UnweightedUnGraph.new(4)
    g << {0, 1} << {1, 2} << {2, 3}
    g.to_undirected.to_set.should eq all_edges.to_set
  end

  it "#each_child" do
    g = UnweightedUnGraph.new(6)
    g << {0, 1} << {0, 2} << {0, 3} << {3, 4} << {3, 5}
    v = [] of Int32
    g.each_child(0, nil) { |e| v << e.to }
    v.should eq [1, 2, 3]
    v.clear
    g.each_child(3, nil) { |e| v << e.to }
    v.should eq [0, 4, 5]
    v.clear
    g.each_child(3, 0) { |e| v << e.to }
    v.should eq [4, 5]
    g.each_child(0, nil).map(&.to).to_a.should eq [1, 2, 3]
    g.each_child(3, nil).map(&.to).to_a.should eq [0, 4, 5]
    g.each_child(3, 0).map(&.to).to_a.should eq [4, 5]
  end
end
require "spec"

# require "../src/graph"
# require "./graph/edge"
struct WeightedEdge(T)
  include Comparable(WeightedEdge(T))

  property to : Int32, cost : T

  def initialize(@to, @cost : T)
  end

  def <=>(other : WeightedEdge(T))
    {cost, to} <=> {other.cost, other.to}
  end

  def to_s(io) : Nil
    io << '(' << to << ", " << cost << ')'
  end

  def inspect(io) : Nil
    io << "->" << to << '(' << cost << ')'
  end
end

struct WeightedEdge2(T)
  include Comparable(WeightedEdge2(T))

  property from : Int32, to : Int32, cost : T

  def initialize(@from, @to, @cost : T)
  end

  def initialize(@from, edge : WeightedEdge(T))
    @to, @cost = edge.to, edge.cost
  end

  def <=>(other : WeightedEdge2(T))
    {cost, from, to} <=> {other.cost, other.from, other.to}
  end

  def reverse : self
    WeightedEdge2(T).new(to, from, cost)
  end

  def sort : self
    WeightedEdge2(T).new(*{to, from}.minmax, cost)
  end

  def to_s(io) : Nil
    io << '(' << from << ", " << to << ", " << cost << ')'
  end

  def inspect(io) : Nil
    io << from << "->" << to << '(' << cost << ')'
  end
end

struct UnweightedEdge
  property to : Int32

  def initialize(@to)
  end

  def initialize(@to, cost)
  end

  def cost : Int32
    1
  end

  def to_s(io) : Nil
    io << to
  end

  def inspect(io) : Nil
    io << "->" << to
  end
end

struct UnweightedEdge2
  property from : Int32, to : Int32

  def initialize(@from, @to)
  end

  def initialize(@from, @to, cost)
  end

  def initialize(@from, edge : UnweightedEdge)
    @to = edge.to
  end

  def cost : Int32
    1
  end

  def reverse : self
    UnweightedEdge2.new(to, from)
  end

  def sort : self
    UnweightedEdge2.new(*{to, from}.minmax)
  end

  def to_s(io) : Nil
    io << '(' << from << ", " << to << ')'
  end

  def inspect(io) : Nil
    io << from << "->" << to
  end
end

module Graph(Edge, Edge2)
  include Enumerable(Edge2)

  getter graph : Array(Array(Edge))

  def initialize(size : Int)
    @graph = Array(Array(Edge)).new(size) { [] of Edge }
  end

  def initialize(size : Int, edges : Enumerable)
    initialize(size)
    add_edges(edges)
  end

  # Add *edge*.
  abstract def <<(edge : Edge2)

  # :ditto:
  def <<(edge : Tuple) : self
    self << Edge2.new(*edge)
  end

  def add_edges(edges : Enumerable) : self
    edges.each { |edge| self << edge }
    self
  end

  delegate size, :[], to: @graph

  # Yields each edge of the graph, ans returns `nil`.
  def each(&) : Nil
    (0...size).each do |v|
      graph[v].each do |edge|
        yield Edge2.new(v, edge)
      end
    end
  end

  def each_child(vertex : Int, parent, &block) : Nil
    graph[vertex].each do |edge|
      yield edge if edge.to != parent
    end
  end

  def each_child(vertex : Int, parent)
    graph[vertex].each.reject(&.to.== parent)
  end

  def reverse : self
    if self.class.directed?
      each_with_object(self.class.new(size)) do |edge, reversed|
        reversed << edge.reverse
      end
    else
      dup
    end
  end

  def to_undirected : self
    if self.class.directed?
      each_with_object(self.class.new(size)) do |edge, graph|
        graph << edge << edge.reverse
      end
    else
      dup
    end
  end

  def to_s(io : IO) : Nil
    io << '['
    join(", ", io) do |edge, io|
      edge.inspect io
    end
    io << ']'
  end

  def inspect(io : IO) : Nil
    io << "[\n"
    graph.each do |edges|
      io << "  " << edges << ",\n"
    end
    io << ']'
  end
end

class DiGraph(T)
  include Graph(WeightedEdge(T), WeightedEdge2(T))

  def self.weighted?
    true
  end

  def self.directed?
    true
  end

  def initialize(size : Int)
    super
  end

  def initialize(size : Int, edges : Enumerable(WeightedEdge2(T)))
    super
  end

  def initialize(size : Int, edges : Enumerable({Int32, Int32, T}))
    super
  end

  def <<(edge : WeightedEdge2(T)) : self
    raise IndexError.new unless 0 <= edge.from < size && 0 <= edge.to < size
    @graph[edge.from] << WeightedEdge.new(edge.to, edge.cost)
    self
  end
end

class UnGraph(T)
  include Graph(WeightedEdge(T), WeightedEdge2(T))

  def self.weighted?
    true
  end

  def self.directed?
    false
  end

  def initialize(size : Int)
    super
  end

  def initialize(size : Int, edges : Enumerable(WeightedEdge2(T)))
    super
  end

  def initialize(size : Int, edges : Enumerable({Int32, Int32, T}))
    super
  end

  def <<(edge : WeightedEdge2(T)) : self
    raise IndexError.new unless 0 <= edge.from < size && 0 <= edge.to < size
    @graph[edge.from] << WeightedEdge.new(edge.to, edge.cost)
    @graph[edge.to] << WeightedEdge.new(edge.from, edge.cost)
    self
  end
end

class UnweightedDiGraph
  include Graph(UnweightedEdge, UnweightedEdge2)

  def self.weighted?
    false
  end

  def self.directed?
    true
  end

  def initialize(size : Int)
    super
  end

  def initialize(size : Int, edges : Enumerable)
    super
  end

  def <<(edge : UnweightedEdge2) : self
    raise IndexError.new unless 0 <= edge.from < size && 0 <= edge.to < size
    @graph[edge.from] << UnweightedEdge.new(edge.to)
    self
  end
end

class UnweightedUnGraph
  include Graph(UnweightedEdge, UnweightedEdge2)

  def self.weighted?
    false
  end

  def self.directed?
    false
  end

  def initialize(size : Int)
    super
  end

  def initialize(size : Int, edges : Enumerable)
    super
  end

  def <<(edge : UnweightedEdge2) : self
    raise IndexError.new unless 0 <= edge.from < size && 0 <= edge.to < size
    @graph[edge.from] << UnweightedEdge.new(edge.to)
    @graph[edge.to] << UnweightedEdge.new(edge.from)
    self
  end
end

describe DiGraph do
  it ".weighted?, .directed?" do
    DiGraph.weighted?.should be_true
    DiGraph.directed?.should be_true
  end

  it ".new(size)" do
    g = DiGraph(Int32).new(5)
    g.size.should eq 5
    g.to_a.should eq [] of WeightedEdge2(Int32)
    expect_raises(ArgumentError) { DiGraph(Int32).new(-2) }
  end

  it ".new(n, edges)" do
    edges = [WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(1, 0, 11)]

    g = DiGraph.new 2, edges
    g.to_a.should eq edges

    g = DiGraph.new 2, edges.values_at(0, 1)
    g.to_a.should eq edges

    g = DiGraph.new 2, [{0, 1, 10}, {1, 0, 11}]
    g.to_a.should eq edges

    expect_raises(IndexError) { DiGraph.new 1, [WeightedEdge2.new(0, 1, 10)] }
  end

  it "#<<, #add_edges" do
    g = DiGraph(Int32).new(5)
    edges = [
      WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(0, 1, 11), WeightedEdge2.new(1, 2, 12),
      WeightedEdge2.new(2, 3, 13), WeightedEdge2.new(3, 4, 14),
    ]
    (g << edges[0]).should be g
    g << {0, 1, 11}
    g << {1, 2, 12}
    g.add_edges(edges[3..4]).should be g
    expect_raises(IndexError) { g << {4, 5, -1} }

    g[0].should eq [WeightedEdge.new(1, 10), WeightedEdge.new(1, 11)]
    g[1].should eq [WeightedEdge.new(2, 12)]
    g.to_a.should eq edges
  end

  it "#reverse" do
    edges = [
      WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(0, 1, 11), WeightedEdge2.new(1, 2, 12),
      WeightedEdge2.new(2, 3, 13), WeightedEdge2.new(3, 4, 14),
    ]
    g = DiGraph(Int32).new(5, edges)
    g.reverse.to_a.should eq edges.map(&.reverse)
  end

  it "#to_undirected" do
    edges = [
      WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(0, 1, 11), WeightedEdge2.new(1, 2, 12),
      WeightedEdge2.new(2, 3, 13), WeightedEdge2.new(3, 4, 14),
    ]
    g = DiGraph(Int32).new(5, edges)
    g.to_undirected.to_set.should eq edges.flat_map { |e| [e, e.reverse] }.to_set
  end
end

describe UnGraph do
  it ".weighted?, .directed?" do
    UnGraph.weighted?.should be_true
    UnGraph.directed?.should be_false
  end

  it "#.new(size)" do
    g = UnGraph(Int32).new(5)
    g.size.should eq 5
    g.to_a.should eq [] of WeightedEdge2(Int32)
    expect_raises(ArgumentError) { UnGraph(Int32).new(-2) }
  end

  it ".new(n, edges)" do
    edges = [WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(0, 1, 11), WeightedEdge2.new(1, 0, 10), WeightedEdge2.new(1, 0, 11)]
    g = UnGraph.new 2, [edges[0], edges[3]]
    g.to_a.should eq edges

    g = UnGraph.new 2, edges.values_at(0, 3)
    g.to_a.should eq edges

    g = UnGraph.new 2, [{0, 1, 10}, {1, 0, 11}]
    g.to_a.should eq edges

    expect_raises(IndexError) { UnGraph.new 1, [WeightedEdge2.new(0, 1, 10)] }
  end

  it "#<<, #add_edges" do
    edges = [
      [WeightedEdge.new(1, 10)],
      [WeightedEdge.new(0, 10), WeightedEdge.new(2, 11)],
      [WeightedEdge.new(1, 11), WeightedEdge.new(3, 12)],
      [WeightedEdge.new(2, 12)],
    ]
    all_edges = [
      WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(1, 0, 10),
      WeightedEdge2.new(1, 2, 11), WeightedEdge2.new(2, 1, 11),
      WeightedEdge2.new(2, 3, 12), WeightedEdge2.new(3, 2, 12),
    ]

    g = UnGraph(Int32).new(4)
    (g << {0, 1, 10}).should be g
    g << {1, 2, 11}
    g << WeightedEdge2.new(2, 3, 12)
    g[0].should eq edges[0]
    g[1].should eq edges[1]
    g[2].should eq edges[2]
    g[3].should eq edges[3]
    g.to_a.should eq all_edges

    g = UnGraph(Int32).new(4)
    g.add_edges([{0, 1, 10}]).should be g
    g.add_edges({WeightedEdge2.new(1, 2, 11), WeightedEdge2.new(2, 3, 12)})
    g[0].should eq edges[0]
    g[1].should eq edges[1]
    g[2].should eq edges[2]
    g[3].should eq edges[3]
    g.to_a.should eq all_edges
  end

  it "#reverse" do
    all_edges = [
      WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(1, 0, 10),
      WeightedEdge2.new(1, 2, 11), WeightedEdge2.new(2, 1, 11),
      WeightedEdge2.new(2, 3, 12), WeightedEdge2.new(3, 2, 12),
    ]

    g = UnGraph(Int32).new(4)
    g << {0, 1, 10} << {1, 2, 11} << {2, 3, 12}
    g.reverse.to_set.should eq all_edges.map(&.reverse).to_set
  end

  it "#to_undirected" do
    all_edges = [
      WeightedEdge2.new(0, 1, 10), WeightedEdge2.new(1, 0, 10),
      WeightedEdge2.new(1, 2, 11), WeightedEdge2.new(2, 1, 11),
      WeightedEdge2.new(2, 3, 12), WeightedEdge2.new(3, 2, 12),
    ]

    g = UnGraph(Int32).new(4)
    g << {0, 1, 10} << {1, 2, 11} << {2, 3, 12}
    g.to_undirected.to_set.should eq all_edges.map(&.reverse).to_set
  end

  it "#each_child" do
    g = UnGraph(Int32).new(6)
    g << {0, 1, 1} << {0, 2, 2} << {0, 3, 3} << {3, 4, 4} << {3, 5, 5}
    v = [] of Int32
    g.each_child(0, nil) { |e| v << e.to }
    v.should eq [1, 2, 3]
    v.clear
    g.each_child(3, nil) { |e| v << e.to }
    v.should eq [0, 4, 5]
    v.clear
    g.each_child(3, 0) { |e| v << e.to }
    v.should eq [4, 5]
    g.each_child(0, nil).map(&.to).to_a.should eq [1, 2, 3]
    g.each_child(3, nil).map(&.to).to_a.should eq [0, 4, 5]
    g.each_child(3, 0).map(&.to).to_a.should eq [4, 5]
  end
end

describe UnweightedDiGraph do
  it ".weighted?, .directed?" do
    UnweightedDiGraph.weighted?.should be_false
    UnweightedDiGraph.directed?.should be_true
  end

  it ".new(size)" do
    g = UnweightedDiGraph.new(5)
    g.size.should eq 5
    g.to_a.should eq [] of UnweightedEdge2
    expect_raises(ArgumentError) { UnweightedDiGraph.new(-2) }
  end

  it ".new(n, edges)" do
    edges = [UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 0)]

    g = UnweightedDiGraph.new 2, edges
    g.to_a.should eq edges

    g = UnweightedDiGraph.new 2, edges.values_at(0, 1)
    g.to_a.should eq edges

    g = UnweightedDiGraph.new 2, [{0, 1}, {1, 0}]
    g.to_a.should eq edges

    expect_raises(IndexError) { UnweightedDiGraph.new 1, [UnweightedEdge2.new(0, 1)] }
  end

  it "#<<, #add_edges" do
    g = UnweightedDiGraph.new(5)
    edges = [
      UnweightedEdge2.new(0, 1), UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 2),
      UnweightedEdge2.new(2, 3), UnweightedEdge2.new(3, 4),
    ]
    (g << edges[0]).should be g
    g << {0, 1}
    g << {1, 2}
    g.add_edges(edges[3..4]).should be g
    expect_raises(IndexError) { g << {4, 5} }

    g[0].should eq [UnweightedEdge.new(1), UnweightedEdge.new(1)]
    g[1].should eq [UnweightedEdge.new(2)]
    g.to_a.should eq edges
  end

  it "#reverse" do
    edges = [
      UnweightedEdge2.new(0, 1), UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 2),
      UnweightedEdge2.new(2, 3), UnweightedEdge2.new(3, 4),
    ]
    g = UnweightedDiGraph.new(5, edges)
    g.reverse.to_a.should eq edges.map(&.reverse)
  end

  it "#to_undirected" do
    edges = [
      UnweightedEdge2.new(0, 1), UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 2),
      UnweightedEdge2.new(2, 3), UnweightedEdge2.new(3, 4),
    ]
    g = UnweightedDiGraph.new(5, edges)
    g.to_undirected.to_set.should eq edges.flat_map { |e| [e, e.reverse] }.to_set
  end
end

describe UnweightedUnGraph do
  it ".weighted?, .directed?" do
    UnweightedUnGraph.weighted?.should be_false
    UnweightedUnGraph.directed?.should be_false
  end

  it "#.new(size)" do
    g = UnweightedUnGraph.new(5)
    g.size.should eq 5
    g.to_a.should eq [] of UnweightedEdge2
    expect_raises(ArgumentError) { UnweightedUnGraph.new(-2) }
  end

  it ".new(n, edges)" do
    edges = [UnweightedEdge2.new(0, 1), UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 0), UnweightedEdge2.new(1, 0)]
    g = UnweightedUnGraph.new 2, [edges[0], edges[3]]
    g.to_a.should eq edges

    g = UnweightedUnGraph.new 2, edges.values_at(0, 3)
    g.to_a.should eq edges

    g = UnweightedUnGraph.new 2, [{0, 1}, {1, 0}]
    g.to_a.should eq edges

    expect_raises(IndexError) { UnweightedUnGraph.new 1, [UnweightedEdge2.new(0, 1)] }
  end

  it "#<<, #add_edges" do
    edges = [
      [UnweightedEdge.new(1)],
      [UnweightedEdge.new(0), UnweightedEdge.new(2)],
      [UnweightedEdge.new(1), UnweightedEdge.new(3)],
      [UnweightedEdge.new(2)],
    ]
    all_edges = [
      UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 0),
      UnweightedEdge2.new(1, 2), UnweightedEdge2.new(2, 1),
      UnweightedEdge2.new(2, 3), UnweightedEdge2.new(3, 2),
    ]

    g = UnweightedUnGraph.new(4)
    (g << {0, 1}).should be g
    g << {1, 2}
    g << UnweightedEdge2.new(2, 3)
    g[0].should eq edges[0]
    g[1].should eq edges[1]
    g[2].should eq edges[2]
    g[3].should eq edges[3]
    g.to_a.should eq all_edges

    g = UnweightedUnGraph.new(4)
    g.add_edges([{0, 1}]).should be g
    g.add_edges({UnweightedEdge2.new(1, 2), UnweightedEdge2.new(2, 3)})
    g[0].should eq edges[0]
    g[1].should eq edges[1]
    g[2].should eq edges[2]
    g[3].should eq edges[3]
    g.to_a.should eq all_edges
  end

  it "#reverse" do
    all_edges = [
      UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 0),
      UnweightedEdge2.new(1, 2), UnweightedEdge2.new(2, 1),
      UnweightedEdge2.new(2, 3), UnweightedEdge2.new(3, 2),
    ]

    g = UnweightedUnGraph.new(4)
    g << {0, 1} << {1, 2} << {2, 3}
    g.reverse.to_set.should eq all_edges.to_set
  end

  it "#to_undirected" do
    all_edges = [
      UnweightedEdge2.new(0, 1), UnweightedEdge2.new(1, 0),
      UnweightedEdge2.new(1, 2), UnweightedEdge2.new(2, 1),
      UnweightedEdge2.new(2, 3), UnweightedEdge2.new(3, 2),
    ]

    g = UnweightedUnGraph.new(4)
    g << {0, 1} << {1, 2} << {2, 3}
    g.to_undirected.to_set.should eq all_edges.to_set
  end

  it "#each_child" do
    g = UnweightedUnGraph.new(6)
    g << {0, 1} << {0, 2} << {0, 3} << {3, 4} << {3, 5}
    v = [] of Int32
    g.each_child(0, nil) { |e| v << e.to }
    v.should eq [1, 2, 3]
    v.clear
    g.each_child(3, nil) { |e| v << e.to }
    v.should eq [0, 4, 5]
    v.clear
    g.each_child(3, 0) { |e| v << e.to }
    v.should eq [4, 5]
    g.each_child(0, nil).map(&.to).to_a.should eq [1, 2, 3]
    g.each_child(3, nil).map(&.to).to_a.should eq [0, 4, 5]
    g.each_child(3, 0).map(&.to).to_a.should eq [4, 5]
  end
end
Back to top page