取消注释COBOL程序!


64

COBOL是一种非常古老的语言,在撰写本文时已经58岁了。实际上,它太老了,以至于它有一个非常有趣的怪癖:每行的前六个字符是注释。

你问为什么呢?好吧,那六个字符原本是要用作行号的,那是在程序不是完全数字化并在计算机上打字的那个日子。

此外,第七个字符只能是一个很小的集合的一部分(通常是 *是注释掉该行或一个空格以将行号与代码分开)

但是,如果您使用的是数字系统,并且只想要原始程序,该怎么办?

评论系统

COBOL中有两种类型的注释:行注释和前面提到的“行号”注释。

取消注释行号很简单:只需从每行中删除前七个字符(六个加一个空格)。

000000 apple
000001 banana
celery donuts

会成为:

apple
banana
donuts

行注释使它变得更加困难。行注释以星号开头,该星号*位于行的第七个字符位置,如下所示:

000323* this is a comment

这不是一行注释:

*00000 this isn't a comment

要取消注释行注释,只需删除整行。

一个示例注释了“程序”:

000000 blah blah
000001* apples
000002 oranges?
000003* yeah, oranges.
000*04 love me some oranges

未注释的版本:

blah blah
oranges?
love me some oranges

换句话说,要取消注释字符串,请删除每行的前六个字符,然后返回除以星号开头的每行的第一个字符以外的所有字符。

挑战

创建一个接受注释程序并返回其未注释变体的程序或函数。

澄清说明

  • *在一行的前七个字符之外的任何地方都找不到星号()(我们不要求您验证语法)
  • 每行将始终至少包含7个字符。
  • 您可以假设第七个字符始终是星号或空格。
  • 输入或输出可以是矩阵或列表。
  • 仅可处理可打印的ASCII字符(加上换行符)。
  • 您可以输出尾随换行符。如果您选择这样做,您还可以假设输入将包含尾随换行符。

计分

由于这是,因此,字节数最少的答案会获胜!

免责声明:我实际上并不了解COBOL,也不会声称。如果我在此问题上对COBOL提出的任何主张不正确,我将不承担任何责任。


23
行号不是注释。它们是一列。请用术语。
user207421

1
您的示例在后面都有一个空格*。这是巧合吗?
尼尔

6
旧的并不自动暗示不好。我曾在一家敏捷COBOL商店工作过。他们可以在Java中无法完成的AS / 400上完成工作。
托尔比约恩Ravn的安德森

1
嘿...我实际上写了一个COBOL CopyBook解析器,该解析器仅在未打包字段时才起作用。只需将其转换为JSON即可key:{key:{key:length,key:length}}。虽然会剥离所有格式数据和键入数据。
魔术章鱼缸

4
前6个字符可以有空格吗?

Answers:


104

COBOL(GnuCOBOL),191 + 17 = 208字节

我“学习”了COBOL的答案,因此可能没有完全打好高尔夫球。

这是一个完整的程序,接受我假定为标准输入的内容,并写入我假定为标准输出的内容。也许有一天我会回到这一点,并且(1)确定COBOL是否具有函数,如果是,则(2)看看函数解决方案是否会更短。

字节数包括程序和编译器标志(-free-frelax-syntax)。

program-id.c.select i assign keyboard line sequential.fd i. 1 l pic X(80). 88 e value 0.open input i perform until e read i end set e to true end-read if not e and l(7:1)<>'*'display l(8:73).

在线试用

非高尔夫节目

program-id. c.

select i assign to keyboard organization line sequential.

fd i.
    1 l pic X(80).
    88 e value 0.

open input i
perform until e
    read i
        end set e to true
    end-read
    if not e and l(7:1) <> '*'
        display l(8:73).

局限性

从技术上讲,输出不正确。根据我的粗略研究,似乎将字符串存储在COBOL中的唯一实用方法是在固定大小的缓冲区中。我选择了80个字符的缓冲区大小,因为这是固定格式程序的行长限制。这存在两个限制:

  • 超过80个字符的行将被截断。
  • 少于80个字符的行用空格右填充。

我猜这是可以接受的,因为是COBOL。如果没有,我愿意研究替代方法。

致谢

  • -166字节感谢Edward H
  • -2个字节感谢hornj

10
星号(*)永远不会在一行的前七个字符之外的任何位置出现 ……而且……;)
Cœur17年

@Cœur哈哈是的...但是我的解决方案未使用该假设,所以也许合适!
雅各布

