어떻게 든 루비와 수업을 할당하지 않습니다
-
19-09-2019 - |
문제
런타임에 내 코드는 종종 메소드에 대한 정의되지 않은 메소드 오류로 나타납니다. 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를 사용하는 것이지만,이 경우 어떻게 사용할 것인지 잘 모르겠습니다.