Generate /* line number comments */

12

2

Your task is to write a program (or function) that will take a string as input and append text to the beginning of every line that satisfy the following rules:

  • The text appended must contain the line number. You may use 0- or 1-based indexing.
  • The text must be a comment in your language. A comment is defined as a syntacticly valid piece of code that makes no changes to the program's state. Removing the comment should make no change to the program.
  • The comment may only contain newlines at the end of it.
  • You do not have to put line numbers for lines that contain just whitespace and comments.

Specifications

  • You may assume that the input will be a valid program in your language.
  • In indentation-sensitive languages like Python, you may place the line number comment after all indentation. You may choose either tabs or spaces to be your indentation character, but you must specify on your post.
  • You may assume that every statement in the code will take up at most the entirety of 1 line; i.e. no multi-line strings or backslash-continuation.

Test Cases

Python:

#0
a = int(input())
#1
while a:
    #2
    print(a)

C: (Honestly, I'm surprised this compiles)

/*0 */#include <stdio.h>
/*1 */int main()
/*2 */{
/*3 */    char c;
/*4 */    c = getchar();
/*5 */    do
/*6 */    {
/*7 */        putchar(c);
/*8 */    }
/*9 */    while (c);
/*10*/}

This is , so the shortest answer (in bytes) wins.

Esolanging Fruit

Posted 2016-11-20T22:20:32.647

Reputation: 13 542

1Good luck doing this is Retina! – Esolanging Fruit – 2016-11-20T22:20:45.270

Just to be clear, we must generate the type of comment our language uses? What if our language doesn't have comments? – James – 2016-11-20T22:25:14.253

7Making the comments language-dependent makes things complicated. You already had to create a special rule for Python. What about all the other languages that don't have multi-line comments? What about languages that do not have comments at all. What about multi-line strings where comments cannot be placed without side effects? – Dennis – 2016-11-20T22:26:03.580

@Dennis You don't strictly need "comments". For example in befunge I consider "text"!!!! to be a comment because it makes no changes to the program's state. The thing about multi-line strings is true; I'll mention that. – Esolanging Fruit – 2016-11-20T22:33:20.467

@DrMcMoylex See my reply to Dennis about comments. – Esolanging Fruit – 2016-11-20T22:35:16.090

4Fun fact: the rule "removing the comment should make no change to the program" immediately disqualifies any Python answer, because the code—including comments—can be introspected at runtime. I have seen this in play in a production system: a piece of code would raise an AssertionError unless the stack trace contained the phrase foo.py, which was expected to come from a file name but could also appear as a line comment in the context. – wchargin – 2016-11-21T03:09:02.800

@wchargin Hmmm... Let's just say that the program does not directly access its source code or runtime state like that. Also, does that mean that comments are not removed during parsing? Seriously, Python? – Esolanging Fruit – 2016-11-21T03:11:37.297

1

@Challenger5 Correct.

– wchargin – 2016-11-21T03:18:13.370

2"The comment can only contain newlines at the end of it" is inconsistent with the C "test case". – Peter Taylor – 2016-11-21T06:41:28.227

1@PeterTaylor Can, not necessarily will. – Esolanging Fruit – 2016-11-21T07:10:08.880

2What about langs without comments? – NoOneIsHere – 2016-11-21T07:58:34.460

"Can only" generally means "cannot not", hence "must". But if it should be "may only" that's still inconsistent with the C test case, which includes padding whitespace. – Peter Taylor – 2016-11-21T08:23:19.220

@PeterTaylor That's true. I edited it. – Esolanging Fruit – 2016-11-21T09:48:37.890

@wchargin I just don't see why that would ever be useful. Is it ever necessary to detect if a comment exists or contains some text? – Esolanging Fruit – 2016-11-21T09:52:12.590

@Challenger5 In Python, variables can be given a type hint with a comment. You could read the comment to work out the type of he variable and enforce type hints – Blue – 2016-11-21T12:11:11.687

Are we allowed to comment blank lines? – anonymous2 – 2016-11-21T12:49:23.107

4The edit doesn't fix the inconsistency. – Peter Taylor – 2016-11-21T13:38:18.927

@NoOneIsHere A comment is defined here as a block of code that has no effect. For example "comment"!!!!!!! is considered a comment if Befunge. – Esolanging Fruit – 2016-11-22T15:08:43.540

@Challenger5 So 123 is a comment? What about BF? <> (from my memory) is a comment? – NoOneIsHere – 2016-11-22T16:36:46.757

@NoOneIsHere If your language does not do anything with 123, it is a comment. <> is also considered a comment in BF. – Esolanging Fruit – 2016-11-22T23:00:22.273

Test case needed for rule You do not have to put line numbers for lines that contain just whitespace and comments. – Denis Ibaev – 2016-11-28T07:13:50.797

Answers

5

Pyke, 7 bytes

o\Kz++r

Try it here!

o       -  o++
 \K     -  "K"
   z    -  input()
    ++  - sum(^)
      r - while no errors: GOTO start

I'm declaring integer comments to be the integer followed by the character K and then the line. An extra byte is used to stop the newline opcode from kicking in and printing an extra thing.

Blue

Posted 2016-11-20T22:20:32.647

Reputation: 26 661

16

Perl, 8+1 = 9 bytes

say"#$."

Run with -p (1 byte penalty). (Note to people unfamiliar with PPCG rules; you also need to specify a modern version of Perl syntax using -M5.010, but we decided that options to select language versions are free and don't incur a byte penalty, so I didn't mention it in the original version of this post.)

-p places the program into an implicit loop; it basically causes the program to become a filter that processes each line separately (i.e. the entire program is run on the first line, then the second, then the third, and so on). Perl also keeps track of a line number, called $., that records how many lines of input have been read. So all the program's doing is letting -p read a line of input; output a #, the current line number ($.), and a newline (say adds a newline by default, which is helpful in this case, and is also shorter than the more commonly seen print); and then letting -p output the original line of code that it read (typically a program using -p would do some sort of processing on the input, but because we didn't, it's just output unchanged). Comments in Perl run from # to a newline (the # in the program itself doesn't start a comment because it's inside a string literal), so what we're basically doing is taking the opportunity to write comment lines into the file as we process it, without disturbing the "natural" read and write cycle of -p.

user62131

Posted 2016-11-20T22:20:32.647

Reputation:

Can you explain how this works? – Adám – 2016-11-24T14:24:23.877

Sure. I've explained the operation of relevant Perl language features in a tutorial style, given that it's a very basic Perl program that doesn't really make much use of the language's power. I need to remember that not everyone knows how a -p loop or an automatically updating line number work, though. – None – 2016-11-24T15:04:46.197

Note that say"$.;" would work as well, because the question specified that "You may assume that every statement in the code will take up at most the entirety of 1 line". – msh210 – 2016-11-24T15:20:59.777

That's not really a comment, though; although it does nothing useful, it ends up in the AST (and because Perl's optimizer is kind-of sucky, I think that actually will end up slowing the program down, something you wouldn't really want a comment to do). – None – 2016-11-24T16:05:07.650

Not working for rule You do not have to put line numbers for lines that contain just whitespace and comments. – Denis Ibaev – 2016-11-28T06:58:28.707

"You do not have to" ≠ "You can't". I don't think any of the other answers omit line numbers on such lines either, because it would require considerably more code to do so. – None – 2016-11-28T16:25:10.557

9

Javascript, 43 39 bytes

a=>a.replace(/^/gm,_=>`/*${++b}*/`,b=0)

Thanks to ETH and Conor for saving 4 bytes.

SuperJedi224

Posted 2016-11-20T22:20:32.647

Reputation: 11 342

41 bytes: a=>(b=0,a.replace(/^/gm,_=>/*${++b}*/)) (use a formatting string) – Conor O'Brien – 2016-11-21T00:06:16.237

139 bytes: a=>a.replace(/^/gm,_=>`/*${++b}*/`,b=0) – ETHproductions – 2016-11-21T00:13:35.077

5

V, 10 bytes

O:1òYjjP

Try it online!

James

Posted 2016-11-20T22:20:32.647

Reputation: 54 537

3

Lua, 80 75 Bytes

Saved some bytes by abusing the langauge.

x=1print("--[[1]]"..(...):gsub("\n",load('x=x+1return"\\n--[["..x.."]]"')))

Simple enough starter answer.

Ungolfed, +

x=1                                                     -- Assign x to 1...
print(                                                  -- Print...
      "--[[1]]"                                         -- The first line number comment...
      ..                                                -- With...
      (...):gsub(                                       -- The input, replacing all...
                 "\n",                                  -- Newlines...
                    load                                -- with a string compiled function...
                    (' \
                    x=x+1                               --Increment x by one... \
                    return"\\n--[["..x.."]]"            -- And return the new linecomment. \
                    ')
                 )
      )

ATaco

Posted 2016-11-20T22:20:32.647

Reputation: 7 898

I don't know Lua, but are you sure that it will always generate comments that are the same length? For example if a program is 10 lines long than the last comment will be --[[10]] which is 1 character longer than --[[9]] unless you correctly pad it with spaces. – Esolanging Fruit – 2016-11-20T22:51:25.933

1Oh, I didn't notice that rule. That seems... A bit redundant... – ATaco – 2016-11-20T22:59:51.633

1Yes. Maybe I'll remove it...
[EDIT]: removed.
– Esolanging Fruit – 2016-11-20T23:00:41.430

3

Batch, 91 bytes

@set n=
@for /f "delims= tokens=*" %%a in (%1) do @set/an+=1&call echo @rem %%n%%&echo %%a

Batch doesn't have a way of reading STDIN until EOF, so instead the file name has to be passed as a command-line parameter.

Neil

Posted 2016-11-20T22:20:32.647

Reputation: 95 035

3

Gema, 16 15 characters

*\n=\!@line\n$0

In Gema there are only line comments, starting with !.

Sample run:

bash-4.3$ cat l33t.gema 
e=3
g=9
i=1
o=0
t=7

bash-4.3$ gema -f l33t.gema <<< 'Hello World!'
H3ll0 W0rld!

bash-4.3$ gema '*\n=\!@line\n$0' < l33t.gema > l33t-nr.gema

bash-4.3$ cat l33t-nr.gema
!1
e=3
!2
g=9
!3
i=1
!4
o=0
!5
t=7

bash-4.3$ gema -f l33t-nr.gema <<< 'Hello World!'
H3ll0 W0rld!

The following are to answer Adám's question, whether is possible to add the line number in kind of ignored code.

Gema code is essentially a collection of from=to transformation rules, or template=action in Gema terms. I see no way to define a template that will never ever match anything, this alone not seems to be the way.

Gema, 18 characters

*\n=c:\=@line\;:$0

Transforms e=3 into c:=1;:e=3.

Luckily in Gema there are domains, kind of namespaces. The above code defines the dummy rules in namespace c, that we never use. Unfortunately a mentioned domain remains in effect until the end of line, so we have to explicitly to switch back to default domain.

Gema, 18 characters

*\n=@line\=\$0\;$0

Transforms e=3 into 1=$0;e=3.

A less complicated alternative is to use effectless code instead of ignored one. I mean to put back exactly what was matched.

manatwork

Posted 2016-11-20T22:20:32.647

Reputation: 17 865

But couldn't you insert a string and have some code around it which makes it ignored? – Adám – 2016-11-24T14:26:15.957

You mean kind of e=3 transformed in if (false) { 1 }; e=3 instead of the current !1 e=3? Yeah, there would be a 19 character long workaround. – manatwork – 2016-11-24T14:42:44.057

2

Kotlin extension function, 69 60 bytes

fun String.a()=lines().mapIndexed{i,s->"/*$i*/$s"}.joinToString("\n")

fun String.a(){lines().mapIndexed{i,s->println("/*$i*/$s")}}

Example usage:

fun main(args: Array<String>) {
  //language=kotlin
  val code = """fun main(args: Array<String>) {
  println("Hello world!")
}"""
  code.a()
}

Output:

/*0*/fun main(args: Array<String>) {
/*1*/  println("Hello world!")
/*2*/}

F. George

Posted 2016-11-20T22:20:32.647

Reputation: 317

2

Qbasic, 91 89 bytes

OPEN"I",1,"i"
OPEN"O",2,"o"
DO UNTIL EOF(1)
i=i+1
INPUT#1,a$
PRINT#2,STR$(i)+"'"+a$
LOOP

Input:

CLS
PRINT "Hello!"
a$="Welcome"
INPUT "Type your name: ", b$
PRINT a$; ", "; b$
END

Output:

 1'CLS
 2'PRINT "Hello!"
 3'a$="Welcome"
 4'INPUT "Type your name: ", b$
 5'PRINT a$; ", "; b$
 6'END

anonymous2

Posted 2016-11-20T22:20:32.647

Reputation: 421

1Been a while since I've used QBasic, but doesn't that make the program text all a comment, rather than the line numbers? Or am I misremembering something? – None – 2016-11-21T15:37:56.773

Thanks for the input! Actually, the ' just comments that which follows on the line. – anonymous2 – 2016-11-21T16:50:10.393

4Yes, which is why I think it's turning the program into comments. Rather than just adding line numbers, it changes the meaning into a program that does nothing. (Honestly, it'd be cool for an entry in a BASIC dialect to add real line numbers and renumber the program if it already has numbers, but that's probably not really needed.) – None – 2016-11-21T19:22:10.310

2

BASH (+ GNU sed) 27 bytes

sed 'i#
='|sed 'N;s/\n//;N'

The first part (i# \n =) almost works in GNU sed (for 4 bytes), but it puts a newline after the #.

Riley

Posted 2016-11-20T22:20:32.647

Reputation: 11 345

2

awk (19 13 bytes)

19 bytes : This insert "#"+line number above each line of code

{print"#"NR"\n"$0}

13 bytes : Credit & thanks to @manatwork for two 13 bytes solution

As 1 action defaults to print $0:

{print"#"NR}1

Or by replacing $0 content

$0="#"NR RS$0

Adam

Posted 2016-11-20T22:20:32.647

Reputation: 591

{print"#"NR}1 or $0="#"NR RS$0? – manatwork – 2016-11-21T21:01:09.680

@manatwork i'm quite ashamed and grateful to discover those subtilities – Adam – 2016-11-21T21:35:35.447

1

CJam, 21 Bytes

I am not well-versed in CJam at all, but I knew for a fact it has comments :)

qN%ee{"e#"o(oNo(oNo}/

Explanation coming soon.

Kade

Posted 2016-11-20T22:20:32.647

Reputation: 7 463

oNo can be replaced with n on TIO. – Esolanging Fruit – 2017-04-27T19:00:44.560

1

Mathematica, 58 bytes

i = 1; StringReplace[#, StartOfLine :> "(*" <> ToString@i++ <> "*)"] &

spacemit

Posted 2016-11-20T22:20:32.647

Reputation: 41

1

jq, 31 characters

(27 characters code + 4 characters command line options.)

"#\(input_line_number)\n"+.

In jq there are only line comments, starting with #.

Sample run:

bash-4.3$ cat l33t.jq 
gsub("e";"3")|
gsub("g";"9")|
gsub("i";"1")|
gsub("o";"0")|
gsub("t";"7")

bash-4.3$ jq -Rr -f l33t.jq <<< 'Hello World!'
H3ll0 W0rld!

bash-4.3$ jq -Rr '"#\(input_line_number)\n"+.' l33t.jq > l33t-nr.jq

bash-4.3$ cat l33t-nr.jq 
#1
gsub("e";"3")|
#2
gsub("g";"9")|
#3
gsub("i";"1")|
#4
gsub("o";"0")|
#5
gsub("t";"7")

bash-4.3$ jq -Rr -f l33t-nr.jq <<< 'Hello World!'
H3ll0 W0rld!

manatwork

Posted 2016-11-20T22:20:32.647

Reputation: 17 865

Dear Perl and Ruby coders, please observe jq's input_line_number. Being Thanksgiving, any special feeling to express for $.? – manatwork – 2016-11-24T13:29:47.010

1

C# 6, 66 61 bytes

Thanks to CSharpie

(666, devils code ^^) not any more ...

This works for all languages using "C style comments" (C, C++, C#, Java, ....)

It simply splits the string into lines, prepends every line with its index and joins the edited lines again with new line characters.

s=>string.Join("\n",s.Split('\n').Select((l,i)=>$"/*{i}*/"+l));

old version:

s=>string.Join("\n",s.Split('\n').Select((l,i)=>$"/*{i,3}*/{l}"));

Stefan

Posted 2016-11-20T22:20:32.647

Reputation: 261

1Technically 64 since op didnt mention any padding with zeros. Also you can save 1 more byte by wirting: $"/{i}/"+l. (Moving the L-parameter out of the interpolation.) – CSharpie – 2016-11-24T21:51:19.423

You're right ^^ but that destroys my "evil score" hehe – Stefan – 2016-11-24T22:55:15.343

1

GolfScript, 23 Bytes

n/0:i;{"#"i):i+n+\+}%n*

There are only line comments starting with "#".

Ungolfed & explained:

           # the input is pushed on the stack automatically
n          # n is a predefined variable for "\n"
/          # splits the input string with the previously pushed "\n" as delimiter
0:i;       # i = 0
{          # A code block: It is used for map here (going through the input)
    "#"    # push a "#" onto the stack
    i):i  # save i + 1 in i, the value is again not popped from the stack
    +      # implicitly converts the number i to a string and concatenates "#" with it
    n      # newline
    +      # add a newline (# introduces a *line* comment)
    \      # switch the top to elements (-> yields the comment as the bottom, and the line as the top element on the stack)
    +      # concatenate them
}          # end of the code block
%          # map
n          # newline
*          # join the list with newlines between them
           # outputs are done implicitly

I am pretty sure that this can be further simplified, especially the i can probably be left out.

You can test it here: https://golfscript.apphb.com/ Because this site doesn't support adding inputs, you'll have to put a string surrounded with double quotes in front of the code. '\n' will be a newline. Be aware of the fact, that there are other escape sequences as well. User '\\' if you are not sure.

CodenameLambda

Posted 2016-11-20T22:20:32.647

Reputation: 121

0

Python 2, 82 bytes

Works for space-only indentation

for i,l in enumerate(input().split('\n')):print l.split(l.lstrip())[0]+'#%d\n'%i+l

Indentation-less version for 56 bytes

for x in enumerate(input().split('\n')):print'#%d\n%s'%x

Rod

Posted 2016-11-20T22:20:32.647

Reputation: 17 588