ShellScript Rotate rectangular text 45 °
I need to make a script for bash to solve 8-way wordplay. I was able to do some code, but the last thing I got stuck was how to rotate the table to find words in all directions. 90 ° is not a problem, but 45 ° ... I think awk can help, but I'm not very good at it. Thank you.
Example:
abcd efgh ijkl
=>
a eb ifc jgd kh l
Example 2:
abcde fghij klmno
=>
a fb kgc lhd mie nj o
Example 3:
abc defg hi
=>
a db hec if g
source to share
$ cat tst.awk
BEGIN { FS="" }
{
for (i=1;i<=NF;i++) {
a[NR,i]=$i
}
numCols = (NF>numCols?NF:numCols)
numRows = NR
}
END {
rowNr=1
for (colNr=1;colNr<=numCols;colNr++) {
for (;rowNr<=numRows;rowNr++) {
printf "%*s", colNr-1, ""
for (delta=0;delta<rowNr;delta++) {
printf "%s%s", a[rowNr-delta,colNr+delta], (delta<(rowNr-1)?FS:RS)
}
}
rowNr=numRows
}
}
...
$ awk -f tst.awk file1
a
eb
ifc
jgd
kh
l
$
$ awk -f tst.awk file2
a
fb
kgc
lhd
mie
nj
o
$
$ awk -f tst.awk file3
a
db
hec
if
g
see comments below from @JoseRicardoBustosM. that the above does not give the desired output from one of its sample inputs, it is suggested here input4
:
$ cat input4 Jose y Ricardo y Gloriset
and above it script do the following:
$ awk -f tst.awk input4
J
yo
Rs
yie
Gc
la
or
rd
io
s
e
t
and here's a modified script to input blank characters when no IF exists, which was the desired behavior, which I think is highly unlikely:
$ cat tst2.awk
BEGIN { FS="" }
{
for (i=1;i<=NF;i++) {
a[NR,i]=$i
}
numCols = (NF>numCols?NF:numCols)
numRows = NR
}
END {
rowNr=1
for (colNr=1;colNr<=numCols;colNr++) {
for (;rowNr<=numRows;rowNr++) {
printf "%*s", colNr-1, ""
for (delta=0;delta<rowNr;delta++) {
printf "%s%s", ((rowNr-delta,colNr+delta) in a ? a[rowNr-delta,colNr+delta] : " "), (delta<(rowNr-1)?FS:RS)
}
}
rowNr=numRows
}
}
$ awk -f tst2.awk input4
J
yo
R s
yi e
G c
l a
o r
r d
i o
s
e
t
source to share
I would suggest using perl
instead awk
. perl
is very efficient in word processing and the syntax is quite similar to C
.
As I understand it, what "45 ° text rotation" means, the following script does a rotation like this:
rotate_text_45.pl
:
#!/usr/bin/perl
use strict;
use warnings;
my @input = <>;
my $lines_count = scalar @input;
my $global_max_diag = 0;
for my $i (0 .. scalar @input - 1){
chomp $input[$i];
$input[$i] = [split //, $input[$i]];
my $max_diag = $i + scalar(@{$input[$i]}) - 1;
$global_max_diag = $max_diag if $max_diag > $global_max_diag;
}
for my $diag (0 .. $global_max_diag){
for my $i (0 .. $diag){
next if $diag - $i >= $lines_count;
$input[$diag - $i][$i] = ' ' unless defined $input[$diag - $i][$i];
print $input[$diag - $i][$i];
}
print "\n";
}
Assuming the input file looks like this:
$ cat in.txt
iftkn
iarwp
cooop
froas
blmaz
The script produces this result:
$ ./rotate_text_45.pl in.txt
i
if
cat
fork
brown
loop
map
as
z
To do a 135 ° or 225 ° rotation, I suggest a 90 ° (180 °) rotation and then a 45 ° rotation.
source to share
awk '
BEGIN{
sum = 0;
}
{
words[NR] = $0;
sum += length($0);
}
END{
cant_words = length(words);
for(i=1; i<=cant_words; i++){
flag[i] = 2-i;
}
cont_letter = 0;
row = 1;
while(cont_letter<sum){
out = "";
for(i=0; i<row-cant_words; i++){
out = out" ";
}
cont_space = 0;
for(i=cant_words; i>=1; i--){
if(flag[i] >= 1 && flag[i] <= length(words[i])){
for(j=0; j<cont_space; j++){
out=out" "
}
cont_space = 0;
out=out""substr(words[i],flag[i],1);
cont_letter = cont_letter + 1;
}else{
if(flag[i] > length(words[i])){
cont_space = cont_space + 1;
}
}
flag[i] = flag[i]+1;
}
print out;
row = row + 1;
}
}
' input
input1:
abcd efgh ijkl
output1:
a eb ifc jgd kh l
entrance2
abc defg hi
exit2
a db hec if g
entrance3
abc defg hi jklm
output3
a db hec jif kg l m
entrance4
Jose y Ricardo y Gloriset
output4
J yo R s yi e G c la or rd io s e t
source to share