0

I could pipe the output below to awk '{print $1$1$1$1$1$1$1$1$1$1$1$1$1}' to get the desired output as posted in the print alphabet wave at CodeGolf SE.

Is there a better way to copy/repeat columns as another column (vertically?) using bash and/or other *nix utilities?

for i in {0..25}; do 
  printf \\$( printf '%03o' $((i+65)) );
  printf \\$( printf '%03o' $((-~i%26+65)) ); 
  echo; 
done

AB
BC
CD
DE
EF
FG
GH
HI
IJ
JK
KL
LM
MN
NO
OP
PQ
QR
RS
ST
TU
UV
VW
WX
XY
YZ
ZA
KM.
  • 2,224

2 Answers2

2

First of all, you could simplify your 2 printfs + 1 echo to a single printf I think:

for i in {0..25}; do 
  printf '%b%b\n' \\$( printf '%03o' $((i+65)) ) \\$( printf '%03o' $((-~i%26+65)) )
done

If you want to keep everything in the shell, you could use the trick described here Writing a character N times using the printf command, i.e.

for i in {0..25}; do 
  printf "$(printf '%b%b' \\$( printf '%03o' $((i+65)) ) \\$( printf '%03o' $((-~i%26+65)) ))%.0s" {1..13}
  printf \\n
done

or, more transparently

for i in {0..25}; do 
  printf -v xy '%b%b' \\$( printf '%03o' $((i+65)) ) \\$( printf '%03o' $((-~i%26+65)) )
  printf "${xy}%.0s" {1..13}
  printf \\n
done

If you're not set on using pure shell, then a couple of other techniques to reduplicate each letter pair that come to mind are

  1. using perl's multiplication operator

    . . . | perl -lne 'print $_ x 13'
    
  2. using a sed loop

    . . . | sed -E ':a; /.{26}/! s/../&&/; ta'
    

In fact, you could do the letter pairing in sed as well

$ printf \%b {A..Z} A \\n | 
    sed -E '/^Z/! s/(.)(.)/&\n\2/; P;D; b' | sed -E ':a; /.{26,}/! s/../&&/; ta'
ABABABABABABABABABABABABAB
BCBCBCBCBCBCBCBCBCBCBCBCBC
CDCDCDCDCDCDCDCDCDCDCDCDCD
DEDEDEDEDEDEDEDEDEDEDEDEDE
EFEFEFEFEFEFEFEFEFEFEFEFEF
FGFGFGFGFGFGFGFGFGFGFGFGFG
GHGHGHGHGHGHGHGHGHGHGHGHGH
HIHIHIHIHIHIHIHIHIHIHIHIHI
IJIJIJIJIJIJIJIJIJIJIJIJIJ
JKJKJKJKJKJKJKJKJKJKJKJKJK
KLKLKLKLKLKLKLKLKLKLKLKLKL
LMLMLMLMLMLMLMLMLMLMLMLMLM
MNMNMNMNMNMNMNMNMNMNMNMNMN
NONONONONONONONONONONONONO
OPOPOPOPOPOPOPOPOPOPOPOPOP
PQPQPQPQPQPQPQPQPQPQPQPQPQ
QRQRQRQRQRQRQRQRQRQRQRQRQR
RSRSRSRSRSRSRSRSRSRSRSRSRS
STSTSTSTSTSTSTSTSTSTSTSTST
TUTUTUTUTUTUTUTUTUTUTUTUTU
UVUVUVUVUVUVUVUVUVUVUVUVUV
VWVWVWVWVWVWVWVWVWVWVWVWVW
WXWXWXWXWXWXWXWXWXWXWXWXWX
XYXYXYXYXYXYXYXYXYXYXYXYXY
YZYZYZYZYZYZYZYZYZYZYZYZYZ
ZAZAZAZAZAZAZAZAZAZAZAZAZA

It should be possible in a single sed invocation, something like

printf \%b {A..Z} A \\n | 
  sed -E ':1; /^Z/! s/(.)(.)/&\n\2/; :2; /.{26}\n/! s/../&&/; t2; P;D; b1'

but I can't quite get the terminating condition right without resorting to exotic GNU extensions

printf \%b {A..Z} A \\n |  
  sed -E ":1; /^Z/! s/(.)(.)/&\n\2/; :2; /.{26}(\n|\')/M! s/../&&/; t2; P;D; b1"
steeldriver
  • 81,074
1

Without attempting to optimise your code in any way (that's the challenge!), you could do

x=$(printf ..statement1..)
y=$(printf ..statement2..)

and then simply

echo "$x$y$x$y$x$y$x$y$x$y...."

eg

for i in {0..25}; do 
  x=$(printf \\$( printf '%03o' $((i+65)) ))
  y=$(printf \\$( printf '%03o' $((-~i%26+65)) )) 
  echo "$x$y$x$y$x$y$x$y"
done

There are a lot of ways to optimise this, though.

  • What are some areas for improvement? Not looking for answers, but some hints would be great ... Please (_: – KM. Aug 21 '16 at 22:00
  • One example: Instead of y= the second printf line could be x=$x$(printf...) and now the final echo would just be echo "$x$x$x$x" because $x would hold both characters; the echo line is now a lot shorter. Could you make the printf itself simpler? – Stephen Harris Aug 21 '16 at 22:03