8
您赢得了一个互联网。
约书亚

@Cœur,但在COMPUTE语句中除外。
ClickRick

1
恭喜您获得金牌!
caird coinheringaahing

20

Python 2中39 38 37个字节

-1个字节,感谢LyricLy。-1个字节感谢Mego。

lambda s:[i[7:]for i in s if'*'>i[6]]

在线尝试!

I / O作为字符串列表。


2
通过更换保存字节!=<,因为空间的代码点比一个星号的一个低,第七个字符将永远是一个空间或一个星号。
LyricLy

那么,第7个字符将始终是空格还是星号?
完全人类

是。You may assume the seventh character is always an asterisk or a space.
LyricLy

1
if'*'!=i[6]
Mego


11

V13 11 10字节

Î6x<<
çª/d

在线尝试!

说明

Î       ' On every line
  x     ' delete the first...
 6      ' 6 characters
   <<   ' and unindent the line (removes the leading space)
ç /     ' on every line
 ª      ' matching \*
   d    ' delete the line

十六进制转储:

00000000: ce36 783c 3c0a e7aa 2f64                 .6x<<.../d

你能7x代替6x<<吗?
DJMcMayhem

1
然后它将删除*
nmjcman101 '17

先删除lins *然后再删除是否可行Î7x?(假设*不能位于字符0-5中)
12431234123412341234123 '17年

@ 12431234123412341234123不幸的是,因为*前6个字符中可能有一个。
nmjcman101

9

Paradoc(v0.2.8 +),8个字节(CP-1252)

µ6>(7#;x

获取行列表,并生成未注释行列表。

说明:

μ        .. Map the following block over each line (the block is terminated
         .. by }, but that doesn't exist, so it's until EOF)
 6>      .. Slice everything after the first six characters
   (     .. Uncons, so now the stack has the 6th character on top
         .. and the rest of the line second
    7#   .. Count the multiplicity of factors of 7 in the character
         .. (treated as an integer, so '*' is 42 and ' ' is 32)
      ;  .. Pop the top element of the stack (the rest of the line)...
       x .. ...that many times (so, don't pop if the 6th character was a
         .. space, and do pop if it was an asterisk)

嗨,我写了一种高尔夫编程语言。:)

我仍在开发此程序,并在尝试编写此代码后添加/调整了许多内置函数,以便有一种比“ 7#” 更合理的区分空格和星号的方法,但是我觉得那样会使此方法失去竞争力。幸运的是,它仍然可以解决问题(它仅使用了三天前提交的v0.2.8中的功能)。


“嗨,我写了一种高尔夫球编程语言。” 发布此挑战之前或之后,您使用的版本是发布的吗?
桅杆

1
它可以在三天前的这个版本上运行:github.com/betaveros/paradoc/releases/tag/v0.2.8
betaveros

是的,您提到了,但是以某种方式未明确注册...
桅杆


7

八度,23字节

@(s)s(s(:,7)~=42,8:end)

在线尝试!


4
我从来不知道Octave可以做这样的字符串... MATLAB,来吧。xD
Sanchises

自从R2016b引入了字符串数组以来,我很确定这也可以在MATLAB中使用@Sanchises!我目前只能访问R2015b,因此无法确认。MATLAB可以使用74个字节(可能更少)来完成此操作@(s)cellfun(@(r)r(8:end),s(cellfun(@(r)r(7)~=42,s)),'uniformoutput',false),这里s是一个单元格数组,而不是字符串数组。使用regexp之类的方法可能会更短一些,但是我编写的方法与仅适用于旧MATLAB的答案中的方法相当
-Wolfie

6

果冻11 9字节

ṫ€7Ḣ⁼¥Ðf⁶

在线尝试!

输入和输出为行列表。

-2个字节,感谢@EriktheOutgolfer和@JonathanAllan

这个怎么运作

ṫ€7Ḣ=¥Ðf⁶
 €           On each line:
ṫ 7            Replace the line with line[7:]
      Ðf     Keep all lines that meet condition:
     ¥         Dyad:
   Ḣ             First Element (modifies line)
    =            Equals
        ⁶    Space


像这样将其降低到9:ṫ€7Ḣ⁼¥Ðf⁶
Jonathan Allan

5

PowerShell,32字节

$input-replace'^.{6}( |.*)'-ne''

在线尝试!

管道输入以字符串数组形式出现,-replace可在每个字符串上使用,并且-ne ''(不等于空字符串)应用于数组,用于过滤出空行。


