Skip to content

Instantly share code, notes, and snippets.

@yammerjp
Created April 11, 2023 04:57
Show Gist options
  • Select an option

  • Save yammerjp/c4d4a7b2e45212b082808f18d04c43f1 to your computer and use it in GitHub Desktop.

Select an option

Save yammerjp/c4d4a7b2e45212b082808f18d04c43f1 to your computer and use it in GitHub Desktop.

ABC266のawkの最短解答は、現在次のもののようです。(私の書いたコードではありません)

$0=$(gsub(_,FS)/2)

https://atcoder.jp/contests/abc266/submissions/34440987

この回答が面白かったので、以下にどのようなコードであるかの解説を書きます。

awkの基本文法

awkプログラムの構成

awkのプログラムは 条件 { 処理 } という形式で記述され、(デフォルトでは)入力行ごとに「条件が真(0でない)であれば処理を行う」となっています。

例:

  • $ echo "hello" | awk '1{print "yes"}は、yesを出力する
  • $ echo "hello" | awk '0{print "yes"}'は何も出力されない

{処理} の省略

今回は{処理}が記述されていません。このときは{print $0}が省略されているとして、$0の値が標準出力されることになっています。 ($0は入力行を表します)

例:

  • $ echo 'hello' | awk '1'helloが出力される
  • $ echo 'hello' | awk '0'は何も出力されない

$0$1、...

$0は特別な変数で、入力行を初期値としてプログラムが実行されます。 ただし、プログラム中で自由に代入できます。

$数字 は、$0 を区切り文字FS(デフォルトでは空白) で区切ったときの数字番目の文字列が返されます。

例:

  • $echo 'h e l l o' | awk "{print $2}"eを返す

回答例の説明

$0=

$0は入力行全体が入っている変数ですが、代入すれば上書きできます。 $0=で始まっているので、今回は 条件 が代入式で真になります。更にパターンが省略されているので、代入された値が最後に出力されます。

gsub(_,FS)/2

gsubは組み込みの関数です。第一引数に正規表現、第二引数に置換先文字列、第三引数に置換対象変数が渡されます。実行すると、置換対象変数の値が直接書き換わり、置換回数が戻り値になります。

  • 第一引数: 置換時にマッチさせる正規表現を渡します。今回 _ は未定義変数なので、''(空文字) と同等になります。空文字のときはすべての場所にマッチします
  • 第二引数: 置換先文字列を渡します。今回のFSは、デフォルトで (スペース)が入っている変数です
  • 第三引数: 置換対象変数を渡します。省略されると $0を指定したのと同等になります
  • 戻り値: 置換回数が返ります。今回であれば、実行前の$0の文字数+1が返ります。

実行すると、$0のすべての文字がFS(空白)でバラされたものに置き換わります。

例えば実行前の$0helloのとき、次のようになります

  • 実行後の$0: h e l l o
  • 実行時のgsubの戻り値: 6

例:

$ echo 'hello' | awk '1{gsub(_,FS); print $0}'
 h e l l o 
$ echo 'hello' | awk '1{print gsub(_,FS)}'
6

最後に

$0=$(gsub(_,FS)/2)が実行されると、入力文字列を空白で区切った文字列を、入力文字列で区切ったときの、((入力文字列+1 )/ 2)番目の値が出力されます。これは問題の条件と一致します。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment