LL Golf Hole 5 - 最上位の桁を数え上げる

LL Golf Hole 5LL Golf Hole 5 - 最上位の桁を数え上げるというお題が掲載されています。 日本語で問題を読んだだけでは分かりにくいのですが、サンプルを見れば分かると思います。

さて、どうやって解くかですが、ここでは以下のような方法で解きます。

  • 自然数の数字は標準入力で与えるものとし、0 は自然数に入れるものとします。
  • 0 から標準入力で与えられた数字までをループさせます。(for 文)
  • 上記の for 文で加算されている数字を、10 の、桁数から 1 を引いた累乗 (10 ^ (桁数 - 1)) で割ります。
  • 割り切れれば表示します。割り切れない場合は無視します。

これと同じような方法で解かれている方も何人かいらっしゃるようです。

#! /usr/bin/gawk -f
# keta.awk

{

    for (i = 0; i <= $0; i++) {

        if (i % 10 ^ (length(i) - 1) == 0) {

            print i;
        }
    }
}

さて実行してみます。

$ echo 300 | gawk -f keta.awk
0
1
2
3
4
5
6
7
8
9
10
20
30
40
50
60
70
80
90
100
200
300

正しく計算されているようです。

元々短いものですが、ゴルフをしてみます。 ここでは私の思考の断片が分かるようにいくつかのものを書いておきます。 私はゴルフは得意ではありませんが、こういう過程が垣間見れると面白いのではないかと思い書いてみました。

# 上記のものを三項演算子で記述
$ echo 300 | gawk '{for(i=0;i<=$0;i++)printf"%s",i%10^(length(i)-1)?"":i"\n"}'
# if 文で記述しなおし
$ echo 300 | gawk '{for(i=0;i<=$0;i++){if(i%10^(length(i)-1)==0)print i}}'
# for 文の最初の項を削除する代わりに +0 が必要
$ echo 300 | gawk '{for(;i<=$0;i++){if(i%10^(length(i)-1)==0)print i+0}}'
# for 文の括弧は不要
$ echo 300 | gawk '{for(;i<=$0;i++)if(i%10^(length(i)-1)==0)print i+0}'
# 比較演算子ではなく否定演算子でやってみた
$ echo 300 | gawk '{for(;i<=$0;i++)if(!(i%10^(length(i)-1)))print i+0}'
# while 文 + 正規表現かつ三項演算子
$ echo 300 | gawk '{i--;while(i<$0)printf++i~/^.0*$/?i"\n":""}'
# while 文 + 正規表現 + if 文
$ echo 300 | gawk '{i--;while(i<$0)if(++i~/^.0*$/)print i}'
$ echo 300 | gawk '{for(;i<=$0;i++)if(i~/^.0*$/)print i+0}'
$ echo 300 | gawk '{for(i=-1;i++<$0;)if(i~/^.0*$/)print i}'
# 頭の切り替え
$ echo 300 | gawk '{for(i=0;i<=$0;i++){if(substr(i,1,1)!=a)print i;a=substr(i,1,1)}}'
  • ダブリの表示が禁止されているので、三項演算子 (条件演算子) の方が長くなってしまっています。
  • for 文の初期値を入れないと 0 の時に数字として認識されないため、i+0 としています。
  • 累乗の演算順序が低いので、括弧が多くなっています。
  • 正規表現版はスマートです。
  • seq コマンドが使えればなぁ。

最後のものは少し異なったアプローチですが、awk で uniq コマンドを使う場合に良く使われる手法です。(結果的に長くなってしまいましたが)

もっと短いものを考えて、チャレンジしてみてください。 まだまだ行けるはずです。

ゴルフに最適な zsh

ゴルフを行なう時は、何度も何度も実行しますので、勝手にヒストリに記憶されても困ることが多々あります。 ゴルフでベストスコアを出したときの爽快感の後に無残な戦歴を刻んだ使えないヒストリだけが残されることがあります。 そんな時にオススメなのが zsh です。

setopt HIST_IGNORE_SPACE

上記のように ~/.zshrc に記述しておくと、行頭にスペースを入れたものはヒストリに含まれなくなりますが、直前の履歴だけを保持してくれます。 これで自分のヒストリを汚すことなく、思う存分ゴルフができると思いますので、頑張ってみてください。

tag_nawk.pngtag_nawk.pngtag_nawk.pngtag_nawk.png