2010-02-08 7 views
0

런타임에 내 코드는 종종 mate 메서드에 대해 정의되지 않은 메서드 오류가 발생합니다. 내가 생각할 수있는 한, Person은 어떻게 든 코드 excution을 따라 언제든지 균열을 통과하여 allele이 할당되지 않도록 관리합니다.어떻게 든 Ruby 클래스를 할당하지 않음

코드 (가장 좋은 포맷되지 면책 조항) :

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 

무엇 즉시 잘못 보인다?

+0

코드 크기입니다. 관련 부분을 게시하는 것이 훨씬 더 이해할 수 있습니다. – johannes

+0

나는 어느 정도 생각했지만, 실제로 오류를 그려내는 곳을 직접 추적 할 수 없었기 때문에, 실제로 내가 단축 된 부분 (배열 삭제)을 편집했을 것입니다. 그러나 일했다. – deeb

답변

3

egosys가 말했듯이, 반복하는 배열에서 삭제하지 말아야합니다.

"4x do"를 시작하는 또 다른 문제가 루프에 있습니다. 때때로 여성 배열이 비어 있으므로 크기 0을 반환합니다. rand (0)은 random float> = 0이고 <입니다. 1. 빈 female_array에 대한 배열 인덱스로이를 사용하면 nil을 반환하고, mate로 전달됩니다.

하지만 그 이상이 잘못되었습니다. 각각을 사용하여 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 

전달 된 인수를 수정하는 함수가 없기 때문에 부작용에 문제가 없습니다.

예를 들어 Population을 일류 객체로 만들고 "male", "female", "random_pairs"및 "reproduce"함수를 이동하는 등 OO 스타일을 더 많이 수행 할 수 있습니다. 나는 그것을 독자를위한 운동으로 남겨 둘 것이다.

+0

이상 및 이상에 대해 설명합니다.좋은 대답. – deeb

+0

추가 참고 : "shuffle"은 표준 라이브러리에 없습니다. "sort_by {rand}"로 정의해야했습니다. – deeb

+0

1.8.7에 있습니다. 1.89로 역 이동 한 1.9 기능이라고 생각합니다 (루비는 1.8 루피에서 1 피트, 1.9에서 1 피트). 1.8.6 이전 버전을 실행하고 있습니까? –

1

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

+0

undefined는 'mate'에서와 같이 나타납니다. nil : NilClass (NoMethodError)에 대해서는 정의되지 않은 메소드 'allele'이 아니라 삭제 호출에서옵니다. 친구의 전화가 무슨 소리 야? – deeb

+0

이것은 반복자 아래에서 목록을 변경하여 발생할 수있는 정의되지 않은 동작의 일종입니다. – corprew