4

C,63 59 55 48 47 46字节

感谢匿名用户 ”摆脱了另一个字节。

感谢Felix Palmen提醒我“ 您可能会假设第七个字符始终是星号或空格。 ”,这又减少了一个字节。

f(char**a){for(;*a;++a)(*a)[6]&2||puts(*a+7);}

使用方式如下:

char** program = { "000000 apple", "000001 banana", "celery donuts", 0 };
f(program);

在线尝试!


3

实际上,13个字节

⌠6@tp' =*⌡M;░

输入和输出作为字符串列表完成。

说明:

⌠6@tp' =*⌡M;░
⌠6@tp' =*⌡M    for each line:
 6@t             discard the first 6 characters
    p            pop the first character of the remainder
     ' =         is it a space?
        *        multiply the string by the boolean - returns the string if true, and an empty string if false
           ;░  filter out empty strings

在线尝试!


3

盖亚 9字节

6>¦'*«⁈ḥ¦

接受字符串列表并返回字符串列表的函数。

在线尝试!

说明

6>¦        Remove the first 6 characters of each string
   '*«⁈    Filter out ones that start with *
       ḥ¦  Remove the initial space from each

我数了十个字符,并且由于三个是非ASCII字符,它们占用的字节数不超过一个字节吗?
WGroleau '17

@WGroleau «均为1个字符。使用非ASCII字符(也许是Neim除外)的高尔夫语言使用自定义编码,该编码允许将所有这些非ASCII计数为单个字节。这是Gaia的代码页
Xcoder先生17年

@ Mr.Xcoder Neim也有编码。
暴民埃里克(Erik the Outgolfer)'17年

3

Pyth,9个字节

请注意,这仅在至少1行不是注释并且至少1行注释时才有效。所有其他解决方案在任何情况下均适用。

-2个字节感谢@pizzakingme

m>d7.m@b6

在这里尝试!

说明

m>d7.m@b6     - Full program with implicit input. Takes input as a list of Strings.

m>d7          - All but the first 7 letters of 
    .m   (Q)  - The input, filtered for its minimal value using the < operator on
      @b6     - the 7th character -- note that "*" is greater than " "
              - Implicitly Output the result.

Pyth,11个字节

tMfqhTdm>d6

在这里尝试!

说明

tMfqhTdm> d6-带有隐式输入的完整程序。将输入作为字符串列表。

       m> d6-删除每行的前6个字符。
    hT-获取每个字符的第一个字符。
  fq d-保留第一个字符的星号。
tM-删除每个字符的第一个字符。
            -隐式输出。

腐霉菌,11个字节

m>d7fqd@T6Q

在这里尝试!

说明

m> d7fq @ T6dQ-完整程序。将输入作为字符串列表。

      @ T6-每个的第六个字符。
    fq dQ-保留空格的行为^。
m> d7-裁剪前7个字符。
             -隐式输出。

Pyth,12个字节

tMfnhT\*m>d6

在这里尝试!

说明

tMfnhT \ * m> d6-带有隐式输入的完整程序。将输入作为字符串列表。

        m> d6-删除每行的前6个字符。
    hT-获取每个字符的第一个字符。
  fn \ *-过滤不等于星号的那些字符。
tM-删除每个字符的第一个字符。
             -隐式输出。

Pyth,12个字节

m>d7fn@T6\*Q

在这里尝试!

说明

m> d7fn @ T6 \ * Q-完整程序。将输入作为字符串列表。

      @ T6-获取每个字符串的第六个字符
    fn \ * Q-过滤不等于星号的那些字符。
m> d7-裁剪前7个字符。
              -隐式输出。

让那些第一个字符不是星号的人保持星号。”
凯文·克鲁伊森

m>d7.m@b6应该以9字节工作,*按字典顺序在空间之后滥用
Dave

如果需要,我可以使用解释/测试链接对其进行编辑!
戴夫

@pizzakingme,如果您能编辑,我会很高兴,因为我在移动设备上。非常感谢,不要忘记相信自己的新解决方案!
Xcoder先生17年

如果所有行都是行注释,这行得通吗?(我不确定您是否必须处理此案)
betaveros

3

GNU Sed,19 + 2 = 21个字符

需要的-E参数以sed启用扩展的正则表达式。

/^.{6}\*/d;s/^.{7}/

您可以执行与perl家伙相同的操作,s/^.{6}( |.*)//g
markasoftware



3

C(gcc)53 48 46字节

