Code JP 2015 出し物班やりました(回答編) #codejp

CodeJP 2015へ参加しました。
参加した皆様お疲れ様でした。

今回出題がQRコード+暗号文解読という内容でしたが、いかがでしたでしょうか。
出題直後の反応といたしましては、出題者のひとりとして冷や冷やしましたが、
見事上級回答者が出たということでほっとしております。

ちなみに問題は こちら にあります。
回答読まずにとりあえずチャレンジしたい方はスクロールせず上記の「こちら」をクリックしてください。

準備編

今回はZbarのPythonライブラリを使います。 このライブラリ pip install zbar だけですとMacで正常に起動しません。 なので、ソースにpatchを当てて、導入します。
参考: Pythonで画像ファイルからQRコードを読み込む (MacOS)

まず、brewでZbarインストール(コンパイル用のヘッダーファイルが欲しい)

$ brew install zbar

次に、Pythonで使うためのライブラリ導入。 pypiのサイトからソースファイル、Githubからパッチファイルをダウンロードし、 patch コマンドを使い Segmantation fault 11 の発生を防ぎます。
参考: Zbar + python, crashes on import (OSX 10.9.1)
参考: added sentinel for imagescanner_get_results

$ mkdir -p /tmp/work/qrcode
$ cd /tmp/work/qrcode2
$ virtualenv -p /usr/bin/python2.7 venv
Running virtualenv with interpreter /usr/bin/python2.7
New python executable in venv/bin/python
Installing setuptools, pip...done.

$ . venv/bin/activate
(venv)$ pip install -U pip
(venv)$ mkdir -p venv/src/
(venv)$ cd venv/src
(venv)$ curl -O https://pypi.python.org/packages/source/z/zbar/zbar-0.10.tar.bz2
(venv)$ curl -O https://github.com/npinchot/zbar/commit/d3c1611ad2411fbdc3e79eb96ca704a63d30ae69.diff
(venv)$ tar jxvf zbar-0.10.tar.bz2
(venv)$ cd zbar-0.10.tar.bz2
(venv)$ patch -p1 < ../d3c1611ad2411fbdc3e79eb96ca704a63d30ae69.diff
patching file imagescanner.c

(venv)$ python setup.py install
(venv)$ cd ../../../
(venv)$ pwd
/tmp/work/qrcode

画像操作のため、Pillowモジュールを入れます。

(venv)$ pip install pillow

初級編(Q1)の回答

QRコードを読み込んだら、数字の羅列が取得できます。

91 67 111 100 101 74 80 50 48 49 53 93

これを、アスキーとして文字に変換すると

[CodeJP2015]

となります。
答えは、 [CodeJP2015] となります。

コード

#!/usr/bin/env python
# coding: utf-8

import zbar
import PIL.Image

scanner = zbar.ImageScanner()
scanner.parse_config('enable')

def decode_qrcode(img_path):
    pil = PIL.Image.open(img_path).convert('L')
    (w, h) = pil.size
    raw = pil.tostring()

    image = zbar.Image(w, h, 'Y800', raw)
    scanner.scan(image)

    decode_text = ''
    for symbol in image:
        if str(symbol.type) == 'QRCODE':
            decode_text += symbol.data

    del(image)
    return decode_text

if __name__ == '__main__':
    text = decode_qrcode('./01-01.jpg')
    print 'decode_qrcode:', text

    ans = ''
    for val in text.split(' '):
        ans = ans + chr(int(val))

    print 'ans:', ans

結果

$ python ans.py
decode_qrcode: 91 67 111 100 101 74 80 50 48 49 53 93
ans: [CodeJP2015]

中級編(Q2)の回答

16枚のQRコードを解読して連結すると、Base64エンコードされた文字列が出てきます。

Vmtab1VtUlZiRVpOV0Zwb1YwZFNiMU5WV2t0a2JVNUlWbXBPV2xkSGRIcFdWRXBIWkRKT1NFOVliR2xsVlVwRFdUSTFVbG94VmtoU2JteG9aVmhvYVZVeU1EVk9iR3hZVGxoS1lWWXlkRzVWTUdNMVRVVnNSMVJ1WkdwaVYzZ3hWMnBPVDFwRmVFWmhTRnBvVWpGYWQxbFVUbk5rYTJ4R1ZXMW9hVlV6YUU5WFZtaExUVmRGZVU5WVVscFZNRXBLV1dwT1Vsb3hWWHBSYm14b1ZucFdkVk5WVm05a2JWSklWbTVOUFE9PQ==

