Right-align text

Your job is to take a string input and a number and align the string to the right, making the width of the text the number. When a line is too long, break it and put the rest on the next line, repeating until it's not necessary. If a line is shorter than the width, then pad it with spaces. Multiple newlines can occur, and should be treated like any other single character.

For example, the string

Programming
Puzzles
&
Code
Golf

and the number 5 would produce:

Progr
ammin
g
Puzzl
es
&
Code
Golf

Whereas the same string and the number 10 would produce:

Programmin
g
Puzzles
&
Code
Golf

The string

a

b

and the number 5 would produce:

a
<-- note the 5 spaces
b

Shortest code wins!

• The text says “Break the lines when necessary [...]”, but your examples suggest that you break after every word, even when it would fit. Please clarify: do we place each word on a new line, or do we implement an actual word-wrapping algorithm? – Timwi Sep 24 '15 at 0:39
• Can there be spaces in the middle of an input line, e.g. Programming Puzzles\n&\nCode Golf? – Sp3000 Sep 24 '15 at 2:04
• @sp3000 There can be any character, including spaces. – Trebuchette Sep 24 '15 at 2:08
• @Timwi: The example has one word per line. It would have been better to include some multi-word lines to make it clear that space within a line isn't special. (i.e. there are only newlines, and non-newlines.) – Peter Cordes Sep 24 '15 at 8:58

Pyth, 14 bytes

