我不确定我是否在标题中完全清楚了,但我的问题是这样的:我有do-while循环,它接受一个初始化的数组散列(HoA),计算一个新的维数组,然后将生成的数组与每个键的数组相关联的数组进行比较(为简单起见,键是数字的...所以最好这样做就像数组一样)。如果某些crietria适合(例如,新值在特定的"距离"内),则为HoA生成新密钥,并且使用新密钥将生成的阵列添加到HoA。
奇怪的是,我使用do-while循环限制了新键的数量,但有时当我运行代码时(根本没有进行任何更改),我得到了#34;额外的"密钥。
我的代码如下,任何帮助都会很棒。
use strict;
use warnings;
use Data::Dumper;
my $PolymerSize=6;
# each monomer/node can bond upto 3 times
my $maxNeighbors=3;
#Store coordinates and number of neighbors for each monomer/node
# (in C would be an array of structs)
my %HoA;
my %BondHoA; #who are my neighbors
my @coordsNeighbors;
my $element; #Iteration dummy variable
my %dist; #temporary distance hash
my $return_flag;
$coordsNeighbors[0]=0; #Xcoord
$coordsNeighbors[1]=0; #YCoord
$coordsNeighbors[2]=0; #ZCoord
$coordsNeighbors[3]=0; #How many bonded neighbors?
#Intialize origin (first node/monomer)
push @{$HoA{0}}, $coordsNeighbors[0];
push @{$HoA{0}}, $coordsNeighbors[1];
push @{$HoA{0}}, $coordsNeighbors[2];
push @{$HoA{0}}, $coordsNeighbors[3];
#Generate new nodes/monomer and "grow" polymer
do{
for(my $j=0;$j<3;$j++){
#generate coords of potent. monomers/node
$coordsNeighbors[$j] = int($PolymerSize*rand());
}
$coordsNeighbors[3]=0;
#loop through existing monomers/nodes
foreach $element ( keys %HoA) {
#if this monomer doesn't have the max bonds proceed
if( ($HoA{$element}[3])!=$maxNeighbors) {
my $tempx=$HoA{$element}[0]-$coordsNeighbors[0];
my $tempy=$HoA{$element}[1]-$coordsNeighbors[1];
my $tempz=$HoA{$element}[2]-$coordsNeighbors[2];
#make hash of L1 distances
$dist{$element} .=abs($tempx)+abs($tempy)+abs($tempz);
}
}
#check if any distance is != 1; no-bond could be made if so
foreach(keys %dist){
if($dist{$_}!=1) {
delete $dist{$_};
}
}
#potential monomer is good, so add to HoA and update bonds
foreach $element (keys %dist){
$HoA{$element}[3]++;
my $newKey=scalar (keys %HoA);
if($newKey!=($PolymerSize-1)){
push @{$HoA{$newKey}}, $coordsNeighbors[0];
push @{$HoA{$newKey}}, $coordsNeighbors[1];
push @{$HoA{$newKey}}, $coordsNeighbors[2];
push @{$HoA{$newKey}}, $coordsNeighbors[3]+1;
push @{$BondHoA{$element}}, "$newKey";
push @{$BondHoA{$newKey}}, "$element";
}
delete $dist{$element};
}
} while((keys %HoA)<$PolymerSize-1);
foreach $element (keys %HoA) {
print "$element \t $HoA{$element}[0] \t $HoA{$element}[1] \t $HoA{$element}[2]\n";
}
这段代码背后的一般理念是做一些像3D一样生成像DLA(扩散限制聚合体)这样的聚合物,所以有两件事情需要它才能正常工作:
1)获得正确数量的单体(上面提到的HoA键)。
2)确保没有单体重叠(L1距离为0(曼海坦距离,因为我们在网格上))。
[编辑] 我显然忘了包含所需的输出(我道歉)。
输出应该是这样的:
0 0 0 0
1 1 0 0
2 0 1 0
3 2 0 0
4 2 1 0
5 2 2 0
但我最终得到了类似的东西:
0 0 0 0
1 1 0 0
2 0 1 0
3 0 0 0
4 1 1 0
5 0 1 1
6 2 0 0
(有时甚至是第8或第9个值)
答案 0 :(得分:0)
按照@Schwern的建议,我回去看了
foreach $element (keys %dist){ ...
循环并意识到确实发生的事情是,即使删除了所有与%dist哈希值中的非一个值一致的键,我也可以在%dist哈希中拥有多个成员。然后一个简单的修复是添加“最后一个”
foreach $element (keys %dist){
$HoA{$element}[3]++;
my $newKey=scalar (keys %HoA);
if($newKey!=($PolymerSize-1)){
push @{$HoA{$newKey}}, $coordsNeighbors[0];
push @{$HoA{$newKey}}, $coordsNeighbors[1];
push @{$HoA{$newKey}}, $coordsNeighbors[2];
push @{$HoA{$newKey}}, $coordsNeighbors[3]+1;
push @{$BondHoA{$element}}, "$newKey";
push @{$BondHoA{$newKey}}, "$element";
#here I add a last to break out and go to the next do-while iter.
last
}
然后在do-while循环的顶部添加对undef(%dist)的调用,以清除它以便再次使用。
此外,在修复此错误后,我回过头来清理了大部分代码,现在为感兴趣的人提供了以下内容:
#!/usr/bin/perl;
use strict;
use warnings;
use Data::Dumper;
my $PolymerSize=8;
my $maxNeighbors=3; #each monomer/node can bond upto 3 times
my %HoA; #Store coordinates and number of neighbors for each monomer/node (in C would be an array of structs)
my %BondHoA; #who are my neighbors
my @coordsNeighbors;
my $element; #Iteration dummy variable
my %dist; #temporary distance hash
my $selected;
$coordsNeighbors[0]=0; #Xcoord
$coordsNeighbors[1]=0; #YCoord
$coordsNeighbors[2]=0; #ZCoord
$coordsNeighbors[3]=$maxNeighbors; #How many bonded neighbors?
my $tempx;
my $tempy;
my $tempz;
my $tempL1;
#Intialize origin (first node/monomer)
push @{$HoA{0}}, $coordsNeighbors[0];
push @{$HoA{0}}, $coordsNeighbors[1];
push @{$HoA{0}}, $coordsNeighbors[2];
push @{$HoA{0}}, $coordsNeighbors[3];
my $iter=0;
#Generate new nodes/monomer and "grow" polymer
do{
#print "$iter\n";
# $iter++;
undef(%dist);
for(my $j=0;$j<3;$j++){
$coordsNeighbors[$j]=int($PolymerSize*rand()); #generate coords of potent. monomers/node
}
$coordsNeighbors[3]=$maxNeighbors;
foreach $element ( keys %HoA) { #loop through existing monomers/nodes
$tempx=int($HoA{$element}[0])-int($coordsNeighbors[0]);
$tempy=int($HoA{$element}[1])-int($coordsNeighbors[1]);
$tempz=int($HoA{$element}[2])-int($coordsNeighbors[2]);
$tempL1=abs($tempx)+abs($tempy)+abs($tempz);
if($tempL1==1){
$dist{$element} .= $tempL1;
} elsif($tempL1==0){
undef(%dist);
last;
}
}
foreach $element (keys %dist){
if ( ($HoA{$element}[3]>0)){ #potential monomer is good, so add to HoA and update bonds
my $newKey=scalar (keys %HoA);
if($newKey<=($PolymerSize-1)){
$HoA{$element}[3]--;
push @{$HoA{$newKey}}, $coordsNeighbors[0];
push @{$HoA{$newKey}}, $coordsNeighbors[1];
push @{$HoA{$newKey}}, $coordsNeighbors[2];
push @{$HoA{$newKey}}, $coordsNeighbors[3];
push @{$BondHoA{$element}}, "$newKey";
push @{$BondHoA{$newKey}}, "$element";
last;
}
}
}
} while((scalar (keys %HoA))<=$PolymerSize-1);
foreach $element (keys %HoA){
print "$element \t $HoA{$element}[0] \t $HoA{$element}[1] \t $HoA{$element}[2]\n";
}
答案 1 :(得分:-1)
一个简单的修改就可以了
确保散列大小为6
my $newKey=scalar (keys %HoA);
print "newKey<$newKey>\n";
if($newKey !=($PolymerSize-1)){
# changed to
if($newKey <=($PolymerSize-1)){
确保哈希的大小为6
} while((keys %HoA)<$PolymerSize-1);
#change to
} while((keys %HoA)<=$PolymerSize-1);