문제

런타임에 내 코드는 종종 메소드에 대한 정의되지 않은 메소드 오류로 나타납니다. mate. 내가 알 수있는 한, a Person 어떻게 든 코드의 발병을 따라 언젠가 균열을 통해 미끄러 져서 allele 그것에 할당되었습니다.

코드 (가장 좋은 형식이 아닌 면책 조항) :

class Allele
  attr_accessor :c1, :c2

  def initialize(c1, c2)
    @c1 = c1
    @c2 = c2
  end

 #formats it to be readable
 def to_s
  c1.to_s + c2.to_s
 end

 #given Allele a
 def combine(a)
  pick = rand(4)
  case pick
   when 0
    Allele.new(c1,a.c1)
   when 1
    Allele.new(c1,a.c2)
   when 2
    Allele.new(c2,a.c1)
   when 3
    Allele.new(c2,a.c2)
  end
 end
end

class Person
 attr_accessor :allele, :male

 def initialize(allele,male)
    @allele = allele
  @male= male
  end

 #def self.num_people
  #@@num_people
 #end

 def to_s
  "Allele:" + allele.to_s + " | Male:" + male.to_s
 end

 def male
  @male
 end

 def allele
  @allele
 end

 def mate(p)
  if rand(2) == 0
   Person.new(allele.combine(p.allele),true)
  else
   Person.new(allele.combine(p.allele),false)
  end
 end
end

male_array = Array.new
female_array = Array.new
male_child_array = Array.new
female_child_array = Array.new

# EVENLY POPULATE THE ARRAY WITH 5 THAT PHENOTYPICALLY MANIFEST TRAIT, 5 THAT DON'T
# AND 5 GIRLS, 5 GUYS
pheno_dist = rand(5)
#make guys with phenotype
pheno_dist.times { male_array << Person.new(Allele.new(1,rand(2)),true) }
#guys w/o
(5-pheno_dist).times { male_array << Person.new(Allele.new(0,0),true) }
#girls w/ pheno
(5-pheno_dist).times { female_array << Person.new(Allele.new(1,rand(2)),false) }
#girls w/o
pheno_dist.times { female_array << Person.new(Allele.new(0,0),false) }

puts male_array
puts female_array
puts "----------------------"

4.times do
 #mates male with females, adding children to children arrays. deletes partners as it iterates
 male_array.each do
  male_id = rand(male_array.length) #random selection function. adjust as needed
  female_id = rand(female_array.length)
  rand(8).times do
   child = male_array[male_id].mate(female_array[female_id])
   if child.male
    male_child_array << child
   else
    female_child_array << child
   end
  end
  male_array.delete_at(male_id)
  female_array.delete_at(female_id)
 end

 #makes males male children, females female children, resets child arrays
 male_array = male_child_array
 female_array = female_child_array
 male_child_array = []
 female_child_array = []

 puts male_array
 puts female_array
 puts "----------------------"
end

무엇이 잘못 보이는가?

도움이 되었습니까?

해결책

Egosys가 말했듯이, 반복되는 배열에서 삭제해서는 안됩니다.

또 다른 문제는 "4.times do"를 시작하는 루프에 있습니다. 때로는 암 배열이 비어 있으므로 크기 0을 반환합니다. rand (0)는 임의의 float> = 0 및 <1입니다. 비어있는 female_array의 배열 인덱스로 사용하여 nil을 반환 한 다음 메이트에게 전달됩니다.

그러나 그 이상의 잘못이 있습니다. 당신은 각각을 사용하여 male_array를 반복하지만 무작위로 남성을 선택합니다. 이를 통해 일부 남성은 두 번 이상 짝짓기를 할 수 있습니다. 다른 사람들은 전혀 그렇지 않습니다. 마찬가지로, 일부 여성은 각 반복 할 때 두 번 이상 짝짓기를하고 재생산하며 다른 여성은 전혀 그렇지 않습니다. 그게 당신의 의도인가요?

먼저 모든 남성과 여성을 동일한 배열에 유지하는 것을 고려해 봅시다. 이것은 물건을 단순화 할 것입니다. 그러나 때때로 모든 남성과 때로는 모든 여성을 찾아야하므로 다음을위한 방법을 만들어 드리겠습니다.

def males(population)
  population.find_all do |person|
    person.male?
  end
end

def females(population)
  population.find_all do |person|
    person.female?
  end
end

남성과 여성이 무작위로 짝을 이루어야한다면 더 생물학적으로 정확하지만 아무도 두 번 이상 짝짓기를하지 않습니다. 아주 간단합니다.

def random_pairs(males, females)
  males.shuffle[0...females.size].zip(females.shuffle)
end

그런 다음 인구의 재생산은 간단하게됩니다.

def make_children(male, female)
  # return an array of children
end

def reproduce(population)
  children = []
  random_pairs(males(population), females(population)).each do |male, female|
    children << make_children(male, female)
  end
  children
end

그러한 기능을하면 4주기의 재생산을 수행하는 것은 다음과 같이 간단합니다.

people = # ... generate your initial list of people of all sexe.
4.times do
  people = reproduce(people)
end

기능이 전달 된 인수를 수정하지 않으므로 부작용에 문제가 없습니다.

예를 들어, 인구를 일류 대상으로 만들고 "남성", "여성", "랜덤_Pairs"및 "재생산"을 옮기는 등 OO 스타일로 더 많은 것을 수행 할 수 있습니다. 나는 그것을 독자를위한 운동으로 남겨 둘 것이다.

다른 팁

각각 반복하는 배열에서 삭제하면 정의되지 않은 동작이 있습니다. 일반적으로 조언은 배열#delete_if를 사용하는 것이지만,이 경우 어떻게 사용할 것인지 잘 모르겠습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top