jm.[\ QdscRQ.z

Demonstration

Python 2, 84

s,n=input()
for w in s.split('\n'):
w=w or' '
while w:print w[:n].rjust(n);w=w[n:]

Takes as input a string with newlines and a number, and prints the result. For each line in the input, takes and prints n chars at a time, using the built-in rjust to pad the left with spaces before printing.

I fixed the empty line case with the hack w=w or' '. There's probably a better method but I'm not going to think much about it.

CJam, 21 bytes

li_qN/Sfe|f/ff{\Se[N}

Thanks to @Sp3000 for golfing off 1 byte and paving the way for 3 more.

Try it online in the CJam interpreter.

How it works

li                     Read an integer L from the first line of input.
_                    Push a copy.
qN/                 Split the remaining input at linefeeds.
Sfe|             Map OR " "'; the replaces empty lines with a space.
f/           Split each line into chunks of length L.
ff{     }  For each chunk, push L and the chunk; then:
\         Swap L with the chunk.
Se[      Left-pad the chunk to length L by prepending " ".
N     Push a linefeed.

Pyth, 16

jm>Q+*\ QdscRQ.z

Try it online here

Explanation

jm>Q+*\ QdscRQ.z             : Q is the number on the first line, .z takes the rest
cRQ.z             : chop each line of .z into chunks of Q characters
m        s                  : remove nested lists and map over the result
+*\ Qd                   : add Q spaces to each line d
>Q                         : take the last Q characters of that result
j                            : join results on newlines

Perl, 39 bytes

perl -ni5 -e 's!^$|.{1,$^I}!printf"%${^I}s ",$&!ge'

36 bytes + 3 bytes for -ni. The wrap width is passed as the argument to -i.

Handles blank lines properly by padding them with spaces:

$echo -e "Programming\nPuzzles\n\n&\n\nCode\nGolf" | perl -ni5 -e 's!^$|.{1,$^I}!printf"%${^I}s
",$&!ge' Progr ammin g Puzzl es & Code Golf How it works This solution uses the substitution operator to loop through the input, saving a byte over the equivalent for loop. The real trick, though, is in the regex on the LHS of the substitution: ^$|.{1,$^I} With the global modifier, this will match$^I characters at a time; when there are less than $^I characters remaining in the string, it will match everything to the end. The alternation with ^$ is required to handle blank lines. For example:

$echo -e "foo\n\nbar" | perl -ni2 -E 'say "<$_>" for /^$|.{1,$^I}/g'
<fo>
<o>
<>
<ba>
<r>

The RHS of the substitution simply uses printf to left-pad the matched chunk with spaces.

Javascript (ES6), 107

(a,b)=>a.replace(eval(/(.{${b}})(?!\\n)/g),$1
).split
.map(c=>(Array(b).join +c).slice(-b)).join


Explanation:

(a, b)=>

// searches for sequences of characters longer than b without a newline after them and
// adds a newline after every b characters of the sequence
a.replace(eval(/(.{${b}})(?!\\n)/g`), '$1\n')
.split('\n')
.map(c=>

// prepends b spaces to each string then slices it from the right down to length b
( Array(b).join(' ') + c ).slice(-b)

).join('\n')

Julia, 126 bytes

Ungolfed:

function f(s::String, n::Int)
for i in split(s, "\n")
while length(i) > 0
length(i) < n ? break : (i = i[min(n+1,end):end])
end
end
end

Bash, 62, 61+feature, 59

Shorter if N can be set by the caller, instead of having to read it as the first line of input.

# width as a function arg: 59 chars
f()while read -rn$1 r;do [[$r ]]&&printf %$1s\\n "$r";done
# width on stdin: 64 chars  (not updated with later suggestions&ideas)
read N;while read -rn$N r;do [[$r ]]&&printf %$N's\n' "$r";done

This fails to handle empty lines in the input. Otherwise, this doesn't subject the input data to word-splitting, pathname expansion, or otherwise treat it as more than just raw data.

read -n$N saves one character, but lets read munge \. The [[$r ]]&& is needed because read -n4 can't lookahead to see that the next char is a newline. So it sets r to a 4-char string, and the next read produces a zero-char empty string. Filtering these false newlines without filtering real newlines would require tracking state: whether the previous line was max-length or not. Either more code or a totally different approach would be needed.

[[ $r ]] is shorter than [ -n "$r" ] which is needed to avoid errors if the line starts with -z foo, or is * or something, if you used [ $r ]. Justication happens with the standard printf "%4s" format string. Test with f()(while read -rn$1 r;do [[ $r ]]&&printf %$1s\\n "$r";done); (echo 4; echo -e "*\n\\"; cat /tmp/lines) | f 4 • 1. I'd include -r in the byte count. 2. f()(while ... done) is a bit shorter. – Dennis Sep 24 '15 at 6:36 • @Dennis: Without [[$r ]]&&, if N=4, an input line of length 4 will produce a blank output line where there wasn't one before. Because read returns a string of 4 chars, then sees a newline on the next call and returns right away. Also, thanks for the () tip. I didn't know you could define fns that way. – Peter Cordes Sep 24 '15 at 6:37
• I recommend reading Tips for golfing in Bash. It's a great resource. – Dennis Sep 24 '15 at 6:39
• Actually, since while is already compound, you don't even need the parentheses: f()while ... done – Dennis Sep 24 '15 at 6:42
• @Dennis: wow, haxx. Thanks for the link. A couple of those things were new to me, and I fixed a couple things in another answer :) I don't normally golf, but >15 years of being a command-line junkie has taught me a thing or two :) – Peter Cordes Sep 24 '15 at 7:18

import Data.List.Split
k[]=[""]
k x=x
f n=unlines.(map(\l->([1..n-length l]>>" ")++l).k.chunksOf n=<<).lines

Usage example:

*Main> putStr $f 5 "a\n\nb\ncd\nMatamorphosis" a b cd Matam orpho sis How it works .lines -- split input string at newlines =<< -- for every line chunksOf n -- split into chunks of length n k -- fix empty lines map -- for every chunk \l->([1..n-length l]>>" " -- make a string of missing spaces ++l -- and append the chunk unlines -- join padded chunks with newlines in-between GNU awk + bash, 70 f()(awk -vFPAT=.\{,$1} '{for(i=0;i++<NF;){printf "%'$1's\n",$i}}/^$/') Using bash to slot the count into the awk program is prob. smaller than reading it with a NR==1{N=$0} block.

Read a line at a time. Split into at-most-4 character chunks, using FPAT. (matches the fields, rather than the separators. GNU extension.) printf each field separately. (Default ORS = \n).

The /^$/ rule is there to print empty lines, which have NF=0 and thus don't print at all in the other block. So unlike my pure-bash solution, this actually works in the general case. Semi-unrelated, but my idea so far for perl is 112 chars for just the perl code: (echo 4; echo -e 'foo\nbar'; echo -e "*\n\\"; echo '~$(true)'; cat /tmp/lines) |  # test input
perl -e '$N=<>;$/=\1;print "$N\n"; while(<>){if(/\n/ or length($l)>=$N){printf("%$4s\n",$l);$l=/\n/?"":$_;}else{$l.=$_;}}' This eats one of the newlines, and is way too long.$/=\1 reads a byte at a time. We append to $l. Probably a line-at-a-time with fixed-width split approach would be shorter. Bash + GNU utils, 41 fold -$1|sed ":;s/^.\{,$[$1-1]\}\$/ &/;t" String is input via STDIN, width is input by command-line arg: ubuntu@ubuntu:~$ echo 'Programming
Puzzles
&
Code
Golf'|./ralign.sh 10
Programmin
g
Puzzles
&
Code
Golf
ubuntu@ubuntu:~$Python 2, 151 bytes s,n=input();N='\n' for w in[i.lstrip()if i.replace(' ','').isalpha()else i for i in s.replace(N,'\n ').split(N)]: while w:print w[:n].rjust(n);w=w[n:] This is a adaptation of @xnor's answer above, as his does not properly handle newlines. The for loop was changed from: for w in s.split('\n'): to: for w in[i.lstrip()if i.replace(' ','').isalpha()else i for i in s.replace(N,'\n ').split(N)]: Example$ python main.py
"Programming\n\n\nPuzzles\n\n&\n\nCode\nGolf", 5
Progr
ammin
g

Puzzl
es

&

Code
Golf

C#, 143 bytes

Linq lets you make pretty gnarly expressions. GroupBy is useful here, but it's a shame they couldn't create function overloads taking the index.

Assign the lambda to a Func<string, int, string> to run it

Less golfed:

Func<string, int, string> Align = (s, n) => Join("\n",
s.Split('\n')
.SelectMany(l => (l.Any() ? l : " ")
.Select((c, i) => new { c, i })
.GroupBy(o => o.i / n, o => o.c)

Groovy, 63 bytes

Returns the correctly alligned string. Didn't know there was a padLeft (and padRight, padCenter) function until now.

f={s,n->s.split("(?<=\\G.{$n})|\n")*.padLeft(n," ").join("\n")} JavaScript 174 136 function R(s,x){return s.replace(new RegExp(".{"+x+"}","g"),"$&\n").replace(/[^\n]*/g,function(m){
while(m.length<x)m=" "+m;return m;})}

Matlab, 99 bytes

Thanks to @beaker for removing 6 bytes!

Using and anonymous function:

@(s,k)fliplr(char(cellfun(@fliplr,strsplit(regexprep(s,sprintf('\\S{%i}',k),'$0\n'),'\n'),'un',0))) Define the function and use ans to call it: >> @(s,k)fliplr(char(cellfun(@fliplr,strsplit(regexprep(s,sprintf('\\S{%i}',k),'$0\n'),'\n'),'un',0)))

ans =

@(s,k)fliplr(char(cellfun(@fliplr,strsplit(regexprep(s,sprintf('\\S{%i}',k),'$0\n'),'\n'),'un',0))) >> ans(['Programming' 10 'Puzzles' 10 '&' 10 'Code' 10 'Golf'], 5) %% 10 is line feed ans = Progr ammin g Puzzl es & Code Golf Burlesque, 28 Bytes Same as the version below, but treats line 1 as the number and the other lines as the string. lng_riPpun{pPco{pP' lp}mu}Wl Usage as in:$ cat input.txt | blsq --stdin "lng_riPpun{pPco{pP' lp}mu}Wl"
Progr
ammin
g
Puzzl
es
&
Code
Golf

Old Version (16 bytes):

{5co{5' lp}mu}Wl

Example:

blsq ) "Programming\nPuzzles\n&\nCode\nGolf"{5co{5' lp}mu}Wl
Progr
ammin
g
Puzzl
es
&
Code
Golf