Python Code Reviewer

6

Task

Your mission is to create a program that reviews Python code. The solution can be written in any language!

It must take input that contains python code. The program must add # This is not pythonic! before each block of non-whitespace lines.

Input

  • The data can be entered via stdin.
  • The data will contain at least 3 lines with one blank one in between them.

Minimum input example.

print "Hello World!"

Print "Bye World!"

Sample Input

from os.path import abspath

lines = []
with open(__file__, 'r') as f:
    for line in f:
        lines.append(line)

if lines is not None:

    newLines = []
    hasReviewedBlock = False

    for line in lines:
        if len(line) > 1: # \n
            if hasReviewedBlock == False:
                newLines.append("# This is not pythonic!\n")
                hasReviewedBlock = True
        else:
            hasReviewedBlock = False

        newLines.append(line)
    with open("d:/test.py", 'w') as f:
        for line in newLines:
            f.write(line);

Output

Output has to be written to STDOUT or closest alternative.

Sample Output

# This is not pythonic!
from os.path import abspath

# This is not pythonic!
lines = []
with open(__file__, 'r') as f:
    for line in f:
        lines.append(line)

# This is not pythonic!
if lines is not None:

# This is not pythonic!
    newLines = []
    hasReviewedBlock = False

# This is not pythonic!
    for line in lines:
        if len(line) > 1: # \n
            if hasReviewedBlock == False:
                newLines.append("# This is not pythonic!\n")
                hasReviewedBlock = True
        else:
            hasReviewedBlock = False

# This is not pythonic!
        newLines.append(line)
    with open("d:/test.py", 'w') as f:
        for line in newLines:
            f.write(line);

Scoring:

Lowest number of bytes wins. -5 bytes if your program can be used as valid input.

marsh

Posted 2015-09-12T13:51:05.073

Reputation: 199

3You haven't explained how you decide if code is pythonic or not. – Blue – 2015-09-12T13:59:20.390

2All python code is not Pythonic. Edited my question. – marsh – 2015-09-12T14:03:26.167

So what you're saying is that python itself is not pythonic? – Blue – 2015-09-12T14:04:02.093

5So, simply put, we have to insert "# this is not pythonic" before each block of non-whitespace lines? We're all for a joke here, but please make your spec crystal clear. – Level River St – 2015-09-12T14:08:15.403

Yes, sorry I am not sure how to make it more clear. I have not made a code golf question before. – marsh – 2015-09-12T14:12:39.690

1I don't quite understand the bonus. What does "can be used as valid input" mean? I figure pretty much any program in any language can be used as an input. What makes it valid? – Reto Koradi – 2015-09-12T15:05:57.773

2Couple more questions: Can the first line be empty? Can there be sequences of multiple empty lines? – Reto Koradi – 2015-09-12T15:15:40.210

@RetoKoradi You can only put a blank line at the second line of code when the minimum is a 3LOC input with a line in "between". In this case, the first line can never be empty. – mınxomaτ – 2015-09-12T16:06:49.533

Are functions allowed? – Downgoat – 2015-09-12T16:20:47.510

Functions are allowed, the first line can not be empty. Valid input is python code. So basically to get the bonus it has to be in python, and have 2 code blocks. – marsh – 2015-09-12T23:54:01.017

whitespace\tis\tEVIL! – Max – 2015-09-17T08:06:05.610

Answers

3

awk, 64 56 54 bytes

/^$/{i=0}/./{if(!i++)print"# This is not pythonic!"}1

Test:

echo '/^$/{i=0}/./{if(!i++)print"# This is not pythonic!"}1' > solution.awk
awk -f solution.awk < pyth.py
awk -f solution.awk < pyth.py

Explanation:

/^$/ - matches empty line,

/./ - matches non-empty line,

1 - matches each line. No body is equivalent to {print;} - each line of input is printed.

pawel.boczarski

Posted 2015-09-12T13:51:05.073

Reputation: 1 243

2

Wren, 73-5 = 68 bytes

Luckily enough, Wren has an automatic WYSIWYG that gains the bonus.

