I've got some Java pseudocode that uses whitespace instead of curly braces, and I want you to convert it.
I/O
Your program should take an input file along with a number designating how many spaces are used to indent a block. Here's an example:
$ convert.lang input.p 4 // Convert using 4 spaces as the block delimiter $ convert.lang input.p 2 // Convert using 2 spaces as the block delimiter
It should then convert the result using the specified block delimiter and output the result to stdout.
The meat of the program
Blocks open with :
and each line within the block is indented using the block delimiter, like Python code.
while(true): System.out.println("Test");
Each :
is replaced with a {
, and a }
is appended to the end of the block.
while(true) { System.out.println("Test"); }
Examples
Input:
public class Test: public static void main(String[] args): System.out.println("Java is verbose...");
Output:
$ convert Test.pseudojava 4 public class Test { public static void main(String[] args) { System.out.println("Java is verbose..."); } }
Input:
main(): printf("Hello World");
Output:
$ convert test.file 2 main() { printf("Hello World"); }
Input:
def generic_op(the_stack, func): # Generic op handling code b = the_stack.pop() if isinstance(b, list): if b: return top = b.pop(0) while b: top = func(top, b.pop(0)) the_stack.push(top) else: a = the_stack.pop() return func(a, b)
Output:
$ convert code.py 4 def generic_op(the_stack, func){ # Generic op handling code b = the_stack.pop() if isinstance(b, list) { if b { return } top = b.pop(0) while b { top = func(top, b.pop(0)) } the_stack.push(top) } else { a = the_stack.pop() return func(a, b) } }
Scoring
The code with the least amount of bytes wins!
-
1\$\begingroup\$ Can we assume that the input contains no comments? \$\endgroup\$Martin Ender– Martin Ender2015年10月19日 07:19:37 +00:00Commented Oct 19, 2015 at 7:19
-
1\$\begingroup\$ @MartinBüttner It may contain comments, but the comments won't contain ':'. Basically, yes. \$\endgroup\$jado– jado2015年10月19日 07:32:45 +00:00Commented Oct 19, 2015 at 7:32
-
3\$\begingroup\$ What about labels, which are the usual reason that a line would end in a colon in valid Java source? \$\endgroup\$Peter Taylor– Peter Taylor2015年10月19日 08:11:29 +00:00Commented Oct 19, 2015 at 8:11
-
1\$\begingroup\$ I've never seen a label anywhere but the beginning of a line. \$\endgroup\$SuperJedi224– SuperJedi2242015年10月19日 13:20:15 +00:00Commented Oct 19, 2015 at 13:20
-
2\$\begingroup\$ I've just been reminded of how much I hate Java. \$\endgroup\$lirtosiast– lirtosiast2015年11月16日 04:46:57 +00:00Commented Nov 16, 2015 at 4:46
3 Answers 3
Perl, 41 bytes
#!perl -p0
1while s/( *).*\K:((
1円 .*)+)/ {2円
1円}/
Counting the shebang as two, input is taken from stdin. A command line argument need not be provided. Any valid nesting context can be determined (and matched) without knowing the indentation size.
Regex Break-Down
( *) # as many spaces as possible (1円)
.* # as many non-newline characters as possible \
(greediness ensures this will always match a full line)
\K # keep all that (i.e. look-behind assertion)
: # colon at eol (newline must be matched next)
(
(
\n1円 # newline with at least one more space than the first match
.* # non-newlines until eol
)+ # as many of these lines as possible
) # grouping (2円)
Sample Usage
in1.dat
public class Test:
public static void main(String[] args):
System.out.println("Java is verbose...");
Output
$ perl py2java.pl < in1.dat
public class Test {
public static void main(String[] args) {
System.out.println("Java is verbose...");
}
}
in2.dat
main():
printf("Hello World");
Output
$ perl py2java.pl < in2.dat
main() {
printf("Hello World");
}
in3.dat
def generic_op(the_stack, func):
# Generic op handling code
b = the_stack.pop()
if isinstance(b, list):
if b:
return
top = b.pop(0)
while b:
top = func(top, b.pop(0))
the_stack.push(top)
else:
a = the_stack.pop()
return func(a, b)
Output
$ perl py2java.pl < in3.dat
def generic_op(the_stack, func) {
# Generic op handling code
b = the_stack.pop()
if isinstance(b, list) {
if b {
return
}
top = b.pop(0)
while b {
top = func(top, b.pop(0))
}
the_stack.push(top)
}
else {
a = the_stack.pop()
return func(a, b)
}
}
-
\$\begingroup\$ i just wrote this in ruby \$\endgroup\$Not that Charles– Not that Charles2015年11月16日 07:54:49 +00:00Commented Nov 16, 2015 at 7:54
Python 3, (削除) 299 (削除ここまで) 265 bytes
import sys;s=int(sys.argv[2]);t="";b=0
for l in open(sys.argv[1]):
h=l;g=0
for c in l:
if c!=" ":break
g+=1
if g/s<b:h=" "*g+"}\n"+h;b-=1
if l.strip().endswith(":"):h=l.split(":")[0];h+=" {";b+=1
t+=h+"\n"
b-=1
while b>-1:
t+=" "*(b*s)+"}\n"b-=1
print(t)
Boom bam pow.
Algorithm used:
//global vars string total //total modified program int b //indent buffer line thru lines: //iterate over every line string mline = "" //line to be added to the total //calculate the amount of spaces before the line (could be a lot easier) int spaces = 0 //total spaces c thru line: //go through every character in the line if c != " ": //if the current char isn't a space (meaning we went though all of them break //break out of iterating through chars spaces++ //increment the spaces because we've hit a space (hurr derr) if spaces/SPACE_SETTING < b: //if indent count of the current line is less than the indent buffer mline = "}\n" + line //add closing bracket to beginning of line b-- //decrement buffer if line.endswith(":"): //if the line ends with a `:` remove : from line mline += " {" //append { b++ //increment buffer total += mline //add modified line to total print(total)
-
\$\begingroup\$ Can you include an explanation? \$\endgroup\$TanMath– TanMath2015年11月16日 05:22:22 +00:00Commented Nov 16, 2015 at 5:22
-
\$\begingroup\$ @TanMath Added the algorithm I used \$\endgroup\$jado– jado2015年11月16日 05:39:04 +00:00Commented Nov 16, 2015 at 5:39
-
\$\begingroup\$ Does it work with Python 2? \$\endgroup\$wb9688– wb96882015年11月17日 07:16:54 +00:00Commented Nov 17, 2015 at 7:16
-
\$\begingroup\$ @wb9688 No idea, I only tested it with Python 3 \$\endgroup\$jado– jado2015年11月17日 07:17:34 +00:00Commented Nov 17, 2015 at 7:17
-
\$\begingroup\$ I just tested, and it works with Python 2 \$\endgroup\$wb9688– wb96882015年11月17日 07:25:24 +00:00Commented Nov 17, 2015 at 7:25
Ruby, 70
x=$_+"
"
1while x.sub! /^(( *).*):
((2円 .*?
)*)/,'1円 {
3円2円}
'
$><<x
Adds a trailing newline. Does not need the indent block-size parameter.
Run this with -n0
(this is really 68+2). Thank you greatly to @primo for saving over a dozen bytes.
-
\$\begingroup\$ I think
-p0
also works for ruby (-0
reads all input at once,-p
stores stdin into$_
, and auto-prints it at the end). \$\endgroup\$primo– primo2015年11月16日 08:47:44 +00:00Commented Nov 16, 2015 at 8:47 -
\$\begingroup\$ @primo Good point. In case it wasn't clear with my comment above, this isn't a port of your code, but my own work that does exactly what yours does (but with more bytes) \$\endgroup\$Not that Charles– Not that Charles2015年11月16日 15:01:15 +00:00Commented Nov 16, 2015 at 15:01
-
\$\begingroup\$ I understood correctly, just providing a tip to remove the (rather verbose)
x=$<.readlines*''
. While I'm doing that,sub!
also has a two parameter overload (rather than one paramater + block) that accepts a replacement string, so you can use1円
,2円
, etc. instead of needing to concatenate it all. \$\endgroup\$primo– primo2015年11月16日 15:08:25 +00:00Commented Nov 16, 2015 at 15:08 -
\$\begingroup\$ @primo Thanks! I tried the two-parameter version before and abandoned it at some point last night. \$\endgroup\$Not that Charles– Not that Charles2015年11月16日 16:53:20 +00:00Commented Nov 16, 2015 at 16:53