从前一“行”获取值二维 C 数组
我正在开发 1D 生命游戏(基于 Mathworld 中规定的规则) 。本质上,每一代都表示为一行 0 或 1(死的或活的),下一代是基于“规则”命令行参数的二进制表示创建的。
例如,规则 30 变成 00011110(二进制 30),这用于确定哪些位模式将产生新细胞或在下一代中自行死亡。
为了对此进行编程,我需要能够访问前一行中三个一组的位(以应用规则)。下面是一个示例图像(请注意,起始行始终是 0,中间有一个 1):
00000100000 #seed row
11001011001 #generated from seed row
...........
11110010101 #n-th row, generated from n-1 row
为了生成一行,我必须以三组为一组查看上面行中的位,然后将规则应用为 1/ 0,生/死的决定。
基本上,我计划匹配 3 位模式和规则,并使用它为后代打印 0 或 1。这是一般算法:
if three_bit_pattern == 'xxx' && rule[x] == 0/1 {print 0/1} else {print 1/0}
程序中我遇到困难的部分是访问前一行的内容。我所有的尝试都会产生垃圾或不正确的数据。
简而言之,我如何以三位为一组访问前一行的值?
行是这样创建的:
int i, j, k;
int row = atoi(argv[1]) + 1;
int col = 2 * atoi(argv[1]) + 1;
int arr[col];
int output[col];
char rule[9]; //binary representation of rule (2^8 stores up to 255 + null term)
int2binary(atoi(argv[2]), &rule, 10);
for(i = 0; i < row; i++){
for(j = 0; j < col; j++){
if(i == 0){
if(j == col / 2) //print 1 in center of first row
arr[i] = 1;
else
arr[i] = 0;
printf("%d", arr[i]);
}
else{
//output[i] = arr[i-1];
output[i+1] = arr[i];
output[i+2] = arr[i+1];
output[i+3] = arr[i+2];
printf("%s", output);
}
}//end inner for_loop
printf("\n");
}//end outer for_loop
}
好吧,我让这变得更加简单,并且只有两个数组(一个保存前一列,一个保存当前列)。我不明白的是为什么打印输出数组会产生垃圾? output[i] = arr[i] 不是一个有效的表达式吗?
I'm working on a 1D Game of Life (based upon the rules set out here at Mathworld). Essentially, each generation is represented as a row of 0's or 1's (dead or alive) and the next generation is created based upon the binary representation of a "rule" command line argument.
For example, rule 30 turns into 00011110 (binary for 30) and this is used to determine which patterns of bits will spawn new cells or die off themselves in the subsequent generation.
In order to program this, I need to be able to access bits in groups of three (to apply a rule to) from the previous row. Below is a sample image (note that the starting row is always 0's with a central 1):
00000100000 #seed row
11001011001 #generated from seed row
...........
11110010101 #n-th row, generated from n-1 row
In order to generate a row, I must look at the bits from the row above in groups of three and then apply the rule as a 1/0, live/die decision.
Basically I plan to match the 3 bit pattern and the rule and use that to print either a 0 or a 1 for the offspring. this is the general algo:
if three_bit_pattern == 'xxx' && rule[x] == 0/1 {print 0/1} else {print 1/0}
The portion of the program where I am having difficulties is in accessing the contents of the previous row. All my attempts yield garbage or incorrect data.
In short, how would I access the previous row's values in groups of three bits?
The rows are created like this:
int i, j, k;
int row = atoi(argv[1]) + 1;
int col = 2 * atoi(argv[1]) + 1;
int arr[col];
int output[col];
char rule[9]; //binary representation of rule (2^8 stores up to 255 + null term)
int2binary(atoi(argv[2]), &rule, 10);
for(i = 0; i < row; i++){
for(j = 0; j < col; j++){
if(i == 0){
if(j == col / 2) //print 1 in center of first row
arr[i] = 1;
else
arr[i] = 0;
printf("%d", arr[i]);
}
else{
//output[i] = arr[i-1];
output[i+1] = arr[i];
output[i+2] = arr[i+1];
output[i+3] = arr[i+2];
printf("%s", output);
}
}//end inner for_loop
printf("\n");
}//end outer for_loop
}
Ok so I made this a whole lot simpler and am just going to have two arrays (one holding the previous column and one with the current). What I don't understand is why printing the output array produces garbage? Is output[i] = arr[i] not a valid expression?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您尚未指定输入或输出,这可能会影响要使用的数据结构。例如,如果在计算时打印出来,您可能只需要保留两行,甚至只需要保留一行。看起来您计划将所有行保留在一个数组中。
看起来您在第一行中有一个逻辑错误:
应该是
或更简单的东西。
生成其他行的算法并不复杂。
1) 使用上面行的元素构建一个从 0 到 7 的数字。
2)按位& 1<<(number from 1) with therule to get result
有一些明显的方法可以让这个更快。例如,根据前一列的父级和右上角的单元格构建此列的父级: &与 3,左移,|与细胞内容物。唯一难看的部分是分别处理第一列和最后一列。
编辑评论:
该算法在具有位运算的整数中具有一些自然的实现,这就是“规则 XX”想法的来源。
从本质上讲,当前空间的选择是由其上方的三个空间决定的。这些有 8 种可能性。我们可以将它们视为对应于一个字节的 8 位。
每个规则都是从 8 种可能性的集合到集合 {0,1} 的对应。有 2^8 = 256 种可能的对应关系或规则,这恰好与一个字节的可能值的数量相同。
标记规则的最方便的方法是使用一个数字,该数字准确显示当前单元格将如何填充(由父单元格确定)。例如,
规则 30:
30 = 16 + 8 + 4 + 2 = 2^4 + 2^3 + 2^2 + 2^1
因此,规则是当父单元格为:
又例如,什么是仅仅复制前一行的规则吗?
在这种情况下,如果上面的单元格被填充,我们就填充该单元格,但相邻的单元格可以是任何东西:
所以这是规则 2^2 + 2^3 + 2^6 + 2^7 = 规则 4 + 8 + 64 + 128 = 规则 204。
我希望确定单元格的算法现在更有意义。
1)确定父母的图案数量。
2) 确定 2^pattern 是否是规则的一部分。如果是这样,请填写该单元格。
我的另一个评论是你需要存储多少。如果直接输出,则只需要数组的一行(即只有一维)。当您遍历该行时,您可以将条目替换为下一行的值。唯一的困难是您需要以某种方式保留要替换的当前值,以便在确定下一个单元格时使用。
但是你可以使用相同的技巧保留这个值并减少计算量:保留最后一个父数字; &与 3 一起删除左父项;左移 1; |它的父级在右边。这将为您提供当前的家长号码。小心地适当处理数组的末尾条目,然后就完成了。
另一个编辑:
首先实现以前的版本,但如果您真的想疯狂地节省空间,并且更加扭曲您的想法,请尝试将行存储为整数的位值,而不是 1 和 0 的数组。如果您想要的行甚至比 long 中的位数还要长,那么您需要一个保存这些位的整数数组,以及一些疯狂的位操作来处理两个此类整数边界上的单元格。玩得开心!
You haven't specified the inputs or outputs, which might influence the data structures to use. For example, you might only have to keep two rows or even just one row if you print them out as you compute them. It looks like you plan to keep all the rows in an array.
It looks like you have a logic error in the initial row:
should probably be
or something even simpler.
The algorithm to generate the other rows is not that complicated.
1) build a number from 0 to 7 using the elements of the row above.
2) Bitwise & 1<<(number from 1) with the rule to get result
There are some obvious ways to make this quicker. E.g., build the parent for this column based on the parent of the previous column and the cell to the upper right: & with 3, shift left, | with cell contents. The only ugly part is handling the first and last columns separately.
EDIT IN RESPONSE TO A COMMENT:
The algorithm has some natural implementations in integers with bit operations, which is where the "rule XX" idea comes from.
At its heart, the choice for the current space is determined by the three spaces above it. There are 8 possibilities for these. We can think of these as corresponding to the 8 bits of a byte.
Each rule is a correspondence from the set of 8 possibilities to the set {0,1}. There are 2^8 = 256 possible correspondences or rules, which coincidentally is the same as the number of possible values for a byte.
The most convenient way to label the rules is with a number that shows exactly how the current cell is to be filled as determined by the parent cells. For example,
rule 30:
30 = 16 + 8 + 4 + 2 = 2^4 + 2^3 + 2^2 + 2^1
So the rule is to fill the cell when the parent cells are:
For another example, what is the rule that merely copies the previous row?
In this case we fill in the cell if the cell above is filled, but the neighbouring cells can be anything:
So this is rule 2^2 + 2^3 + 2^6 + 2^7 = rule 4 + 8 + 64 + 128 = rule 204.
I hope the algorithm to determine the cell makes more sense now.
1) determine the number of the pattern of the parents.
2) determine if 2^pattern is part of the rule. If so, fill in the cell.
The other comment I had was how much you need to store. If you output as you go, you only need one row of the array (that is, only one dimension). As you traverse the row, you can replace entries with values for the next row. The only difficulty is that you need to somehow keep the current value that you are replacing to use in determining the next cell.
But you can keep this value and reduce the amount of computation with the same trick: keep the last parent number; & it with 3 to remove the left parent; shift it left by 1; | it with the parent on the right. This gives you the current parent number. Be careful to handle the end entries of the array appropriately, and you're done.
ANOTHER EDIT:
Implement the previous version first, but if you really want to get crazy on saving space, and warp your mind even more, try storing the row as bit values of an integer instead of an array of 1s and 0s. If you want a row even longer than the number of bits in a long, then you need an array of integers holding the bits, and some crazy bit manipulation to handle cells on the boundary of two such integers. Have fun!