How to echo lines of text vertically in PHP?
The code below will print $str
vertically.
$lines = preg_split("/\r\n/", trim($str));
$nl = count($lines);
$len = max(array_map('strlen', $lines));
foreach ($lines as $k => $line) {
$lines[$k] = str_pad($line, $len, ' ', STR_PAD_LEFT);
}
for ($i = 0; $i < $len; $i++) {
for ($j = 0; $j < $nl; $j++) {
echo $lines[$j][$i].($j == $nl-1 ? "\n" : " ");
}
}
As others have already demonstrated, array_map
is able to do the flip over which is basically the main problem you need to solve. The rest is how you arrange the code. I think your version is very good because it's easy to understand.
If you're looking more to some other extreme, handle with care:
$str = 'PHP is a
widely-used
general-purpose
server side
scripting
language';
$eol = "\n";
$turned = function($str) use ($eol) {
$length = max(
array_map(
'strlen',
$lines = explode($eol, trim($str))
)
);
$each = function($a, $s) use ($length) {
$a[] = str_split(
sprintf("%' {$length}s", $s)
);
return $a;
};
return implode(
$eol,
array_map(
function($v) {
return implode(' ', $v);
},
call_user_func_array(
'array_map',
array_reduce($lines, $each, array(NULL))
)
)
);
};
echo $turned($str), $eol;
Gives you:
g
e
n
e
w r s
i a e
d l r s
P e - v c l
H l p e r a
P y u r i n
- r p g
i u p s t u
s s o i i a
e s d n g
a d e e g e
This fixes the output of the other answer, which was incorrect (now fixed).
$a = explode(PHP_EOL, trim($str));
$h = max(array_map('strlen', $a));
$w = count($a);
$m = array_map('str_split', array_map('sprintf', array_fill(0, $w, "%{$h}s"), $a));
$t = call_user_func_array('array_map', array_merge(array(null), $m));
echo implode(PHP_EOL, array_map('implode', array_fill(0, $h, ' '), $t)), PHP_EOL;
PHP_EOL should be replaced with "\n", "\r\n" or '<br/>' where appropriate. The whole code after the first line could easily become one big expression, only its readability would suffer a little bit ;-)
$a
is the array of lines, $h
is the final height, $w
is the final width, $m
is the matrix of characters (after padding the strings), $t
is the transposed matrix.
The array_fill(0, $h, ' '),
on the last line can simply be omitted if the space between columns is not needed. On the other hand, not printing trailing space characters can be achieved like this:
echo implode(PHP_EOL, array_map('rtrim', array_map('implode', array_fill(0, $h, ' '), $t))), PHP_EOL;
I have taken the question as an excercise in avoiding explicit loops (which are usually more expensive than loops inside PHP functions, although in this case the advantage could be lost). The important trick here is the matrix transposition, which I have taken from this answer by Codler
Anyhow, the complexity of the whole algorithm is O(width × height)
, just like the one of most algorithms on this page, except for those that repeatedly concatenate strings in order to obtain the lines, whose complexity is O(width² × height)
I took some of the code from @bsdnoobz and simplified it. I'm using \n as a line break because I work on a Mac and \r\n doean work here.
$lines = preg_split("/\n/", trim($str));
$len = max(array_map('strlen', $lines));
$rows = array_fill(0,$len,'');
foreach ($lines as $k => $line) {
foreach (str_split(str_pad($line, $len, ' ', STR_PAD_LEFT)) as $row => $char){
$rows[$row] .= $char;
}
}
echo implode("\n",$rows)."\n";