为什么我收到此错误:未定义方法`[]'表示0..5:范围(NoMethodError)

时间:2015-05-19 03:59:51

标签: ruby nomethoderror

我正在Ruby中创建一个状态机简化器。循环遍历我创建的表以简化状态机,它正确运行并产生所需的输出,但是,我收到以下错误:

undefined method `[]' for 0..5:Range (NoMethodError)
    from C:/Users/Sara/workspace/StateMachineSimplifier/statemachine_simplifier.rb:64:in each
    from C:/Users/Sara/workspace/StateMachineSimplifier/statemachine_simplifier.rb:64:in x_out
    from C:/Users/Sara/workspace/StateMachineSimplifier/statemachine_simplifier.rb:268:in main
    from C:/Users/Sara/workspace/StateMachineSimplifier/statemachine_simplifier.rb:274:in <main>

我知道错误是由调用函数的while循环引起的。如何只调用该函数足够的时间来结束最终表格?

=begin 
File: statemachine_simplifier.rb 
Author: Sara Tibbetts 
Date: 04/24/2015 
Description: This program takes in .txt file with a state table 
and reduces it to its simplest form 
=end 

def dup_remove(table0)
  #Simplifies states with same output and next states 
  for i in 0..((table0.size)-1) 
    check1 = table0[i][1]
    check2 = table0[i][2]
    for j in 0..((table0.size)-1)
      if i != j then 
        #States are exactly the same 
        if (table0[i][1] == table0[j][1]) and (table0[i][2] == table0[j][2]) then 
          #Replaces all instances of state to be removed with equivalent state 
          to_rep = table0[i][0] 
          to_rem = table0[j][0]

          t_index = []
          #Removes the state from the array 
          table0[j] = "-1"
          for i in 0..((table0.size)-1)
            for j in 0..((table0[0].size)-1)
              if table0[i][j] == to_rem then 
                table0[i][j] = to_rep 
              end 
            end 
          end 
        end 
      end 
    end
  end

  #Removes the placeholders from the table 
  for i in 0..((table0.size)-1)
    if table0[i] == "-1" then 
      t_index.push(i) 
    end
  end

  if t_index != nil then 
    for i in 0..((t_index.size)-1)
      table0.delete_at(t_index[i])
      for j in i..((t_index.size)-1)
        t_index[j] = t_index[j]-1
      end 
    end 
  end 


  #puts table0.inspect 
  return table0
end 

#loops through the given array, and minimizes the states 
def x_out(arr1, s_table)
  #puts arr1.inspect
  #puts arr1.size
  for i in 0..((arr1.size)-1)
    #Loops through each row of the columns 
    #puts i
    #puts arr1.inspect
    #puts arr1[i].inspect
    for j in 0..((arr1[i].size)-1)
      #If the cell is not an "X"
      if arr1[i][j].size != 1
        #If the states are not equal 
        if arr1[i][j][0] != arr1[i][j][2]                                       ###################1
          #If the first state is less than the second state
          if arr1[i][j][0] < arr1[i][j][2]                                      ###################2
            #If arr1[small-1][(big-2)-(small-1)] = "X"
            if arr1[(arr1[i][j][0])-1][(arr1[i][j][2]-2)-(arr1[i][j][0]-1)] == "X"        ###################3   
              arr1[i][j] = "X" 
            end                                                                 ###################3
            #If the first state is more than the second state 
          else                                                                  ###################2
            #If arr1[small-1][(big-2)-(small-1)] = "X"
            if arr1[arr1[i][j][2]-1][(arr1[i][j][0]-2)-(arr1[i][j][2]-1)] == "X"          ###################4  
              arr1[i][j] = "X"
            end                                                                 ###################4
          end                                                                   ###################2
        end                                                                     ###################1
        if arr1[i][j].size != 1
        #print "Loop 2", arr1.inspect, "\n"
          #If the states are not equal 
          if arr1[i][j][1] != arr1[i][j][3]
            #If the first state is less than the second state
            if arr1[i][j][1] < arr1[i][j][3]
              #puts arr1[i][j].inspect
              #puts arr1[(arr1[i][j][1])-1][(arr1[i][j][3]-2)-(arr1[i][j][1]-1)].inspect
              #If arr1[small-1][(big-2)-(small-1)] = "X"
              if arr1[(arr1[i][j][1])-1][(arr1[i][j][3]-2)-(arr1[i][j][1]-1)] == "X"                         
                arr1[i][j] = "X" 
              end 
              #If the first state is more than the second state 
            else 
              #If arr1[small-1][(big-2)-(small-1)] = "X"
              if arr1[arr1[i][j][3]-1][(arr1[i][j][1]-2)-(arr1[i][j][3]-1)] == "X"             
                arr1[i][j] = "X"
              end 
            end 
          end 
        end
      end 
    end 
  end 
end 

