th0x0472.log

アクセスカウンタ

zoom RSS #SECCON 2013 オンライン予選 プログラミング・Crypt100 Write up未満

<<   作成日時 : 2014/01/28 01:16   >>

ブログ気持玉 0 / トラックバック 0 / コメント 0

「計算せよ」というタイトルとともに示されたサーバにつなぐと、謎の文字列が渡されます。タイトルからすると計算するんでしょうが、どういう計算をすれば良いのか、しばらくの間はサッパリ分かりませんでした。

しかし、ボウリングのスコアであると気づいた方がいて、とりあえず文字列を受け取ってスコアを計算するスクリプトを書きました。

awk で。

「awkでやることじゃない」というのももはや褒め言葉。 ← ひどい勘違い。


「計算工夫してラクに書こう」なんていう、なんていう甘い考えに走ったこともありましたが、あまい、あまかったですよ。結局はボウリングのスコア計算を日本語で説明したモノそのままのスクリプトになりました。

ボウリングの点数計算についてはWikiepdiaに簡潔にまとまっています。


簡単に作戦を説明すると次の3ステップです。

1) 受け取った入力はすべて数値にして配列に格納。一投でひとつ。これが PIN[n] です。
2) フレームごとの点数を計算。これが FSCORE[FRAME] です。
3) 最後にフレームごとの点数を合計して出力。

1) は 13〜24行目、2) は26〜47行目、3) は49〜52行目です。

1) については特に何も言うことはありません・・・・。というか、むしろ、スペアが来たときに i の値を確認せずに PIN[i-1] にアクセスしてるので触れたくありません。

2) は、10フレーム目だけ、ストライク・スペアでも次の投球で倒したピンの数を加算しないので分岐してます。そのため、何フレーム目かを FRAME で表していて、それをアップデートするために、そのフレームで1投目か2投目かを THROW で表しています。9フレーム目まではストライク・スペアだったら無条件でFRAMEを進めてTHROWを1に設定、10フレーム目ではFRAMEもTHROWも忘れて単純計算しています。

ここでも、なにも考えずに PIN[n+1], PIN[n+2] にアクセスしてますが見逃してください。

これだけじゃ問題サーバと通信できませんが、はなっからそこは @togakushi 師が何とかしてくれるだろうと踏んでました。そして実際その通りでした。


実際に問題を解いているときは時間の感覚がおかしくなっていて正確なことは追跡できず具体的な数字は出せないのですが、スクリプトを書き始めてから最初にとりあえず出来た、と思ったまでの時間よりも、それから修正をしてた時間の方が遙かに長かったはずです。
しかし、その修正は、ボウリングのスコア計算の仕方を整理してから手を付ければ間違いなく避けられたはずのものがほとんどでした。

物事の進め方の大切さは少しは分かってたつもりなのに・・・。


あとは、100ゲーム分答えるとそれまでのスコアの合計を聞かれ、それに答えるとさらにハイスコアを聞かれるという、オマケがついてましたが、ここまで来てしまえば悩むこともないかと。



 1:#!/usr/bin/awk -f
 2:
 3:BEGIN { 
 4:  SCORE=0;
 5:  THROW=1;
 6:  FRAME=1;
 7:  for (i=1; i<=10  i++){FSCORE[i]=0;}
 8:  for (i=1; i<=21  i++){PIN[i]=0;}
 9:}
10:
11:{
12:  gsub(" ","",$0); gsub("=","",$0);
13:  for(i=1; i<=length($0); i++){
14:    C=substr($0, i, 1);
15:    if (C=="X"){
16:      PIN[i]=10;
17:    }else if (C=="/"){
18:      PIN[i]=10-PIN[i-1];
19:    }else if (C=="-" || C=="G"){
20:      PIN[i]=0;
21:    }else{
22:      PIN[i]=C;
23:    }
24:  } 
25:
26:  for (i=1;i<=length($0); i++){
27:    C=substr($0, i, 1);
28:    if (FRAME<10){
29:      if (C=="X"){
30:        FSCORE[FRAME] += PIN[i] + PIN[i+1] + PIN[i+2];
31:        THROW=1; FRAME++;
32:      }else if(C=="/"){
33:        FSCORE[FRAME] += PIN[i] + PIN[i+1];
34:        THROW=1; FRAME++;
35:      }else {
36:        FSCORE[FRAME] += PIN[i];
37:        THROW++;
38:        if (THROW>2 ){
39:          THROW=1;
40:          FRAME++;
41:        }
42:      }
43:    }else{
44:      FSCORE[FRAME] += PIN[i];
45:      THROW++;
46:    }
47:  }
48:
49:  for (i=1;i<=10;i++) {
50:    SCORE+=FSCORE[i];
51:  }
52:  print SCORE;
53:}

テーマ

関連テーマ 一覧


月別リンク

ブログ気持玉

クリックして気持ちを伝えよう!
ログインしてクリックすれば、自分のブログへのリンクが付きます。
→ログインへ

トラックバック(0件)

タイトル (本文) ブログ名/日時

トラックバック用URL help


自分のブログにトラックバック記事作成(会員用) help

タイトル
本 文

コメント(0件)

内 容 ニックネーム/日時

コメントする help

ニックネーム
本 文
#SECCON 2013 オンライン予選 プログラミング・Crypt100 Write up未満 th0x0472.log/BIGLOBEウェブリブログ
文字サイズ:       閉じる