# Do the needful? [closed]

Goal

Replace all comments in C, C++, or Java Code with the comment // Do the needful.

Specifics

This coding challenge is a simple one. Take as input the name of a file. The input file shall contain C, C++, or Java code. The code shall contain one or more comments. The comments can be single line /* */ or // delimited, as well as multi-line /* */ delimited. The output of the program should be identical to the input except all of the comments should be converted to // Do the needful.

For example if the input file is:

#include <iostream.h>

int   result;    // the result of the calculations
char  oper_char; // the user-specified operator
int   value;     // value specified after the operator

/* standard main function */
int main()
{
result = 0; // initialize the result

// Loop forever (or till we hit the break statement)
while (1) {
cout << "Result: " << result << '\n';

/* This code outputs display and requests
input from the user */
cout << "Enter operator and number: ";
cin >> oper_char;
cin >> value;

if (oper_char = '+') {
result += value;
} else {
cout << "Unknown operator " << oper_char << '\n';
}
}
return (0);
}


The output of the program should read

#include <iostream.h>

int   result;    // Do the needful
char  oper_char; // Do the needful
int   value;     // Do the needful

// Do the needful
int main()
{
result = 0; // Do the needful

// Do the needful
while (1) {
cout << "Result: " << result << '\n';

// Do the needful
cout << "Enter operator and number: ";
cin >> oper_char;
cin >> value;

if (oper_char = '+') {
result += value;
} else {
cout << "Unknown operator " << oper_char << '\n';
}
}
return (0);
}


Scoring

This is a popularity contest. You get two extra votes added to your score if none of the following words appears in your program in any case variation: {"do", "the", "needful"}. Score is number of votes plus bonus if applicable.

Allowances

If comments appear in string literals it is acceptable to convert them to // Do the needful as well. After all... you can never have enough needful.

• You know that the bonus is easily acquired by using "d" + "o", "t" + "he" and "need" + "ful"? Also, does the submission have to be able to deal with any valid C, C++ or Java code? That's pretty harsh and amounts to writing a lexer for all three languages (I'm thinking about comment literals in strings and vice-versa.) If so, what about 3rd-party lexer libraries? May 26 '14 at 23:55
• What should the program do when a /* ... */ precedes a non-comment on a line? May 27 '14 at 0:27
• Do we need to consider cases like char str[]="/**///"; or a comment-start sequence /* appears in a /* comment, or a backslash-newline appears in a // comment, or a // comment within a /**/ comment? May 27 '14 at 0:37
• Why make this a popularity contest and not code golf? It works just fine as golf. May 27 '14 at 2:41
• eventually lots of solutions are based on the same regex replacement. What about some bonus points for non regex solutions? May 27 '14 at 14:34

# CoffeeScript (66 bytes)

(c)->c.replace /\/\/.*\n?|\/\*[^]*?\*\//g,"// D\o t\he needfu\l\n"


This code will parse strings, but there is a good reason. You see, there is a possibility that there is a comment in a template generating C /**/ comments.

This gets the bonus, as it avoids exact case insensitive matches for Do, the, and needful. It also uses ES5 candle ([^]) operator to do stuff. I would put a comment Do the needful in this program, but that would remove the bonus.

# Perl, 68 characters

perl -0pe's@((//).*?(\n)|(/\*).*?(\*/))@\2\4 Do the needful \3\5@sg'


This takes some liberties with the specification, and retains the original comment style. This avoids the problem with /* ... */ comments appearing before the end of the line.

No attempt is made to avoid comments within string literals, and no claim is made for the bonus points.

• I am having a ball using this on source code! May 27 '14 at 1:08
• I would say it improves upon some commenting styles. May 27 '14 at 1:09
• You can get the bonus point like this May 27 '14 at 1:23
• perl -0pe 's/((\/\/).*?(\n)|(\/*).*?(*\/))/\2\4 D\coo th\coe needfu\cul \3\5/sg' May 27 '14 at 1:23
• @FDinoff: Yes, that was a liberty I took to simplify the problem, otherwise you have to figure out what to do with code lines where a /* ... */ comment precedes actual code (you can't naively turn it into a // comment). May 27 '14 at 7:11

# Perl

First world anarchy! :)

"you can never have enough needful"

