僕の考えた最強のパラメータ格納法

パラメータ格納

マイクロマウスではいろいろなパラメータ,調整項目があります.きれいに走るためには,たくさんのパラメータを真心込めて調整してあげる必要があります.ほんとうにしんどい.

さて,乱雑なコードを書いているといろんなよくない問題が発生します.
例えば,

  • 同じパラメータが複数ヶ所で定義されている
  • 使われていないパラメータが乱立している
  • 変更したいパラメータがどこに書かれているか見つからない

……などなど.ちなみに全て実話です

というわけで,パラメータの格納方法はこだわったほうがいいというのがこの記事で言いたいことです.

先駆者

某先輩がポインタまみれのスラロームパラメータ保存を紹介していました.全容を把握するのには苦労しますが,すべてのパラメータを#defineするよりも良い方法だと思います.
C言語を頑張りたい人はこの記事を読んで,ポインタとは何者なのか理解しちゃいましょう!

ぼくのかんがえた(以下略

では,僕の考えた最強のパラメータ格納法をででんと紹介します.

あ,予め言っておきますがC++11とSTLを使いまくっているので,用法用量にはお気をつけください.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
namespace slalomparams{
enum class RunType : uint8_t {
SLALOM90SML_RIGHT,
SLALOM90SML_LEFT,
SLALOM90_RIGHT,
SLALOM90_LEFT,
SLALOM180_RIGHT,
SLALOM180_LEFT,
SLALOM45IN_RIGHT,
SLALOM45IN_LEFT,
SLALOM45OUT_RIGHT,
SLALOM45OUT_LEFT,
SLALOM135IN_RIGHT,
SLALOM135IN_LEFT,
SLALOM135OUT_RIGHT,
SLALOM135OUT_LEFT,
SLALOM90OBL_RIGHT,
SLALOM90OBL_LEFT,
TRAPACCEL,
PIVOTTURN,
};

struct pack{
float d_before;
float d_after;
float acc_rad;
float deg;
float const_deg;
float in_vel;
float out_vel;
float min_vel;
float acc_lin;
};
typedef struct pack pack_t;
}

array< map<float,pack_t>* , 16> slalomparams::getParams(){
static map<float, pack_t> SLALOM90SML_RIGHT = {
// { vel, {d_bef, d_aft, a_rad, deg, cnsdeg, in_vel, out_vel, min_vel, acc_lin}},
{0.25, {0.010, 0.012, 9000,95.5, 30, 0.25, 0.25, 0.25, 0.0}},
};
static map<float, pack_t> SLALOM90SML_LEFT = {
// { vel, {d_bef, d_aft, a_rad, deg, cnsdeg, in_vel, out_vel, min_vel, acc_lin}},
{0.25, {0.010, 0.012, 9000,95.5, 30, 0.25, 0.25, 0.25, 0.0}},
};
static map<float, pack_t> SLALOM90_RIGHT = {};
static map<float, pack_t> SLALOM90_LEFT = {};
static map<float, pack_t> SLALOM180_RIGHT = {};
static map<float, pack_t> SLALOM180_LEFT = {};
static map<float, pack_t> SLALOM45IN_RIGHT = {};
static map<float, pack_t> SLALOM45IN_LEFT = {};
static map<float, pack_t> SLALOM45OUT_RIGHT = {};
static map<float, pack_t> SLALOM45OUT_LEFT = {};
static map<float, pack_t> SLALOM135IN_RIGHT = {};
static map<float, pack_t> SLALOM135IN_LEFT = {};
static map<float, pack_t> SLALOM135OUT_RIGHT = {};
static map<float, pack_t> SLALOM135OUT_LEFT = {};
static map<float, pack_t> SLALOM90OBL_RIGHT = {};
static map<float, pack_t> SLALOM90OBL_LEFT = {};

static array< map<float,pack_t>* , 16> params = {
&SLALOM90SML_RIGHT,
&SLALOM90SML_LEFT,
&SLALOM90_RIGHT,
&SLALOM90_LEFT,
&SLALOM180_RIGHT,
&SLALOM180_LEFT,
&SLALOM45IN_RIGHT,
&SLALOM45IN_LEFT,
&SLALOM45OUT_RIGHT,
&SLALOM45OUT_LEFT,
&SLALOM135IN_RIGHT,
&SLALOM135IN_LEFT,
&SLALOM135OUT_RIGHT,
&SLALOM135OUT_LEFT,
&SLALOM90OBL_RIGHT,
&SLALOM90OBL_LEFT,
};

return params;
}

struct pack がスラロームの1パラメータを格納した構造体です.
スラロームには,代表的なターンが16種類あるので,
1種類のスラロームパラメータをまとめたもの(A) へのポインタを,サイズ16の配列(B) にしています
(A)map<float, pack_t>で,(B)array< map<float, pack_t>*, 16>です.

(A)にstd::mapを使うことで,パラメータの存在確認を可能にしました.
スラロームのターン速を引数に取ることで,欲しいパラメータを参照することができます.

具体的には,次のようなコードでターンパラメータを取得・参照できます.

1
2
3
4
5
6
using namespace slalomparams;
auto it = getParams().at(static_cast<uint16_t>(RunType::SLALOM90SML_RIGHT))->find(0.25f);
if(it == getParams().at(static_cast<uint16_t>(RunType::SLALOM90SML_RIGHT))->end()) printf("Undefined parameter");

it->second.deg; //95.5
it->second.d_before; //0.01

ちなみに,諸事情あってconstにはしていませんが,問題なくconstをつけられると思います.

第29回マイクロマウス東北地区大会で足立法を実装した話

東北大会

マイクロマウス東北地区大会は,我々Miceが毎年大変お世話になっている大会です.
毎年多くのフレッシュマンが精神と時の部屋でとてつもない成長を遂げます.

本年度も6人のフレッシュマンがエントリーし,うち3名が完走.そしてその3名が上位1〜3位を独占という結果になりました! まずは良い結果になり,ホッとしています.正直自分の出走より何倍もドキドキしていました.

反省点も色々と考えているようなので,次の大会も期待しています.博多ラーメン食べられるのが今週の活力.

精神と時の部屋での成長

調整時間にあまり他の人に構えなくて申し訳なく思っていますが,なんせ自分の進捗が怪しいので頑張っていました.

今年のマウスはマイコンを変えただけでなく,プログラムをイチから書き直しています.というのも,コンパイラを変えたことでC++14が使えるようになったので,色々と直したいところが出てきたためです.
ついでにクラス設計も考え直しました.今のところ,いい感じにコードが動いているように思います.

さて,そのせいもあり,容易には昨年度のプログラムを流用することができなくなっています.
精神と時の部屋では,壁情報の保存,歩数マップの展開,足立法の実装を終えることができました.(あれっ,進捗遅くない???)
そういえばモードを実装しようと思っていましたが,間に合いませんでした.そのうちがんばります.

さて,ここからは技術的な話.毎度言っていますが,参考にするときは完全に自己責任で.より良い方法があればご教示いただきたいです.
足立法で走行するプログラムは,こんな感じになっています.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
VelocityControl vc;
Position pos;

Adachi adachi;
Map map;
Walldata walldata;
WallSensor wall;

adachi.setGoal(11, 11);
vc->runTrapAccel(0.0f, 0.25f, 0.25f, 0.045f, 2.0f); while(vc->isRunning());

while(true){
walldata = wall->getWall();
map.addWall(pos.getPositionX(), pos.getPositionY(), pos.getAngle(), walldata);

adachi.setMap(map);
adachi.renewFootmap();
slalomparams::RunType runtype = adachi.getNextMotion(pos.getPositionX(), pos.getPositionY(), pos.getAngle(), walldata);

if(runtype == slalomparams::RunType::TRAPACCEL){
vc->runTrapAccel(0.25f, 0.25f, 0.25f, 0.078f, 2.0f); while(vc->isRunning());
} else if(runtype == slalomparams::RunType::PIVOTTURN){
vc->runTrapAccel(0.25f, 0.25f, 0.0f, 0.045f, 2.0f); while(vc->isRunning());
vc->runPivotTurn(360, 180, 1000); while(vc->isRunning());
vc->runTrapAccel(0.0f, 0.25f, 0.25f, 0.045f, 2.0f); while(vc->isRunning());
} else if(runtype == slalomparams::RunType::SLALOM90SML_RIGHT){
vc->runSlalom(RunType::SLALOM90SML_RIGHT, 0.25f); while(vc->isRunning());
} else if(runtype == slalomparams::RunType::SLALOM90SML_LEFT){
vc->runSlalom(RunType::SLALOM90SML_LEFT, 0.25f); while(vc->isRunning());
} else {
vc->runTrapAccel(0.25f, 0.25f, 0.0f, 0.045f, 2.0f); while(vc->isRunning());
break;
}

pos.setNextPosition(runtype);

if(pos.getPositionX() == 11 && pos.getPositionY() == 11){
vc->runTrapAccel(0.25f, 0.25f, 0.0f, 0.045f, 2.0f); while(vc->isRunning());
break;
}
}
adachi.setMap(map);

壁情報を Walldata クラスでやり取りできるので,記述がなかなか楽になっています.
それから,足立法と座標管理部分と実際のセンサやモータ駆動部分を分離したため,シミュレータにそのまま移植できるはずです.

第34回マイクロマウス東日本地区大会を見に行ってきた

本年度の予定

マイクロマウスシーズンが始まりました.
今年は,これだけの大会に参加しようと思います.

日程 大会 目標(または結果)
7月10日 関西大会 スタートセンサを切った
9月11日 台湾大会 台湾旅行を楽しんだ
10月2日 東日本大会 団体特別賞をいただいた
10月9日 東北大会 ゴールする
10月16日 九州大会 最短ゴールする
10月23日 中部大会 速度を上げる
10月30日 学生大会 シードを取る
11月6日 北信越大会 賢いパスを考える
11月19・20日 全日本大会 決勝で最短ゴールする

と,なかなか旅行三昧かつ高めの目標を立てていますが,頑張っていきたいと思います.
(なんせ就活に使うには今年の大会で成績を残しておかないといけない)

他の目標

成績面での目標は挙げましたが,他に実装したい機能がいくつかあります.
どこまでできるかわかりませんが,とりあえず書き留めておきます.

  • マウス単体でのパラメータ調整
    僅かな数値調整のためにいちいちコンパイル&書き込みするのが鬱陶しいので,マウスで調整したいと思いました.
    一応案はあるので,そのうち実装したいと思っています.
  • 最短経路の時間ベース導出
    ターンに要する時間を考慮した上での最短経路を出したいと思っていました.
    ひとまずは,なんとか松先輩から聞いた方法で試そうかなと考えています.
  • 位置補正
    海外勢がやっている,壁センサのみで区画中心に戻る動作をやりたいです.
    尻当てができない形状なので,格好良くシュッと補正したいと思っています.
  • 最短経路導出プログラムのライブラリ化
    シミュレータと同じコードで動かしたいので,ライブラリにしたいです.
    動的リンクでなかなか苦しんでいるけど…….

以下完全に妄想

  • 迷路中の自己位置推定
    探索でコケた際,それまでに記録した迷路データと周囲の壁情報から自己位置が推定できそうな気がしています.
    壁情報の比較アルゴリズムの最適化と,区画中心に戻る方法をこれから考えていきたいところ.
  • 最短パラメータの自動設定
    最短パラメータを人間が設定しているのは正直イマイチ.
    ロボットを置くことと,スタートボタンを押すことだけにしたいなあと妄想中.

東日本地区大会のまとめ

今更まとめることもないと思いますが,感想はいくつか.

  • 今年のフレッシュマンは強い
    一昨年のフレッシュマン(大嘘)は詐欺です.
    それに比べ,今年のフレッシュマンは未経験からのスタートで本当に頑張ってるなと思います.クォーターではいろいろなバッヂを手に入れ,エキスパートマウスも何台か誕生しました.部室で苦しんでいる姿をよく見ますが,これからの活躍にとても期待しています!
    あ,一応補足しておきますが FND,お前はフレッシュマンじゃねえぞ (エキスパートとして応援しています)
  • 中学生すごい
    中学3年生でハーフサイズゴールをキメていました.本当にすごいと思います.(授業では加速度を習っているところだそう)
    ただでさえ難しい競技の上,ノウハウも全然ないそうなので,相当苦労されているんじゃないかと思います.是非今度遊びに来てください.
  • 副部長つよい
    しかし部長が副部長には負けてられない.
    今シーズンも頑張っていきます.

関数を作る

この記事の目的

この記事は部員向けに書いています.初めて壁情報を保存しようと頑張っている人,使いやすい関数を作りたい人,キーの打ち間違えが多くて困っている人は読んでみてください.
壁の追加関数を作りながら,関数の作り方を学習していきましょう.

この記事ではC言語の関数のみを扱います.また,あくまで僕の考えをまとめたものなので,すべての内容が正しいことは保証されません.

関数とは

関数とはなんでしょうか?
具体的なコードを見てみましょう.

1
2
3
4
5
6
7
8
int sum(int a, int b){
return a+b;
}

int main(){
int n = sum(3, 5);
printf("%d", n);
}
1
8

関数sumは,与えた2つの引数の和を返す関数です.超便利な関数ですよね!
「’+’使えばいいじゃん」
……なるほど,ではこれはどうでしょうか?

1
2
3
4
5
6
7
8
9
10
11
12
13
int sum2(int a, int b){
int i;
int w=0;
for(i=a; i<=b; ++i){
w += i;
}
return w;
}

int main(){
int n = sum2(3, 5);
printf("%d", n);
}
1
12

関数sum2は,与えた引数a以上b以下の数字の和を返す関数です.なるほどこれは便利だ!

という感じで,ある一つの機能を持った小さなプログラムが関数だと思ってください.

関数を作る

作る関数を決める

では,関数を作ってみることにしましょう.今作りたい機能は,マイクロマウスを走らせながら迷路(壁)情報を保存し,読み出すことができる機能だとします.
初めにすべきことは,機能の分割です.今言った機能はすごく大雑把な表現なので,どのような関数が必要か考えてみましょう.

壁を何らかの変数(おそらく配列)に格納すると思います.この変数に,任意の1枚の壁を追加する関数が必要そうです.同時に,この変数から任意の1枚の壁が存在するかどうかを調べる関数も必要でしょう.
というわけで,まずは1枚の壁を追加する関数を作っていきたいと思います.

さて,関数を作る時に意識すべきことは,使いやすい引数を設定することです.
壁を追加する時に,どのような命令で壁を指定すると便利でしょうか?

僕は「壁の面する座標と,壁の存在する方角」を引数にすると便利だと考えました.というわけで,関数のプロトタイプ宣言はこのようにしてみます.

1
int addSingleWall(int x, int y, int dir);

引数として追加したい壁のx,y座標,壁の存在する方角を取り,
返り値は壁の追加に成功した場合0,失敗した場合それ以外の数字を返すようにします.

そういえば,引数にある int dir は具体的にどうやって指定すればいいのでしょうか? いまいちわかりにくいので,改良しておきましょう.

1
2
3
4
5
6
7
8
enum Direction {
DIR_NORTH,
DIR_EAST,
DIR_SOUTH,
DIR_WEST
}

int addSingleWall(int x, int y, enum Direction dir);

関数を実装する

では,addSingleWallを実装していきましょう!
まずはとりあえず実装してみます.
(壁情報の持ち方については,旧ブログ記事を参照してください)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
unsigned short wall_column[15];
unsigned short wall_row[15];

int addSingleWall(int x, int y, enum Direction dir){
switch(dir){
case DIR_NORTH:
wall_row[y] |= (0x1 << (15-x));
break;
case DIR_EAST:
wall_column[x] |= (0x1 << (15-y));
break;
case DIR_SOUTH:
wall_row[y-1] |= (0x1 << (15-x));
break;
case DIR_WEST:
wall_column[x-1] |= (0x1 << (15-y));
break;
}
return 0;
}

さて,このプログラムは正しく動作するでしょうか?
もちろんお気づきかと思いますが,問題がありますね.引数値として,例えば(0, 0, DIR_WEST)を与えた場合に配列の領域外にアクセスすることになります.もしくは,(-100, 150, DIR_NORTH)などの範囲外を与えた場合にもエラーが返って来ず,恐ろしいことになりそうです.

今回気をつけなければいけなかったことは,次のようなことです.

  • 正しい処理をする
    言うまでもなく,適切な壁を追加してくれないと困ります.
  • 誤った引数が来ても問題なくする
    今回の場合,壁が追加できないような引数が来た場合には何もせずにエラーコードを返すべきです.
    誤った壁を追加したり,配列の領域外にアクセスするといったことは絶対にしないように気をつけます.

以上を踏まえた上で実装を行いました.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
unsigned short wall_column[15];
unsigned short wall_row[15];

int isInRange(int x, int min, int max){
if(x >= min && x <= max) return 1;
else return 0;
}

int addSingleWall(int x, int y, enum Direction dir){
switch(dir){
case DIR_NORTH:
if(!isInRange(x, 0, 15)) return 1;
if(!isInRange(y, 0, 14)) return 1;
wall_row[y] |= (0x1 << (15-x));
break;
case DIR_EAST:
if(!isInRange(x, 0, 14)) return 1;
if(!isInRange(y, 0, 15)) return 1;
wall_column[x] |= (0x1 << (15-y));
break;
case DIR_SOUTH:
if(!isInRange(x, 0, 15)) return 1;
if(!isInRange(y, 1, 15)) return 1;
wall_row[y-1] |= (0x1 << (15-x));
break;
case DIR_WEST:
if(!isInRange(x, 1, 15)) return 1;
if(!isInRange(y, 0, 15)) return 1;
wall_column[x-1] |= (0x1 << (15-y));
break;
default:
return 1;
break;
}
return 0;
}

壁が存在するかを読み取る関数や,他に必要と思った関数は自分で実装をしてみてください.

関数を拡張する

さて,先程作ったaddSingleWall関数を改良してみましょう.

壁情報を複数個持ちたい場合があるかもしれません.まずは壁情報であるunsigned short wall_column[15]unsigned short wall_row[15]をまとめて構造体にしておきます.

1
2
3
4
struct WallData{
unsigned short column[15],
unsigned short row[15]
}

では,安直に次のように実装してみます.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
struct WallData wd1;
struct WallData wd2;

int isInRange(int x, int min, int max){
if(x >= min && x <= max) return 1;
else return 0;
}

int addSingleWall1(int x, int y, enum Direction dir){
switch(dir){
case DIR_NORTH:
if(!isInRange(x, 0, 15)) return 1;
if(!isInRange(y, 0, 14)) return 1;
wd1.row[y] |= (0x1 << (15-x));
break;
case DIR_EAST:
if(!isInRange(x, 0, 14)) return 1;
if(!isInRange(y, 0, 15)) return 1;
wd1.column[x] |= (0x1 << (15-y));
break;
case DIR_SOUTH:
if(!isInRange(x, 0, 15)) return 1;
if(!isInRange(y, 1, 15)) return 1;
wd1.row[y-1] |= (0x1 << (15-x));
break;
case DIR_WEST:
if(!isInRange(x, 1, 15)) return 1;
if(!isInRange(y, 0, 15)) return 1;
wd1.column[x-1] |= (0x1 << (15-y));
break;
default:
return 1;
break;
}
return 0;
}

int addSingleWall2(int x, int y, enum Direction dir){
switch(dir){
case DIR_NORTH:
if(!isInRange(x, 0, 15)) return 1;
if(!isInRange(y, 0, 14)) return 1;
wd2.row[y] |= (0x1 << (15-x));
break;
case DIR_EAST:
if(!isInRange(x, 0, 14)) return 1;
if(!isInRange(y, 0, 15)) return 1;
wd2.column[x] |= (0x1 << (15-y));
break;
case DIR_SOUTH:
if(!isInRange(x, 0, 15)) return 1;
if(!isInRange(y, 1, 15)) return 1;
wd2.row[y-1] |= (0x1 << (15-x));
break;
case DIR_WEST:
if(!isInRange(x, 1, 15)) return 1;
if(!isInRange(y, 0, 15)) return 1;
wd2.column[x-1] |= (0x1 << (15-y));
break;
default:
return 1;
break;
}
return 0;
}

……どう考えても冗長なコードです(先日部員がこのようなコードを書いていて驚愕しました).
これでは満足行かないので,addSingleWallの引数を次のように工夫してみます.

1
int addSinglewall(int x, int y, enum Direction, struct WallData *);

実装すると次のような感じでしょうか.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
struct WallData wd;

int isInRange(int x, int min, int max){
if(x >= min && x <= max) return 1;
else return 0;
}

int addSingleWall(int x, int y, enum Direction dir, struct WallData *wall){
switch(dir){
case DIR_NORTH:
if(!isInRange(x, 0, 15)) return 1;
if(!isInRange(y, 0, 14)) return 1;
wall->row[y] |= (0x1 << (15-x));
break;
case DIR_EAST:
if(!isInRange(x, 0, 14)) return 1;
if(!isInRange(y, 0, 15)) return 1;
wall->column[x] |= (0x1 << (15-y));
break;
case DIR_SOUTH:
if(!isInRange(x, 0, 15)) return 1;
if(!isInRange(y, 1, 15)) return 1;
wall->row[y-1] |= (0x1 << (15-x));
break;
case DIR_WEST:
if(!isInRange(x, 1, 15)) return 1;
if(!isInRange(y, 0, 15)) return 1;
wall->column[x-1] |= (0x1 << (15-y));
break;
default:
return 1;
break;
}
return 0;
}

まとめ

関数は使いやすさが第一です.自分の使いやすい関数を作り,楽に開発を進めましょう.
機能ごとに関数を分割することでデバッグも楽になるはずです.

2016年マイクロマウス台湾大会に付き添ってきた話

出発まで

すべての元凶であるF先輩が台湾大会に行きたいと言い出し,僕とM先輩が巻き込まれました.そして大勢のマウス関係者のご協力のおかげで無事参加できることになりました.ところがどっこい,F先輩が「金ないから行かない」とか言い出したのでLCCを使った最高のプランを提案し,無事3人で参加することになりました.まったく迷惑かけさせんなよ

初めての台湾

Vanilla Airを使って格安で台湾に行くことができました.現地では,予め契約しておいたルーターのおかげでインターネットに困ることはありませんでした.

台湾で先輩たちと合流した後,ノープラン台湾旅行1日目が始まりました.僕とF先輩は全く分からなかったので,何かしらの情報を持っていたM先輩の案内のもと九份に行くことにしました.
これは九份にあったセブンイレブンの様子です.

九份でお茶を飲んだときの様子です.

台湾の交通系ICカードの写真です.

台北101でちびっているF先輩の様子です.

夜に遊びに行ったときのM先輩の様子です.

たまこまグッズを見つけてテンションが上がったときの僕の様子です.

大会

ものすごい坂道に建っている大会会場に到着しました.
無事に二人とも最短走行が成功してよかったです.僕も頑張らないと.

帰国

最終日はマウス関係者の皆さんに誘われて淡水観光をしました.どでかい川があったり,アニキ撮影会があったり,よくわからない文化遺産があったりして,とても楽しかったです.

今回ご協力いただいた皆さん,本当にありがとうございました.これに懲りず,また参加しようと目論んでいるのでそのときはよろしくお願いします.
無謀な計画に付き合ってくれたみなさん,ありがとうございました.僕は全く反省していないので,どんどん連れ回しますがお付き合いください.

はてなサマーインターン2016で最高の夏を過ごしてきた

はてなサマーインターン

とは

はじめまして,id:hantasです(誰だお前).
はてなではhantas,それ以外ではtanihoを使っているのでややこしいですが,今回はid:hantasとしてはてなサマーインターンに参加してきました!

はてなサマーインターンとは,あの有名な株式会社はてなが1年に1度実施しているインターンシップです.20日間のうち前半は講義,後半はチームに配属されて開発を行います.なんと後半課程では給与が発生します! 嬉しい!
詳しくは次の募集サイトを見てみてください.
はてなサマーインターン2016

なぜ参加したのか

「時代は静的ブログだ!」とか言ってはてなブログ(hantas’s blog)からhexoに乗り換えた自分が,どうしてはてなのインターンに参加してしまったのでしょうか?
僕が小学生の頃.ロボットを通してプログラミングを学び始めた頃から,ちらほらと「プログラマーかっこいいなー」と思っていました.中学ではその世界から離れ,高校ではプログラムは少しだけ書いていたものの,ろくな活動はしていませんでした.「大学ではバリバリコード書くぞ!」と思っていたのですが,電気工学科がバリバリコードを書ける環境にあるかというと,ぶっちゃけそうでもなく.気づいたら 悪徳宗教サークルMice に入部して組み込み開発と機械設計の毎日を送っていました.
学生生活もあと2年を切り,悔いのないようにしたいと思ったのが学部3年の5月.セキュリティキャンプの応募を考えている頃に,同時に将来のことなんかも考えていました.将来どんな仕事をしようか? 定年まで働くの? 大学院は? いろいろ考えないといけないことがあります.周りの友達が「インターン,インターン! インターン!!」と叫び出したので,とりあえずの気持ちでインターンに応募し始めました.
ハーフマウスの開発にお金が吹き飛んでいったことを言い訳にして「無給インターンは行きたくない! お金の出るところだけ応募するぞ!」というとても厚かましいことを言い出し,LINE,yahoo,pixiv,はてなの4社に応募しました.結果,yahoo以外はすべて1次選考通過したのですがスケジュールの兼ね合いで一番行きたかったはてなに行くことにしました!
はてなインターンシップの選考ではポートフォリオを出すように指定されたので,参考にも僕のポートフォリオサイトを公開しておきます.デザインがひどい件については,幅広くアドバイスを募集しています.
Portfolio - taniho0707

おいマウスやれよ

誰かに会う度に言ってる気がするんですが,インターンにこの夏のすべてを捧げた感じがします.

休日が壊滅的に存在しない

マウスで圧倒的進捗して台湾大会で優勝する予定(大嘘)だったのですが,インターンシップがたいへんハードなスケジュールだったので進捗を出せるはずもなく.Perl書きすぎてC++書けなくなってるかもしれませんが,10月からは頑張りたいと思います.

前半

前半の講義が始まる前に,環境構築の時間がありました.僕のパソコンではMySQLが起動しないという大変な事態が起こっていたのですが,id:polamjagくんやメンターのid:windymeltさんに助けてもらい,あっという間に解決しました.感謝!
この内容については別記事を書く予定です.

講義が始まったら,毎日新しい分野の専門講義を受講し,午後にそれを用いた課題に取り組みます.特にトラブルがなければ,必須課題は終わります.遅くても帰る時間(22時)には絶対終わると思います.ただ,応用課題はすごいざっくりとした課題なので,好きなだけ凝ることができます.そして気付いたら22時になって悲しくなります.初めの2週間は,大体こんな感じで過ぎていきました.
そういえば,この講義では超基本的なことはあまり触れられません.事前課題があるので,最低ラインの知識があること前提なのでしょう.しかし,最高の教科書と最高のメンターと,最高の講義のおかげもあり,メキメキと知識がついていくことが実感できました.

前半のハイライトです.

グリーンカレー初めて食べたけど美味しかった.

生まれて初めてのファミコン.

id:nanto_viさんに京都観光に連れて行ってもらいました!
コースは,平等院鳳凰堂からの下鴨神社! 晩御飯は美味しい京野菜のお店に行きました!

帰った後たまこラブストーリー観ました.subsonic最高だわ.

中間

京都にいるのでいろんな人といろんなところに遊びに行きました.この章ははてなと関係ありません.

  • 東京から友達が来たので,ダリ展とか,日本橋とか,〜禁則事項〜地とか,深夜の伏見稲荷大社とか,地主神社とか行きました.

  • コミケの打ち上げを京都でやりました.近々DLSiteに登録するので,是非ご購入ください!

  • 地元の友達と花火しました.儚く落ちる線香花火.夏っぽくていいですね.

後半

配属

後半では,それぞれのチームに2人ずつ配属されました.僕たちは機械学習・自然言語処理・アドテクノロジーコースということで,はてなブックマークなどなどを扱っている最高のチームに配属され,メンターのid:syou6162さんにサポートしてもらいながら作業していました! チームメンバーとなった id:takuya-nakamura くん,2週間の間お世話になりました!
後半課程として与えられた課題は,検索結果を改善すること.前半課程で学んだ機械学習の知識をフル活用し,検索エンジンの改良に取り組みました.

事件

とある昼休みにはこんなことがありました.

なんでもインターンあるあるだとか.
そんなこともあったブログチームですが,なんと最速リリースをして「優勝! 優勝!」と叫んでいました.

定時後

3週目の定時後には毎日イベントが開催されており,毎日飲んで食べて踊っていました.

面談

社長面談があるということは事前に聞いていたのですが,まさかCTO面談,人事面談,社長面談と,3つも面談があるとは思っていませんでした!
社長とお話できる時間が用意されているのは,はてなインターンの魅力の一つではないかと思います.面談でなくてもお昼休みには役員・社員のみなさんが一緒にご飯を食べているので,話しかけ放題です.

最終発表

最終日,配属されたチームごとに最終発表を行いました.僕達のチームは「機械学習とはなんぞや?」というところから易しく説明して,いかに苦労してフィルタが完成したか,というところを発表しました.
残念ながら1票という僅差で3位でしたが,多くの社員さんが感想と共に投票してくださり,とても嬉しかったです.

その他

ダメ

インターンもあと1週間となった頃,ふと良くないことに気付いてしまいました.
「帰り道に,ゲーセンあるじゃん」

インターン生

楽しいインターン生ばかりでした.特に印象的だった出来事を3つだけピックアップ.

超便利画像

さてさて,最後になりましたが
超便利画像を大公開! はてなで出たご飯,はてなでおごってもらったご飯一覧です!!!

ほんの少しでも興味がある人へ

Web系の仕事に興味がある人!
プログラムを作ることが好きな人!
共同でコードを書いてみたい人!
すごい人たちと知り合いたい人!
はてなが大好きな人!

是非このインターンに参加すべきです! 来年の夏休みの予定をあけて,パソコンとエディタを用意しておきましょう! 心配することはなにもありません.インターンに合格するくらいなら,きっとついていけます.

その中で,インターン絶対合格したいという人は何か作りましょう! 「ものを作っている人,それを完成させた人であれば,はてなに来てもやっていけるだろう」という考えを聞きました.「ゲーム作りたいなー」というのは簡単ですが,本当に完成させるのはなかなか大変です.ゲームじゃなくてロボットでも良いです.もちろんWebサービスでもいいでしょう.要するに,手を動かして何かを完成させる経験をするべきです.僕はマウスをサボってが完成していないので偉そうには言えませんが,このことを心がけるといいでしょう.

総括

お世話になった皆さん,お仕事が特に忙しい中に,本当にありがとうございました! 最高だったはてな京都オフィスで,最高の経験をすることができました!

夏休みが終わったら

やらないといけないことがたくさん溜まっている気がしますが多分幻想だと思うので,これに尽力します.

セキュリティ・キャンプ2016全国大会に参加した

セキュリティキャンプとは

セキュリティ・キャンプ全国大会2016:IPA 独立行政法人 情報処理推進機構
詳しくはこちらを見てください.とても熱いイベントでした.

宣伝

美味しいご飯の様子など,キャンプ中に書いた記事があります.個別の講義の内容などもこちらにまとめてあります(頑張って内容を充実させようと思います……そのうち).良ければご覧ください.

seccamp2016 DAY1 | taniho’s blog
seccamp2016 DAY2 | taniho’s blog
seccamp2016 DAY3 | taniho’s blog
seccamp2016 DAY4 | taniho’s blog
seccamp2016 DAY5 | taniho’s blog

今回の記事では,キャンプ中には触れなかった話,すごいどうでもいい感想や,真面目な話をしようと思います.

参加するまでの経緯

僕がこのキャンプを知ったのが大学に入学してすぐでした.「情報に興味があるんだったらこんなイベント好きそう」とか言って先輩に紹介を受けました.
その年はまだトラック制だった時代で,僕が応募したネットワーク・セキュリティ・クラスは謎のファイルが与えられ,その解読から始まるという課題が出されていました.僕はまだWindowsしか使っていない頃で,fileコマンドすら知らずに苦労した覚えがあります.そのため,とにかく問題をなんとしてでも解かなければいけないと思って必死に調べ回りました(今思えば,あんなのの何が’必死’だ,という感じですが).
当時の応募用紙を見返しているのですが,まあ当然知識量は(まだまだ未熟ではあるけれど)今よりずっと少ないです.ただ一番の問題はそこではなく,圧倒的に熱意が足りていないと思います.当時は知識問題というものがありましたが,一言二言で答えている問題が多くありました.多分,知識がなくて困った人は必死に調べ回ったり人に聞いたりして勉強したはずです.そのプロセスをアピールしないと,熱意は伝わらないと思います.

ちなみに今年の応募用紙は,偉大なる先輩に読んでもらって,意味がわからないところや不自然に感じたところなどを指摘していただきました.大いに熱意を伝えるのは良いことだと思いますが,読みやすく伝わりやすい文章を作ることも大切ではないかと思います.
(まあ補欠の自分が偉そうに言えた立場じゃないですけどね)

少し話がそれましたが2014年はお祈りメールが届き(コミケは初当選),続く2015年もダメでした.この年はそもそも準備を始めるのが遅かったことが原因です(と言い訳).

年齢制限のため最後の2016年は本気で頑張ろう……と思い立ち,1ヶ月まるまるかかって応募用紙を作りました.
詳しくはこちらの記事を見てください.
セキュリティ・キャンプ2016に応募した | taniho’s blog

DAY0

キャンプが始まるまでの間は,グループウェア上で受講する講義の抽選や,事前課題の発表,他にもOSやプログラミング言語などの話題で交流をしていました.また,twitterでは参加者のリストを作られているチューターさんがいたのですが,そのリストも賑わっていました.みなさんすごいリプ飛ばし合っててすごいなあと思っていました.(もしかしたらミニキャンプとかで既に知り合っているとかなのかな)
Facebookの申請も飛び交っていましたが,みなさんイケメンですごいですね(小並感)

さて僕はというと,「考えてみましょう」・「調べておいてください」系の課題をやりつつ,激重課題の「サーバに対する攻撃とその影響度を調べてディスカッションする講義」を進めていました.
予め用意された「攻撃された形跡のある」サーバに接続し,その内容を解析し,発表資料を作るというものです.まあとりあえず何らかのログファイルを見ればいいだろうなあとは思いましたが,かなりの種類・分量のファイルがあるため非常に大変でした.詳しくはDAY3の記事に書いているので(これから書くつもりなので)そちらもご覧ください.

DAY1

会場に入ると早速お土産が置いてありました.セキュリティキャンプシールがもらえてとても嬉しい! のですが,オンボロのThinkPadに貼るのはもったいない気がして保留中…….

そういえばThinkPadに貼ったシールを見て話しかけてくれた方が何名かいましたが,Emacsよりも,ボコ(ガルパン)よりも,FA機器.comが一番注目されていたようです.そんなに不思議なシールだったのかなー.
(FA機器.comでは学生無料のお持ち帰り企画が開催されています.とてもありがたいイベントでした.良ければ是非.)
メカトロ部品学生無料|FA機器.com 産業用部品買取販売サイト

1日目はまあ静かに終わりました.ずっと話を聞き続けていたので結構疲れてしまい,コンビニツアーにも行かずすぐ寝ました.

DAY2

この日は集中講義でしたが相変わらず詳細は個別の記事を見てください.

CTFは散々でした.テスト用の問題と,シーザー暗号の問題の2問だけでタイムアップです.チーム「.t」は200点.

この後CTFのチームを作ってる人たちに声をかけて,一つのグループに招待してもらいました.始めたばかりですが,これから頑張っていこうかなと思っています.

DAY5

グループワーク

ごそっと時間が飛びますが,最終日にはグループワークの発表がありました.
僕のチームは,倫理問題について新しい解決法を提案しました.

残念ながら賞をもらうことはできませんでしたが,5日間にわたってチームのメンバーと活動できて,とても楽しかったです.また,講師の方々にインタビューに伺い,色んな話を聞けたことも良い経験になりました.ご協力いただいた方々,ありがとうございました.

閉講式

閉講式では修了証と大臣からのお言葉を頂き,全員が10秒のコメントを残していきました.

みんな「twitterでもよろしくね!」みたいなことを言ってて,かぶるのも面白くないなあと思ったので「セキュキャンはいいぞ」と一言だけ残しました.イマイチ受けが良くなかったような気がしますが気にしない.あ,みんなtwitterでも今後ともよろしくね!

写真撮影

「今日も一日〜」
「「「頑張るぞい!」」」パシャッ
って10回位やりました.

コミケin幕張

無作為に選ばれた班から順に退出し,本などをいただくことができました.


僕は本を頂いたあと,頂いた書籍のサイン集めに走り回っていました.一番狙っていた本は取れませんでしたが,どちらも欲しかった本なのでとてもうれしいです.

ご提供いただいた企業の方々,また翌日のコミケで出す新刊をくださった@nekoruriさんありがとうございました.
いま本が手元にないのですが,家に帰ったら楽しく読みたいと思います.

受講した講義のすべての講師の方々にもサインをいただきました.写っているお魚はニジマスとのことです.

大切な宝物になりました.

感想

雑多なこと

グループワークの資料提出の形式が.pdfでよいと言われたことがとても新鮮でした.普段は.pptか.pptxって言われるので,pdfで良いかわざわざ確認を取りに行っています.
EmacsとVimの話が普通に通じる環境もとても楽しかったです.三対一,一対三というチーム名を見たときは爆笑しました.いまだにどっちがヴィムでどっちがイーマックスなのかわかりません.
デスクトップ環境について良い情報ももらえました.チューターさんにQtileをオススメしてもらったので,インターンが終わり次第試してみようと思います.
とにかく,技術的な話題がどんどん出てきて,みなさん本当に詳しかったのでとても楽しかったです.僕もいつかプロになりたい.

コミュニケーション

キャンプの5日間は,おそらく人生で一番コミュ力を発揮してコミュニケーションを取っていました.5日間の間に100人を超える方々とお会いし,それに近い枚数の名刺を交換し,食事の度に違う人とお話をしました.もう脳が何度もパンクしていたと思います.名刺もらったのに名刺くださいと言っちゃった人ごめんなさい.もらった名刺は見れば思い出せるし,顔とtwitterアカウントは覚えてるので許してください.

普段ならまずお話できないような方ともお話する機会がありました.IPAの理事長と相席させてもらったときは,情報処理技術者試験についてお話を聞くことができました.答えが出る問題を作るのは簡単だけれど,答えが一つしかない問題を作るのは相当に難しいそうです.力を入れて,本当に良い問題を作られているのだなと思いました.

僕は幸いにも年齢制限限界で参加することができたのですが,年下の参加者が大勢いて,若さを感じました(老害感).僕が高校の頃はC言語も勉強したてで,技術的なことは何も分からなかった記憶がありますが,すごい人は本当にすごいです.隣の席に座ったミズゴロウくん(アカウント名より言いやすいのでこれで勘弁)は普段からバグ探しをしていて,過去の報告で名前が載ったこともあるそうです.すごいなあ.

ネット上でフォローしている方ともお会いしました.とさいぬくん,BDの件ではお世話になりました.詳しくは次の記事をどうぞ.
ArchLinuxでBlu-rayを再生する | taniho’s blog

山下さんにはとても雑な話題で話しかけに行ってしまい,すみませんでした.たまこまーけっとが好きな人がいてとても嬉しかったのでつい話しかけてしまいました.再上映がもしかすると実現するかも知れないので,要チェックです.
映画 たまこラブストーリーを映画館で上映しよう! | ドリパス

今後は,このように大勢と交流する機会があるかも知れませんが,僕にとってはこんなに一気に交流することは初めてでした(入学式でも少人数としか話さないと思う).本当に良い機会をいただきました.キャンプでの積極さは絶対に忘れず,存分に発揮していきたいと思います.
また,キャンプ中お話してくださった方々,本当にありがとうございました.これからもよろしくお願いします.

興味がある人へ

つべこべ言わず応募用紙を書きましょう.とにかく提出しましょう.恐れる必要は何もないです.
当日の講義はかなりレベルが高そうなことが書いてありますが,初心者でも大丈夫です.そのためにチューターさんがいっぱいいるし,そのために丁寧なテキストまで用意されています.遠慮なく質問しまくって,どんどん突っ込んでいけばいいと思います.

僕は,今年何か成果を出すことができたら,来年以降のチューターに応募してみようかと思っています.
その時は是非幕張でお会いしましょう!

seccamp2016 DAY5

おつかれさまでした

今日で長くも短かったキャンプのおわりです(なおブログを書いているのはかなり後の模様).
とりあえず最終日の雑なまとめだけでも書いておきます.
総まとめは事後課題と一緒に投稿しようと思います.

いただきました


恒例のキャンプTシャツです!!
今年は参加者がピンク,チューター・講師・運営の方々がもうちょい濃い色(何色?)でした.


いろはすも毎日増えていったのでお持ち帰りします.
なお,外にはもっと大量においてある模様……

コミケ会場



有明でこみっくまーけっととかいうイベントが開催されていたようですが,幕張の方が熱いコミケ会場になっていました.

お家に帰って

これだけのものを頂いてきました.
提供いただいた企業や個人の方々,本当にありがとうございます.
書籍の詳細は別の記事に書こうと思います.

もっと詳しいまとめ

がんばってまとめ記事書くので楽しみにしていてください(誰がこんなブログ好き好んで読むのか知らないけど)

今日の飯テロ


seccamp2016 DAY4

6-C 車載LAN上を流れるメッセージの解析

車載LANであるCANネットワークに接続し,そこを流れるパケットをキャプチャ解析して遊びました.
今回の機材は安価で手に入れられるということなので,問題のない範囲で遊びたいと思います.

7-A ID連携基礎

今回のセキュリティ・キャンプのなかでは非常に高いレイヤの話でした.具体的にはHTTPより上のレイヤでした.
非常に残念ながら最後まで演習をする時間がありませんでしたが,とても興味が湧いたのでまた演習したいと思います.
Burp使えるようになりたい.

企業プレゼンテーション

AAとかtwitterアカウントとかコミケのブースとか紹介されました.
質問の時間も多くとっていただきました.インターンシップの話なんかは良い情報を聞きました.

グループワーク

今日はチューターさんが「寝ろ」と言わずにデブ活している……
一部の方には「夜は自分の部屋にいなkくぁwせdrftg……
徹夜つらい……
徹夜つらい……
徹夜つらい……

今日の飯テロ

朝ごはん

昼ごはん

夜ごはん


謎ごはん


seccamp2016 DAY3

いろはす

室内でもいろはすが無限に増え続けている件について.

3-B フィジカル・リバースエンジニアリング入門

JTAGまで行けなくてとても残念でした.
法を破らない範囲で楽しく分解調査をしていきたいと思いました.

4-C オンラインゲームアタック&ディフェンスチャレンジ

ほぼすべて演習という感じの講義でしたが,なかなかにつらかったです.僕の仕事は強い人を観察することということなので色々と様子を見ていたのですが,本当に強いですね…….
jsはインターンで扱わないといけないので,これから頑張っていきたい所存.あとWebSocketもとても手軽に扱えそうなので,是非触ってみたいです.

5-C サーバに対する攻撃とその影響度を調べてディスカッションする講義

唐突な差し入れで受講者の心を鷲掴みにする川口先生素敵でした!!

一番目の発表者がスライド40枚分作ってきていて,できる人はこんなにいっぱい調べられるんだなあと驚きました.
僕は問題点2個だけピックアップしてプレゼンしました.
模範解答の発表では色々と納得の行く調査をしていて,やはり本業の方はすごいなあという感想を抱きました.

企業プレゼン

DNPさんのプレゼンを聞きに行きました.
「TAME Range」というサーバセキュリティの演習環境を開発されているそうです.印刷業のメーカーからしては全然イメージできないジャンルでしたが,色々な紹介を聞くことができました.

グループワーク

すすめています(白目)

今日の飯テロ