こちらを4回デコードするとキーワードが出てきます。

Mt. Moiwa Ropeway,Sapporo Art Park,[Jozankei Hot Springs],Hoheikyo Dam,Marukoma Hot Spring Hotel

答えは、 [Jozankei Hot Springs] となります。

コード

#!/usr/bin/env python
# coding: utf-8

import zbar
import PIL.Image
import base64

scanner = zbar.ImageScanner()
scanner.parse_config('enable')

def decode_qrcode(img_path):
    pil = PIL.Image.open(img_path).convert('L')
    (w, h) = pil.size
    raw = pil.tostring()

    image = zbar.Image(w, h, 'Y800', raw)
    scanner.scan(image)

    decode_text = ''
    for symbol in image:
        if str(symbol.type) == 'QRCODE':
            decode_text += symbol.data

    del(image)
    return decode_text

if __name__ == '__main__':
    text = ''
    for i in range(16):
        text = text + decode_qrcode('./qr/02-{0:0>2}.png'.format(i))
    print 'decode_qrcode:', text

    ans = text
    for i in range(4):
        print '{0}: {1}'.format(i, ans)
        ans = base64.b64decode(ans)

    print 'ans:', ans

結果

$ python ans.py
decode_qrcode: Vmtab1VtUlZiRVpOV0Zwb1YwZFNiMU5WV2t0a2JVNUlWbXBPV2xkSGRIcFdWRXBIWkRKT1NFOVliR2xsVlVwRFdUSTFVbG94VmtoU2JteG9aVmhvYVZVeU1EVk9iR3hZVGxoS1lWWXlkRzVWTUdNMVRVVnNSMVJ1WkdwaVYzZ3hWMnBPVDFwRmVFWmhTRnBvVWpGYWQxbFVUbk5rYTJ4R1ZXMW9hVlV6YUU5WFZtaExUVmRGZVU5WVVscFZNRXBLV1dwT1Vsb3hWWHBSYm14b1ZucFdkVk5WVm05a2JWSklWbTVOUFE9PQ==
0: Vmtab1VtUlZiRVpOV0Zwb1YwZFNiMU5WV2t0a2JVNUlWbXBPV2xkSGRIcFdWRXBIWkRKT1NFOVliR2xsVlVwRFdUSTFVbG94VmtoU2JteG9aVmhvYVZVeU1EVk9iR3hZVGxoS1lWWXlkRzVWTUdNMVRVVnNSMVJ1WkdwaVYzZ3hWMnBPVDFwRmVFWmhTRnBvVWpGYWQxbFVUbk5rYTJ4R1ZXMW9hVlV6YUU5WFZtaExUVmRGZVU5WVVscFZNRXBLV1dwT1Vsb3hWWHBSYm14b1ZucFdkVk5WVm05a2JWSklWbTVOUFE9PQ==
1: VkZoUmRVbEZNWFpoV0dSb1NVWktkbU5IVmpOWldHdHpWVEpHZDJOSE9YbGllVUpDWTI1UloxVkhSbmxoZVhoaVUyMDVObGxYTlhKYVYydG5VMGM1TUVsR1RuZGpiV3gxV2pOT1pFeEZhSFpoUjFad1lUTnNka2xGVW1oaVUzaE9XVmhLTVdFeU9YUlpVMEpKWWpOUloxVXpRbmxoVnpWdVNVVm9kbVJIVm5NPQ==
2: VFhRdUlFMXZhWGRoSUZKdmNHVjNZWGtzVTJGd2NHOXlieUJCY25RZ1VHRnlheXhiU205NllXNXJaV2tnU0c5MElGTndjbWx1WjNOZExFaHZhR1ZwYTNsdklFUmhiU3hOWVhKMWEyOXRZU0JJYjNRZ1UzQnlhVzVuSUVodmRHVnM=
3: TXQuIE1vaXdhIFJvcGV3YXksU2FwcG9ybyBBcnQgUGFyayxbSm96YW5rZWkgSG90IFNwcmluZ3NdLEhvaGVpa3lvIERhbSxNYXJ1a29tYSBIb3QgU3ByaW5nIEhvdGVs
ans: Mt. Moiwa Ropeway,Sapporo Art Park,[Jozankei Hot Springs],Hoheikyo Dam,Marukoma Hot Spring Hotel