x;main(y){for(y=&x;gets(y-6);x&2||puts(y+1));}

在线尝试!

-5个字节:将这个“ 整个程序 ”减小到与gurka函数相同的大小非常棘手。现在,它正在错误类型的数组的界外(双向)写入数据,并依靠小端字节4字节整数找到星号...但是,它可以工作了;)

-2个字节:好吧,如果我们已经写入某个“随机” .bss位置,那为什么还要费心声明一个数组!因此,出现了既不使用char类型也不使用数组的字符串处理程序。


真好!而且*x&2让我记住“您可能会假设第七个字符始终是星号或空格。”,因此我应该能够将答案中的某些字符删掉:-)
simon

@gurka谢谢:D -2,呵呵
Felix Palmen '17

3

R,47 45字节

function(x)gsub("(?m)^.{6}( |.*\\n)","",x,,T)

如果您将输入作为字符串列表,我认为您可以将regex缩短为“ ^。{6}(|。* $)”为-6。
刑事

@CriminallyVulgar正确。在这种情况下,我也可以删除该pe=T论点。但是,我不确定是否允许输入为字符串列表。
Sven Hohenstein

从OP:Input or output may be a matrix or list.
全人类的

@CriminallyVulgar问题是输出中存在空字符串。
Sven Hohenstein

@SvenHohenstein当然,我没有考虑过。
刑事

3

SNOBOL4(CSNOBOL4)72 70 66 50字节

R	INPUT POS(6) (' '  REM . OUTPUT | '*') :S(R)
END

在线尝试!

SNOBOL中的模式匹配与正则表达式完全不同,但是这里的思想仍然相同:如果一行匹配“六个字符,然后一个星号”,则将其删除,否则,删除该行的前七个字符并打印结果。

现在,这实际上可以更好地利用SNOBOL的条件赋值运算符。

该模式被POS(6) (' ' REM . OUTPUT | '*')解释为:

从位置6开始,匹配一个空格或一个星号,如果匹配一个空格,则将行的其余部分分配给OUTPUT


3

Vim,14个字节

Ctrl-VG5ld:%g/\*/dEnter

加载输入文件作为要编辑的缓冲区,然后输入上述命令。输出是新缓冲区。


2

Ruby39 38 36 29 23 22 20 +1 = 21字节

$_[/.{6}( |.*
)/]=''

在线尝试!

使用-p标志。

说明:

-p标志在代码周围添加了一个隐式块,因此实际运行的代码如下所示:

while gets
    $_[/.{6}( |.*
)/]=''

    puts $_
end

gets读取一行文本并将其结果存储在中$_

$_[/.../]=''删除中出现的regex的第一次...出现$_

/.{6}( |.*\n)/在行的开头匹配任何字符的6,后跟空格或行的其余部分。因为该空格首先出现,所以它将尝试只删除前6个字符和一个空格,然后再尝试删除整行。

$_ 然后将其打印出来,并对每一行重复此过程。


1
Ruby中的方法调用不需要括号,删除它们将为您节省一个字节。
m-chrzan



2

JavaScript(ES6),48个字节

s=>s.map(c=>c[6]<"*"?console.log(c.substr(7)):1)

在线尝试!


1
这既不是函数也不是完整的程序,因为它假定输入存储在中z,此处不允许这样做。但是,您可以将其转换为匿名箭头功能,以使其有效。
caird coinheringaahing

1
@cairdcoinheringaahing你是完全正确的。更新了解决方案-不确定关于fn (及其)周围的规则是什么,请确保添加这些规则。
sgtdck

1
您不需要()around函数,但是看起来不错。
caird coinheringaahing

2

> <>,57 53字节

