代码或AOC的出现是软件工程师中众所周知的事件。它每年进行,参与者每天从12月1日至12月25日解决一系列编程难题。这些难题可以用任何编程语言来解决,这使其成为各个级别开发人员练习技能并尝试新语言的绝佳机会。每天的难题基于上一个难题,为参与者创造了具有挑战性和凝聚力的体验。
今年,我们(在Researchable)举行了一场内部竞争,其中为那些使用COBOL完成难题的人提供了额外的积分。 COBOL或以业务为导向的通用语言是一种专为业务应用程序设计的高级编程语言。它是最早被广泛使用的编程语言之一,许多系统仍然依靠它。
但这不是全部。解决方案还以某些非常规语言(例如HTML和CSS)(是的,HTML和CSS,而不是JavaScript,而不是SCSS)以及COBOL提交了解决方案。在这篇博客文章中,我们将展示两个有趣的解决方案,以解决一些第一个AOC问题 - 一个在HTML和CSS中,另一个在COBOL中。
。作为未经验丰富的COBOL开发人员,我们只能完成COBOL中的前几个难题。对于后来的语言,我们使用了其他(尽管仍然很酷),例如Rust,Ruby,Go和C ++。这些博客文章不会出现这些。
在HTML中求解AOC第1A
第1天的代码出现问题(AOC)为您提供数字列表,并询问您最大数字组的总和是多少。仅在HTML和CSS中可以解决这个问题(无JavaScript,没有SCSS或其他计算语言)。该方法是首先应用一些预处理(以查找和替换命令的形式),以将输入转换为有效的HTML,然后应用一些CSS样式规则以在浏览器的“ Inspect element element devtools”中读取答案。
预处理输入到HTML
最终目标是将每个数字变成我们可以将样式应用于的DIV,并将每个数字(用空线隔开)包裹为我们可以样式的其他Divs。具体而言,我想转动一个看起来像这样的列表:
4235
342
6564
234534
4234
进入:
<body>
<div class=”block”>
<div class="num" style="--hght: 4235px"></div>
<div class="num" style="--hght: 342px"></div>
<div class="num" style="--hght: 6564px"></div>
</div>
<div class=”block”>
<div class="num" style="--hght: 234534px"></div>
<div class="num" style="--hght: 4234px"></div>
</div>
</body>
:%s/^$/<\/div><div class=”block”>/g
接下来,我将所有数字替换为<div class=”num” style=”--hght: __px”></div>
在下划线上的正确数字中代替。我为此使用了以下替代命令:
:%s/\(\d\+\)/<div class=”num” style=”--hght: \1px”><\/div>/g
剩下要做的是在文件的开头和结尾添加其余的HTML,例如将所有内容包装在
中,并添加第一个和最后一个的启动和结尾标签元素。此后,完成了预处理步骤。使用CSS计算解决方案
如果我们使用上述HTML,则没有任何施加任何样式,我们最终会出现所有DIVS(如块级元素默认情况下)。这几乎就是我们想要的,因为我们想要在每个块div中出现的divs添加高度。但是,我们不想加总所有块元素的高度。我们只对最大块元素的高度感兴趣。因此,我们将每个数字块放置在彼此相邻。为此,我们给他们的父母(身体)一个弹性课,并设置数字元素的正确高度。此外,我们确保所有事物的高度根据其内容增长,并且不仅限于浏览器视口:
<style>
body {
margin: 0px;
display: flex;
flex-direction: row;
height: fit-content;
}
.block {
height: fit-content;
}
.num {
width: 1px;
height: var(--hght);
}
</style>
完成此操作,我们现在可以在浏览器的开发工具中读取答案,如身体高度:68787像素,这意味着最大块的总和为68787。
在COBOL中解决AOC第4天
在第4天,AOC挑战是为每对2个数字范围找到,无论其域是否重叠。这个难题的输入具有以下形状:
5-8,6-7
24-54,8-14
.. many more ..
COBOL用户可能熟悉的一个问题是,这种输入形式没有固定宽度(每个数字的数字数可能不同),这使得对未经启发的COBOL用户的难度更大,例如我自己解析输入。我再次求助于一些预处理,这次是在Python完成的,以解决我的动态宽度问题。
预处理所有数字以具有固定宽度。
在对问题输入的简要检查后,我发现这些数字都不大,并且每数字使用三位数应足以适应所有内容。为了适应这一点
请注意,第12行上实际上存在一个小错误,这会导致第二范围用逗号而不是破折号打印。这不会影响COBOL解析,因为COBOL假设每个数字都位于特定位置,并且忽略了所有其他文本。此外,让我们忘记以下事实:在相同数量的Python代码中,我也可以解决整个问题:D
在输入上运行此脚本后,结果预处理输入(应)具有以下形状:
005-008,006-007
024-054,008-014
.. many more ..
这在COBOL程序中阅读要简单得多。原因将在以后变得明显。
COBOL程序的结构
COBOL程序分为几个部分和部门。我不确定一个部门和部门之间的区别是什么。每个COBOL程序的结构都以标识部门开头,该部门包含程序的名称,作者名称以及我没有填写的其他有用信息。
下一个部门是环境部,其中包含描述该程序IO行为的部分。这是我指定我的程序读取标准输入的地方。接下来是数据部,这是指定程序的内存布局的位置。这是必须声明程序中使用的每个变量的地方。此外,这里描述了文件描述符,这是指定要读取的文件的结构的方式。至关重要的是,这必须在编译时间中知道(对于未经处理的输入,我们不知道这一点)。总而言之,这些部分的结合如下:
请注意,有些事情称为学生,因为我从正在处理学生数据的教程中复制了一个示例COBOL程序。
我们程序的内存布局
在COBOL中,您必须提前定义所有变量的结构,这是很好的。为了适应这一天问题的输入,我创建了以下形式的文件描述符和变量:
这大致意味着输入学生文件的每一行(我们的标准输入)将包含一个PIC 9(3)(三位数),然后是一个PIC X(文本字符),然后是3位数字,A文本字符,3位数字,另一个字符和3位数字。这完全匹配了早些时候创建的123-456,234-567输入之一。我还创建了一个称为WS-Line的变量,该变量具有完全相同的结构,除了这次,此结构描述了变量而不是文件描述符。除了声明WS-Line外,我还声明WS-Count(工作存储计数),WS-EOF(这是确定输入到达EOF(文件末尾)和WS-Surfacetotal的标志第2部分的变量。
程序本身
该程序本身由一个过程组成,该过程重复直到我们到达EOF,然后打印出简单的计数。这是使用以下COBOL代码编写的:
您可以看到,Cobol读取就像英语一样,这一定意味着代码是自我记录的。
COBOL有趣的部分是读取语句,它可以根据已读取的文件描述符的结尾来执行不同的操作。在这种情况下,在文件末尾,将WS-EOF标志设置为“是),该标志会导致循环终止。如果我们尚未到达文件的末尾,则调用二人路程序(实际上是第2部分的实现)。另外,请注意,正在读取的行将写入变量WS-Line,这将被破坏为我们的4个数字和3个定界符(占位符)字符。
计数包括对
对于本AOC的第1部分,我们将计算彼此包含的范围对数。为了在我们的COBOL程序中执行此操作,我们只需在四个数字上使用一些if statement,以查看另一个范围是否包含在另一个范围中。
请注意,COBOL没有其他语句,因此我不得不将另一个IF语句嵌套在其他分支中。后来我了解到COBOL确实有一个评估语句,该语句可以采用多个分支(例如现代语言的开关语句)。
计数重叠范围
对于第2部分,我们必须计算仅与另一个范围重叠的范围的数量。这可以通过多种方式解决,但是我不想考虑所有的边界检查。取而代之的是,我诉诸于一种称为Pigonhole原理的证明技术。我计算了从最低低边界到最高高边界的总尺寸,并将其与两个单个范围的大小进行了比较。如果两个单独的范围不适合外部范围的总面积,则意味着它们共享一些空间,这意味着它们重叠。为此,优雅地使用最小功能和最大功能。在正常的编程语言中,这看起来像这样:surface = max(num2,num4) - min(num1,num3)+1。但是,在COBOL中,它看起来像以下怪兽:
不幸的是,任何函数调用都必须以函数为前缀。请注意,+1之所以存在,是因为我们正在处理闭合间隔,并且[6,6]的范围覆盖了1个空间。出于相同的原因,每个范围的计算在每个范围内都有+1(因此A +2)。
另外,请注意,我尚未学会如何在COBOL中编写功能(我甚至不知道它们是否存在),因此使用返回语句是不可能的。取而代之的是,一切都是通过突变全局变量来完成的,并确保它们在使用之前将其初始化为明智的东西。