上級編(Q3)の回答前半

上記2問までは「手で解けるもの」、こっからは「コード書かないと無理」という方針のもと少し面倒臭いものにしました。 ということで、こちらはQRコード4096枚連結して、Base64の文字列を取ります。(435809文字)

(はてなブログさんに「長すぎるので投稿できません」言われたので省略)

こちらをBase64で3回デコードすると、dataURL形式の「data:」を抜いた文字列を取得できます。

application/zip;base64,UEsDBBQAAAAAAG1vCEeVaIB2CgAAAAoAAAAIAAAAaGludC50eHQhIGZpenpidXp6UEsDBBQAAAAAAG1vCEdnRikfsAEAALABAAALAAAAcXIvMDAwMS5wbmeJUE5HDQoaCgAAAA1JSERSAAABIgAAASIBAAAAAHXF4hsAAAF3SURBVHic7ZlBjoMwEAR71pY4mh/kKebL+wP8FH5gHyMR9R5sZyE57F4MyBkfEpGU5NYwGjeNEH+v8PUPCFBKKaWUUurqlJRlASQLINVfplN1f ... (省略) ... AAAAAQEBATY5AABF4QEAAAA=

ZIPのバイナリをBase64からデコードして書き込むのも面倒臭いので、htmlのaタグに埋め込んで、zipをダウンロードできるようHTMLを書きます。

ここまでで、一旦くぎります。

コード

#!/usr/bin/env python
# coding: utf-8

import zbar
import PIL.Image
import base64

scanner = zbar.ImageScanner()
scanner.parse_config('enable')

def decode_qrcode(img_path):
    pil = PIL.Image.open(img_path).convert('L')
    (w, h) = pil.size
    raw = pil.tostring()

    image = zbar.Image(w, h, 'Y800', raw)
    scanner.scan(image)

    decode_text = ''
    for symbol in image:
        if str(symbol.type) == 'QRCODE':
            decode_text += symbol.data

    del(image)
    return decode_text

if __name__ == '__main__':
    text = ''
    for i in range(1, 4097):
        text = text + decode_qrcode('./qr1/{0:0>4}.png'.format(i))
    print 'decode_qrcode:', text

    for i in range(3):
        print '{0}: {1}'.format(i, text)
        text = base64.b64decode(text)

    print ''
    print text

    with open('zip.html', 'w') as f:
        f.write('<a href="data:{0}">downloads</a>'.format(text))

結果

(長いので省略。真実を知りたい人は是非実行してみよう。)

上級編(Q3)の回答後半

作成したHTMLを開きます。

$ open ./zip.html

ブラウザからリンクをクリックし、ダウンロードします。
Zipを解凍すると、 hint.txtqr と書かれた ディレクトリに256枚のQRコードが入っています。

$tree -L 1 .
.
├── hint.txt
└── qr/

hint.txt! fizzbuzz とあります。
fizzbuzzは3の倍数のとき「fizz」、5の倍数のとき「buzz」、3の倍数かつ5の倍数のとき「fizzbuzz」と表示するものです。
それに「!」がついていますので、今回はfizzbuzzに該当しないQRコードのファイル名を解読し、連結します。

Vm0wd2QyUXlVWGxWV0d4V1YwZFNUMVp0TVc5V01WbDNXa2M1VjFKc2JETlhhMk0xVjBaYWMySkVUbGhoTVVwVVZtcEdTMlJIVmtkWGJGcE9ZV3RGZUZadGNFSmxSbVJJVm10a1dHSkdjSEJXTUZwSFRURmFkRTFVVWxSTmF6RTFWa2QwYzJGc1NuUlZhemxhVmpOU2FGVXhXbXRXTVhCRlZXeHdWMDFWY0VwV2JURXdZekpHYzFOdVVtaFNlbXhXVm0xNFlVMHhXbk5YYlVacVlraENSbFpYZUhkV01ERldZMFZ3VjJKVVJYZFpWRXBIWXpGT2RWWnNTbWxTTTJoWVZrWldZVmxXVWtkV1dHaFlZbFZhY2xWcVFURlNNV1J5VjJ4T2FGWnNjSGxXTVZKSFZqSkZlVlZZWkZoV2JWSklWbXBHVDJSV1ZuTlhiV3hvVFVoQ1dsWXhXbE5TTVd4WFYxaG9hbEpXV2xSWmJHaFRWMFpTVjJGRlRsTmlSbkJaV2xWVk5WWlhTa1pqUldoWFRXNUNhRlpxU2tkamJVVjZZVVprVjFKWVFrbFhhMVpoV1ZkU1YxTnVUbFJpUjFKVVZGUkJkMDFSUFQwPQ==