>i~i~i~i~i~i~i67*=\
<o$/?:$/?=a:;?(0:i<
\~$/~\ $
/  <o\?/

在线尝试

说明

>i~i~i~i~i~i~i67*=    Read in the first seven bytes of the line
 i~i~i~i~i~i~         Read, and discard 6 characters
             i        Read the seventh
              67*=    Check if the seventh character was an 
                      asterisk (and leave that value on the stack );

<o$/?:$/?=a:;?(0:i<    Read characters until a newline or eof
                 i     Read the next character of the line
            ;?(0:      If it's a -1, terminate the program
       /?=a:           If it's a newline, break out of the loop
   /?:$                If the seventh character was not an asterisk
<o$                    Output this character
\~$/                   otherwise discard it

   /~\ $    Having reached the end of the line, output
/  <o\?/    the newline only if it was not a comment

编辑:53个字节

>   i~i~i~i~i~i~i67*=\
/?=a<o/?$@:$@:$;?(0:i<
~   \~/

基本上与以前相同,但略有重组

附带说明:我很失望,没有人在cobol中做到这一点。


2

C#,16014590 89字节

t=>{var o="";foreach(var s in i.Split('\n'))if(s[6]!=42)o+=s.Substring(7)+"\n";return o;}

感谢Pavel&auhmaan减小了尺寸。


欢迎来到PPCG!我建议您在答案中添加一个在线尝试链接,以便其他人可以测试您的代码。除此之外,第一(好,第二)的答案很好!
LyricLy

您可以通过写以下形式的lambda来缩短此时间t=>{...}
Pavel

@LyricLy实际上,我尝试这样做,但是由于某些原因,这在这里不起作用。不过,它在VS控制台应用程序中工作得很好。
snorepion

@Pavel喜欢吗?我不确定我是否完全正确地完成了操作;我从来不需要使用过lambda表达式。
snorepion

对,就是这样。您可以通过将其分配给进行测试func<string, string>
帕维尔

2

Python 3,71个字节(无正则表达式)

def f(s):
 for w in s.split('\n'):
  t=w[6:]
  if t[0]!='*':print(t[1:])

有用!

>>> s="""000000 blah blah
000001* apples
000002 oranges?
000003* yeah, oranges.
000*04 love me some oranges"""
>>> f(s)
blah blah
oranges?
love me some oranges


1

JavaScript,44 34字节

划掉的44仍然是常规44。

tsh节省了6个字节

a=>a.replace(/^.{6}( |.*\n)/gm,'')

在线尝试!


s=>s.replace(/^.{6}( |\*.*\s)?/mg,'')
tsh

s.match(/(?<=^.{6} ).*/mg) ESNext(非标准,Stage3)Chrome62 +
tsh

@tsh。在没有稳定的解释器允许它之前,我想它不会算作有效的编程语言。

如果最后一行是注释行,这似乎不能提供正确的输出。
LyricLy

@LyricLy。这是因为我假设输入将始终包含尾随新行。您可以看到它的工作原理是输入后有一个空行。如果我不认为这一点,那么修复将花费1个字节(?在之后添加\n)。

1

C ++(GCC),121112字节

感谢@gurka节省了9个字节!

#import<bits/stdc++.h>
void f(std::list<std::string>l){for(auto s:l)if(s[6]-42)std::cout<<s.substr(7,s.size());}

将输入作为行列表。

在线尝试!


#import?另外,我认为可以省略标准包含。
simon

#import不是标准的C ++,但至少GCC和MSVC支持它。省略一些include可以在C中使用,但不能在C ++中使用。如果没有包含,该代码将无法正常工作,因此必须将它们计入总字节数。
Steadybox

啊哈,我想您可以跳过include,因为import在python答案或usingC#答案中看不到任何内容。另外,#include <bits/stdc++.h>您的答案会不会更短?
simon

@gurka是的,它会更短。谢谢!
Steadybox

@gurka导入在Python答案算在内,只是Python具有很多不需要导入的功能。C#往往没有using语句,因为它通常system.foo()using system;foo()
Pavel

1

Java 8,95 54 53字节

s->s.filter(x->x.charAt(6)<33).map(x->x.substring(7))

-42字节感谢@OliverGrégoire,使用Stream<String>而不是String in和输出。

说明:

在这里尝试。

s->                          // Method with Stream<String> as parameter and return-type
  s.filter(x->x.charAt(6)<33)//  Filter out all lines containing an asterisk as 7th char
   .map(x->x.substring(7))   //  And remove the first 7 characters from the remaining lines
                             // End of method (implicit / single-line body)

看起来您可以使用String[]List<String>作为-12个字节的输入。
雅各布

或者,Stream<String>如果有帮助。范例:s->s.map(x->x.charAt(6)!=42?x.substring(7):"")
OlivierGrégoire'17

1
哦,需要过滤...然后s->s.filter(x->x.charAt(6)!=42).map(x->x.substring(7))是54个字节。
奥利维尔·格雷戈尔

1
使用<42而不是!=42因为“您可能会假设第七个字符始终是星号或空格”。
奥利维尔·格雷戈尔(OlivierGrégoire),

1
@OlivierGrégoire啊,错过了该规则,否则我本人会这样做。感谢您的更正。
凯文·克鲁伊森
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.