ShellScript将rectangulous文本旋转45°

时间:2021-05-22 16:03:13

I need to do a script for bash to solve the word game for 8 directions. I have managed to make some code, but the last thing I am stuck on, is how to rotate the table to find the words in all directions. 90° is not a problem, but 45°... I think awk could help but I am not really good at it. Thanks.

我需要为bash做一个脚本来解决8个方向的文字游戏。我已经设法制作了一些代码,但最后我坚持的是如何旋转表格来查找所有方向的单词。 90°不是问题,但45°......我觉得awk可以提供帮助,但我并不擅长它。谢谢。

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

3 个解决方案

#1


$ 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

wrt the comments below from @JoseRicardoBustosM. suggesting that the above does not produce the desired output from one of his sample inputs, here's the suggested input4:

以下来自@JoseRicardoBustosM的评论。建议上面没有从他的一个样本输入产生所需的输出,这是建议的输入4:

$ cat input4
Jose
y
Ricardo
y
Gloriset

and the above script run on it:

以上脚本在其上运行:

$ awk -f tst.awk input4
J
yo
Rs
yie
Gc
 la
  or
   rd
    io
     s
      e
       t

and here's a modified script to inject blank chars when none exist IF that was the desired behavior which I think is extremely 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

#2


I would suggest using perl instead of awk. Perl is very powerful in processing texts, and the syntax is quite C-like.

我建议使用perl而不是awk。 Perl在处理文本方面非常强大,而且语法非常像C语言。

As far as I understand what 'rotating a text by 45°' means, the following script performs such a rotation:

据我所知,“将文本旋转45°”意味着,以下脚本执行这样的旋转:

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 is as follows:

假设输入文件如下:

$ 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 perform rotation by 135° or 225° I suggest rotation by 90° (180°) and then rotation by 45°.

要进行135°或225°的旋转,我建议旋转90°(180°)然后旋转45°。

#3


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

input2

abc 
defg 
hi

output2

a
db
hec
 if 
   g

input3

abc 
defg 
hi
jklm

output3

a
db
hec
jif 
 k g
  l  
   m

input4

Jose
y
Ricardo
y
Gloriset

output4

J
yo
R s
yi e
G c
 l a
  o r
   r d
    i o
     s
      e
       t

#1


$ 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

wrt the comments below from @JoseRicardoBustosM. suggesting that the above does not produce the desired output from one of his sample inputs, here's the suggested input4:

以下来自@JoseRicardoBustosM的评论。建议上面没有从他的一个样本输入产生所需的输出,这是建议的输入4:

$ cat input4
Jose
y
Ricardo
y
Gloriset

and the above script run on it:

以上脚本在其上运行:

$ awk -f tst.awk input4
J
yo
Rs
yie
Gc
 la
  or
   rd
    io
     s
      e
       t

and here's a modified script to inject blank chars when none exist IF that was the desired behavior which I think is extremely 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

#2


I would suggest using perl instead of awk. Perl is very powerful in processing texts, and the syntax is quite C-like.

我建议使用perl而不是awk。 Perl在处理文本方面非常强大,而且语法非常像C语言。

As far as I understand what 'rotating a text by 45°' means, the following script performs such a rotation:

据我所知,“将文本旋转45°”意味着,以下脚本执行这样的旋转:

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 is as follows:

假设输入文件如下:

$ 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 perform rotation by 135° or 225° I suggest rotation by 90° (180°) and then rotation by 45°.

要进行135°或225°的旋转,我建议旋转90°(180°)然后旋转45°。

#3


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

input2

abc 
defg 
hi

output2

a
db
hec
 if 
   g

input3

abc 
defg 
hi
jklm

output3

a
db
hec
jif 
 k g
  l  
   m

input4

Jose
y
Ricardo
y
Gloriset

output4

J
yo
R s
yi e
G c
 l a
  o r
   r d
    i o
     s
      e
       t