计算Quipu:新世界的十大基础


41

Quipus是一种古老的装置,在前哥伦布时期被印加人用来在绳子上以10为底的打结位置系统中记录数字,其工作方式如下:

每个结簇都是一个数字,并且有三种主要类型的结:简单的过头结;“长结”,由一个或多个附加转弯的手结组成;和八字形结。

  • 沿线的位置显示10的幂,并且此位置在连续的线束之间对齐。
  • 10个或更高功率的位置上的数字由简单结簇表示(例如,在“十”位位置,连续40个结是四个简单结)。
  • 处于“一个”位置的数字由长结表示(例如,4是四圈结)。由于打结的方式不同,无法以这种方式显示数字1,而在此位置用八字形数字表示。
  • 零表示在适当位置没有结。

细节

对于这个挑战,Quipu的每个链都代表一个数字(不过,如Wikipedia文章所述,您可以在一个链上代表多个数字,在这个挑战中,我们不能)。

每个结将由单个ASCII字符表示。

  • . 代表一个简单的结
  • : 代表一个长结的转一圈
  • 8 代表八字形结
  • | 表示数字之间没有结以及定界符。

构建Quipus

遵循以下规则构造Quipu。

  1. 股线以位置降序从上到下排列(例如,单位数字将位于股线的底端)。链上的数字由字符(|)分隔。
  2. 数字代表的10的幂由它在链上的位置决定,其方式与使用数字系统中的数字索引来计算数字的10的幂相同。也就是说,24a 2处于十位,a 4处于单位位,将由两个结表示,一个定界符(|),然后是四个结。
  3. 处于相同位置的数字朝着链的底部对齐。如果某个位置的一位数字的结数少于同一位置上其他数字的其他数位,则这些结点的不存在用(|)表示。
  4. 连续的简单结(.)代表其位置的值。
  5. 每个数字至少由1个字符表示。当quipu中所有数字的数字值均为0时,表示不存在结(|)。
  6. 单位所处地方特殊对待。单位位置的一个由八字形结(8)表示。单位位置中的两个或多个值由连续的长节(:)表示。
  7. 当Quipo中所有数字的单位数字均为0时,不打印结点,但保留十位数的结尾定界符。
  8. 单位数字后没有定界符。

规则

  • 输入将包含可通过任何默认输入方法接收的非负整数的非空列表。您可以假设这些整数均小于或等于21474836472^31-1。尽管测试用例是用空格分隔的,但是您的输入格式可以以任何方便您的语言的方式来分隔输入,无论是逗号分隔,换行分隔,数组分隔等等。
  • 输出由根据上述规则构造的单个Quipu组成。可以通过任何默认输出方法给出输出
  • 您的代码应该是程序或函数,尽管它不必是命名函数。
  • 打结需要花费一些时间,以节省时间,使您的代码越短越好。

与往常一样,如果问题仍然不清楚,请告诉我。祝你好运,打高尔夫球!

例子

输入:

5 3 1 0

输出:

:|||
:|||
::||
::||
::8|

输入:

50 30 10 0

输出:

.|||
.|||
..||
..||
...|
||||

输入:

330

输出:

.
.
.
|
.
.
.
|

输入:

204 1

输出:

.|
.|
||
||
||
:|
:|
:|
:8

输入:

201 0 100 222

输出:

.||.
.|..
||||
|||.
|||.
||||
|||:
8||:

输入:

1073741823 2147483647

输出:

|.
..
||
|.
||
.|
.|
.|
..
..
..
..
||
|.
|.
|.
|.
..
..
..
||
.|
.|
.|
..
..
..
..
||
|.
|.
|.
|.
..
..
..
..
||
|.
|.
..
||
.|
.|
..
..
..
..
..
..
||
|.
|.
..
..
||
|:
|:
|:
|:
::
::
::

输入:

0

输出:

|

更长的测试用例

进一步阅读


Answers:


3

Pyth,64个字节

