| Bytes | Lang | Time | Link |
|---|---|---|---|
| 023 | Uiua | 240307T154345Z | noodle p |
| 084 | JavaScript Node.js | 231008T003938Z | noodle p |
| 126 | Swift 5.9 | 240308T132609Z | macOSist |
| 026 | ☾ | 250406T141211Z | noodle p |
| 013 | Vyxal 3 | 250218T194448Z | pacman25 |
| 031 | Perl 5 + lF\| M5.10.0 | 240309T152258Z | Dom Hast |
| 050 | Perl 5 pl | 240308T220345Z | Xcali |
| 043 | GolfScript | 231011T034444Z | noodle p |
| 074 | Ruby | 231008T211935Z | noodle p |
| 136 | Java 11 | 160909T073150Z | Kevin Cr |
| 096 | Haskell | 231010T111316Z | Laikoni |
| 079 | JavaScript Node.js | 231008T012743Z | l4m2 |
| 925 | Vyxal j | 231008T130631Z | lyxal |
| 016 | Japt R | 231008T123934Z | noodle p |
| 017 | Japt R | 230823T210555Z | Shaggy |
| 209 | Go | 230822T160933Z | bigyihsu |
| 025 | Thunno 2 N | 230822T143303Z | The Thon |
| 028 | APL Dyalog Unicode | 160909T124900Z | Adá |
| 016 | Stax | 210609T163237Z | Razetime |
| 103 | AWK | 210607T195254Z | cnamejj |
| 099 | Python 3.8 prerelease | 210608T174514Z | kur0dama |
| 108 | Python 3 | 210607T184046Z | KinuTheD |
| 029 | 05AB1E | 180605T095432Z | Kevin Cr |
| 010 | Jelly | 180605T130936Z | Erik the |
| 089 | Funky | 171113T230525Z | ATaco |
| 085 | GolfScript | 160910T155339Z | FedeWar |
| 035 | Turtlèd | 160921T031908Z | Destruct |
| 032 | CJam | 160913T163211Z | Neorej |
| 063 | Perl | 160912T091310Z | Ton Hosp |
| 154 | C# | 160910T195016Z | pinkfloy |
| 094 | Floroid | 160910T140208Z | Yytsi |
| 099 | Python 2 | 160909T100830Z | ElPedro |
| 041 | Jelly | 160911T022541Z | Jonathan |
| 132 | Python 2 | 160909T060519Z | Jonathan |
| 038 | Vim | 160909T221944Z | Jordan |
| 030 | Pyth | 160910T001307Z | TheBikin |
| 086 | GNU sed 85 + 1 for r | 160909T153541Z | Riley |
| 023 | Pyth | 160910T024413Z | Maltysen |
| 080 | Ruby | 160909T071207Z | Jordan |
| 031 | MATL | 160909T121732Z | Luis Men |
| 099 | PowerShell v2+ | 160909T134230Z | AdmBorkB |
| 034 | Retina | 160909T083702Z | Martin E |
| 111 | Groovy | 160909T082253Z | norganos |
| 024 | Pyke | 160909T124546Z | Blue |
| 123 | Scala | 160909T112434Z | AmazingD |
| 109 | PHP | 160909T090720Z | Titus |
| 135 | Haskell | 160909T081851Z | sudee |
| 092 | JavaScript ES6 | 160909T083923Z | Neil |
Uiua, 42 36 33 26 23 bytes
≡⊂≡↻₁⬚@ \◇(⌝↘⧻)°/$"_|_"
Try it: Uiua pad
Revisiting one of my first Uiua solutions over a year later, I was able to shave off quite a few more bytes, in part thanks to the addition of ⌝↘ (anti-drop) to prepend a given number of spaces to a string, as well as changes made to filled \ (scan).
JavaScript (Node.js), 84 79 84 bytes
c=>s=>s.split`|`.map(l=>z="".padEnd(z.length)+l,z="").map(l=>l.padEnd(z.length+1)+c)
After a year and a half I realized this was bugged all along :) fixed!
Swift 5.9, 153 152 126 bytes
{var x={{String.init}()(" ",$0)},i=0
for c in($0+"").split{$0=="|"}{print(x(i)+c+(i+=c.count,x($0.count{$0 != "|"}-i)).1,$1)}}
This is an almost direct port of Kevin Cruijssen's Java answer.
Vyxal 3, 13 bytes
'|÷:σ«ʈ»␣+$+”
basically a port of Vyxal 2, but really wants the "append string with space before" because that saves 3 bytes
Perl 5 + -lF\| -M5.10.0, 31 bytes
A different approach to both the existing Perl answers.
$,=v12;say@F," .[A@{[<>]}.."x@F
Explanation
Sets $, (which is the record separator, automatically printed between each item of a list) to v12 (which is chr(12), or form feed - which moves the cursor down a line), then we say @F (which is the input, split on |), followed by a raw string consisting of space, the ANSI escape sequence for "up one line", the comment char from STDIN (<>), which is embedded to the string using @{[...]}, and two backspace characters, which is repeated the same number of times as there are items in the input (using the list of input, @F, in a scalar context yield the list length).
GolfScript, 44 43 bytes
~:~;"|"/[""\{\," "*\+.}/,):l;]{l" "*+l<~n}/
This was my first GolfScript submission, and I’ve improved quite a lot since I first tried this task.
Explanation:
~:~;
Eval STDIN as GolfScript. Assign the comment character to the ~ variable, and pop out of the stack, so the code is on top.
Using a symbol instead of a letter as a command name let me remove a whitespace later on.
"|"/
Split the code on |s.
[""\{\," "*\+.}/
This is equivalent to a scan (reduce, keeping in-between values) by repeating spaces to the length of the previous value, and prepending that to the current value.
GolfScript doesn’t have scan built-in, so this is implemented somewhat cumbersomely, using / (each) and duplicating the result each iteration.
,):l;]
The previous step left an extra copy of the last value. We take its length, increment that, and assign it to l.
{l" "*+l<~n}/
For each line ({ … }/): append l spaces (l" "*+), take the first l characters (l<), then push ~ (the comment character) and n (newline).
The entire stack is printed when the program ends.
Original solution:
GolfScript, 64 63 bytes
~n+:c;0:a;."|"/""*,):b;{.124={;b" "*c" "a*}{a):a;b(:b;}if}%" "c
Full program, takes input like "abc|def|g" "#" on STDIN.
I’ve always thought GolfScript seemed interesting but have never actually tried it. After using quite a few more modern golfing languages with hundreds of built-ins, the terse but very readable syntax of GolfScript is really refreshing. I had a lot of fun trying to get this to work, so I’m glad I could beat the 75 byte solution posted in 2017.
I had a 50-or so byte version that used stack manipulation instead of variables, but couldn’t get it to work.
I hope you like the smileys ): (: :b :c ={
Explanation
Eval the input; this leaves two strings on the stack. Append a newline to the top one, store it in c as the comment character, and pop it off the stack. The variable a is initialized to 0. The variable b is initialized to the length of splitting the input on | and joining it back.
The top of the stack is now the |-separated string. Map each character of the input string to:
If the character is
|, leavebspaces,c, a newline, andaspaces on the stack.Otherwise, increment
a, decrementb, and leave the original character in the stack.
Finally, push a space and c to the stack. The whole stack is implicitly output at the end.
Ruby, 80 74 bytes
->i,c{a=0;(i=i.split ?|).map{" "*a+_1+" "*(1+i.join.size-(a+=_1.size))+c}}
I managed to golf a non-regex based solution to beat the other Ruby. The solution previously tied but I found a slightly different method that is 6 bytes shorter.
Explanation:
->i,c{…} Proc (lambda function) taking arguments i (code) and c (comment)
a=0;Assign variableato zero(i=i.split ?|)Assignito it split on|.map{…}Map each_1in the list to:" "*aaspaces+_1Append the list item+" "*(…)Append this many spaces:1+i.join.sizeThe size ofiwith|removed, plus one for the extra space-(a+=_1.size)Add the size of the list item toaand subtractafrom this.
+cAppend the comment character to the end of the line.
Java 11, 189 159 136 bytes
s->c->{int p=0;for(var a:s.split("\\|"))System.out.println(" ".repeat(p)+a+" ".repeat(s.replace("|","").length()-(p+=a.length())+1)+c);}
-30 bytes converting Java 7 to Java 10 and optimizing the loops.
-23 bytes converting Java 10 to Java 11, so String#repeat builtin can be used.
Explanation:
s->c->{ // Method with String & char parameters and no return-type
int p=0; // Position-integer, starting at 0
for(var a:s.split("\\|")) // Loop over the parts split by "|":
System.out.println( // Print with trailing newline:
" ".repeat(p) // `p` amount of spaces
+a // plus the current part
" ".repeat(s.replace("|","").length()-(p+=a.length())+1)
// plus the correct trailing amount of spaces
// (and add the length of the current part to `p` at the
// same time)
+c);} // plus the current comment character
Haskell, 96 bytes
f"".lines.map r
r '|'='\n'
r c=c
w=(' '<$)
f l(a:s)c=(w l++a++(w=<<c:s)++c):f(l++a)s c
f l s c=s
Eplanation
The function r is defined to map pipe characters to newlines (r '|'='\n') and every other char to itself (r c=c). lines.map r thus first replaces all pipes in the input string with new lines (map r), and then splits the string at the newlines with the build-in lines function.
The main function f iterates over this list of strings and constructs the output line by line with the expression w l++a++(w=<<c:s)++c where
ais the part of the code that appears on the current linecis the comment character (as a string) that gets put at the end of the linewis a function that replaces each character of a string by spaces (definde byw=(' '<$))lis the string of code fragments to the left ofa, which is put at the beginnig of the line as spaces withw lsis the list of remaining code strings which are also converted to spaces, concatenated, and put aftera(cis added tosto get the extra space required before the comment character)
JavaScript (Node.js), 79 bytes
c=>s=>s.split`|`.map((_,i,a)=>a.map(y=>i--?y.replace(/./g,' '):y).join``+' '+c)
+4 to add an extra space before #
Vyxal j, 74 bitsv2, 9.25 bytes
\|/:¦↳:t↲Ḋ
Bitstring:
01101010100010101110000101000000110001011111111110001111111100110011110001
Explained
\|/:¦↳:t↲Ḋ
\|/ # Split on "|"s
:¦ # Push the cumulative sums without popping. This acts as the space length before each section
↳ # Pad each item right with spaces to length in ^
:t↲ # And pad each item left with spaces to length of tail of ^
Ḋ # Append " {comment char}" to each
Implicitly join on newlines
💎
Created with the help of Luminespire and not this challenge.
Japt -R, 16 bytes
q| åÏiXîÃú m+S+V
The boilerplate is similar to @Shaggy's 17 byte Japt submission.
Explanation:
q| split on |
åÏ cumulatively reduce each X, Y to:
i prepend to Y
Xî spaces to the length of X
à end cumulative reduce
ú right-pad each to the longest line
m+ to each, append
S+V space (S) and comment char (V)
flag -R join the final result on newlines
Japt -R, 17 bytes
There's a byte to be saved here, at least, I just can't quite see it.
q| ËùT±DÊÃú Ë+ViS
q| ËùT±DÊÃú Ë+ViS :Implicit input of strings U=programme & V=character
q| :Split U on |
Ë :Map each D
ù : Left pad with spaces to length
T± : Increment T (initially 0) by
DÊ : Length of D
à :End map
ú :Right pad each with spaces to length of longest
Ë :Map
+ : Append
Vi : V prepended with
S : Space
:Implicit output joined with newlines
Go, 209 bytes
import."strings"
func f(C,c string)string{L,Q,S:=Split(C,"|"),[]string{},0
for _,l:=range L{q:=len(l)
if q<1{continue}
Q=append(Q,Repeat(" ",S)+l+Repeat(" ",len(Join(L,""))-q+1-S)+c)
S+=q}
return Join(Q,"\n")}
Explanation
import."strings"
func f(C,c string)string{
// split C into substrings, and init the output slice and space count
L,Q,S:=Split(C,"|"),[]string{},0
// for each substring...
for _,l:=range L{
// if it's empty, skip it
q:=len(l)
if q<1{continue}
// add to the output slice...
Q=append(Q,
// initial spaces
Repeat(" ",S)+
// the substring
l+
// the following spaces
Repeat(" ",len(Join(L,""))-q+1-S)
// and the comment
+c)
// increment the space count
S+=q}
// join together with newlines
return Join(Q,"\n")}
Thunno 2 N, 25 bytes
'|/DJl⁺X0Yıyṣs+xðĿnlẏ+ƥ¹+
Explanation
(Yes, this is in the exact same format as the outputs for this challenge :P)
'|/DJl⁺X0Yıyṣs+xðĿnlẏ+ƥ¹+ '# Implicit input
'|/ '# Split the input on "|"
DJl # Duplicate, join, and get length
⁺X # Increment this and store it in x
0Y # Store 0 in y
ı # Map over the list:
yṣ # Push y spaces
s+ # Prepend this to the input
xðĿ # Pad with spaces to length x
nlẏ+ƥ # Add the length to y
¹+ # Append the second input
# Implicit output, joined on newlines
APL (Dyalog Unicode), 28 bytes
Full program. Prompts for code, then for comment character.
⍞,⍤1⍨⎕FMT⎕TC[2]@('|'∘=)⍞,' '
⍞,' ' append a space the to prompted-for code
⎕TC[2]@(…) place the 2nd Terminal Control character (Line Feed) at the positions indicated by:
'|'∘= the mask indicating where the pipe symbol is equal to the characters
⎕FMT ForMaT as a character matrix, evaluating terminal control characters (Line Feed moves the "cursor" down one line)
⍞,⍤1⍨ prompt for comment character and append it to each line (lit. to each 1D sub-array)
AWK, 107 104 103 bytes
w=2-(n=split($1,p,"|"))+gsub(t=".",FS,$1){for(;s++<n;gsub(t,FS,b))y=y substr((b=b p[s])$1,1,w)$2RS}$0=y
Thanks to Pedro Maimere for helping shave off more 3 chars
One interesting thing about this challenge... I found a quirk about the TIO AWK setup. I can't figure out way to specify input where a positional argument can contain a space. Meaning setup a TIO test that behaves like this commandline,
echo "this is the first parameter" second | gawk '{ print $1 }'
In TIO, the first parameter will be "this not the whole string. That means while it works in a terminal window, I can't show that it handle the second test for this challenge in TIO.
Here's how the code works... The test associated with the codeblock is always truthy, so the code always runs. It's only a test (rather then code) to avoid needing a ; character. It does a couple of things by using AWK's willingness to combine multiple expressions into one "line" of code.
w=2-(n=split($1,p,"|"))+gsub(t=".",FS,$1)
First is splits the first parameter into in array of strings using the pipe character as the delimeter with n=split($1,p,"|"). It also saves the number of substrings generated in n. Then it changes all the characters in the first parameter to spaces with gsub(t=".",FS,$1) setting convenience constants t and n in the process.
Finally the value of w is set to the number of non-pipe characters in the first parameter by subtracting the number of sub-strings from the total number of characters in the original.
The associated code block is one statement, a for loop, that processes each substring.
for(;s++<n;gsub(t,FS,b))y=y substr((b=b p[s])$1,1,w)$2RS
The iteration check is simple s++<n. The end of loop statement converts all the characters in the previous output line to blanks gsub(t,FS,b), which turns it into the prefix for the next line. The body of the loop constructs and appends the next line of output to an accumulator y. That string is a concatenation of the previous string, plus the current string (code fragment) with a bunch of blanks appended (meaning $1) (b=b p[s])$1. That mess is truncated to the length we want w and the comment delimiter and LF are appended with y=y substr(...,w)$2RS.
Once all the code substrings have been processes, assigning $0 to the accumulator takes care if printing out the results.
$0=y
Python 3.8 (pre-release), 99 bytes
Different approach:
def f(c,d,i=0):
for y in(x:=c.split('|')):z=[' '*len(e)for e in x];z[i]=y;print(''.join(z),d);i+=1
Ungolfed with explanation:
def f(c,d,i=0):
x=c.split('|') # break string by '|'
for y in x: # for each element of list
z=[' '*len(e) for e in x] # create a list of blank strings
z[i]=y # insert element we care about into otherwise blank list
print(''.join(z),d) # print line
i+=1 # increment
Python 3, 108 bytes
s,c=input().split("|"),input()
i,S=0,len("".join(s))
for l in s:L=len(l);print(" "*i+l+" "*(S-L-i+1)+c);i+=L
Try it online! Simple solution -- keep track of how many spaces we have (i) and accumulate.
05AB1E, 29 38 31 29 bytes
'|„ǝʒ:'ǝ¡'ʒмεD®>úsg®+©s}.Bεð²J,
Can definitely be golfed, but at least its working now..
+9 bytes because ¡ (split) removes empty items automatically, so I had to add '|„ǝʒ:'ǝ¡'ʒм..
-2 bytes thanks to @MagicOctopusUrn by changing '|„ǝʒ:'ǝ¡'ʒм to '|¶:.BεðÜ} (current solution doesn't work on items with trailing spaces, but I've assumed that's allowed according to the test cases).
Explanation:
'|¶: # Take the first input, and replace every "|" with "¶"
# i.e. "abc|d|e||fg" → "abc¶d¶e¶¶fg" (¶ are new-lines in 05AB1E)
.B # Box all the items (appending trailing whitespace to make it a rectangle)
# i.e. "abc¶d¶e¶¶fg" → ['abc','d ','e ',' ','fg ']
εðÜ} # Remove all trailing spaces from each item
# i.e. ['abc','d ','e ',' ','fg '] → ['abc','d,'e','','fg']
# NOTE: `'|¡` would have resulted in ['abc','d','e','fd'], hence the use of
# Box which implicitly splits on new-lines to keep empty items
ε # For-each:
D # Duplicate the current item
®>ú # Prepend global_variable + 1 amount of spaces
# (+1 because the global_variable is -1 by default)
# i.e. "e" and 3+1 → " e"
sg # Swap so the duplicated item is at the top, and take its length
®+ # Sum it with the global_variable
# i.e. "e" (→ 1) and 4 → 5
© # And store it as new global_variable
s # Then swap so the space appended item is at the end again
} # And end the for-each loop
.B # Box all the items (appending the appropriate amount of spaces)
# i.e. ['abc',' d',' e',' ',' fg']
# → ['abc ',' d ',' e ',' ',' fg']
ε # For-each again:
ð # A space character
I # The second input-character
J # Join both together with the current item
, # And print the current row with trailing new-line
Funky, 89 bytes
s=>c=>{y=0forn inl=s::split"|"print((v=" "::rep)(y)+l[n]+v((#l::reduce@++1)-y+=#l[n])+c)}
GolfScript, 85 bytes
{(;);}:r;", "%(r\(r n+:c;;.,\'|'%.,@\-)):l;0:m;{.,0>}{" "m*\(.,m+:m l\-" "\*+c@}while
2017 Update - GolfScript - 71 bytes
', '/~~:c;~1/.,\.{'|'=},,@\-):l;['|']/0:i;{.,i+:i l i-' '*c+\' '*"
"\}/
Explanation
', '/~~:c;~1/ # Parses input
.,\.{'|'=},,@\-):l; # Computes string length without '|'
['|']/ # Splits the array
0:i; # Counter
{., # Length of the substring
i+:i # Counter update
l i-' '*c+\ # Adds spaces after the substring
' '*"\n"\ # Adds spaces before the next substring
}/ # ...For each substring
Turtlèd, 35 bytes (noncompeting)
Takes one input, the last character is the comment character. Does not work with comment character as space, but I assume that isn't necessary.
!' [*.+(|' dl)r_]' r[*+.(|u)_][ .d]
Explanation:
! take input into string variable
' write space over current cell
[* ] while cell is not *
.+ write pointed char of string, stringpointer+1 (starts 0)
(| ) if current cell is |
' dl write space (over |), move down, left
r_ move right, write * if pointed char is
last char, else space
' r write space, move right
[* ] while cell is not *
+. increment pointer and write pointed char
(|u) if cell is |, move up
_ write * if the pointed char is the last char
[ ] while cell is not space
.d write the pointed char from string, move down
CJam, 32 bytes
l'|/_s,)L@{1$,S*\+}%@f{Se]}lN+f+
Explanation
l get code string
'|/ split into code parts
_s,) length of all the parts +1
L@{1$,S*\+}% left pad spaces to every part for the length of the previous parts
@f{Se]} right pad spaces
lN+f+ add comment character and newline
Perl, 63 bytes
Includes +5 for -Xpi
Run with input on STDIN and comment character after -i:
perl -Xpi% esolang.pl <<< "Ab|Cd||ef"
esolang.pl:
s/
/|/;s%(.*?)\|%$"x$`=~y/|//c.$1.$"x$'=~y/|//c." $^I
"%eg
Totally boring straightforward solution
C# 176 167 154 bytes
string f(string s,char x){var c=s.Split('|');var d="";int i=0;foreach(var b in c)d+=b.PadLeft(i+=b.Length).PadRight(s.Length+2-c.Length)+x+"\n";return d;}
UnGolfed
string f(string s, char x)
{
var c = s.Split('|');
var d = "";
int i = 0;
foreach (var b in c)
d += b.PadLeft(i += b.Length).PadRight(s.Length + 2 - c.Length) + x + "\n";
return d;
}
A LINQ solution would have been 146 but needed using System.Linq; bringing it back up to 164:
string f(string s,char x){var c=s.Split('|');int i=0;return c.Aggregate("",(g,b)=>g+b.PadLeft(i+=b.Length).PadRight(s.Length+2-c.Length)+x+"\n");}
Old solutions:
167 bytes:
string f(string s,char x){var c=s.Split('|');var d="";int i=0;foreach(var b in c){d+=b.PadLeft(i+b.Length).PadRight(s.Length+2-c.Length)+x+"\n";i+=b.Length;}return d;}
176 bytes using string interpolation
string f(string s,char x){var c=s.Split('|');var d="";int i=0;foreach(var b in c){d+=string.Format($"{{1,{i}}}{{0,-{s.Length+2-c.Length-i}}}{x}\n",b,"");i+=b.Length;}return d;}
Floroid - 94 bytes
Ah(a,b):c=a.fn("|");z(" "+b+"\n".y(' '*Z("".y(c[:j]))+l+" "*Z("".y(c[j+1:]))Kj,lIai(c))+' '+b)
Uses an approach similar to @JonathanAllans' Python solution.
Testcases
Call: h("a|bc|d|e|fgh|ij|k|l|mn|op", "#")
Output:
a #
bc #
d #
e #
fgh #
ij #
k #
l #
mn #
op #
Python 2, 107 105 102 99 bytes
Tested with all test cases above
EDIT Golfed off 2 bytes by changing d=a.split("|");i=0 to d,i=a.split("|"),0 Not sure how I missed that one. Thanks @Oliver Ni
Another 3 bytes gone. Thanks again.
Suggestion from @Jonathan actually saves 3 bytes and takes it down to the magic 99. Thanks.
def c(a,b):
d,i=a.split("|"),0
for e in d:j=i+len(e);print" "*i+e+" "*(len("".join(d))-j+1)+b;i=j
Jelly, 41 bytes
This looks like it has far to many increments, and probably too many links...
ṫø⁹‘‘µFL‘⁶ẋ
‘ị
ḣFL⁶ẋ$;ç@;1ŀ
J’ç@€
ṣ”|Ç;€Y
Test it at TryItOnline
How?
ṫø⁹‘‘µFL‘⁶ẋ - link 1: get the spaces for after the code, dyadic(split string, index)
ø - next chain as a nilad
⁹‘‘ - right argument incremented twice (the index we actually want)
ṫ - tail (get the rest of the split string)
µ - next chain as a monad
FL‘ - flatten, get its length and increment
⁶ - a space character " "
ẋ - repeat the space character that many times
‘ị - Link 2: get the code for a line dyadic(index, split string)
‘ - increment the index
ị - retrieve the string at that index
ḣFL⁶ẋ$;ç@;1ŀ - Link 3: get the code and join with spaces, dyadic (index, split string)
ḣ - head: split string[index:]
FL - flatten and get its length
$ - previous two atoms as a monad
⁶ - a space character, " "
ẋ - repeat the space that many times
; - concatenate with
ç@ - the result of the previous link (the code) - reverse inputs
; - concatenate with
1ŀ - the result of Link 1 (the spaces after the code)
J’ç@€ - Link 3: a for loop, monadic(split string)
J’ - [0,...,Len(split string)-1]
ç@€ - the result of the previous link, with revered inputs, for each
ṣ”|Ç;€Y - Main Link: dyadic(code string, comment character)
ṣ”| - split on "|"
Ç - the result of the previous link
;€ - concatenate each with the comment character
Y - join with line feeds
- implicit print
Python 2, 125 124 132 bytes
-1 byte thanks to @TuukkaX (missed golfing the space from i, v)
def g(s,c):x=s.split('|');print((' '+c+'\n').join(' '*len(''.join(x[:i]))+v+' '*len(''.join(x[i+1:]))for i,v in enumerate(x))+' '+c)
All test cases on ideone
Vim, 39 38 keystrokes
-1 byte thanks to DJMcMayhem
Expects as input a buffer (e.g. a file) whose first character is the comment delimiter, followed by the code, e.g. #foo|bar|baz.
"cxqaf|m`Yp<Ctrl+o>v$r jv0r x@aq@a$p<Ctrl+v>gg$C <Ctrl+r>c<Esc>
Explanation
("_" denotes a literal space.)
"cx " Delete the first character (the comment delimiter) and store in register 'c'
qa " Start recording macro 'a'
f|m` " Advance to the first '|' on the line and set mark
Yp<Ctrl+o> " Duplicate this line and return to mark
v$r_ " Replace everything after the cursor on this line (inclusive) with spaces
jv0r_x " Go down a line and replace everything before the cursor on this line (inclusive) with
" spaces, then delete one space
@a " Call macro recursively
q@a " Stop recording and immediately call the macro
$p " Paste the deleted space at the end of the last line
<Ctrl+v>gg$ " Highlight the column where the comment delimiters will go and all trailing spaces
C_<Ctrl+r>c<Esc> " Replace the highlighted text on each line with a space and the contents of
" register 'c' (the comment delimiter)
Pyth, 30 bytes
VJcE\|s[*ZdN*h--lsJZlNdQ)=+ZlN
or
jm+dQ.t.t+MC,.u*l+NYdJc+Ed\|kJ
Both are full programs that take input on STDIN of the comment string, and then the program string, newline-separated.
How they work
VJcE\|s[*ZdN*h--lsJZlNdQ)=+ZlN Program. Inputs: E, Q
cE\| Split E on "|"
J Assign to J
Implicit Z=0
V For N in that:
[ ) Create a list with elements:
*Zd Z spaces
N N
-lsJZ len(concatenate(J))-Z
- lN -len(N)
h +1
* d spaces
Q Q
s Concatenate the list
Implicitly print
=+ZlN Z=Z+len(N)
jm+dQ.t.t+MC,.u*l+NYdJc+Ed\|kJ Program. Inputs: E, Q
+Ed Add a trailing space to E
c \| Split that on "|"
J Assign to J
.u Cumulatively reduce J with:
k starting value empty string and
function N, Y ->
l+NY len(N+Y)
* d spaces
, J Two-element list of that and J
C Transpose
+M Map concatenation over that
.t Transpose, padding with spaces
.t Transpose again
m+dQ Map concatenation with Q over that
j Join on newlines
Implicitly print
GNU sed (85 + 1 for -r) 86
:s;h;:;s,\|( *)[^ \|](.),|\1 \2,;t;s,\|,,g
p;g;:l;s,^( *)[^ \|],\1 ,;tl;s,\|,,;/\S/bs
The inputs are strings separated by a space.
Tests:
input.txt:
a|b|c|d|e|f|g ,
abcdefg :
4|8|15|16|23|42 %
E|ac|h s|ecti|on is| one c|haracte|r longer| than the| last! !
This|Code|has||empty||sections @
Output:
$ cat input.txt | sed -rf template
a ,
b ,
c ,
d ,
e ,
f ,
g ,
abcdefg :
4 %
8 %
15 %
16 %
23 %
42 %
E !
ac !
h s !
ecti !
on is !
one c !
haracte !
r longer !
than the !
last! !
This @
Code @
has @
@
empty @
@
sections @
Pyth - 28 27 24 23 bytes
Might be able to golf a little off. A lot off, apparently!
jt+R+;zC.t.u+*lNdYcQ\|k
Ruby, 96 80 bytes
->s,c{s.gsub(/(^|\|)([^|]*)/){" "*$`.count(t="^|")+$2+" "*(1+$'.count(t))+c+$/}}
See it on eval.in: https://eval.in/639012
I really ought to just learn Retina.
MATL, 33 31 bytes
'\|'0'|'hYXo8M&YbY:&YdtaZ)0ihYc
Explanation
The builtin function Yd (blkdiag), which builds a block-diagonal matrix from its inputs, does most of the work. The fill values in the matrix are 0, and char 0 is treated as a space for displaying purposes. The code would simply split on |, build a matrix from the resulting blocks, convert to char, and append two columns with space and comment symbol.
However, the possibility of empty sections in the input string complicates makes the problem more interesting: the resulting block would be empty and thus wouldn't show in the resulting matrix.
To solve this, we introduce a char 0 before each |, so no block will be empty; and then in the resulting char matrix we remove columns that are formed by char 0 only. A non-empty code section will have some printable ASCII char, and thus the columns it spans will survive. An empty section will contribute a row, but won't introduce an extra column.
'\|' % Push this string: source for regexp matching. It's just | escaped
0'|'h % Push a string formed by char 0 followed by | (no escaping needed)
YX % Input string implicitly. Replace first of the above string by the second
o % Convert from chars to code points. Gives a numeric vector
8M % Push '|' again
&Yb % Split numeric vector at occurences of | (the latter is automatically
% converted to its code point). This gives a cell array of numeric vectors
Y: % Unbox cell array: pushes the numeric vectors it contains
&Yd % Form a block-diagonal matrix from those vectors
ta % Duplicate. Compute vector that equals true for columns that have some
% nonzero value
Z) % Used that as a logical index (mask) for the columns of the matrix.
% This removes columns that contain only zeros
0ih % Input comment symbol and prepend char 0 (which will be displayed as space)
Yc % Append that to each row of the matrix. The matrix is automatically
% converted from code points to chars
% Display implicitly
PowerShell v2+, 103 99 bytes
param($a,$b)$a-split'\|'|%{" "*$l+$_+" "*(($a-replace'\|').length+1-$_.length-$l)+$b;$l+=$_.Length}
Takes input as two strings, -splits the first on literal pipe (since split uses regex syntax), and feeds the elements into a loop |%{...}.
Each iteration, we construct a string as being a number of spaces defined by $l concatenated with the current element. For the first loop, $l initializes to $null, which gets evaluate here as 0.
That string is further concatenated with another number of spaces (defined by how long $a would be if we -replaced every pipe with nothing, plus 1 for the additional padding between code and comments, minus the .length of the current element, minus $l which is how many spaces we padded left on this iteration), concatenated with our comment character $b. That's left on the pipeline.
We then update $l for the next iteration.
The resultant strings are all left on the pipeline, and output via implicit Write-Output happens at program execution, with a newline between them by default.
Examples
PS C:\Tools\Scripts\golfing> .\esolang-comment-template-generator.ps1 "This|Code|has||empty||sections" "@"
This @
Code @
has @
@
empty @
@
sections @
PS C:\Tools\Scripts\golfing> .\esolang-comment-template-generator.ps1 "a|bc|def|ghi|h" "|"
a |
bc |
def |
ghi |
h |
Retina, 35 34 bytes
Byte count assumes ISO 8859-1 encoding.
\|
·$'¶$`±
T0-2`·±|p`___ `.+±.|·.+
The two input strings are separated by a space (which is unambiguous since we know that the comment delimiter is always a single character).
Groovy, 120 113 111 Bytes
def m(s,c){s.split(/\|/).inject(0,{e,t->println((' '*e+t).padRight(s.replace('|','').size()+1)+c);e+t.size()})}
ungolfed*
def m(s,c){
s.split(/\|/).inject(0, { e, t ->
println((' '*e+t).padRight(s.replace('|','').size())+' '+c)
e+t.size()
})
}
(First Draft with 120 Bytes)
def m(s,c){def l=0;s.split(/\|/).collect{l+=it.size();it.padLeft(l).padRight(s.replace('|','').size())+' '+c}.join('\n')}
ungolfed*
def m(s,c){
def l=0 // minimized version needs a semicolon here
s.split(/\|/).collect{
l+=it.size() // minimized version needs a semicolon here
it.padLeft(l).padRight(s.replace('|','').size())+' '+c
}.join('\n')
}
Tests
%> m('a|bc|d|e|fgh|ij|k|l|mn|op', '#')
a #
bc #
d #
e #
fgh #
ij #
k #
l #
mn #
op #
%> m('Hello|World', '/')
Hello /
World /
%> m('a|b|c|d|e|f|g', ',')
a ,
b ,
c ,
d ,
e ,
f ,
g ,
%> m('abcdefg', ':')
abcdefg :
%> m('4|8|15|16|23|42', '%')
4 %
8 %
15 %
16 %
23 %
42 %
%> m('E|ac|h s|ecti|on is| one c|haracte|r longer| than the| last!', '!')
E !
ac !
h s !
ecti !
on is !
one c !
haracte !
r longer !
than the !
last! !
%> m('This|Code|has||empty||sections', '@')
This @
Code @
has @
@
empty @
@
sections @
Scala, 123 bytes
def?(i:String,c:String)={var b=0
i.split('|').map{s=>println(" "*b+s+" "*(i.replace("|","").size-b-s.size+1)+c)
b+=s.size}}
Test code + Output:
?("a|b|c|d|e|f|g", ",")
a ,
b ,
c ,
d ,
e ,
f ,
g ,
?("abcdefg", ":")
abcdefg :
?("4|8|15|16|23|42", "%")
4 %
8 %
15 %
16 %
23 %
42 %
?("E|ac|h s|ecti|on is| one c|haracte|r longer| than the| last!", "!")
E !
ac !
h s !
ecti !
on is !
one c !
haracte !
r longer !
than the !
last! !
?("This|Code|has||empty||sections", "@")
This @
Code @
has @
@
empty @
@
sections @
PHP, 120 117 116 110 109 bytes
foreach($a=split('\|',$argv[1])as$i=>$t){$c=preg_replace('#.#',' ',$a);$c[$i]=$t;echo join($c)," $argv[2]
";}
or
foreach($a=split('\|',$argv[1])as$t){$c=preg_replace('#.#',' ',$a);$c[$i++|0]=$t;echo join($c)," $argv[2]
";}
Haskell, 139 135 bytes
s#p=j$foldl g("",0)s where g(a,n)c|c=='|'=(j(a,n)++"\n"++q n,n)|1>0=(a++[c],n+1);q m=' '<$[1..m];j(a,n)=a++q(sum[1|c<-s,c/='|']-n+1)++p
Saved 4 bytes by inlining a definition.
Ungolfed:
template :: String -> String -> String
template code comment = format $ foldl g ("", 0) code
where g (acc, n) c
| c == '|' = (format (acc, n) ++ "\n" ++ spaces n, n)
| otherwise = (acc ++ [c], n+1)
l = length $ filter (/= '|') code
spaces n = replicate n ' '
format (acc, n) = acc ++ spaces (l-n+1) ++ comment
JavaScript (ES6), 92 bytes
f=
(s,c)=>s.split`|`.map((_,i,a)=>a.map((e,j)=>i-j?e.replace(/./g,` `):e).join``+` `+c).join`
`
;
<div oninput=o.textContent=f(s.value,c.value)><input id=s placeholder=Code><input id=c size=1 maxlength=1 value=#><pre id=o>
