无法读取,3183 3001字节
在圣诞节庆祝活动之间不停地进行工作,这是一个有趣的挑战。感谢您的发表!打高尔夫球很有趣,因为规范中充满了例外情况和特殊情况,这需要很多if条件。另外,虽然这次我不需要转换为十进制,但确实需要排序的“ max”函数来确定每个数字中的最大位数和每个位置中的最大值。
它的第一个版本是4844字节,只是让您了解我打了多少高尔夫球。
程序期望输入为逗号分隔的整数列表。没有空格或换行符。使用这些将产生不确定的行为。
'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“” “”“”“'”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“” '“”“”“'”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“'”“”“”“”“”“”“”“”“”“”“” '“”“'”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “'”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”““”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “'”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“ “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“'”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“ “'”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“” '“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “'”“'”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“ “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“” “'”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“ '“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“'”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“ “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “'”“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“'”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“ “”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”'“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“'”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”
说明
我将通过向您展示它如何处理特定输入来向您介绍该程序的工作方式202,100,1
。
首先,我们构造一些稍后将需要的值-主要是我们将输出的字符的ASCII码。
如您所见,'8'
并且'.'
已经可用。'|'
,但实际上是124,而不是14。我们使用while循环在插槽#1上将临时值加倍,以获得124(即14 + 55×2,因为while循环运行56−1 = 55迭代)。这样可以节省一些字节,因为像124这样的大整数文字确实很长。在下图中,我显示了程序使用的每个变量的位置。
接下来,我们要输入所有字符并将它们存储在从单元格#12开始的磁带上(p是为此的运行指针)。同时,我们想知道最长的数字有多长时间(几位数)。为了实现这一点,我们在单元格#-1(我们将q用作运行指针)的左侧保持一元运行总和。在第一个输入数字()之后,磁带现在如下所示:202
您会注意到数字以4偏移。嗯,当我们第一次输入它们时,它们是它们的ASCII值,因此它们以48偏移“ off”,逗号是44。对于每个字符,我们从中复制46 '.'
放入r,然后用while循环将其减去(减去45),然后加1。这样做是为了使逗号(我们的分隔符)为0,因此我们可以使用条件语句来识别它。
此外,您还将注意到我们将单元格11保留为0。我们需要使用该值来识别第一个数字的边界。
下一个字符将是逗号,因此我们在#15中存储一个0,但是当然这次我们不前进q。相反,我们将q设置回0并开始“覆盖”已经放置的1。
处理完所有其余字符后,我们得到以下信息:
如您所见,q所写的1 现在(一元)表示最长数字的长度。
现在,我们使用while循环将q移动到最左边,然后在此处放置另一个指针,我将其称为r2。r2的目的将在稍后阐明。
在这一点上,让我阐明在整个过程中将使用的术语。
- 通过 号码,我的意思是用逗号隔开输入数字中的一个。在我们的示例中,它们是202、100和1。
- 通过 数字表示,是指其中一个数字中的一个数字。第一个数字有3位数字。
- 通过 位置,我是指一个位置,十个位置,数百个位置,等等。因此,如果我说“当前位置的数字”,而当前位置是一个位置,则这些数字分别是2、0和1订购。
现在回到我们的常规编程。程序的其余部分是一个大循环,向前移动q直到到达单元格#0。沿途的每个单元格代表一个位置,这些位置在最右边。 q将从最高有效位开始。在我们的示例中,就是数百个地方。
我们通过增加单元格q点(即* q)继续进行。
我们现在已进入数百个“阶段2”。在这个阶段,我们将找出数百位所有数字中最大的数字。为此,我们使用相同的一元计数技巧,除了这次的指针称为r和指针 r2标记为起始位置,每次我们移至下一个数字时都需要将其重置为该位置。
让我们从第一个数字开始。我们首先将p设置为11(所有数字的硬编码开始位置)。然后,我们使用while循环查找数字的结尾,然后在此处设置p2来标记位置。同时,我们还将q2设置为0:
不要因为以下事实而分心: q2指向变量。我们在那里没有空白单元格的填充,因为我们可以仅因为它的数字为零而检测到单元格#0。
接下来,我们通过将p和q2递减直到* p为零来遍历当前数。在每个地方,* q2的值都告诉我们我们需要做什么。1表示“什么都不做”,因此我们继续前进。最终,我们在单元格#-3中遇到了2。每当* q2不等于1时,q2总是等于q。
正如我已经说过的,第二阶段是“确定这个地方的最大位数”。因此,我们将r设置为r2,使用while循环将* p递减并向左移动r并用1s填充磁带,然后使用另一个while循环将r移回右侧并再次增加* p来恢复值。请记住,每个while循环的迭代次数都比我们使用它的值少;因此,写入的1的数量将比数字值多3(而不是4),并且存储回* p的最终值将多2。因此,这实际上将* p减少了2。
之后,将p设置为p2的值,然后再次执行所有操作。第二次将q2设置为0,通过将p向右移动找到数字的结尾,然后通过将p和q2减一来遍历此数字的数字。再一次,我们将在单元格#-3中遇到2,并在* r的左边写上1 。
在第三个数字的情况下,我们最终什么也不做,因为它没有上百个位(因此q2永远不会达到q),但这没关系,因为这不会影响最大数字值的计算。
我们还设置了单元格*(r − 4)为1(即使它已经为1),该我在这里用未标记的箭头标记。我不会告诉你为什么,但是也许你已经猜到了?
* q的下一个增量将使我们进入阶段3,即“从当前位置的所有数字中减去最大数字”。和以前一样,我们将p重置为11,将q2重置为0,然后像上一阶段一样遍历所有数字;除了这次,* q = 3而不是2。每次q2遇到q并且p在数百个地方时,我们使用while循环将* p递减与* r2左边的块中有1s的次数相同(5在我们的示例中)使用r作为运行指针。我们实际上将其递减一遍,以使最大数位以−2结束,原因稍后将变得清楚:
处理完所有数字后,我们现在进入第3阶段的结尾。在这里,我们执行两个奇异的事情。
- 首先,我们还从* q中减去r块(加1)的大小,但使用r2指针,将其留在左侧。* q通过这种方式变为负数。在我们的情况下,r -block有五个1,因此* q变为-3。
- 其次,我们设置一个变量了一个非零值,表明我们现在进入的输出级。(从技术上讲,* q为负这一事实已经表明了输出阶段,但这很难检查,因此需要额外的变量。)
您现在已经了解到,我们不断浏览数字,找到每个数字中的当前位置(由* q的非1值表示),然后根据* q的值进行操作。我们看到* q首先增加到2(=计算最大数字值),然后增加3(从该位置的每个数字减去最大数字值),然后减去它以使其为负数。从那里开始,它将继续上升直到达到1,从而恢复表示“不执行任何操作”的值。在这一点上,我们继续下一步。
现在,当* q为负时,我们正在输出。* q恰好是正确的值,因此我们将在达到1之前输出正确的字符行数;如果最大位数为2,则需要输出3行。让我们看看* q的每个值会发生什么:
- * q = −2:
- 对于第一个数字,* p为-2,这表示我们需要输出
'.'
(点)或':'
(冒号)。我们通过查看q来确定哪一个:如果它是-1,那么我们在那个地方,所以输出a ':'
(我们将其计算为'8'
+2),否则输出a '.'
。
- 对于第二个数字,* p为-3。任何不为-2的值都表示我们输出
'|'
(管道),然后增加该值。这样,它将在正确的位置达到−2,然后输出该数字其余部分的'.'
s / ':'
s。
- 在每种情况下,在处理数字之前,我们还将变量pd设置为0 ,并将pd(=“ printed”)设置为非零值以表明我们已经打印了字符。
- 对于第三个数字,因为第三个数字没有百位,所以不会进行任何处理。在这种情况下,处理完数字后pd仍为0,表示我们仍需要输出a
'|'
(但仅当out为非零时,否则,我们仍处于阶段2或3)。
- 处理完所有数字后,如果out不为零,则输出换行符。请注意,我们需要out变量,以便在阶段2或3中不输出换行符。
- * q = -1:与以前相同,不同之处在于前两个数字的 * p均为-2,因此两者都输出a
'.'
(第三个数字'|'
与以前一样输出a)。
- * q = 0:当 * q为0时,这意味着“如果我们在那个位置,则什么也不做,否则
'|'
不管 * p都输出一行s”。这样,我们得到了数字之间的填充。
现在我们将q递增以移至下一个位置(十位数),然后在此处递增* q。在阶段2的开始,磁带如下所示:
然后,我们像以前一样执行阶段2。请记住,这实际上是从该位置的每个数字减去2,并且还剩下* r2的一进制数表示最大数字。我们不理会先前的一元数,而只是将磁带向左延伸;这样只会花费不必要的额外代码来“清理”。完成后,我们增加* q,在第3阶段开始时,磁带现在为:
实际上,这是一个谎言。还记得以前我说过将*(r − 4)设置为1的情况,但我没有告诉你为什么吗?现在,我告诉你为什么。适用于这种情况,其中最大的数字实际上为0,这意味着该位置的所有数字均为0。将上面未标记箭头指示的*(r-4)设置为1,将一进制数扩展为1,但仅在这种特殊情况下。这样,我们假装好像最大的数字是1,这意味着我们将多输出一行。
在阶段3(从当前位置的所有数字中减去最大数字)之后,包括使* q变为负数的额外步骤,磁带看起来像这样。上一次,最大的数字在* p块中用-2表示,但是这次它们都是-3,因为它们实际上都是零,但是我们假装好像最大数字是1。
现在,让我们看看* q朝1前进时会发生什么:
- 当* q = -1时,* p值均为-3,这意味着我们输出
'|'
s并将其递增。
- 当* q = 0时,我们输出,
'|'
因为这是* q = 0 时我们始终执行的操作,而与* p无关。
这样,我们得到了两排管道。
最后,我们将* q移到自己的位置。这一点很有趣,因为':'
如果实际数字不是1,那么我们需要输出s,但是'8'
如果它是1,则需要输出s 。让我们看看程序如何进行。首先,我们增加* q以启动阶段2:
在第2阶段(“计算最大位数”)之后,剩下的是:
在阶段3(“从当前位置的所有数字中减去最大数字值”)之后,磁带如下所示:
现在让我们依次遍历* q的每个迭代:
- * q = −2:
- 第一个数字:已经在-2处,因此输出a
':'
(而不是a,'.'
因为q = -1)。
- 第二个数字:-4,所以输出a
'|'
和增量。
- 第三个数字:-3,所以输出一个
'|'
。但是,这一次,不是增加,而是触发了一种特殊情况。仅当我们输出最后一个位置(q = -1),并且位于该位置的倒数第二行(* q = −2),并且数字实际上为1时(* p = −3) ,然后将其设置为-1 ,而不是将其增加到-2。换句话说,我们使用-1作为特殊值来表示在下一次迭代中,我们需要输出'8'
而不是':'
。
- * q = -1:
- 第一个数字:已经在-2处,因此输出一个
':'
。
- 第二个数字:-3,所以输出a
'|'
。特殊条件不会触发,因为* q不再为-2。因此,增加。
- 第三个数字:-1,所以输出
'8'
。
- * q = 0:通常,我们将在
'|'
这里输出s的填充行,但是在特殊情况下,我们位于那个位置( q = -1),则跳过该行。
此后,q递增到0,大while循环结束。
现在您知道了类似的输入是如何202,100,1
工作的。但是,还有一种特殊情况我们还没有涉及。您可能还记得,当我们处理最后一个位时,当* p为-3时,我们将其设置为-1 1
(而不是将其递增为-2),以便下一次迭代将输出一个'8'
。这仅起作用,因为我们进行了一次迭代,其中* p为-3,并且我们决定是否将其递增或将其设置为-1。我们不会有这样的迭代,如果所有的在个位数字是0或1。在这种情况下所有的* P为1秒将值开出为-2; 没有机会决定将其设置为-1而不是将其从-3增加。因此,第3阶段存在另一个特殊情况(“从当前位置的每个数字中减去最大数字”)。我声称从每个数字中减去最大数字值之后(此时最大数字为-1),我们只是将其再次递减,但是实际上存在一个条件,该条件如下:
如果我们要查看的位数等于该位置的最大位数(* p = -1),并且此位置是一个位数(q = -1),并且最大位数为1(*(r + 5) = 0,即一元块在很左边是只有5个细胞长),才把我们离开* p在-1,以指示只有输出必须输出一个迭代'8'
。在所有其他情况下,我们将其再次递减。
做完了 新年快乐!
编辑1(3183→3001):新年快乐打高尔夫球!我设法完全摆脱了变量p2和r2!p现在来回奔波以不断寻找数字的开头和结尾,但是在代码中似乎更短了。我也尝试摆脱q2,但是我无法以这种方式使代码更短。
我还发现了一些其他可以应用典型的不可读高尔夫技巧的地方,例如重新使用while循环的最后一个值。给你一个例子,而不是
while *(++p) { 1 } // just increment p until *p is 0; the 1 is a noop
if (pd) { x } else { y } // where pd is a variable
我可以通过以下方式保存'""""
(先执行第一个,然后执行第二个)和'"""
(常量1)
if (while *(++p) { pd }) { x } else { y }
当然,这仅在我知道while循环将至少运行一次迭代的情况下才有效,但是如果这样做,则其返回值为pd,因此我可以将其用作if的条件。