def main()
  #Reads in the .txt file 
  print("Enter a file: ")
  filename = gets.chomp



  #Creates array to store information from file 
  s_table = ""
  i = 0 
  j = 0 


  f = File.open(filename,"r")
    puts "\nState table input: \n"
  f.each_line do |line|
    puts line
    s_table = s_table + line 
  end

  s_table = s_table.split("\n")
  s_table = s_table.map { |data| data.split(' ') }

  #Groups states based on outputs 
  table1 = []
  table0 = []

  for i in 0..((s_table.size)-1)
    if s_table[i][3] == "1" then 
      table1.push(s_table[i])
    elsif s_table[i][3] == "0" then 
      table0.push(s_table[i])
    end
  end

  while dup_remove(table0) != table0
    table0 = dup_remove(table0)
  end

  while dup_remove(table1) != table1 
    table1 = dup_remove(table1)
  end


  #Removes the rest of the unnecessary states 

  #table of states that have the possibility of being combined 
  pos_comb = []

  #Need to make table reflecting staircase [ [AB, AC, AD, AE, AF, AG], [BC, BD, BE, BF, BG], [CD, CE, CF, CG], [DE, DF, DG], [EF, EG], [FG] ]
  for i in 0..((s_table.size)-2)
    # 0 :6, 1: 5, 2:4 . . . 
    #(s_table.size)-(i+1)
    pos_comb[i] = Array.new(s_table.size-(i+1), "0")
  end 

  #puts pos_comb.inspect

  #Creates an array with a numerical equivalent of the state number 
  s0_arr = Array.new(table0.size)
  for i in 0..((s0_arr.size)-1)
    if (table0[i][0].ord >= 30) && (table0[i][0].ord <= 57)  
      s0_arr[i] = table0[i][0] 
    elsif (table0[i][0].ord >= 65) && (table0[i][0].ord <= 90)  
      s0_arr[i] = table0[i][0].ord - 64
    else 
      s0_arr[i] = table0[i][0].ord - 96
    end 
  end 


  s1_arr = Array.new(table1.size)
  for i in 0..((s1_arr.size)-1)
    if (table1[i][0].ord >= 30) && (table1[i][0].ord <= 57)  
      s1_arr[i] = table1[i][0] 
    elsif (table1[i][0].ord >= 65) && (table1[i][0].ord <= 90)  
      s1_arr[i] = table1[i][0].ord - 64
    else 
      s1_arr[i] = table1[i][0].ord - 96
    end 
  end 

  #Loops through all of the items in the s1_arr and s0_arr and places 
  # an "X" on their combined position in the pos_comb array 
  for i in 0..((s0_arr.size)-1)
    for j in 0..((s1_arr.size)-1)
      if s0_arr[i] < s1_arr[j] then 
        #puts (s1_arr[j]-s0_arr[i]-1)
        pos_comb[s0_arr[i]-1][(s1_arr[j]-s0_arr[i])-1] = "X"
      else 
        pos_comb[s1_arr[j]-1][(s0_arr[i]-s1_arr[j])-1] = "X"
      end 
    end 
  end 

#  #reverses the items in the pos_comb arrays 
#  for i in 0..((pos_comb.size)-1)
#    pos_comb[i].reverse
#  end 

  #puts pos_comb.inspect
  #puts pos_comb[0][5]

  #Need to go through the pos_comb array, and wherever there is not an X, fill the 
  #next states of the combination 

  #Loops through the pos_comb array, and wherever there is not an X, places an array of 
  #to hold the next states of the combination 
  for i in 0..((pos_comb.size)-1) 
    for j in 0..((pos_comb[i].size)-1)
      if pos_comb[i][j] != "X"
        pos_comb[i][j] = Array.new(4, 0)

        #Places numerical form of state transitions into new array 

        #Columns 
        for k in 0 .. 1
          #numbers 
          if (s_table[i][k+1].ord >= 30) && (s_table[i][k+1].ord <= 57)
            pos_comb[i][j][k] = s_table[i][k-1]
          #uppercase
          elsif (s_table[i][k+1].ord >= 65) && (s_table[i][k+1].ord <= 90)
            pos_comb[i][j][k] = s_table[i][k+1].ord - 64
          #lowercase
          else 
            pos_comb[i][j][k] = s_table[i][k+1].ord - 96
          end 
        end 

        #Rows 
        for k in 2 .. 3
          #numbers 
          #puts s_table[j].inspect
          if (s_table[(i+j)+1][k-1].ord >= 30) && (s_table[(i+j)+1][k-1].ord <= 57)
            pos_comb[i][j][k] = s_table[j+1][k-1]
          #uppercase
          elsif (s_table[(i+j)+1][k-1].ord >= 65) && (s_table[(i+j)+1][k-1].ord <= 90)
            pos_comb[i][j][k] = s_table[(i+j)+1][k-1].ord - 64
          #lowercase
          else 
            pos_comb[i][j][k] = s_table[(i+j)+1][k-1].ord - 96
          end 
        end 

      end 
    end 
  end 

  puts pos_comb.inspect 
  count = 0

  while x_out(pos_comb, s_table).size == pos_comb.size
    #pos_comb = x_out(pos_comb, s_table)
    pos_comb = x_out(pos_comb, s_table)

  end
  puts "HERE!"
  puts pos_comb.inspect
end

main()

我的文字文件如下所示

A B C 1
B D F 1
C F E 0
D B G 1
E F C 0
F E D 0
G F G 0

我知道问题在于调用函数,但我不确定如何调用它适当的次数来获得正确最小化状态表的输出。

1 个答案:

答案 0 :(得分:0)

你的问题在这里:

pos_comb = x_out(pos_comb, s_table)

xout会返回外部for loop的值range。在ruby中,for循环是一种表达。例如:

x = for i in (0..5) do puts i end # x is equal to (0..5)

相同
def x_out()
    for i in (0..5) do puts i end
end

x = x_out()  # x is equal to (0..5)

x_out返回后,您将使用范围pos_comb覆盖0..5的值。然后将其传递回x_out,这会导致您在while循环的第二次迭代中出现问题。

现在看来你想从你的arr1函数中返回x_out,所以试试

  ...
  end
  arr1  # <- insert this at the last line in your function
end

在函数末尾改为返回arr1