=QjRTQjCmj\|+:R"[8:]"\.PdedCmm+*\|-h.MZdk*?tk\:\8kdC.[L0h.MZlMQQ

在线尝试!

这个怎么运作

=QjRTQ   Converts each number in input to decimal (as a list)
         123 becomes [1,2,3]

----

jCmj\|+:R"[8:]"\.PdedCmm+*\|-h.MZdk*?tk\:\8kdC.[L0h.MZlMQQ

                                              .[L0       Q  0-leftpad each #
                                                  h.MZlMQ   (max length) times

                                             C              transpose

                      mm                    d    for each digit:
                        +                        [convert to] sum of
                         *\|                     "|" repeated
                            -                    the difference of
                             h.MZd               maximum digit in same row
                                  k              and itself.. that many times
                                   *?tk\:\8      and (digit > 1 then ":" or "8") repeated
                                           k     itself many times


the list:
[11,23,52]
->[[1,1],[2,3],[5,2]]
->[[1,2,5],[1,3,2]]
->[["||||8","|||::",":::::"],["||8",":::","|::"]]

                     C      transpose

->[["||||8","||8"],["|||::",":::"],[":::::","|::"]]

  m                          for each number
      +                      [convert to] sum of
                 Pd          every element but the last
       :R"[8:]"\.            with "8" and ":" replaced by "."
                   ed        and the last element
   j\|                       joined with "|"

  C                          transpose
 j                           join (with newlines)

除了一个问题,这是一个很好的答案。最后的结并不总是八字形结8。实际上,8当最后一位数字为1时,这只是个结(请参见规则6)。您正在转换所有最终的结,但与规范不符。另外,您可以在线试用!链接具有与此处发布的代码不同的代码,显然
Sherlock9'9

22

无法读取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移动到最左边,然后在此处放置另一个指针,我将其称为r2r2的目的将在稍后阐明。

在此处输入图片说明

在这一点上,让我阐明在整个过程中将使用的术语。

  • 通过 号码,我的意思是用逗号隔开输入数字中的一个。在我们的示例中,它们是202、100和1。
  • 通过 数字表示,是指其中一个数字中的一个数字。第一个数字有3位数字。
  • 通过 位置,我是指一个位置,十个位置,数百个位置,等等。因此,如果我说“当前位置的数字”,而当前位置是一个位置,则这些数字分别是2、0和1订购。

现在回到我们的常规编程。程序的其余部分是一个大循环,向前移动q直到到达单元格#0。沿途的每个单元格代表一个位置,这些位置在最右边。 q将从最高有效位开始。在我们的示例中,就是数百个地方。

我们通过增加单元格q点(即* q)继续进行。

在此处输入图片说明

我们现在已进入数百个“阶段2”。在这个阶段,我们将找出数百位所有数字中最大的数字。为此,我们使用相同的一元计数技巧,除了这次的指针称为r和指针 r2标记为起始位置,每次我们移至下一个数字时都需要将其重置为该位置。

让我们从第一个数字开始。我们首先将p设置为11(所有数字的硬编码开始位置)。然后,我们使用while循环查找数字的结尾,然后在此处设置p2来标记位置。同时,我们还将q2设置为0:

在此处输入图片说明

不要因为以下事实而分心: q2指向变量。我们在那里没有空白单元格的填充,因为我们可以仅因为它的数字为零而检测到单元格#0。

接下来,我们通过将pq2递减直到* 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向右移动找到数字的结尾,然后通过将pq2减一来遍历此数字的数字。再一次,我们将在单元格#-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):新年快乐打高尔夫球!我设法完全摆脱了变量p2r2p现在来回奔波以不断寻找数字的开头和结尾,但是在代码中似乎更短了。我也尝试摆脱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的条件。


“不可读”无疑是一个恰当的名字……
Alex A.

9
-1没有足够的解释
戴帽子的家伙

7

使用Javascript(ES6)750 744 690 604 498 346个 245 234字节

我是PPCG的新手,以为我可以尝试一下它,因为它很简单。男孩我错了!我已经做了一段时间了,而且我还有很多打高尔夫球的事情……
建议得到鼓励!-尽管要理解这一点并非易事。

当输入是数字数组时输出绳索(例如:)[204, 1]

a=>(o=m=s="",l=a.map(n=>(s+="|",l=(n+"").length)>m?m=l:l),h=[],a=a.map((n,i)=>[..."0".repeat(m-l[i])+n].map((d,j)=>d<h[j]?d:h[j]=d)),h.map((n,i)=>{i?o+=s+`
`:0;for(j=n;j--;o+=`
`)a.map(d=>o+="|.:8"[d[i]-j<1?0:i<m-1?1:d[i]-1?2:3])}),o)

说明

a=>(

  o=m=s="",                      // m = max number of digits in a number, s = separator string         
  l=a.map(n=>(                   // l = lengths of each number
      s+="|",                    // set the separator string
      l=(n+"").length                 // convert each number to a string
    )>m?m=l:l                    // get max length
  ),
  h=[],
  a=a.map((n,i)=>
    [..."0".repeat(m-l[i])+n]    // add leading 0s to make all same length
    .map((d,j)=>d<h[j]?d:h[j]=d) // set each digit of h to max
  ),

  h.map((n,i)=>{
    i?o+=s+`
`:0;
    for(j=n;j--;o+=`
`)
      a.map(d=>
        o+=
          "|.:8"[
            d[i]-j<1?0
            :i<m-1?1
            :d[i]-1?2:
            3
          ]
      )
  }),
  o
)

输入:数字数组:[4,8,15,16,23,42]
输出:

|||||.
|||||.
||||..
||....
||||||
|:||||
|:||||
|:|:||
|:::||
::::||
:::::|
::::::
::::::

+1令人印象深刻的高尔夫。您将在输入和输出中包括一个示例吗?
DavidC

@DavidC谢谢!并包括示例。从控制台调用它,它返回一个字符串。:)
Aᴄʜᴇʀᴏɴғᴀɪʟ

7

Python 3 624 598 595 574 561 535 532 527 525 426 345 328 324 294 288 286 283 280 280 267 265 255 251 245 238 235 234 234 230 228字节

z=input().split();v=max(map(len,z));d=''.join(i.zfill(v)for i in z);x=['']*len(z)
for k,c in enumerate(d):j=k%v;m=int(max(d[j::v]));c=int(c);x[k//v]+="|"*(m-c+0**m+(j>0))+":8."[(c<2)|-(j<v-1)]*c
for r in zip(*x):print(*r,sep='')

好的,因为这个问题需要答案,所以我在这里提供了一个答案,其中输入应该是用空格分隔的数字字符串,例如"204 1"。男孩,是一个长的。欢迎任何打高尔夫球的建议(或更好的答案)。

编辑:通过混合制表符和空格保存的字节。

编辑:通过更改获取数字的位数的方式,我节省了很多字节(从该数字的零填充字符串中创建一个列表,然后在代码正文中进行转置以获取数百位,十位,等等。 )

编辑:通过将最后一个:8循环合并到主quipu循环中,我还保存了一些内容。现在,只要我能弄清楚为什么b=d[j*v+i]==m(d[i::v])不起作用。弄清楚了,解决方案占用了太多字节。(字节数也减少了,因为标签以某种方式又变成了四个空格。这可能是该站点上的代码块格式)

编辑:我重新组织了如何制作quipus。现在,它一次创建一根线,然后转置进行打印。

编辑:将我的答案转回Python 3程序以节省更多字节。

编辑:我在我的代码中发现一个错误,使其无法正确在数字中间打印零(请参见204 1上面的测试用例)。在解决这个问题时,我设法打高尔夫球了:)

编辑:我更改了打印以节省10个字节。我把所有旧字节数都归还了,仅仅是因为。

编辑:打高尔夫球的v使用分配map为四个字节。感谢CarpetPython,因为我得到了他们的答案的想法在这里

编辑:将中间的“ for循环内的for循环”,变成一个for循环的六个字节。

编辑:现在使用enumerate。不再使用l=len(z)。将三元数if-else转换为列表三元数。有关详情,请参见下文。

编辑: Sp3000建议print对三元条件进行编辑,并对三元条件进行编辑,每个条件都保存一个字节。

取消高尔夫:

s = input()
z = s.split()
v = max(map(len, z))                # the amount of digits of the largest number
d = ''.join(i.zfill(v) for i in z)  # pad zeroes until every number is the same length
                                     # then join the numbers into one string
x = ['']*len(z)                     # a list of strings for the output, one for each number

for k,c in enumerate(d):          # for every digit in every number
    i,j = divmod(k, v)            # i is the index of the number we're on
                                   # j is the index of the digit of the number we're on
    m = int(max(d[j::v]))         # the largest of all the digits in the j-th place
    c = int(c)                    # the digit in j-th place of the i-th number
    x[i] += "|"*(m-c+0**m+(j>0))  # pad | to size m-c, until the knots are correctly spaced
                                  # add a | if m<1, all j-th place digits are 0
                                  # add a | if j>0, if it's not at the start, as delimiters
    x[i] += ":8."[(c<2)|-(j<v-1)] * c
    # this is essentially the following code
    # if j<v-1:
    #     x[i] += "."*c      # . knots if not in the units place
    # else:
    #     if c == 1:
    #         x[i] += "8"*c  # 8 knots for ones in the units place
    #     else:
    #         x[i] += ":"*c  # : knots for something else is in the units place

for r in zip(*x):       # transpose so all the rows (the quipu strings) now hang down
    print(*r, sep='')    # join the strings together at each knot
                         # and print each on a separate line

这里有特定于Python 3的东西吗?如果不是这样,将其转换为Python 2可以节省很多字节
Cyoce

@Cyoce也不是Python 3特有的。我刚开始使用Python 3,因为那是我的版本。我将在ideone上测试Python 2版本。
Sherlock15年

@Maltysen不适用于以开头的输入0,例如0 12 4
Sherlock15年

您可以通过在制表符2中交替使用制表符和空格来节省一些字节,我相信1个制表符== 8个空格,这
取决于

for r in zip(*x):print(''.join(r))->print(''.join(r)for r in zip(*x))
Leaky Nun

4

C,238235字节

严重依赖C预处理程序以使代码尽可能短。作为副作用,这也使它几乎不可读。

#define l strlen(a[i])
#define d l<k||a[i][l-k]-48
#define m(e) for(i=1;a[i];e<=r?i++:r++);
#define p(e) {m(!putchar(e?'|':k>1?46:d<2?56:58))puts("");}
k,r;main(int i,char**a){m(l)for(k=r,r=1;k;r=k>1){m(d)for(;r;r--)p(d<r)if(--k)p(1)}}

在Ubuntu 14.04上,您可以直接编译代码gcc quipu.c(请忽略警告)。运行可执行文件的示例:

$ ./a.out 1 2 3 2 1
||:||
|:::|
8:::8

针对所有OP的测试用例进行了测试。

非源代码:

// Standard library; leaving out the includes still gives executable code despite the warnings.
#include <stdio.h>
#include <string.h>

// 4 preprocessor macros.
// Note: some of these actually make use of the fact that parentheses have been left out

// l: length of argument i
#define l     strlen(a[i])

// d: shorthand for a digit
#define d     l<k || a[i][l-k]-'0'

// m: loop across all arguments; calculates r as the maximum of expression e
#define m(e)  for (i=1; a[i]; e<=r ? i++ : r++);

// p: prints one line of output
// note: intentionally does not use the r++ code branch of m;
//       putchar always returns a non-zero number here, so !putchar is zero,
//       which is always <=r (because r is never negative)
// note: the semicolon after m(...) is redundant;
//       the definition of m already contains a semicolon
// note: puts("") outputs a newline
#define p(e)  { m(!putchar(e ? '|' : k > 1 ? '.' : d < 2 ? '8' : ':')); puts(""); }

// k: knot position; 1 for units, 2 for tens, 3 for hundreds...
int k;

// r: input and output value for m
// note: the first time we call m, we need r to be zero;
//       by defining it outside main, it is automatically initialized as such
int r;

// function main
// note: parameter i (normally named argc by convention) is not needed
//       (the last element of argv is known; it is followed by a NULL pointer)
//       but we cannot leave it out (otherwise we cannot access argv)
//       so it serves as a local variable (to loop through arguments; see m)
// note: parameter a (normally named argv by convention)
//       is the array of arguments (starting from index 1)
int main(int i, char **a)
{
    // Determine the longest argument; store its length in r.
    // This is the number of knot positions to consider.
    m(l)

    // Iterate k through the knot positions from top to bottom.
    // Note: k > 0 has been abbreviated to k.
    // Note: for each iteration, we also initialize r with either 0 or 1.
    //       0 = suppress printing when all knots are zero
    //       1 = always print, even when all knots are zero
    for (k = r, r = 1; k > 0; r = k > 1)
    {
        // Determine the highest digit at this knot position.
        // Note: due to the absence of parentheses, d mixes up with <=r into:
        // (l < k) || (a[i][l-k]-'0' <= r)
        m(d)

        // Count the digits down.
        for (; r; r--)
        {
            // Print a single line of output.
            // When d (the digit in the current strand) is less than the counter,
            // then print a '|', otherwise print a knot.
            p(d < r)
        }

        // Decrement k (go to next knot position).
        // If this was not the last iteration...
        if (--k > 0)
        {
            // Print separator line.
            p(1)
        }
    }

    // Return exit code zero; redundant.
    return 0;
}

恭喜你!作为赏金期限内发布的最短答案,您已收到我的+50 rep赏金。好答案!:)
Alex A.

4

Mathematica 436453357352347字节

t=Transpose;y=ConstantArray;a=Table;
g@j_:=(s=t[PadLeft[#,Max[Length/@i]]&/@(i=IntegerDigits@#)]&;p_~u~o_:=(m=Max@p;c=If[o==-2,":","."];w=If[o==-2,"8","."];p//.{0->a["|",Max@{1,m}],1->Join[a["|",{m-1}],{w}],n_/;MemberQ[2~Range~9,n]:>Join[y["|",m-n ],c~y~n]});t[Join@@@t@Join[u[#,0]&/@Most@#,u[#,-2]&/@{#[[-1]]}]]&[Riffle[(s@j),{a[0,Length@j]}]]//Grid)

以上

  • 使用IntegerDigits; 将每个整数分解为数字列表。在每个数字的左边填充零(以确保间隔相等);现在分解为数字的每个输入数字对应于数组的一行;每列代表一个位置值。数组已转置。
  • 用带填充的结列表替换数字。单元使用的模式匹配例程略有不同。

g[Range[0, 50]]

五十


Transpose@Join?应该这样吧?
CalculatorFeline

是。感谢您抓住这一点。
DavidC

在此之前的空间。
CalculatorFeline

1

的R - 446 444

我看到还没有R解决方案,所以这里是一个。该函数采用带有整数的向量。

function(x){r=nchar(max(x));c=length(x);m=matrix(0,r,c);for(i in 1:c){t=as.numeric(strsplit(as.character(x[i]),"")[[1]]);m[(r+1-length(t)):r,i]=t};Q=c();for(i in 1:r){d=m[i,];z=ifelse(max(d)>0,max(d),1);q=matrix("|",z,c);for(j in 1:c){v=m[i,j];if(i==r){if(v==1)q[z,j]=8;if(v>1)q[(z-v+1):z,j]=rep(":",v)};if(i<r){if(v>0)q[(z-v+1):z,j]=rep(".",v)}};if(i!=1&sum(d)>0)q=rbind(rep("|",c),q);Q=rbind(Q,q)};for(i in 1:nrow(Q))cat(Q[i,],sep="",fill=T)}

不打高尔夫球

# Some test data
test <- c(201, 0, 100, 222, 53)

# Define function
quipu <- function (x) {

    # Create matrix with a row for each digit and a column for each number
    r=nchar(max(x));c=length(x);m <- matrix(0,r,c)
    for(i in 1:c) {
        t=as.numeric(strsplit(as.character(x[i]),"")[[1]])
        m[(r+1-length(t)):r,i]=t
    }

    # Loop through each row (digit) starting at the top of the quipu
    Q=c() # Empty matrix to store quipu 
    for(i in 1:r){

        d=m[i,]
        z=ifelse(max(d)>0,max(d),1)
        q=matrix("|",z,c)

        # Loop through each column (number in the vector) starting at the leftmost quipu
        for(j in 1:c){

            # The digit
            v=m[i,j]

            # If it is the last segment of the quipu
            if(i==r){
                if(v==1){q[z,j]=8} # If unit digit =1
                if(v>1){q[(z-v+1):z,j]=rep(":",v)} # If unit digit >1               
            }

            # If it is not the last segment of the quipu
            if(i<r){
                if(v>0){q[(z-v+1):z,j]=rep(".",v)} # If non-unit digit >0   
            }
        }

        # Add segment to Q
        if(i!=1 & sum(d)>0){q=rbind(rep("|",c),q)}
        Q=rbind(Q,q)    
    }

    # Print quipu
    for(i in 1:nrow(Q)) {cat(Q[i,], sep="", fill=T)}
}

# Test
quipu(test)

if(v>0)您的if(i<r)子句中需要吗?R是否接受类似z+1:zwhen 的范围v==0q[z+1:z,j]我想,如果是这样的话根本不会受到影响。另外,R是否有else关键字和某种else if关键字?如果是这样,您将可以打高尔夫球其中一些条件。
Sherlock9年

if(v>0)是必需的,因为如果v=0,索引将超出范围(即,尝试获取第nrow + 1行)。R确实有else,我实际上尝试了您的建议并else在可能的情况下使用了它,但结果却是相同的字节数。
慢懒猴
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.