ちなみに、fizzbuzzの該当する方も連結するとBase64っぽいものが出ます。

Vm0wd2QyUXlVWGxWV0dST1ZtMW9WMVl3Wkc5V2JGbDNXa1JTVjFac2JETlhhMXBQVmxVeFYyTkljRmhoTWsweFZtcEJlRmRIVmtkWGJGcE9ZbXRLVlZadE1YcGxSbVJJVm10V1VtSkdXbkJWYlhoM1ZWWmFkRTFVVWxwV01VcEpWbTEwYTJGR1NuUlZiR2hoVmpOU1IxcFZXbUZqYkd0NllVWlNUbFpVVmtsV2JUQXhWakpHUjFOdVRtcFNWR3hZV1d4b1UwMHhXWGhYYlhSWFRWWmFlVnBGV2s5aFZscHpZak5rVjFaNlJYZFdha1pYWkVaT2NtRkhhRk5sYlhoWFZtMDFkMUl5VW5OWGJHUllZbFZhY1ZsclpGTmxiRmw1VFZSQ1ZXSlZjRWhaTUZwM1ZqRmFObEpZWkZoV2JWSklWbXBHVDJSV1VuUmpSbEpUVmxoQ1dsWnJXbGRoTVZWNVZXNU9hbEpzY0ZsWmJGWmhWa1pTVjFkdVpFNVNia0pIVmpKNFQxWlhTa2RqUkVKaFVrVTFNMVpxUmt0ak1rNUhZVVprYUdFeGNGVlhXSEJIVkRKT2MxZHVUbFJpUjFKVVZGUkJkMDFSUFQwPQ==

そのあと、Base64で12回デコードしますと、答えが出ます。

[Eat.Drink.Sleep.]

fizzbuzzも連結側もBase64で11回デコードすると、答えっぽい偽物が出ます。

