第1回ビネクラ杯参加記-プログラミングできないけどとりあえず解答を提出する-

>ポスドク〜〜
>エンジニアリング〜〜

>「この記事は、限界中年ポスドクの記述でお送りしております。」

#第1回ビネクラ杯に参加したい

###前置き

最近なにかと話題のプログラミングコンテストなるものを読者のみなさまはご存知でしょうか。
プログラミングコンテストはすげーエンジニアリング力（ぢから）（多分53万以上）をもった方々がプログラミングで天下一を決めるための大会です。
この記事は、そんな世界にちょっと憧れを抱くエンジニアリング力（ぢから）1ミリの私が、2019年7月30日〜2019年8月31日までの期間でビネット&クラリティ社（以下ビネクラ社）が開催していた[第1回ビネクラ杯](https://vigne-cla.com/18-1/)に参加し、提出第1号かつ暫定1位（2019年8月1日0時時点）になったときに行なったデータマイニング（笑）の記録です。

記念画像
<img width="300" alt="順位.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240748/8a17c8d6-1c98-bdc6-8dee-6f065b831ec4.png">
(なおこの記録は100倍以上の圧倒的な大差で次の日に抜かれます)

###問題を読む
問題を解く前にはまず問題を読まなければなりません。
以下が問題文へのリンクです。
[第１回ビネクラ杯（問題編）](https://vigne-cla.com/18-1/)
問題設定が面白いですが、ストーリー部分にヒントがあります。

ここです。
>社長「新米のくせに生意気だな！いまある見積りの中で、うまくケーブルを通してできるだけ多くのシステムを稼働させろ！」

つまり、脳筋的に頑張ったら10個くらいしか繋がらなくても、「これが私の全力全開」って言えば社長は許してくれそうということです（ぇ
さらに言えば、プログラミングがあんまりできなくても一部はなんとかなるだろうということがわかるわけです（ほんとか？

そこでこの記事では、発電機と装置の座標から人力でつなげられそうなものだけを抽出して提出ファイルを作成して解答することを目指します。

###早速解いてみる
以下、pythonでファイルの中身を見たりして最終的に脳内筋で問題を処理・解答します。
[JupyterNotebook](https://jupyter.org/)というツールを使うと便利だったので、これの上でぽちぽちコマンドを叩いて行きます。

####とりあえず使いそうなライブラリをインポートする
```
import pandas as pd
```
表計算的な処理といえばこのライブラリとネットで言われている（？）ライブラリをインポートします。

####ファイルを読み込む
問題文のリンクからダウンロードしてきたファイルを読み込みます。

```
generators = pd.read_csv(filepath_or_buffer="generators.txt", encoding="ms932", sep=" ",header=None, index_col=None)
equipments = pd.read_csv(filepath_or_buffer="equipments.txt", encoding="ms932", sep=" ",header=None, index_col=None)
```

####読み込んだデータの確認
```
generators.head()
```

![スクリーンショット 2019-09-18 14.43.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240748/aa050e9a-5527-95c2-c806-21e971c36d0a.png)

```
equipments.head()
```
![スクリーンショット 2019-09-18 14.43.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240748/f4a81998-d2a9-9a9f-537f-5befac26cd23.png)

####各カラムの名前を変えておく
各行の一番最初が対になる発電機-装置番号となるのでこれはこのままでいいと思いますが、列名が番号のままだと座標である事が分かりにくいため、列名を変えます。
発電機の場合はgeneratorsの(x, y, z)座標なのでxg, yg, zg、
装置の場合はequipmentsの(x, y, z)座標なのでxe, ye, zeとします。


```
generators = generators.rename(columns={0:"xg", 1:"yg", 2:"zg"})
generators.head()
```
![スクリーンショット 2019-09-18 14.49.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240748/d5ea7fe6-13eb-f5d7-ae6c-1e4c5454a16d.png)

```
equipments = equipments.rename(columns={0:"xe", 1:"ye", 2:"ze"})
equipments.head()
```
![スクリーンショット 2019-09-18 14.49.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240748/8f3ba15a-09de-bad3-0377-068334ecc3db.png)

すこし人類に優しい見た目になりました。

####対応する発電機-装置の座標が隣り合った表にする
二つのファイルを片方ずつ見るのはしんどいので二つ合わせた表にします。

```
generators_and_equipments = pd.concat([generators, equipments], axis=1)
generators_and_equipments.head()
```
![スクリーンショット 2019-09-18 14.53.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240748/8b103876-b713-7943-80c2-70044c9498eb.png)

####発電機と装置の距離を考える
人力でなんとかするために発電機から装置へ格子点を通りながら進んだ時の距離（マンハッタン距離と言うらしい）が小さいペアを考えたくなります。

そのためここから、
1. 上までで作った表に距離の列を足し、
2. 発電機と装置の距離を計算し、
3. 距離が近い順で表示する。
ということを目指します。

#####1. 距離の列を足す
列の名前は距離の英語Distanceから取って適当にDistとします。
Distの初期値は0にしておきます。（問題文から距離0のペアはありえないため）

```
generators_and_equipments = generators_and_equipments.assign(Dist=0)
generators_and_equipments.head()
```

![スクリーンショット 2019-09-18 14.59.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240748/6fc7edde-7005-033a-bef8-4b0846ffe313.png)

#####2. 発電機と装置の距離を計算する
発電機-装置のペアに関して、X座標、Y座標、Z座標の差の絶対値を取れば、それが求めている格子点を通りながら進んだ時の発電機と装置の距離になります。

```
for i in range(generators_and_equipments.shape[0]):
    generators_and_equipments.iloc[i, 6] = abs(generators_and_equipments.iloc[i, 0] - generators_and_equipments.iloc[i, 3])  \
    + abs(generators_and_equipments.iloc[i, 1] - generators_and_equipments.iloc[i, 4]) \
    + abs(generators_and_equipments.iloc[i, 2]-generators_and_equipments.iloc[i, 5])
generators_and_equipments.head()
```
![スクリーンショット 2019-09-18 15.03.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240748/80f8dab1-9267-ad22-4bee-ad50ac2b6b6e.png)

#####3. 距離が近い順で表示する

```
generators_and_equipments = generators_and_equipments.sort_values(by=["Dist"], ascending=True)
generators_and_equipments.head()
```

![スクリーンショット 2019-09-18 15.04.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240748/c41536c4-7ec9-70b7-d5a2-d745bd7653b7.png)

####解答を作成する
いよいよ大詰めです。私はエンジニアリング力が1ミリしかないので、距離が1のものだけしか解答できませんが、距離が2以上あるものも考えらえる方は上を目指していただきたいです。

例として距離が1のもので解答する場合、以下のように数字をテキストファイルに直接書き込んで提出すれば完成です。

```
4
2
7 8 7
7 7 7
2
19 14 5
19 14 4
2
15 5 16
15 5 17
2
19 13 14
19 13 13
```

###最後に
上でも書いたのですが、これで解答第1号かつ暫定1位&有識者レベルになったものの、次の日にはスコア500越えの神がランクインして2位に転落し、プログラミングができる人はすごいなぁという気持ちになりました。

以下のビネクラ杯関連リンク集に、より強い有識者レベルになるにはどうするか、また最高位であるホルス神レベルになるにはどうしたらよいかが書いてあります。
また神々の戦いの体験記もありますので、よろしければ合わせてお読みください。
[ビネクラ杯関連リンク集](https://vigne-cla.com/18-x/)

またQiita内にもホルス神レベルについての@ttttkkkkk31525さんの記事がありましたのでこちらもリンクさせていただきます。
[第1回ビネクラ杯でスコア517を取る方法(Cythonの布教も兼ねて)](https://qiita.com/ttttkkkkk31525/items/4e107248595851bd5704)
（神か.........

また次回〜〜