未定义的方法`[]' for false:FalseClass(NoMethodError)

时间:2015-08-28 11:04:22

标签: ruby dijkstra

我是ruby的初学者在这里我附上我的错误代码请帮我解决我在Dijkstra算法实现中的错误

  #!/usr/bin/env ruby

def minDistance(dist,sptSet)
 min=999,min_index=0,v=0
 for v in 0...9 
 if sptSet[v]==false && dist[v]<=999
   min=dist[v],min_index=v
 end
 end
return min_index
end

   def printSolution(dist,n)
    puts "Vertex  Distance from Source"
    for i in 0...9
    puts "#{i}  #{dist[i]}"
    end
     end

    def dijkstra(graph,src)
    dist=Array.new(9)
    sptSet=Array.new(9)

    for i in 0...9
     dist[i]=999,sptSet=false
     end
     dist[src]=0
     for count in 0...8
     u=minDistance(dist,sptSet)
     sptSet[u]=true
     for v in 0...9
     if sptSet[v]==false && graph[u][v] && dist[u]!=999 && dist[u]+graph[u] [v]<dist[v]
    dist[v]=dist[u]+graph[u][v]
    end
    end
    end
     printSolution(dist,9)
     end


   def main

     graph=[[0,4,0,0,0,0,0,8,0],[4,0,8,0,0,0,0,11,0],[0,8,0,7,0,4,0,0,2],[0,0,7,0,9,14,0,0,0],[0,0,0,9,0,10,0,2,0,0],[0,0,0,14,0,2,0,1,6],[8,11,0,0,0,0,1,0,7],[0,0,2,0,0,0,6,7,0]]


    dijkstra(graph,0)

      end

      main

以下是向我显示的错误。请帮我找一个正确解释错误的地方

            in `block in minDistance': undefined method `[]' for     false:FalseClass (NoMethodError)
            from rubyfirst.rb:5:in `each'
            from rubyfirst.rb:5:in `minDistance'
            from rubyfirst.rb:29:in `block in dijkstra'
           from rubyfirst.rb:28:in `each'
           from rubyfirst.rb:28:in `dijkstra'
           from rubyfirst.rb:46:in `main'
           from rubyfirst.rb:50:in `<main>'

3 个答案:

答案 0 :(得分:1)

代码很难理解,但直觉告诉我问题是关于线的 dist[i]=999,sptSet=false

因为在定义sptSet之前有3行 sptSet=Array.new(9)

所以首先你要制作数组,然后你将它改为false。你想要达到的目标可能是: dist[i]=999,sptSet[i]=false

答案 1 :(得分:1)

您将false分配给sptSet

 dist[i]=999,sptSet=false

将其传递给minDistance,并且在此方法体中,您希望sptSet为Array

if sptSet[v]==false && dist[v]<=999

答案 2 :(得分:0)

我的Dijkstra实现示例:

class Dijkstra
    attr_accessor :graph, :origin, :destination, :edges, :verticies

    def initialize(origin, destination, edges)
        self.graph = []
        self.edges = edges
        self.verticies = unique_verticies
        populate_graph(origin, destination)
    end

    def populate_graph(origin, destination)
        self.origin = origin
        self.destination = destination
        self.graph = create_nodes
        populate_neighbors
        recursive_dijkstra
    end

    def shortest_distance
        self.graph.detect { |node| node[:vertex] == self.destination }[:distance]
    end

    def shortest_path
        path = [self.destination]
        predecessor = self.destination
        while !predecessor.nil?
            predecessor = self.graph.detect { |node| node[:vertex] == predecessor }[:predecessor]
            path.unshift(predecessor) unless predecessor.nil?
        end
        path
    end

    private

    def unique_verticies
        self.edges.flatten.uniq.select { |edge| edge.class == String }
    end

    def create_nodes
        self.verticies.map do |vertex|
            node = { vertex: vertex, closed: false, predecessor: nil, distance: Float::INFINITY, neighbors: [] }
            node[:distance] = 0 if vertex == origin
            node
        end
    end

    def populate_neighbors
      self.verticies.each do |vertex|
        self.edges.each do |edge|
          if edge.include?(vertex)
            self.graph.detect { |node| node[:vertex] == vertex }[:neighbors] << edge.detect { |neighbor| neighbor != vertex && neighbor.class == String }
          end
        end
      end
    end

    def recursive_dijkstra
        open_verticies = self.graph.select { |node| node[:closed] == false }.sort_by { |node| node[:distance] }
        return if open_verticies.count == 0
        node = open_verticies.first
        node[:closed] = true
        node[:neighbors].each do |neighbor|
            neighbor_vertex = self.graph.detect { |node| node[:vertex] == neighbor && node[:closed] == false }
            next if neighbor_vertex.nil?
            self.edges.each do |edge|
                if edge.include?(node[:vertex]) && edge.include?(neighbor_vertex[:vertex])
                    matcher_distance = node[:distance] + edge[2]
                    if matcher_distance < neighbor_vertex[:distance]
                        neighbor_vertex[:distance] = matcher_distance
                        neighbor_vertex[:predecessor] = node[:vertex]
                    end
                end
            end
        end
        recursive_dijkstra
    end
end

您必须以

格式传递边缘
[['vertex_1', 'vertex_2', weight], ['vertex_2', 'vertex_3', weight ], ...]