[https://goo.gl/xGFW4m]

開くと、回答者にスペシャルヒント+煽りが表示されます。

ですので、答えは [Eat.Drink.Sleep.] となります。

コード

#!/usr/bin/env python
# coding: utf-8

import zbar
import PIL.Image
import base64

scanner = zbar.ImageScanner()
scanner.parse_config('enable')

def decode_qrcode(img_path):
    pil = PIL.Image.open(img_path).convert('L')
    (w, h) = pil.size
    raw = pil.tostring()

    image = zbar.Image(w, h, 'Y800', raw)
    scanner.scan(image)

    decode_text = ''
    for symbol in image:
        if str(symbol.type) == 'QRCODE':
            decode_text += symbol.data

    del(image)
    return decode_text

if __name__ == '__main__':
    ans = ''
    dummy = ''
    for i in range(1, 257):
        if i % 3 == 0 or i % 5 == 0:
            dummy = dummy + decode_qrcode('./qr/{0:0>4}.png'.format(i))
        else :
            ans = ans + decode_qrcode('./qr/{0:0>4}.png'.format(i))
    print 'decode_qrcode:', ans

    for i in range(12):
        print 'ans   {0:>2}: {1}'.format(i, ans)
        ans = base64.b64decode(ans)

    for i in range(11):
        print 'dummy {0:>2}: {1}'.format(i, dummy)
        dummy = base64.b64decode(dummy)


    print ''
    print 'ans:', ans
    print 'dummy:', dummy

結果

$ python ans.py
decode_qrcode: Vm0wd2QyUXlVWGxWV0d4V1YwZFNUMVp0TVc5V01WbDNXa2M1VjFKc2JETlhhMk0xVjBaYWMySkVUbGhoTVVwVVZtcEdTMlJIVmtkWGJGcE9ZV3RGZUZadGNFSmxSbVJJVm10a1dHSkdjSEJXTUZwSFRURmFkRTFVVWxSTmF6RTFWa2QwYzJGc1NuUlZhemxhVmpOU2FGVXhXbXRXTVhCRlZXeHdWMDFWY0VwV2JURXdZekpHYzFOdVVtaFNlbXhXVm0xNFlVMHhXbk5YYlVacVlraENSbFpYZUhkV01ERldZMFZ3VjJKVVJYZFpWRXBIWXpGT2RWWnNTbWxTTTJoWVZrWldZVmxXVWtkV1dHaFlZbFZhY2xWcVFURlNNV1J5VjJ4T2FGWnNjSGxXTVZKSFZqSkZlVlZZWkZoV2JWSklWbXBHVDJSV1ZuTlhiV3hvVFVoQ1dsWXhXbE5TTVd4WFYxaG9hbEpXV2xSWmJHaFRWMFpTVjJGRlRsTmlSbkJaV2xWVk5WWlhTa1pqUldoWFRXNUNhRlpxU2tkamJVVjZZVVprVjFKWVFrbFhhMVpoV1ZkU1YxTnVUbFJpUjFKVVZGUkJkMDFSUFQwPQ==
ans    0: Vm0wd2QyUXlVWGxWV0d4V1YwZFNUMVp0TVc5V01WbDNXa2M1VjFKc2JETlhhMk0xVjBaYWMySkVUbGhoTVVwVVZtcEdTMlJIVmtkWGJGcE9ZV3RGZUZadGNFSmxSbVJJVm10a1dHSkdjSEJXTUZwSFRURmFkRTFVVWxSTmF6RTFWa2QwYzJGc1NuUlZhemxhVmpOU2FGVXhXbXRXTVhCRlZXeHdWMDFWY0VwV2JURXdZekpHYzFOdVVtaFNlbXhXVm0xNFlVMHhXbk5YYlVacVlraENSbFpYZUhkV01ERldZMFZ3VjJKVVJYZFpWRXBIWXpGT2RWWnNTbWxTTTJoWVZrWldZVmxXVWtkV1dHaFlZbFZhY2xWcVFURlNNV1J5VjJ4T2FGWnNjSGxXTVZKSFZqSkZlVlZZWkZoV2JWSklWbXBHVDJSV1ZuTlhiV3hvVFVoQ1dsWXhXbE5TTVd4WFYxaG9hbEpXV2xSWmJHaFRWMFpTVjJGRlRsTmlSbkJaV2xWVk5WWlhTa1pqUldoWFRXNUNhRlpxU2tkamJVVjZZVVprVjFKWVFrbFhhMVpoV1ZkU1YxTnVUbFJpUjFKVVZGUkJkMDFSUFQwPQ==
ans    1: Vm0wd2QyUXlVWGxWV0dST1ZtMW9WMVl3Wkc5V1JsbDNXa2M1V0Zac2JETlhhMUpUVmpGS2RHVkdXbFpOYWtFeFZtcEJlRmRIVmtkWGJGcHBWMFpHTTFadE1UUlRNazE1Vkd0c2FsSnRVazlaVjNSaFUxWmtWMXBFVWxwV01VcEpWbTEwYzJGc1NuUmhSemxWVm14YU0xWnNXbUZqYkhCRlZXeHdWMDFWY0VwV2JURXdZVEpHYzFOdVZsSmlSM2hYVkZWYVlWUkdWWGhYYlVaclVqQTFSMWRyV2xOaFZscHlWMVJHVjJFeVVYZFhWbVJIVmpGT2RWVnNXbWxoTUhCWlYxWlNSMWxXV1hoalJWWlRZbGhTV0ZSV2FFTlNiRnBZWlVVNVZXSkZjRWhXTW5CaFZqSkdjbUV6YUZkV1JYQklXa1ZhWVdSV1NuTlRiR1JUVFRBd01RPT0=
ans    2: Vm0wd2QyUXlVWGROVm1oV1YwZG9WRll3Wkc5WFZsbDNXa1JTVjFKdGVGWlZNakExVmpBeFdHVkdXbFppV0ZGM1ZtMTRTMk15VGtsalJtUk9ZV3RhU1ZkV1pEUlpWMUpJVm10c2FsSnRhRzlVVmxaM1ZsWmFjbHBFVWxwV01VcEpWbTEwYTJGc1NuVlJiR3hXVFVaYVRGVXhXbUZrUjA1R1drWlNhVlpyV1RGV2EyUXdXVmRHVjFOdVVsWmlhMHBZV1ZSR1lWWXhjRVZTYlhSWFRWaENSbFpYZUU5VWJFcEhWMnBhVjJGcmEzaFdWRXBIWkVaYWRWSnNTbGRTTTAwMQ==
ans    3: Vm0wd2QyUXdNVmhWV0doVFYwZG9XVll3WkRSV1JteFZVMjA1VjAxWGVGWlZiWFF3Vm14S2MyTkljRmROYWtaSVdWZDRZV1JIVmtsalJtaG9UVlZ3VlZaclpEUlpWMUpJVm10a2FsSnVRbGxWTUZaTFUxWmFkR05GWkZSaVZrWTFWa2QwWVdGV1NuUlZia0pYWVRGYVYxcEVSbXRXTVhCRlZXeE9UbEpHV2paV2Fra3hWVEpHZEZadVJsSldSM001
ans    4: Vm0wd2QwMVhVWGhTV0doWVYwZDRWRmxVU205V01XeFZVbXQwVmxKc2NIcFdNakZIWVd4YWRHVkljRmhoTVVwVVZrZDRZV1JIVmtkalJuQllVMFZLU1ZadGNFZFRiVkY1Vkd0YWFWSnRVbkJXYTFaV1pERmtWMXBFVWxOTlJGWjZWakkxVTJGdFZuRlJWR3M5
ans    5: Vm0wd01XUXhSWGhYV0d4VFlUSm9WMWxVUmt0VlJscHpWMjFHYWxadGVIcFhhMUpUVkd4YWRHVkdjRnBYU0VKSVZtcEdTbVF5VGtaaVJtUnBWa1ZWZDFkV1pEUlNNRFZ6VjI1U2FtVnFRVGs9
ans    6: Vm0wMWQxRXhXWGxTYTJoV1lURktVRlpzV21GalZteHpXa1JTVGxadGVGcFpXSEJIVmpGSmQyTkZiRmRpVkVVd1dWZDRSMDVzV25SamVqQTk=
ans    7: Vm01d1ExWXlSa2hWYTFKUFZsWmFjVmxzWkRSTlZteFpZWHBHVjFJd2NFbFdiVEUwWVd4R05sWnRjejA9
ans    8: Vm5wQ1YyRkhVa1JPVlZacVlsZDRNVmxZYXpGV1IwcElWbTE0YWxGNlZtcz0=
ans    9: VnpCV2FHUkROVVZqYld4MVlYazFWR0pIVm14alF6Vms=
ans   10: VzBWaGRDNUVjbWx1YXk1VGJHVmxjQzVk
ans   11: W0VhdC5Ecmluay5TbGVlcC5d
dummy  0: Vm0wd2QyUXlVWGxWV0dST1ZtMW9WMVl3Wkc5V2JGbDNXa1JTVjFac2JETlhhMXBQVmxVeFYyTkljRmhoTWsweFZtcEJlRmRIVmtkWGJGcE9ZbXRLVlZadE1YcGxSbVJJVm10V1VtSkdXbkJWYlhoM1ZWWmFkRTFVVWxwV01VcEpWbTEwYTJGR1NuUlZiR2hoVmpOU1IxcFZXbUZqYkd0NllVWlNUbFpVVmtsV2JUQXhWakpHUjFOdVRtcFNWR3hZV1d4b1UwMHhXWGhYYlhSWFRWWmFlVnBGV2s5aFZscHpZak5rVjFaNlJYZFdha1pYWkVaT2NtRkhhRk5sYlhoWFZtMDFkMUl5VW5OWGJHUllZbFZhY1ZsclpGTmxiRmw1VFZSQ1ZXSlZjRWhaTUZwM1ZqRmFObEpZWkZoV2JWSklWbXBHVDJSV1VuUmpSbEpUVmxoQ1dsWnJXbGRoTVZWNVZXNU9hbEpzY0ZsWmJGWmhWa1pTVjFkdVpFNVNia0pIVmpKNFQxWlhTa2RqUkVKaFVrVTFNMVpxUmt0ak1rNUhZVVprYUdFeGNGVlhXSEJIVkRKT2MxZHVUbFJpUjFKVVZGUkJkMDFSUFQwPQ==
dummy  1: Vm0wd2QyUXlVWGROVm1oV1YwZG9WbFl3WkRSV1ZsbDNXa1pPVlUxV2NIcFhhMk0xVmpBeFdHVkdXbFpOYmtKVVZtMXplRmRIVmtWUmJGWnBVbXh3VVZadE1UUlpWMUpJVm10a2FGSnRVbGhhVjNSR1pVWmFjbGt6YUZSTlZUVklWbTAxVjJGR1NuTmpSVGxYWWxoU00xWXhXbXRXTVZaeVpFWk9hVlpzYjNkV1Z6RXdWakZXZEZOcmFHaFNlbXhXVm01d1IyUnNXbGRYYlVacVlrZFNlbFl5TVRCVWJVcEhZMFp3VjFaNlJYZFhWbVJIVmpGT2RWUnRjRlJTVlhCWlZrWldhMVV5VW5OalJscFlZbFZhVkZSV1duZE5SbkJHVjJ4T1ZXSkdjREJhUkU1M1ZqRktjMk5HYUZkaGExcFVXWHBHVDJOc1duTlRiR1JUVFRBd01RPT0=
dummy  2: Vm0wd2QyUXdNVmhWV0doVlYwZDRWVll3WkZOVU1WcHpXa2M1VjAxWGVGWlZNbkJUVm1zeFdHVkVRbFZpUmxwUVZtMTRZV1JIVmtkaFJtUlhaV3RGZUZaclkzaFRNVTVIVm01V2FGSnNjRTlXYlhSM1YxWmtWMVZyZEZOaVZsb3dWVzEwVjFWdFNraGhSemxWVm5wR2RsWldXbUZqYkdSelYyMTBUbUpHY0ZwV1Z6RXdXVmRHVjFOdVRtcFRSVXBZVkZWa1UyUnNjRlpYYlVaVFRWWndNRnBGV2xOVWJGcDBaRE53VjFKc2NGaFdha1pUWXpGT2NsWnNTbGRTTTAwMQ==
dummy  3: Vm0wd2QwMVhVWGhVV0d4VVYwZFNUMVpzWkc5V01XeFZVMnBTVmsxWGVEQlViRlpQVm14YWRHVkdhRmRXZWtFeFZrY3hTMU5HVm5WaFJscE9WbXR3V1ZkV1VrdFNiVlowVW10V1VtSkhhRzlVVnpGdlZWWmFjbGRzV210TmJGcFpWVzEwWVdGV1NuTmpTRUpYVFVkU2RscFZXbUZTTVZwMFpFWlNUbFp0ZDNwV1JscFhWakZTYzFOclZsSldSM001
dummy  4: Vm0wd01XUXhUWGxUV0dST1ZsZG9WMWxVU2pSVk1XeDBUbFZPVmxadGVGaFdWekExVkcxS1NGVnVhRlpOVmtwWVdWUktSbVZ0UmtWUmJHaG9UVzFvVVZacldsWmtNbFpZVW10YWFWSnNjSEJXTUdSdlpVWmFSMVp0ZEZSTlZtd3pWRlpXVjFSc1NrVlJWR3M5
dummy  5: Vm0wMWQxTXlTWGROVldoV1lUSjRVMWx0TlVOVlZteFhWVzA1VG1KSFVuaFZNVkpYWVRKRmVtRkVRbGhoTW1oUVZrWlZkMlZYUmtaaVJscHBWMGRvZUZaR1ZtdFRNVmwzVFZWV1RsSkVRVGs9
dummy  6: Vm01d1MySXdNVWhWYTJ4U1ltNUNVVmxXVW05TmJHUnhVMVJXYTJFemFEQlhhMmhQVkZVd2VXRkZiRlppV0doeFZGVmtTMVl3TVVWTlJEQTk=
dummy  7: Vm5wS2IwMUhVa2xSYm5CUVlWUm9NbGRxU1RWa2EzaDBXa2hPVFUweWFFbFZiWGhxVFVkS1YwMUVNRDA9
dummy  8: VnpKb01HUklRbnBQYVRoMldqSTVka3h0WkhOTU0yaElVbXhqTUdKV01EMD0=
dummy  9: VzJoMGRIQnpPaTh2WjI5dkxtZHNMM2hIUmxjMGJWMD0=
dummy 10: W2h0dHBzOi8vZ29vLmdsL3hHRlc0bV0=

ans: [Eat.Drink.Sleep.]
dummy: [https://goo.gl/xGFW4m]

おわりに

次は出題経緯と出題時のスクリプトの紹介しようと思います。