#!perl -p0
sub the { s,(?<=\w)(.*)(\n),$1 // do the needful$2,g }
sub needful { s,//.*\n,\n,g,s,/\*.*?\*/,,msg }

do not do the needful


# Python 3.x, regex

Since it's not code golf I didn't fuss about code length. Nothing impressive, but I had fun remembering / relearning regex basics.

import re
import urllib.request as r
def dTN(filename):
with open(filename) as f:
return re.sub(r"//{1}.*", "//{0}".format(dtn), re.sub(r"/\*[A-Za-z \n]*\*/", "// {0}".format(dtn), f.read()))


# sed, 90 characters

Could be improved. I learned a lot about sed while making this.

Reads from standard input, outputs to standard output. Assumes valid input - if you have unterminated comments, it won't treat it as a comment.

Tested on GNU sed v4.2.2.

s_/\*.*\*/_//_
tg
s_/\*.*$_//_ tl :g s_//.*$_// Do the needful_
P
d
:l
s_.*\*/_//_
tg
N
bl


And the prize for readability goes to....?

One-liner version:

s_/\*.*\*/_//_;tg;s_/\*.*$_//_;tl;:g;s_//.*$_// Do the needful_;P;d;:l;s_.*\*/_//_;tg;N;bl


## Explanation

The control flow jumps around a lot, by means of GOTO statements (yes, sed has them!). sed does not have any loops or convenient conditional statements AFAIK.

s_/\*.*\*/_//_              # Substitute /* ... */ with //
tg                          # GOTO g if the substitution occured
s_/\*.*$_//_ # Substitute /*...<ENDOFLINE> with // tl # GOTO l if the substitution occured :g # GOTO-LABEL g s_//.*$_// Do the needful_  # Replace //...<ENDOFLINE> with // Do the needful
P                           # Print the pattern space (current line with substitutions)
d                           # empty the pattern space and move on to the next line
:l                          # GOTO-LABEL l
s_.*\*/_//_                 # Replace ... */ with //
tg                          # GOTO g if the substitution occured
N                           # take another line from input and add it to the pattern space
bl                          # GOTO l


## BrainFuck

Yes, BrainFuck is a Turing-complete language.
Good luck for understanding this code.

,[.-----------------------------------------------[>+>+<<-]>
>[-<<+>>][-]+<[[-]>-<]>[>,----------------------------------
-------------[>+>+<<-]>>[-<<+>>]<>[-]+<[>-<+++++[>+>+<<-]>>[
-<<+>>]<>[-]+<[>-<++++++++++++++++++++++++++++++++++++++++++
.[-]]>[<+++++++++++++++++++++++++++++++++++++++++++++++.----
-----------.++++++++++++++++++++++++++++++++++++.+++++++++++
++++++++++++++++++++++++++++++++.---------------------------
----------------------------------------------------.+++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++.------------.---.-------------------------
--------------------------------------------.+++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++.---------..-.++.+++++++++++++++.---------.[+++++[,------
------------------------------------],----------------------
-------------------------]>-]<<[-]]>[<++++++++++++++++++++++
+++++++++++++++++++++++++.---------------.++++++++++++++++++
++++++++++++++++++.+++++++++++++++++++++++++++++++++++++++++
++.---------------------------------------------------------
----------------------.+++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++.------------
.---.-------------------------------------------------------
--------------.+++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++.---------..-.++.++++++++++
+++++.---------.[,----------]++++++++++.[-]>-]<<[-]<<>-]<<,]


Basically, the pseudo-code is :

get input_char
while (input_char is not null)
{
print input_char
if (input_char is '/')
{
get input_char
if (input_char is '/')
{
print '/ Do the needful'
get input_char until input_char is '\n'
}
else
{
if (input_char is '*')
{
print '/ Do the needful'
get input_char until input_char is '*' followed by '/'
}
else
{
print input_char
}
}
}
get input_char
}


Some online interpreter are broken.
Try it here with the example given by the OP (ended with null-char to break the loop properly) :

#include <iostream.h>\n\nint   result;    // the result of the calculations \nchar  oper_char; // the user-specified operator \nint   value;     // value specified after the operator\n\n/* standard main function */     \nint main()\n{\n    result = 0; // initialize the result \n\n    // Loop forever (or till we hit the break statement) \n    while (1) {\n        cout << "Result: " << result << '\\n';\n\n        /* This code outputs display and requests\n           input from the user */\n        cout << "Enter operator and number: ";\n        cin >> oper_char;\n        cin >> value;\n\n        if (oper_char = '+') {\n            result += value;\n        } else {\n            cout << "Unknown operator " << oper_char << '\\n';\n        }\n    }\n    return (0);\n}\0


## Rebol

It's not code golf, so I'll be wordy.

do-the-needful: function [filename [file!]] [
parse (data: to-string read filename) [
; match the pattern in brackets ANY number of times (zero okay)
any [
; seek the parse position up TO one of the following matches
; if a match is hit, following code in parentheses is executed normally
to [
"/*" (terminator: "*/")
|
"//" (terminator: newline)
]

; save parse position in start, seek up THRU terminator and leave parse
; position at the end of the terminator match (not the beginning as w/TO)
start:
thru terminator
finish:

; Do partial replacement within the input; starting at START
; but limited to FINISH.  Again, structure in parentheses is exec'd as code
(
change/part start combine ["// Do the needful" newline] finish
)
]
]
return data
]


(Note: For political reasons, I am pushing COMBINE here, but it's not standard yet. So if you actually want to run this, use REJOIN. But I hate REJOIN. A wart on an otherwise beautiful language! Tell your friendly neighborhood Red dev leads to listen to me. Thanks.)

PARSE is a dialect, or language-within-a-language, in Rebol and Red. It twists things up, so for instance the symbol types that are used for assignment (the terminator: in terminator: newline) takes on a new meaning when used in the code-as-data paradigm... it saves the current parse position into a variable with that name. You can read more about why it's cool here.

UPDATE: Oh all right, I'll golf it too. In Rebmu, 72 chars... using rebmu/args which injects A as the argument:

pa DtsRDa[anTO["/*"(T"*/")|"//"(Tlf)]SthT F(chpS"// Do the needful^/"f)]d

Exactly the same program.