Fn.new{|i|("

"+i).split("

").join("

# This is not pythonic!
")[2..-1]}

Try it online!

Explanation

Fn.new{|i|    // In this case we define a new
              // anonymous function with the operand i
          ("

"+i)          // We prepend the input with 2 newlines
    .split("

")            // Split the input by newlines,
              // including the preceding newlines
              // that we first prepended
  .join("

# This is not pythonic!
")            // Join the input with 2 newlines
              // , the comment, and another trailing newline
  [2..-1]}    // Slice the input so that the preceding
              // 2 newlines are not present in the final output
```

user85052

Posted 2015-09-12T13:51:05.073

Reputation:

2

Perl 6, 40 - 5 = 35 bytes

{S:g/^|"

"<(/# This is not pythonic!
/}

Try it online!

The bonus is rather weird, but it didn't cost me any bytes to add.

Explanation

{S:g/        /   /}  # Substitute all instances of
     ^                 # The start of the string
      |"  "            # or two newlines
           <(          # But don't actually replace, just append
              ...    # With the given string

Jo King

Posted 2015-09-12T13:51:05.073

Reputation: 38 234

2

AutoIt - 139

$1='# This is not pythonic!'
ConsoleWrite($1&@CRLF&StringRegExpReplace(FileRead($CmdLine[1]),'(*BSR_ANYCRLF)(^\R|\R(?=\R))',"\0"&@CRLF&$1))

I'm assuming the first line cannot be empty as by your specification:

The data will contain at least 3 lines with one blank one in between them.

This program is called like this:

compiled.exe pycode.py > output.txt

The RegEx can be optimized for sure. Works for CRLF only.

mınxomaτ

Posted 2015-09-12T13:51:05.073

Reputation: 7 398

2

Pyth, 39 38 37 bytes

tjbm|d+b"# This is not pythonic!"+k.z

Live demo.

Explanation

tjbm|d+b"# This is not pythonic!"+k.z
                                 +k.z    Prepend the empty line to the string
   m                                     For each line
    |d                                   If it's non-empty, return the same line
      +b"# This is not pythonic!"        Else, return a line break followed by the required text
 jb                                      Join via line breaks
t                                        Remove the unneeded preceding line break

38-byte version

tjbm?dd+b"# This is not pythonic!"+k.z

39-byte version

jbtsm?dd,d"# This is not pythonic!"+k.z

No doubt there's still golfing left to do.

kirbyfan64sos

Posted 2015-09-12T13:51:05.073

Reputation: 8 730

1

Python 3, 86 bytes - 5 = 81

import re

print(re.sub(r"(^\n*|\n\n+)",r"\1# This is not pythonic\n",open(0).read()))

Try it online!


Python 3, 94 bytes - 5 = 89

p=''

for c in open(0).read().splitlines():print("# This is not pythonic!\n"*(p==''!=c)+c);p=c

Try it online!

Mukundan

Posted 2015-09-12T13:51:05.073

Reputation: 1 188

@ReinstateMonica your code adds a # before the first line – Mukundan – 2020-01-08T02:14:25.513

Whoops! 78, my bad

– Reinstate Monica – 2020-01-08T10:27:32.433

1

CJam, 41 bytes

"# This is not pythonic!":TNqN/{_{T}|}%N*

Try it online

Alternate solution that handles multiple empty lines in succession, as well as empty lines at the start. This is 44 bytes, and will become my solution depending on how the pending clarifications turn out:

qN/{_L!e&{"# This is not pythonic!"\}&:L}%N*

Reto Koradi

Posted 2015-09-12T13:51:05.073

Reputation: 4 870

1

JavaScript (ES6), 70

Test running the snippet below.

f=p=>alert((r='# This is not pythonic!\n')+p.replace(/\n\n+/g,x=>x+r))

//// TEST CASES /////

t1=`print "Hello World!"

Print "Bye World!"`
f(t1)

t2=`from os.path import abspath

lines = []
with open(__file__, 'r') as f:
    for line in f:
        lines.append(line)

if lines is not None:

    newLines = []
    hasReviewedBlock = False

    for line in lines:
        if len(line) > 1: # \n
            if hasReviewedBlock == False:
                newLines.append("# This is not pythonic!\n")
                hasReviewedBlock = True
        else:
            hasReviewedBlock = False

        newLines.append(line)
    with open("d:/test.py", 'w') as f:
        for line in newLines:
            f.write(line);`
f(t2)

edc65

Posted 2015-09-12T13:51:05.073

Reputation: 31 086