Diary

Diary

日々学んだことをアウトプットする場として初めてみました

ワンライナーで九九の表を生成する

ワンライナーで九九の表を生成する」というシェル芸の問題は、多くの解法が存在し非常にいい問題なのではないかと感じました。

そこで、自分が今思いつく答えをいくつかメモしておこうと思います(今回は細かいコマンドの使い方は紹介しておりません)

ぜひ自分で考えた後にご覧ください!

[目次]

基本二重ループ

まずはシンプルに、以下のような2重 for ループで実装します

$ for i in {1..9}; do (for j in {1..9}; \
do printf "%2d " $(($i*$j)); done); echo ; done  
 1  2  3  4  5  6  7  8  9 
 2  4  6  8 10 12 14 16 18 
 3  6  9 12 15 18 21 24 27 
 4  8 12 16 20 24 28 32 36 
 5 10 15 20 25 30 35 40 45 
 6 12 18 24 30 36 42 48 54 
 7 14 21 28 35 42 49 56 63 
 8 16 24 32 40 48 56 64 72 
 9 18 27 36 45 54 63 72 81

(cf) while ループの練習

$ i=1; while [ $i -ne 10 ]; \
do (j=1; while [ $j -ne 10 ]; \
do printf "%2d " $(($i*$j)); \
j=$(($j+1)); done); printf "\n"; \
i=$(($i+1)); done

AWK のみ

上と同じように2重ループで実装を、AWKのみでおこないます

awk 'BEGIN{for( i=1;i<=9;i++ ){for( j=1;j<=9;j++ ){printf "%2d ",i*j}print " "}}'

python ワンライナー

pythonワンライナーについては、こちらもご覧ください

koko206.hatenablog.com

$ python -c "[print(f'{i*j:2}') if i == 9 else print(f'{i*j:2}', end=' ') for j in range(1,10) for i in range(1,10)]"

for ループを使わない

ここでは echo のブレース展開を用いて 9 * 9 の組み合わせを作り出します。

ブレース展開とは

基本的な使い方は以下のようになります

# 基本
$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
$ echo {a..e}
a b c d e

# 普通の文字と組み合わせ
$ echo hoge{1..3}
hoge1 hoge2 hoge3

# 複数のブレース展開
$ echo {1..2}{a..c}
1a 1b 1c 2a 2b 2c
$ echo {1..2}{1..3}
11 12 13 21 22 23

# 数字における 0 埋め
$ echo {04..10}    
04 05 06 07 08 09 10

そこで今回は、{1..9}{1..9}というブレース展開により必要な組み合わせを作り、それをうまく利用するという作戦を取ります

# awk の種類・バージョンによってはうまくいかないかも
echo {1..9}{1..9} | tr ' ' '\n' |\
 awk -F '' '{printf"%2s\n",$1*$2}' |\
 paste -d ' ' - - - - - - - - - 

上の awk の部分を、下の例では

  • sed(23 ⇨ 2*3と変換)
  • bc(2*3 ⇨ 6と評価)
  • printf(全数字を2桁で表示)

の3ステップで行っています。

echo {1..9}{1..9} | tr ' ' '\n' | \
sed -E 's@([0-9])([0-9])@\1*\2@g' | \
bc | xargs printf "%2d\n" | paste -d ' ' - - - - - - - - -

おわりに

「九九の問題を作る」ということ1つとっても色々な解法があり、それがシェル芸の面白さだと思います。

他にも面白そうな問題があればまた紹介していきます!