フルスタックエンジニアへの道

「フルスタックエンジニアになりたい。。。いや、なってやる!」という備忘録

8946 Take#9

今回は「http://www.hackerschool.jp/hack/」の正答率が6番目に高い(2019/08/03現在)「Take#9」を解いていきたいと思います。

http://www.hackerschool.jp/hack/www.hackerschool.jp

環境

Take#9

Take#9にアクセスすると、下図のような「ナンバー」を入力するフォームがあるページが出てくると思います。今回は、ナンバーを入手しなければならないようですね。

f:id:ryasshi:20190803173415p:plain

手始めに、「突破する!」を押すとどのような動作をするのかを確認していこうと思います。
[F12]」(もしくは、右クリックをして「検証」)を押して、デベロッパーツールを開き、「突破する!」のボタンの箇所を特定します。
デベロッパーツールが出たら、突破する!のタグがどこにあるかを確認します。上図左上にある赤枠のマウスのカーソルのようなマークをクリックして、「突破する!」をクリックします。すると、「突破する!」の箇所がハイライトされるはずです。

f:id:ryasshi:20190803171805p:plain

ここで、onclick属性に注目してみると「fn_check()」という関数が指定されていて、ボタンが押されるとこの関数を実行するようになっているようです。この関数がどのようなものなのか、確認していきましょう。

このHTML内で関数を検索するために、「fn_check()」をダブルクリックして選択した状態にし、「[Ctrl]+[F]」を押します。すると、自動的に検索バーに文字が入力されます。

f:id:ryasshi:20190803171906p:plain

この状態で「Enter」を押下すると、、、

f:id:ryasshi:20190803172020p:plain

ありました。fn_check()以外にもいろいろありますが、今回は簡単に説明します。 下記にHTMLからコピーしたJavaScriptを記述します。

var now = new Date();
var seconds = now.getSeconds();//秒数取得

function fn_timer(){
    now = new Date();
    seconds = now.getSeconds();
    document.getElementById("sec").innerHTML = seconds;//秒数を画面に表示
    setTimeout('fn_timer()',1);
}

//入力されたナンバーのチェック
function fn_check(){
    //入力されたナンバー
    var input_no = document.form1.input_no.value;

    var answer = ( ( seconds * ( seconds - 1 ) ) / 2 )*(input_no % 2);

    if (answer==990) {
        document.form1.answer_val.value = seconds;
    }
    document.form1.submit();
}

まず、now変数に日付や時刻などをあつかうものを代入し、それを使って「seconds」変数に現在時刻の秒を代入しています。

var now = new Date();
var seconds = now.getSeconds();//秒数取得

次に、fn_timer()関数ですが、これは画面に表示されている数字で、現在時刻の秒です。

function fn_timer(){
    now = new Date();
    seconds = now.getSeconds();
    document.getElementById("sec").innerHTML = seconds;//秒数を画面に表示
    setTimeout('fn_timer()',1);
}

f:id:ryasshi:20190803173603p:plain

最後に大本命の「fn_check()」関数です。

//入力されたナンバーのチェック
function fn_check(){
    //入力されたナンバー
    var input_no = document.form1.input_no.value;

    var answer = ( ( seconds * ( seconds - 1 ) ) / 2 )*(input_no % 2);

    if (answer==990) {
        document.form1.answer_val.value = seconds;
    }
    document.form1.submit();
}

まず、入力されたナンバーを「input_no」変数に代入しています。
次に、「answer」変数に下記の計算結果を代入しています。

( ( seconds * ( seconds - 1 ) ) / 2 )*(input_no % 2)

そして、if文で「answerと990が等しいか」を評価し、等しければform1内にあるname属性が「answer_val」のvalueにseconds変数の値を代入しています。(※input要素ですが、type属性で「hidden」が設定されているため、画面上には表示されていません)

f:id:ryasshi:20190803174724p:plain

関数の最後に「document.form1.submit()」でフォームを送信しています。
つまり、今回突破するにはanswerの計算式の結果が「990」になればいいのです!
それでは再度、計算式を見てみましょう。

( ( seconds * ( seconds - 1 ) ) / 2 )*(input_no % 2)

まず、(input_no % 2)は、「入力したナンバーを2で割った余り」ですので、ナンバーは奇数であれば何でもOKです。今回は、ナンバーに「1」を入力しておきます。

f:id:ryasshi:20190803175251p:plain

また、計算式は下記のように簡略化できます。

( ( seconds * ( seconds - 1 ) ) / 2 )*(1 % 2)  //ナンバーに「1」を入力
=( ( seconds * ( seconds - 1 ) ) / 2 )*1  //1を2で割った余りは「1」
=( ( seconds * ( seconds - 1 ) ) / 2 )  //( ( seconds * ( seconds - 1 ) ) / 2 )に「1」をかける

続いて( ( seconds * ( seconds - 1 ) ) / 2 )ですが、この計算結果が「990」になるようにしなければならないので、seconds変数に代入される値を求めます。
今回は、私が書きなれているPython3で計算します。また、実行環境がない場合は、ブラウザから実行できる「Online PHP/Java/C++... editor and compiler | paiza.IO」などを使いましょう。

for seconds in range(60):
    if seconds * ( seconds - 1 ) / 2 == 990:
        print(seconds)
        break

これでsecondsの値が分かりました。
あとは、求めた「secondsの値」と「画面に表示された数字」が同じ数になったときに「突破する!」をクリックするだけです!

ん?もっと簡単な方法ないのかだって?
ありますよ?笑
先程の説明した『form1内にあるname属性が「answer_val」のvalue』に直接値を指定すればいいのです。編集方法は、fn_timer()関数を検索した時のように、「value」をダブルクリックして行います。記述の仕方は「valeu="値"」で、記述できたらEnterを押下して確定させます。

f:id:ryasshi:20190803183116p:plain

指定できたら突破しましょう!
ナンバーに奇数の数字を入れるのを忘れないでくださいね!
あとは解説を読んで終了です。

f:id:ryasshi:20190803183451p:plain


参考:
http://www.hackerschool.jp/hack/
https://paiza.io/ja/projects/new