Soluzione Grafo

21 Feb 2017

Soluzione Grafo

class Grafo
  def initialize
    # La soluzione più semplice prevede la creazione di una classe
    # che contiene solamente una lista di edges e una lista di vertici
    # Non cerchiamo la soluzione più efficiente ma la soluzione più
    # rapida
    @edges = []
    @vertices = []
  end

  def add(a, b)
    # come sempre per prima cosa controlliamo l'input
    [a, b].each do |v|
      raise ArgumentError, "Vertici sono stringhe" unless v.is_a? String
    end
    # Aggiungiamo i nostri vertici se e solo se la nostra lista
    # li contiene
    [a, b].each do |v|
      @vertices << v unless @vertices.include? v
    end
    # Costruiamo il nostro edge come specificto
    e = {from: a, to: b}
    @edges << e unless @edges.include? e
    # Ritorniamo la istanza alla fine
    return self
  end
  # Gli altri metodi sono estremamente triviali a questo punto
  def get; return @edges; end
  def size; return @edges.size; end
  def getvertex; return @vertices; end

  # L'unico metodo a cui dobbiamo dare un po' di attenzione
  # è il source and sink. Ricostruiamo due Array di from
  # e to partendo dai singoli hash. Poi valutiamo mediante una
  # intersezione dei due set.
  # Una sorgente non rientra nel set di elementi riceventi
  # Un ricevente non rientra nel set di elementi sorgente
  # Aggiungiamo un ulteriore controllo per non avere duplicati
  def source_and_sink
    from, to = [], []

    h = { sources: [], sinks: [] }

    @edges.each do |e|
      from << e[:from]
      to   << e[:to]
    end

    from.each do |f|
      h[:sources] << f unless (to.include?(f) or h[:sources].include?(f))
    end

    to.each do |t|
      h[:sinks] << t unless (from.include?(t) or h[:sinks].include?(t))
    end

    return h
  end
end

Esempio d’uso

g = Grafo.new # crea una nuova pila

g.add( "a", "b")  # aggiunge l'edge
g.add( "a", "b")  # aggiunge l'edge
g.add( "a", "b")  # aggiunge l'edge
g.add( "a", "b")  # aggiunge l'edge
g.add( "a", "c")  # aggiunge l'edge
g.add( "b", "c")  # aggiunge l'edge
g.add( "c", "b")  # aggiunge l'edge
puts g.getvertex
puts g.get
puts g.source_and_sink