OmniAICreator/Qiita-1.07M huggingface dataset:
VimにPythonコードの補完機能を追加して簡単に編集できるようにする

# はじめに

vimのインストールから設定までを書いている記事がなかなか無かったので、
自分で書きます。
vim初心者がとりあえずPythonの補完機能を入れられるように書いています。
以下のサイトを参考にさせていただきました。

+ [dein.vimを導入してjedi-vimを入れる](https://qiita.com/suy0n9/items/2c33b3982530a1666d9c)

# Vimインストール

```
sudo apt-get update
sudo apt-get install vim
```

# Vimの設定

vimのプラグイン管理を行う `dein.vim` というものを使用してjedi-vimをインストールします。
今回は、 `~/.cache/dein` にインストールします。 

```bash
cd ~
mkdir ~/.cache
mkdir ~/.cache/dein
cd .cache/dein/
wget https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh
sh ./installer.sh ~/.cache/dein/
```

次に、プラグインの管理のファイル( `plugin.toml` と `plugin_lazy.toml` )を作成します。
 `plugin.toml` と `plugin_lazy.toml` の使い分けは以下の通りです。
特定の条件とは、Pythonの場合やマークダウンの場合などの開くファイルの種類に応じて
読み込むプラグインが指定できるようになっています。

+ plugin.toml 　　　… 起動時に読み込むプラグインを指定する。
+ plugin_lazy.toml　… 特定の条件でプラグインを指定する。

```bash
cd ~/.cache/
mkdir userconfig
cd userconfig/
vi plugin.toml
```

```plugin.toml
[[plugins]]
 repo = 'Shougo/dein.vim'

[[plugins]]
repo = 'Shougo/vimproc.vim'
```


以下のファイルにPythonのプラグインの設定を行います。

```bash
vi plugin_lazy.toml
```

```plugin_lazy.toml
[[plugins]]
repo   = 'Shougo/unite.vim'

[[plugins]]
repo      = 'Shougo/neomru.vim'
on_source = ['unite.vim']

[[plugins]]
repo = "davidhalter/jedi-vim"
on_ft = ['python']
```

最後に、vimの設定ファイルにプラグインの設定を書き込みます。

```bash
cd ~
vi ~/.vimrc
```

```~/.vimrc
"dein Scripts-----------------------------
if &compatible
  set nocompatible               " Be iMproved
endif

let s:dein_path = expand('~/.cache/dein')
let s:dein_repo_path = s:dein_path . '/repos/github.com/Shougo/dein.vim'

if &runtimepath !~# '/dein.vim'
  if !isdirectory(s:dein_repo_path)
    execute '!git clone https://github.com/Shougo/dein.vim' s:dein_repo_path
  endif
  execute 'set runtimepath^=' . fnamemodify(s:dein_repo_path, ':p')
endif

if dein#load_state(s:dein_path)
  call dein#begin(s:dein_path)

  let g:config_dir  = expand('~/.cache/userconfig')
  let s:toml        = g:config_dir . '/plugin.toml'
  let s:lazy_toml   = g:config_dir . '/plugin_lazy.toml'

  " TOML 読み込み
  call dein#load_toml(s:toml,      {'lazy': 0})
  call dein#load_toml(s:lazy_toml, {'lazy': 1})

  call dein#end()
  call dein#save_state()
endif


" Required:
filetype plugin indent on
syntax enable

" If you want to install not installed plugins on startup.
if dein#check_install()
  call dein#install()
endif
"End dein Scripts-------------------------
```

上記のファイルを保存して、再度vimを開くと、プラグインのダウンロードが始まります。
プラグインがダウンロードし終わった後に、適当なpythonファイルを開きます。

```bash
vi test.py
```

コマンドモードで、以下のコマンドを打つと、jediのヘルプ画面が表示されます。
これでプラグインが読み込まれていることが確認できます。

```
:help jedi
```

![test.png](https://qiita-image-store.s3.amazonaws.com/0/104675/1c26fca2-e6ec-6641-736f-338680357044.png)


ヘルプ画面を閉じるときは、 `:q` で閉じます。

補完機能も確認します。

![test2.png](https://qiita-image-store.s3.amazonaws.com/0/104675/7b94a8af-a25a-95d8-11fe-7935a26867e9.png)

ちゃんと機能していれば、ドットを打った時に一覧が表示されます。

# まとめ

なるべくvim初心者でも設定できるように書いたつもりですが。
わからないところがあればコメントをお願いします
（僕自身が初心者なのでご容赦を・・・）。

また、jedi以外にも便利なプラグインがあれば追記していこうと考えています。
山月記に音と画像を付けてみました

今まであまり手を出さなかったのですが、最近、ノベルゲームの沼に囚われつつあります。
文章のみで構成される小説もとても好きなのですが、音楽と画像で彩られるノベルゲームのあの何ともいえない臨場感は他では得難いものです。~~時間が溶けて~~時間を忘れてのめり込んでしまいます。

最近はWeb技術の発達もあり、ブラウザ上で様々な表現が可能になってきました。
そんな時、ふと思いました。
「Web上でノベルゲーム風のWeb小説」を表現出来ないかと。

#1 実際に作ってみました

中島敦の名作、『山月記』に音と画像を付けてみました。
百聞は一見に如かず、下記URLで実際の本文を読むことができます。↓
http://rojiuraclub.php.xdomain.jp/app/p01.php
<b>注意1：音楽が再生されます</b>
遷移時にダイアログが出て、音を再生するか聞かれますが、
「はい」と答えると音楽が再生されます。
<b>注意2：通信量に気を付けてください</b>
音楽などを使うので、多少通信量が発生するかと思います。
気になる方はWifi環境でアクセスくださいませm(_ _)m


下の画像は実際のキャプチャ画像です。

####《実際の画面 - PC》

![スクリーンショット (15).png](https://qiita-image-store.s3.amazonaws.com/0/200242/bcb5b383-2d9a-94e2-9ab5-3692911546f9.png)


####《実際の画面 - sp》

![スクリーンショット (14).png](https://qiita-image-store.s3.amazonaws.com/0/200242/5208fd93-c4b9-1eb5-2901-fc66d801f770.png)


#2 実装に用いた言語

- HTML
- CSS
- js(jQuery)
- PHP

#3 用いたライブラリなど

## [Barba.js](http://barbajs.org/)
部分的に画面を読み込むためのjsライブラリ。
このライブラリを用いると、pjaxと呼ばれる非同期画面遷移の技術を簡単に実現できます。
今回のこのライブラリが当Web小説機能の肝となっている部分です。

下記サイト様にdemoがございましたので、参照いただけたらと思います。
[jQueryとBarba.jsでpjax対応サイトを制作する【demo有り】](https://oku-log.com/pjax-barba/)

## [jQuery](https://jquery.com/)
言わずと知れたjsライブラリ。
今やjQueryは古い技術になりつつあるようですが、やはり簡潔に書くにはとても便利なので、今回の実装にもふんだんに利用しています。

## [Bootstrap](https://getbootstrap.com/)

こちらも言わずと知れたCSSフレームワークです。
ちょくちょく使っています。

#4 コード

[github](https://github.com/kyutaro/DigitalNovel)の方にソースを上げているので、そちらの方をご覧いただければと思います。
https://github.com/kyutaro/DigitalNovel

あまり特別なことはしていない筈です。
基本的にjsをガチャガチャやって実装しました。

#5 終わりに

そのうち自作の小説に音と画像を付けて公開しようかと画策している所です。
個人的にもっとこういう形態が流行ればいいのにと思いつつ、今いち流行らないのはやはり音や画像を用意するのに手間がかかるからでしょうか＿(:3」∠)＿

#6 素材などをお借りしたサイト

『山月記』本文は[青空文庫様](http://www.aozora.gr.jp/)より配布されている本文より拝借いたしました。

また、当Web小説の作成にあたって、下記サイト様から素材をお借りいたしました。
[ぱくたそ](https://www.pakutaso.com/)
[足成](http://www.ashinari.com/)
[On-Jin ～音人～](https://on-jin.com/)
[魔王魂](https://maoudamashii.jokersounds.com/)
[無料効果音で遊ぼう！](http://taira-komori.jpn.org/)

この場を借りて御礼申し上げます。
組合せ最適化でステンドグラスを解く

Advent Calendar 4日目の記事 [組合せ最適化でエデンの園配置を証明する](https://qiita.com/SaitoTsutomu/items/a6456ecc781bd0b5b567)
Advent Calendar 6日目の記事 [組合せ最適化でタイルペイントを解く](https://qiita.com/SaitoTsutomu/items/ec7cbdb04ba05763c2b8)

## これなに

**ステンドグラス**を、Pythonで[組合せ最適化](https://qiita.com/SaitoTsutomu/items/bfbf4c185ed7004b5721)モデルを作って解きます。
解く楽しみは、モデル化を工夫することになります。

自分でも試してみたい人は、下記を参考にしてください。

- [数独を通して組合せ最適化を学ぼう](https://qiita.com/SaitoTsutomu/items/bd09190d8a02432b3f16)

## 問題

- 線で区切られた部分（ピース）のいくつかを黒くぬります
- 小さな丸は、その丸が接している周囲のピースのうち、黒ピースと白ピースのどちらの数が多いかを表します
- 黒丸なら黒ピースの方が多く、白丸なら白ピースの方が多く、灰色の丸は、同数となります

下記は、左が問題で、右が答えです。

![](https://raw.githubusercontent.com/SaitoTsutomu/opt4puzzle/master/pic/stainedglass.png)

Pythonでは、`npi`（ピースの数）、`hint`（色と周りのピース）を使うことにします。

```py3:python
from pulp import LpProblem, lpSum, value
from ortoolpy import addbinvars
npi = 11 # ピース数
hint = [s.split(',') for s in """\
W,0,1,2
W,0,3
B,0,1,3,4,5
B,1,5
B,1,2,5,6
W,3,4,7
G,5,6,9,10
G,5,7,8,10""".splitlines()]
```


## 数理モデルを作り解く

変数は、各ピースが黒(1)か白(0)にしましょう。

- ヒントが`'W'`：黒のピース数が半分未満
- ヒントが`'B'`：黒のピース数が半分超
- ヒントが`'G'`：黒のピース数がちょうど半分

```py3:python
m = LpProblem() # 数理モデル
v = addbinvars(npi) # 変数(黒かどうか)
for c,*lst in hint:
    vlst = [v[int(i)] for i in lst] # 周囲のピースの変数
    if c == 'W':
        m += lpSum(vlst) <= (len(vlst) - 1) // 2
    elif c == 'B':
        m += lpSum(vlst) >= (len(vlst) + 2) // 2
    else:
        m += lpSum(vlst) == len(vlst) // 2
m.solve()
```

### 結果の表示

```py3:python
print('black:', [i for i in range(npi) if value(v[i])>0.5])
>>>
black: [1, 4, 5, 6, 8]
```

解けていることが確認できます。簡単ですね。

以上
(fd)pexpect+xonshで（シリアル）コンソール自動化

# pexpectとは

https://pexpect.readthedocs.io/en/stable/
対話式のコマンドを自動化するために使われる、expectというコマンドのPython版です。
expectは昔からある有名なコマンドぽいですが、tclという言語を使わなければならず大変とてもつらいので、python実装をできれば使いたい。そんなとこです。

## pexpectの問題　

しかしここで問題になるのがpythonなこと。
そもそもすべてのコマンドが対話なわけでなく、基本的には普通にコマンドを並べて、たまにpexpectしたい場合、そこだけpythonの別ファイルにしなければならず、別ファイルになって見通しが悪くなったり、引数を渡してあげたりしなきゃいけません。

## pexpect+xonsh

xonshだと下みたいにかけます。便利。
（適当な例なのでchpasswdは投げつけないでください…）
ということでpexpect使う場合はxonsh使うと便利と言う話でした。
ちなみにpexpectの部分だけコンソール上に表示されないのは気持ち悪いので、```logfile=os.fdopen(sys.stdout.fileno(), 'wb')```で端末上に出るようにしています。
subprocessはプログレスバーみたいなものが来ると表示が崩れたりして微妙という私見です。

```setup.xsh
import pexpect
import os, sys

username = "test"
passwd   = "hoge"

sudo useradd @(username)
p = pexpect.spawn("sudo passwd "+username, logfile=os.fdopen(sys.stdout.fileno(), 'wb'))
p.expect("password:")
p.send(passwd+"\n")
p.expect("password:")
p.send(passwd+"\n")
mkdir @(username)
# chown...
```

# シリアルコンソールの自動化をする

多分こっから先は、タイトルの機能を切望してる人意外は読まなくていいと思います。

上記の話は正直、そもそも対話を自動化したい時とかあまり無いし、だいたいオプションでなんとかなる。みたいなとこあると思います。長時間ターミナルで対話してるとしても、それ全部シェルスクリプトで自動化できるからみたいなことあると思います。

しかし、ブートローダやRTOSなどでスクリプトというものがない場合や、そもそもネットワークが物理的に使えない場合、ネットワークドライバがまだ安定してない場合、シリアルコンソールを自動化したいことが多々あるんです。そういう話です。

## fdpexpect

先ほどのpexpectに、コマンドのspawnではなくてファイルデバイスを操作するfdpexpectというものがあります。
例えば
1. /dev/ttyUSB0にボーレート38400で接続
2. ローダーのオートブートを止めて適当な設定
3. 成功したらブート
4. Linux立ち上がったらsshで接続
を書くとこんな感じになります。

```boot.xsh
import serial
from pexpect import fdpexpect

# 1.
ser = serial.Serial('/dev/ttyUSB0', 38400)
terminal = fdpexpect.fdspawn(ser, logfile=os.fdopen(sys.stdout.fileno(), 'wb'), timeout=5)

# 2.
terminal.expect("AutoBoot...")
terminal.send("\n")
terminal.expect("loader#")
terminal.send("some boot loader command")
# 3.
res = terminal.expect(["loader#", "Error"])
if res:
    error_handle()
else:
    terminal.send("boot command")

# 4.
terminal.expect("root#")
ssh user@address
```

## fdpexpect+xonshでできること

上の例はそのままsshしてるだけ（でも便利）ですが、

* カーネルがエラー吐いたのをトリガにgrepしてエラーメッセージのコードをvimで立ち上げる
* 対向をホストPCにしたネットワークドライバのテスト自動化
* 起動オプションとftpサーバで見えるカーネルを同期取りながらいろいろなブート試す

とかそんな感じのことできたりします。

…以上です。
アプリリリース後を見据えたアプリを作る

[ネクストスケープ配信事業本部AdventCalendar2017](https://qiita.com/advent-calendar/2017/nextscape-media-delivery-dept)の4日目担当の坂本です。
新しいアプリを開発する場合、まずはアプリのリリースを目標にするかと思いますが
残念ながらアプリのリリースはアプリ開発の終わりではありません。

サービスが続く限りは機能追加や最新OSへの対応を行なっていく必要があります。
サービスイン後に後悔しないために、サービスイン後の作業を見据えたアプリを作りましょう。

（12/4 : 追記予定の項目は順次更新します！）

## ユーザーエージェント（UserAgent）をカスタムする
サーバーと通信して動くアプリの場合、呼び出し元を特定する情報としてUserAgentを渡しているかと思いますが
アプリリリース後を見据えてUserAgentには必要な情報を含めるようにしましょう。

UserAgentに含める情報の例
- アプリケーション名
- アプリバージョン
- OSバージョン
- デバイス名
- デバイスのビルド番号
- UUID（未ログインユーザーの特定やユニークユーザー集計のために利用する）

UserAgentは後述の全ての項目の助けとなるため必ず設定しておきましょう。

## 適切なエラーコードを定義する
まず、アプリリリース後の開発者を悩めるのは以下の問い合わせです。
「エラーが発生しているので原因を調査して下さい」

この時に適切なエラーコードを定義しているかいないかで調査の難易度が激的に変わります。

**[システムエラー]**
**問題が発生しました。**

なんて通知は何の役にも立たないので必ず以下のようなエラー表示にします。

**[エラーコード : 200-12345]**　←　解決の糸口となるエラーコードを含める
**通信エラーが発生しました。しばらく待ってやり直してください。**　←　原因と解消手順があれば教えてあげると問い合わせを減らせる

また、サービスを続けていくうちにエラーコードは増えていきます。
エラーコードを定義する際はエラーコードが増えることを意識して連番は避けましょう。
けっして、iTunesのエラーコードは参考にしてはいけません。
https://support.apple.com/ja-jp/HT203174

## エラー情報を送信する
エラーコードだけでエラー原因を特定するのは難しいため、エラー解析に役立つ情報を送信するようにしましょう。
「OSバージョン」「アプリバージョン」「デバイス名」「内部エラーコード」「WiFi or 3G/LTE」「ストレージ残量」など

よくクラッシュレポートは送信しているけど、エラー情報は送信していないというアプリがありますが
アプリのエラーはクラッシュを伴わないエラーが大半のためエラー情報の送信はしておいたほうが吉です。
ただし、ユーザの中にはエラー情報の送信を嫌がる人も多いため「エラー情報を送信して良いかの確認」を取ることも忘れずに。

## 強制バージョンアップ機能
多くのユーザはアプリのバージョンアップを望んでおりませんが
サービスを進めていくうちにどうしても「古いバージョンのアプリを排他したい」状況が出てきます。
そうした状況を見据えて、強制的にバージョンアップする機能を実装しておきましょう。

強制的にバージョンアップすると言っても、一般的なアプリにはそんな権限はないため
「特定のアプリに最新バージョンのインストールを促す通知を出す」という機能を実現します。

強制バージョンアップを行う際に守らないといけないことは、古いバージョンのアプリからの利用を排他することです。
けっして抜け漏れが無いように慎重に実装しましょう。

実装時に注意する点
- バージョンアップを促す理由は多岐に渡るため「バージョンアップするかどうかの判断」は必ずサーバー側で行う
- 「起動時」など特定のタイミングのみでのチェックは危険。なるべく複数の箇所でチェックすること
- アプリを立ち上げ続けているユーザーのことを考慮する
- バージョンアップのチェック処理がエラーや圏外状態でスキップ出来ないように注意する
- 強制バージョンアップの使いすぎに注意する（レビューが荒れます）

全てのユーザに対して必ずしも「最新のアプリ＝安定版」とはならないため強制的にバージョンアップを促す前に
ユーザが任意にバージョンアップ可能な期間を設けると良いかと思います。

## メンテナンス中の利用を考慮する
サーバーと通信して動くアプリの場合、メンテナンスの考慮が必要です。
ユーザがアプリを利用しようとした際には「メンテナンス中です」という通知を出し、
メンテナンス中でも開発者であればアプリの動作確認を行えるようにメンテナンス中にアプリを利用する方法を用意しておきましょう。

## 慎重に選定したライブラリのみを利用する
(追記予定)
## ポリシーの無い画面回転は実装しない
(追記予定)
## ビルド環境は自動化する
(追記予定)
## 開発中のアプリケーション配布を自動化する
(追記予定)
## テストは自動化する
(追記予定)
WSL Ubuntu上でのNginx + Php-fpm設定注意点

## 2018/11/9追記
nginx.confに「fastcgi_buffering off;」を追記で、nginx+php-fpmが無限ロードする事なく動作するようになります。

参考になったURL
https://stackoverflow.com/questions/46286420/php7-0-fpm-extremly-slow-on-ubuntu-windows-subsystem-linux

## 以下、過去の失敗内容
本文はインストール方法の記事ではない。2017/12/3時点でのWSLへのツール検証結果の備忘録。

## 1. 表題を全てaptでインストール
バージョン指定のインストール方法は割愛。というかろくに控えていない。

## 2. NginxとPhp-fpmの連携設定

###nginxの設定とポイント
+ php側のデフォルトuser/groupが「www-data」権限で動く為、それに合わせる
+ php関連の記述は「snippets/fastcgi-php.conf」に集約されている

```
$ vi /etc/nginx/nginx.conf

#以下の１行を追記
user  www-data;↲
〜省略

http {↲
   〜省略

   server {↲
       location ~ \.php$ {↲
            root     /usr/share/nginx/html;↲

            #以下の１行を追記
            include  snippets/fastcgi-php.conf;↲
        }↲
}
```

###nginxのphp-fpm設定とポイント
+ fastcgi_pass行はnginxとphpの接続方法。TCP接続「127.0.0.1:9000」よりも「*.sock」接続の方が速くなる
+ ソケットの参照先は「/var/run/」「/run/」どちらでも一緒（どちらも同じ参照元になる）

```
$ vi /etc/nginx/snippets/php-fpm.conf

#以下の２行を追記
#fastcgi_pass   127.0.0.1:9000;↲
fastcgi_pass  unix:/var/run/php/php-fpm.sock;↲

# regex to split $uri to $fastcgi_script_name and $fastcgi_path↲
fastcgi_split_path_info ^(.+\.php)(/.+)$;↲

# Check that the PHP script exists before passing it↲
try_files $fastcgi_script_name =404;↲

# Bypass the fact that try_files resets $fastcgi_path_info↲
# see: http://trac.nginx.org/nginx/ticket/321↲
set $path_info $fastcgi_path_info;↲
fastcgi_param PATH_INFO $path_info;↲

fastcgi_index index.php;↲
include fastcgi.conf;↲
}
```

###php-fpmの設定とポイント
+ ソケットを扱う権限はnginxでも設定した「www-data」にする
+ ソケットの参照先は「/var/run/」「/run/」どちらでも一緒（どちらも同じ参照元になる）

```
$ vi /etc/php/7.2/fpm/pool.d/www.conf

#該当箇所を下記で設定
user = www-data↲
group = www-data↲

listen = /var/run/php/php-fpm.sock↲

listen.owner = www-data↲
listen.group = www-data↲
listen.mode = 0660↲
```

#設定結果
結果から言うとダメ。静的ファイル（html等）は問題ないけれど、
phpファイルをブラウザで見た場合、タイムアウトまたは自分から中断しない限りファイルの読込が終わらない。
※ページ内容自体は表示される。http結果も200が返ってくる
※ページ内容はphpinfo()とかの単純な内容のもの

ソケット接続が悪いのかと思い、TCP接続にした場合も同様。
導入がミスってるのかWSLの問題なのか良く分からないし、ググっても同様の症例が検索に出てこない・・・

取り敢えず、次はbrewを使っていれてみる。
DOSプロンプトから Excelマクロにパイプ処理を行う。 VBAで標準入力

# DOSプロンプトから Excelマクロにパイプしたいことないですか？

普通はないと思います。
DOSプロンプトに詳しい人は、DOSプロンプトだけでいろいろできちゃうんだと思います。
でも、私はやってみたかったんです。
```Dir | "C:\Temp\Test.xls" ```
とか
```Sort "C:\temp\test.txt" | "C:\Temp\Test.xls" ```
とかできたら夢が広がりませんか？
あれっ、そんなことない！？
「それなら最初から全部マクロでファイルの列挙とかソートすれば、DOSプロンプトいらないじゃん！？」って思っちゃいました！？
***いいんです。VBAでパイプしてみたかっただけなんです。***
***C++で作ったExeにはできて、VBAにはできないってことがあるのが癪なんです。***

ただ、実はすいません。
```Dir | "C:\Temp\Test.xls" ```
はできません！

こうなります。
```Dir | "[Excel.exeのフルパス]" "C:\Temp\Test.xls"```

たとえば、私の場合だと
```Dir | "C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE" "C:\Temp\Test.xls"```
です。

しかも、これをするには、マクロのセキュリティレベルをさげておかないといけません。

VBAの説明はすっとぱして、コードだけ載せてみます。
ご興味があれば、やってみてください。
以下のコードは***必ず ThisWorkBook オブジェクトに記入してください。***

```
Const STD_INPUT_HANDLE = -10&
Const INVALID_HANDLE_VALUE = -1
Private Declare PtrSafe Function GetStdHandle Lib "kernel32" _
        (ByVal nStdHandle As Long) As LongPtr
Private Declare PtrSafe Function ReadFile Lib "kernel32" _
        (ByVal hFile As LongPtr, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, _
         lpNumberOfBytesRead As Long, ByVal lpOverlapped As LongPtr) As Long

Private Sub Workbook_Open()
    Dim hStdIn As Long
    hStdIn = GetStdHandle(STD_INPUT_HANDLE)
    
    Sheet1.Cells.Clear
    
    If hStdIn = INVALID_HANDLE_VALUE Then
        Sheet1.Cells(1, 1) = "INVALID_HANDLE_VALUE"
        End
    End If
    
    Dim sBuf As String
    Dim sResult As String
    Dim NumberOfBytesToRead As Long
    
    Do
        sBuf = String(10240, vbNullChar)
        If ReadFile(hStdIn, ByVal sBuf, Len(sBuf) - 1, NumberOfBytesToRead, 0) Then
            sResult = sResult & Mid(sBuf, 1, InStr(1, sBuf, vbNullChar) - 1)
        Else
            Exit Do
        End If
        DoEvents
    Loop
    
    Dim i As Long
    Dim vResult
    vResult = Split(sResult, vbLf)
    For i = LBound(vResult) To UBound(vResult)
        Sheet1.Cells(i + 1, 1) = "'" & vResult(i)
    Next
End Sub

```

実行するとこうなります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/215956/1a187830-2696-0a72-a330-69ef24eb8297.png)


![image.png](https://qiita-image-store.s3.amazonaws.com/0/215956/073eb608-679d-51d3-4ac3-78a1b21dd9f6.png)
数値予報モデルGPVの作画方法メモ

### 概要

[気象データ高度利用ポータルサイト](http://www.data.jma.go.jp/developer/index.html#2) から取得可能な [GPVサンプルデータ](http://www.data.jma.go.jp/developer/gpv_sample.html) のうち、局地数値予報モデルGPV (LFM) の風の情報を、できるだけ手間をかけずに作図してみました。
処理が重い・図が見にくいなど問題はありますが、やり方をメモしておきます。


### 作業環境と使用ツール

OS: mac OS Sierra
Software Environment: [Anaconda](https://www.python.jp/install/anaconda/macos/install.html) (3.x系)
Tools:

- [ecCodes](https://software.ecmwf.int/wiki/display/ECC/ecCodes+Home)


### 作業手順

1. ecCodesのインストール
以下のコマンドで ecCodes をインストールします。

    ```bash
conda install -c conda-forge eccodes
```

2. GPVの取得
[GPVサンプルデータ](http://www.data.jma.go.jp/developer/gpv_sample.html) から
局地数値予報モデルGPV(LFM) をダウンロードします。

3. GPVのパース
LSMの地表の風のレイヤー (10u, 10v) の情報をJSON形式で出力します。

    ```bash
grib_dump -j -w shortName=10u Z__C_RJTD_20170126120000_LFM_GPV_Rjp_Lsurf_FH0000_grib2.bin > z_10u.json
grib_dump -j -w shortName=10v Z__C_RJTD_20170126120000_LFM_GPV_Rjp_Lsurf_FH0000_grib2.bin > z_10v.json
```

4. 風の情報の可視化
上の2で出力したJSONを、matplotlibで可視化します。
以下のコードでは、Jupyter Notebook

    ```python
# 可視化のサンプルコード
import json
import numpy as np
import matplotlib.pyplot as plt
#
w10u = {a['key']:a['value'] for a in json.load(open('lsurf_10u.json'))}
wus = [v if v else 0 for v in w10u['values']]
w10v = {a['key']:a['value'] for a in json.load(open('lsurf_10v.json'))}
wvs = [v if v else 0 for v in w10v['values']]
wus[-1], wvs[-1] = 0, 0  # 変な値が入っているので埋める
#  
x, y = w10u['Ni'], w10u['Nj']
X, Y = np.meshgrid(np.arange(x), np.arange(y))
U = np.array(wus).reshape((y, x))
V = np.array(wvs).reshape((y, x))
plt.quiver(X,Y,U,V,color='red',angles='xy',scale_units='xy', scale=5.0)
#  
# 全部描くと遅いので描画範囲を狭くする
plt.xlim([180,230]) # 描くXの範囲
plt.ylim([150,200]) # 描くyの範囲
plt.show()
```
  
  作画された画像
  <img width="952" alt="lfm_surf_wind.png" src="https://qiita-image-store.s3.amazonaws.com/0/65190/0b1d05f5-07ef-d2d7-224d-662b40f2fd88.png">


### 考察

GPVのパースはecCodesで問題なさそうですが、作図は重すぎるので他の方法を探す必要がありそうです。

今後の課題:

- 地図上への重畳表示
- 作画の速度を早く
- 風の矢印を見やすく
Comparatorを使ってListをソートする方法

Java 8において、Listのソート方法を整理します。

#Java 7 and below

Java 7時代のおさらい

```java
List<String> nameList = Arrays.asList("Takahashi", "Tanaka", "Suzuki");
Collections.sort(nameList);
```

#Java 8以降
Java 8以降は、Listにsort(Comparator)が追加され、それを使ってリストをソートすることができます。

```java
nameList.sort(Comparator.comparingInt(String::length));
```

複数条件（文字列長 -> アルファベットの順）でソートする。
thenComparing()を利用することで、ソート条件を追加できます。

```java
nameList.sort(Comparator.comparingInt(String::length)
	.thenComparing(Comparator.naturalOrder()));
```

また、Streamが導入されることにより、Stream#sortedでリストをソースすることができます。

```java
List<String> sortedList = nameList.stream().sorted()
		.collect(Collectors.toList());
```

##Lambdaの利用

文字列長でソートする。

```java
List<String> sortedList = nameList.stream().sorted((s1, s2) -> s1.length() - s2.length())
		.collect(Collectors.toList());
```

アルファベット順でソートする。

```java
List<String> sortedList = nameList.stream().sorted((s1, s2) -> s1.compareTo(s2))
		.collect(Collectors.toList())
```

##Comparatorの利用

文字列長でソートする。

```java
List<String> sortedList = nameList.stream().sorted(
		Comparator.comparingInt(String::length)).collect(Collectors.toList());
```

アルファベット順でソートする。

```java
List<String> sortedList = nameList.stream().sorted(
		Comparator.naturalOrder()).collect(Collectors.toList())
```

##Comparatorで複数条件のソート

文字列長 -> アルファベットの順でソートする。
thenComparing()を利用することで、ソート条件を追加できます。

```java
List<String> sortedList = nameList.stream().sorted(
		Comparator.comparingInt(String::length)
		.thenComparing(Comparator.naturalOrder())).collect(Collectors.toList());
```

##Comparatorでオブジェクトリストのソート
```java
List<Person> sortedList = personList.stream().sorted(new Comparator<Person>(){

	@Override
	public int compare(Person o1, Person o2) {
		return o1.getName().compareTo(o2.getName());
	}
			
}).collect(Collectors.toList());
```
Advent of Code day2をPerl 6で

こんにちは、4日目の投稿になります。

例によって投稿がなかったので[Advent of Code day2](http://adventofcode.com/2017/day/2)の私の回答を貼っておきます。

```
use v6;

$*IN.lines>>.split("\t",:skip-empty)\
>>.Int\
>>.sort\
.map({.[+$_ - 1] - .[0]})\ # (#1)
.sum\
.say;
```

+ ポイント
  + mapの中で同じ配列を2回参照したい場合は`.`か`$_`を使いましょう
  + `.`, `$_` と `*` は使いどころが異なるので注意しましょう。

以上、4日目の投稿でした。

明日は、AnaTofuZさんの『Perl6のdebugの小ネタについて』です。
お楽しみに!
Web系自社開発会社さんで出されたはじめてのコーディングテスト【素数判定プログラム】をJavaで作ってみた件

# はじめに
本投稿文は初心者が独学でJavaを学び、独創的な発想(少し調べながら)で試行錯誤しながらプログラムを書いていくものであり、どう見ても参考にならないようなコードを自己満足で公開していくものです。よろぴこ:boy_tone1:

# コメントちょーだい！LGTMもっとちょーーーーーだいっ！！！！！！
初心者が成長していく姿を温かい目で見守ると同時に、『いや、ここおかしくね(# ﾟДﾟ)!?ふぁっく』という意見を抱くような箇所も当然あると思いますので、その際は遠慮なくコメントをお願いします。

<Details><summary>Qiitaでの投稿について</summary>
今回で2回目の投稿となります。先日投稿した文を見返したところQiitaでの記述法をHTML形式だと勘違いしていましたが、Markdown記述法というものがあり、今回はこの方法で書きたいと思います。ご教授くださいました方本当にありがとうございますm(_ _)m
少しでも見やすくなれたら幸いであります。</Details>

# 面接にて記述した素数判定プログラム
* 家に帰ってコンパイルしてみたらエラーが出まくったので修正したのを載せます。
* あとRandomクラスを使用していますが、これは最近覚えたのでちょっと使ってみました。

先日Javaを使用して素数判定プログラムを作ってくださいという問題を出され、ドヤ顔で書いたのが以下のコード。（これだ、ドドン）

```java
System.out.println("ランダム素数判定プログラム");
java.util.Random rm = new java.util.Random();
int s = rm.nextInt(100);

if (s == 2 || s == 3) {
    System.out.println(s + "は素数です");
} else if (s % 2 == 0 || s % 3 == 0) {
    System.out.println(s + "は素数ではないです");
} else {
    System.out.println(s + "は素数です");
}
```

(いやコードが汚いというツッコミは置いといて)

###### なんて素晴らしいんだ、『素数の定義』が分かっていませんでしたね。

(文系なのでこの手の数学の問題は好きではあるのですが、公式などの記憶が宇宙の彼方でして)

Wikipedia先生によれば、
> 『素数とは、自明な正の約数（1 と自分自身）以外に約数を持たない自然数であり、1 でない数のことである。』

まあ要は

######その数字自身と1でしか割り切れない自然数が素数であり、他の数字で割り切れたら素数ではないということだと思います。  

例えば、2,3,5,7,11…といった感じで、無限に湧き出るものだそうです。

上記のプログラムを少しだけ解説しますと、まあエラーは出ずにコンパイルできますが、素数ではない数字まで素数という判定がされてしまうものでした。

nが2で割り切れたら偶数で、3で割り切れたらnは奇数であるという考えからこういったプログラムが出来上がっています。

しかし、例えば121は11の二乗なので素数ではありませんが、2や3で割り切れないので、素数という判定が出てしまいます。

(高校1年生からやり直しのレベルで少しだけ恥ずかしいですね。)

# 素数判定プログラム（完成）

```java
System.out.println("素数判定プログラム");
int v = 123;
System.out.println("入力された数字は『" + v + "』です");

if (v < 2) {
    System.out.println("2より小さい数字が入力されました");
} else if (v == 2) {
    System.out.println(v + "は素数です");
} else {
    boolean issosu = true;
    for (int u = 2; u < v; u++) {
        if (v % u == 0) {
            is = false;
        }
    }

    if (isSosu) {
        System.out.println(v + "は素数です");
    } else {
        System.out.println(v + "は素数ではないです");
    }
}
```

(おうおう、コードが汚いというツッコミは置いといて)
## あとがき反省

おそれくこれで正しく素数が判定されるとは思いますが、完成するのに2日かかりました。
弟と素数とはどういう数字か話しあい、2で割り切れたら偶数で、それ以外の数字からまたある数字の二乗でない自然数が素数というような感じで紆余曲折しながらプログラムを考えていましたが、多少ネット検索に頼りながらも出た回答がこちら

『**自然数n未満の数字で割り切れないnは素数**』

これに加えて

『**nが2であれば素数、nが2より小さいならエラー**』

というようにnをあらかじめ2より大きい数字に限定したうえで、『n>vで割り切れない数字』あるいは『n>=n-1で割り切れない数字』が素数という判定するプログラムを組むことで完成しました。

しかし単純にfor文を使うとどうしても

5は素数ではありません
5は素数ではありません
5は素数です
5は素数ではありません
5は素数ではありません
．
．
．
みたいな感じでなんかfor文で表出された数字で5(入力した数字)を素数かどうか判定していくようになってしまい、悪戦苦闘しました。

まあ解決方法がわからず、ちょっとググってしまいまいしたが、boolean型で変数isSosuを定義し、初期値をtrueにしておきました。そして、for文でuがvよりも1小さい数字の間でループしてもらい、仮にu%v==0であれば、uが自分自身の数字よりも小さい自然数で割り切れたことになるので、isSosuにfalseを代入していく。こうしたことで、割り切れた場合はfalseで、それ以外の場合をまた検討していくことができ、if(isSosu){・・・　でtrueの場合をSystem.out.printlnすることができるようにしました。(ん～これはなんか分かりづらい。)


boolean型を使用することに着目できず、ググってしまったことによって完璧に自力で作れなかったのが悔いではありましたが、初心者が入門書程度の知識で素数判定プログラムを組むとしたら、このようになるんじゃないかなあとは思いますが、おそらくもっといい効率的な書き方があるとは思います。僕も数学が得意ではないですし、Javaのプログラムもまだあまり組んでいません。

だから、とりあえず、プログラムが組めるかどうかをテストされたときの証拠として、この素数判定プログラムが書けるということが一つの関門になるとは思います。初心者の人でプログラムを作成していくのに、いくつか問題を解くと思いますが、その中のこれの一つの解答がこういうのがあるんだなあ見たいな感じでさらっと読んでいただければと思います。
HackerNewsのAPIを使ってPromiseを復習した


普段Angularで開発をしており、半ば惰性で利用していた `Promise` についていろいろ記事を読んでいて、なんとなく復習していたら、まとめておきたくなったので適当にまとめました。

# Promiseとは

- Promise インターフェースは作成時点では分からなくてもよい値へのプロキシ
- Promise は3種類の状態を持つ
- 非同期のコードがコールバック地獄になるのを防いでくれる


|メソッド|内容|ざっくり使いどころ|
|----|:----|---|
| Promise.all() |Promiseオブジェクトの配列を受け取り、全てのPromiseオブジェクトがresolveされたタイミングでthenが呼び出される|並行で非同期処理を制御するとき|
|Promise.race()|Promiseオブジェクトの配列を受け取り、一つでもresolve, rejectが呼び出されたら、thenもしくはcatchが呼びされる|並行で非同期処理を制御するとき|
|Promise.resolve()|与えられた理由(reason)で失敗となる Promise オブジェクトを返す|逐次処理(直列処理)するとき|
|Promise.reject()|与えられた理由(reason)で失敗となる Promise オブジェクトを生成する|テストコードやデバッグ、一貫性を保つとき|


わかりやすいサイトを列挙しました。全部読んでいくと雰囲気は掴めると思います。

- [mozillaでのPromise](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise)
- [Promiseについて0から勉強してみた](https://qiita.com/toshihirock/items/e49b66f8685a8510bd76)
- [Promiseと仲良くなって気持ち良く非同期処理を書こう](https://qiita.com/progre/items/03626b7f4655007d8cb2)
- [Promiseで簡単！JavaScript非同期処理入門【前編】](https://html5experts.jp/takazudo/17107/)
- [Promiseで簡単！JavaScript非同期処理入門【後編】
](https://html5experts.jp/takazudo/17113/)

# HackerNews APIを使って実装してみた

[Hacker News](https://news.ycombinator.com/)というサイトがあります。
これは、Y Combinator という有名なVCが運営している、ユーザ投稿型のニュースサイトです。

このサイトは実は、APIが誰でも利用可能です。

[HackerNewsAPI](https://github.com/HackerNews/API)

1. HackerNewsAPIでtop storyのうち適当に一つのStory IDを取得する
2. 1.のStoryIDに基づき記事内容のjsonを取得する

というのをやってみます。


```js
const https = require('https');

const TOP_STORY_URL = 'https://hacker-news.firebaseio.com/v0/topstories.json';

var getHackerNewsTopStoryID = () => {
    return new Promise((resolve, reject) => {
        https.get(TOP_STORY_URL, (res) => {
            let body = '';
            res.setEncoding('utf8');

            res.on('data', (chunk) => {
                body += chunk;
            });
          
            res.on('end', (res) => {
                res = JSON.parse(body);
                // console.log(res);
                resolve(res[0]); // 適当に0にしている。
            });
        }).on('error', (e) => { //エラー時
            reject(e.message);
        });
    

    });
}

var getHackerNewsStoryDetailByID = (hackerNewsID) => {
    return new Promise((resolve, reject) => {
        // Hacker NewsのAPIを叩く。
        const INDIV_STORY_URL = `https://hacker-news.firebaseio.com/v0/item/${hackerNewsID}.json?print=pretty`
        https.get(INDIV_STORY_URL, (res) => {
            let body = '';
            res.setEncoding('utf8');

            res.on('data', (chunk) => {
                body += chunk;
            });
          
            res.on('end', (res) => {
                res = JSON.parse(body);
                console.log(res);
                resolve(res);
            });
        }).on('error', (e) => { //エラー時
            reject(e.message);
        });
    

    });
}

const story = getHackerNewsTopStoryID()
    .then( (id) => { return id;})
    .then(getHackerNewsStoryDetailByID);

console.log(story);

```

ネストが深くならずに、記述できました。
内部APIはご存知ですか？

どうも、[日本Zabbixユーザ会](http://www.zabbix.jp/)の @_BSmile_ です。

# 前置き
zabbixには、バージョン1.8からAPIが実装されており、この素晴らしい機能により外部APとの連携が取れるようになりました。
そう、例えば「Zabbixのダッシュボード画面はXXXXXだ！」なんて言っている方々が使っているgrafanaなんかでZabbixダッシュボードを表示している場合はAPIを使用していますね。
一応言っておきますが、XXXXXな画面はZabbix 3.4からちょっと見栄えが良くなりますので使ってみると良いかもしれません。

下の画像は2.2。
![queue.png](https://qiita-image-store.s3.amazonaws.com/0/47801/98569ee1-b42c-5dca-73fa-5eeac96c763d.png)

[APIドキュメント](https://www.zabbix.com/documentation/3.0/manual/api)

# 内部API

さて、今回お話したいのはAPIドキュメントに載っていないAPIがあるという事です。
通称「内部API」。

Zabbixは過去の収集履歴等、ほぼ全ての情報をDBに保存しています。
皆さんが使用するWebUIについては、このDBからデータを検索した結果を見ています。
この点はログインユーザのグループへ「デバッグモード」を有効化すると分かり易いです。

ですが、ZabbixのDBに保持していない情報という物も存在します。
それはキューの情報です。
DBに無い情報をWebUIで取得する、そういう時に内部APIは使用されています。

## キューの情報

キューの情報は、zabbix3.0.8以前は取得・表示できる上限値が500となっておりCのソースとphpの改修が必要でしたがそれ以降はphpのパラメータ変更可能になっています。
https://www.zabbix.com/documentation/3.2/manual/web_interface/definitions

## 手順

* 準備：通常のAPIでユーザのログインを行い、認証トークンを払い出して下さい。

```
[root@localhost ~]# curl -X POST -H 'Content-Type:application/json' -d'{"jsonrpc": "2.0","method":"user.login","params": {"user":"Admin","password":"zabbix"},"id":0}' 127.0.0.1/zabbix/api_jsonrpc.php
{"jsonrpc":"2.0","result":"fa23a03c53c8db0c2654ce0893611747","id":0}
```

* 実践：払い出したトークンを使用し、内部APIを実行

内部APIは、通常のapiとは違いWebサーバは介さずにZabbixサーバの待受ポート(通常は10051/TCP)を使用します。
telnetでは無く、ncコマンドを使用しても取得できます。
queue.getで使用するsidは、先程のuser.loginで取得したresult値を使用してください。

```
[root@localhost ~]# telnet 127.0.0.1 10051
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
{"request":"queue.get", "sid":"fa23a03c53c8db0c2654ce0893611747","type":"overview"}
{"response":"success","data":[{"itemtype":3,"delay5":0,"delay10":1,"delay30":0,"delay60":0,"delay300":0,"delay600":0}]}Connection closed by foreign host.
```
上は、キュー画面の「概要」をJSON型式で取得したものです。
typeを"overview by proxy"や"details"にすると、プロキシの概要や詳細を取得できます。

## まとめ

10分以上経過したキューが埋もれてWebUIから見えなくなってしまった時には、この内部APIが役立つかもしれません。
ソースを読むと意外と面白い事が分かるZabbix、是非チャレンジしてみてください！
三項演算子にチャレンジ

記述量は減るけど、使い方によっちゃ分かりにくすぎて敬遠してた三項演算子
会社で読む機会があったので、簡単だけどまとめておきます。

### PHPの三項演算子（基本パターン）
```php
($bool) ? (真式) : （偽式） ;
```
$boolがTrueである時は真式、falseである時は偽式が呼ばれます。

### 中央が省略された三項演算子パターン
```php
$hoge = $a ?: $b;
```
aがtrue（存在する）の時は、hogeにaが代入されます。
aがnullの時は、hogeにbが代入されます。

ただこれは$aがそもそも、定義されていない時はエラーが発生するので注意！

### ??のパターン
```php
$hoge = $a ?? $b;
```

これは　?:とほぼ同じ意味ですが、??であれば、$aが定義されていなくてもエラーが発生しません。
便利ですね！！！
LilyPond というよりは，Frescobaldi で Swing するまで

#LilyPondでSwingを
![JazzTromboneEnsembleWithDrumsTemplate.png](https://qiita-image-store.s3.amazonaws.com/0/179822/66791810-41b6-b083-07f6-8f9f4142fa01.png)

　さて，まったく見た感じスイングしていない楽譜なんですが，LilyPondの出力です。
実際はLilyPond内包したFrescobaldiの画面なんですけど。

　ちょっと必要に駆られてアンサンブルの編曲と楽譜が必要になり使ってみようと努力してみた経過と要領をまとめておこうという備忘録です。

###そもそもLilyPondって何？
---
http://lilypond.org/website/index.html
を見れば解るのか？

　所謂楽譜の浄書をタイプセットする，TeXのMusiXTeXから生まれたものらしい。現状としてはSchemeでゴニョゴニョされたものになっているようだ。

　楽譜の浄書といえばFinaleのような高価なソフトが定番だしMuseScoreのようなものもある。では何故LilyPondを使ったのかといえば，TeX由来だから...無料で使えそうだし品質は期待できる。

　で結局はまぁそこそこ使えるのではないかと。そういう結論に至ったので，少し覚書にしておこうという中身です。

---
　冒頭の画像は表題通りのものだが，素敵にスイングするMidiのプレイバックが流れる。TeX同様譜面の様々な間隔はお任せだけど多分調整も自在な筈。

　楽譜の真の元である音の羅列部分は，

```latex:trombone
c8 c d d c c b b 
```
というシンプルな文字の羅列で実現される。cを8分音符で，あとは音価はそのままでcddccbbと...
 調号や拍子，ヘ音記号や五線なども勿論設定はするのだけど。

###先ずどうやってLilyPondを使うか
---
　かつて様々にmidiを弄んだりFinaleやら使っていた時に,TeXでも楽譜の浄書ができる話は結構散見したが,どこまでもTeXは僕にとっては理系の数式を自在に操れる便利道具だったし,どうにも音が出ない音楽関連システムなんてってイメージで使いこなそうというところまでは到底思い至らなかった。でも今は違う。

http://frescobaldi.org/
これも以前にも何度か触ったが，こいつがとても使い易くなっていた。
そんな訳でこれを導入するわけだ。

>Mac OS X
>>For Mac OS X DMG disk images are provided, containing an application bundle that you can drag and drop in your Applications folder. 64 bit and 32 bit versions are provided (the "Frescobaldi-2.x.x-x86_64.dmg" and "Frescobaldi-2.x.x-i386.dmg" files, respectively). As an alternative you can install via Homebrew or MacPorts (français, italiano).

>>With either installation method, you might want to enable MIDI playback from within Frescobaldi (français, italiano).

というわけで，MacOSXだと簡単に導入できる。

　そうすると，所謂アプリケーション（フォルダ）に赤い睡蓮アイコンなFrescobaldi
![image.png](https://qiita-image-store.s3.amazonaws.com/0/179822/9cea5780-4c48-c404-4ddb-7ec1bb213748.png)
と白い睡蓮アイコンのLilyPondが揃う筈。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/179822/7dfc31b5-8759-dab5-023b-03087a2e01cd.png)

　あとはサンプルやネットにあるファイルを適当に落として弄れば...良いのだけどこれがもうガラパゴス。

そもそも楽譜って
---

```latex:
\version "2.18.2"
\header { title = "XXX" subtitle = "YYY" composer = "ZZZ" }%
#(set-global-staff-size 18)
#(load "swing.scm")
```
　LilyPondのファイルはこんな感じで始まる。冒頭のバージョン指定は必ず必要らしい。謎である。**\header** はTeXでいうタイトルみたいなものだからどうでも良い。
　問題はそのあとの **#(...)** の部分だ。これがどうやら **Scheme** な部分なようだ。まさにガラパゴス。でも　**#(load "swing.scm")** が今回のお話の山であるプレイバックでスイングやらシャッフルが指定できる　*（つまり，譜面面はイーブンでも排出されるmidiファイルでは，音価がスイングやシャッフルに変換されていて，だからまぁそのmidiファイルを読み込んでもイーブンなデータはない謎仕様というか間に合わせ仕様か）* のだ。

　試しに出来上がったmidiファイルをmusescoreで読み込むと見事に三連符仕様になっていた。
（以下続く）
YAMAHA ルータとVyOSにおけるClassless Static Route Optionの設定

**この記事は[高知工科大 Advent Calendar 2017](https://adventar.org/calendars/2305)の4日目の記事です。**

#概要
YAMAHAルータ(RTX1210)とVyOS(1.1.7)でClassless Static Route Optionを設定する方法。

#Classless Static Route Optionとは？
詳細は[RFC3442](https://tools.ietf.org/html/rfc3442)を参考にしてください。
一般的なDHCPサーバが動いている環境ではクライアントは別のネットワークへのパケットはDHCPで配布されたデフォルトゲートウェイに投げます。
しかし状況によっては別のルータにパケットを直接投げたい場合があります。
この場合はクライアントごとに静的ルートを手動設定することで実現できますが、正直面倒です。
この様な時にDHCPサーバにClassless Static Route Optionを設定することでDHCPクライアントにDHCPサーバから静的ルートを配布することができます。

#用途
VPN接続などと組み合わせ、イントラネット向けパケットのみをVPN経由で送信できたりします。
(この場合インターネット向けパケットはVPNを通らない)
#設定方法
設定するにあたり、宛先ネットワークアドレスとサブネットマスク、ルータのIPアドレスなどの情報を16進数の書式にする必要があります。
例として以下のようなルートを配布したい場合を考えます。

|宛先ネットワーク|宛先サブネットマスク|ルータアドレス|
|:--:|:--:|:--:|:--:|
|198.51.100.0|/24|192.0.2.200|
|203.0.113.0|/24|192.0.2.200|
<br>
次に設定するときに使う16進数に置き換えます。各項目の末尾の0は省略してください。

|宛先ネットワーク|宛先サブネットマスク|ルータアドレス|
|:--:|:--:|:--:|
|C6:33:64|18|C0:00:02:C8|
|CB:00:71|18|C0:00:02:C8|
<BR>
次に`宛先サブネット` `宛先ネットワーク` `ルータアドレス`の順で並び替え、つなげます。

|設定用文字列|
|:--:|
|18:C6:33:64:C0:00:02:C8|
|18:CB:00:71:C0:00:02:C8|

#YAMAHAルータに適用する方法
DHCPスコープ番号は各自の環境に合わせてください。

```
> dhcp scope option <スコープ番号> 121=18,C6,33,64,C0,00,02,C8,18,CB,00,71,C0,00,02,C8
```

#VyOSに適用する方法
一行目の設定は`global-parameters`な事に注意してください。
shared-network-nameは各自の環境に合わせてください。

```
vyos@vyos# set service dhcp-server global-parameters "option rfc3442-classless-static-routes code 121 = string;"
vyos@vyos# set service dhcp-server shared-network-name <text> subnet 192.0.2.0/24 subnet-parameters "option rfc3442-classless-static-routes 18:C6:33:64:C0:00:02:C8:18:CB:00:71:C0:00:02:C8;"
```

#確認
Windows10で静的ルートが追加されているか確認。以下のような項目が追加されていれば成功。

```
>route print
IPv4 ルート テーブル
===========================================================================
アクティブ ルート:
ネットワーク宛先        ネットマスク          ゲートウェイ       インターフェイス  メトリック
     198.51.100.0    255.255.255.0      192.0.2.200  <各自の環境>      2
      203.0.113.0    255.255.255.0      192.0.2.200  <各自の環境>      2

===========================================================================
```
C17 (not C++17)

2017年を1ヶ月残したところで、プログラミング言語C++の国際標準規格 [ISO/IEC 14882:2017](https://www.iso.org/standard/68564.html)、通称「[C++17](https://cpprefjp.github.io/lang/cpp17.html)」が無事に正式発行されました。C++er各位におかれましてはますますご清祥のこととお慶び申し上げます。


# Hello, C17!
ところでC言語は？国際標準は[ISO/IEC 9899:2011](https://www.iso.org/standard/57853.html)通称「C11」が最後なの？

いえいえ。我らが(？)C言語だって、2017年の新規格「C17」発行に向けた準備が進んでいるのです。さっそく C17 の新機能を紹介しましょう...

と続けたいのですが、C17 に **新機能はありません**。C17 はマイナーバージョンアップとされており、機能的には C11 と同一で不具合(DR; Defect Report)修正のみ適用されます[^1]。

[^1]: http://en.cppreference.com/w/c/language/history

# To be continued... C2x
先生の次回作「[C2x](https://qiita.com/yohhoy/items/3e2fb952dc65e4bf2802)」にご期待ください！！
誰得CGRect


自分しか得しなさそうなCGRectを作るextensionまとめ

#1.二つのCGPointから作る

```swift:CGRect+doublePoints
extension CGRect {
    init(point1: CGPoint, point2: CGPoint) {
        self.init(x: min(point1.x, point2.x),
                  y: min(point1.y, point2.y),
                  width: fabs(point1.x - point2.x),
                  height: fabs(point1.y - point2.y))
    }
}
```

```swift:使用例
let rect = CGRect(point1: CGPoint(x: 50, y: 20), point2: CGPoint(x: 10, y: 100))
// (x: 10.0, y: 20.0, width: 40.0, height: 80.0)
```

##使い所
パンジェスチャーの開始地点と終了地点とかでCGRectを用意する時とかに使える。


#2.中心のCGPoint+CGSizeから作る
```swift:CGRect+center
extension CGRect {
    init(center: CGPoint, size: CGSize) {
        self.init(x: center.x - size.width/2,
                  y: center.y - size.height/2,
                  width: size.width,
                  height: size.height)
    }
}
```

```swift:使用例
let rect1 = CGRect(center: CGPoint(x: 200, y: 100), size: CGSize(width: 20, height: 100))
// (x: 190.0,y: 50.0,width: 20.0,height: 100.0)
```
##使い所
UIViewの中心にaddSubviewとかしたい時に使う。


#3.右下CGPoint+CGSizeから作る
```swift:CGRect+bottomRight
extension CGRect {
	init(bottomRight: CGPoint, size: CGSize) {
        self.init(x: bottomRight.x - size.width,
                  y: bottomRight.y - size.height,
                  width: size.width,
                  height: size.height)
    }
}
```

```swift:使用例
let rect = CGRect(bottomRight: CGPoint(x: 100, y: 200), size: CGSize(width: 50, height: 30))
// (x: 50.0,y: 170.0,width: 50.0,height 30.0)
```

##使い所
ごく稀に右下基準でViewを置きたい時に使うけど、本当に稀。

#4.CGRectをX倍した新たなCGRectを作る
```swift:CGRect+scale
extension CGRect {
    init(baseRect: CGRect, scale: CGFloat) {
        self.init(x: baseRect.origin.x,
                  y: baseRect.origin.y,
                  width: baseRect.width * scale,
                  height: baseRect.height * scale)
    }
}
```
```swift:使用例
let rect = CGRect(origin: .zero, size: CGSize(width: 100, height: 100))
let rect2 = CGRect(baseRect: rect, scale: 1.5)
// (x: 0.0,y: 0.0,width: 150.0,height: 150.0)
```
##使い所
これ使うくらいなら、演算子作った方がいいかもって感じ。

#続く？
変わったCGRectを作る機会があれば書く。
SSL Labsでサーバ設定をチェック

サーバにSSLの設定を適用する上で、設定すべき項目は多いし、間違えばセキュリティ的にまずいことになってしまう、あるいは正常に接続できないなど、なかなかややこしいものです。

幸い、そのようなSSLの設定を検証するサービスがあります。

# SSL Labs

[SSL Labs](https://www.ssllabs.com/)は、Qualysというセキュリティ会社が運営している、SSL関連の便利サイトです。右上にある「Test Your server」からサーバのテストモードに入れます。

なお、具体例がないとわかりづらいかと思いますので、ここから先は[`qiita.com`をチェックした結果](https://www.ssllabs.com/ssltest/analyze.html?d=qiita.com)を見ていくことにしましょう。

# サーバのチェック
同じドメインでいくつかサーバがある場合、まずはサーバを選択する画面が出ます（評価はサーバごとに行います）。サーバを選べば、通信を行って、SSLの設定を評価していきます。

## 総合評価

`qiita.com`では「A」ですが、「A+」「A」「A-」「B」「C」「D」「F（致命的に設定がまずい）」「T（証明書が通らない）」のように分かれています。その右側には、「Certificate」「Protocol Support」「Key Exchange」「Cipher Strength」の4つの評価軸で、点数が振られています。

なお、こういう評点を振る系のサービスではよくある話ですが、点数を上げること自体を目的としないようにしましょう。とりわけ、サーバの設定である以上クライアントがあってのものですので、過剰に制限をかけた設定しにしてしまって、クライアントから繋がらなくなれば本末転倒です。

## 証明書（Certificate）

次に出てくるのは証明書の詳細です。発行元、発行日、コモンネーム、署名アルゴリズムなどが確認できます。また、同時に送ってくる中間証明書についてもチェックできます（間違えてルート証明書まで送信していると、「Contains Anchor」と出ます）。

## 接続状況

次に出てくるConfigurationでは、まずSSL/TLSの各バージョンへの対応状況が出ます。そして、次にCipherSuiteのリストが出てきますが、3DESのような強度が不十分なものには「WEAK」、輸出暗号やDES、RC4など破られているものには「INSECURE」と出ます。

そこに続くのは、各ブラウザの対応した暗号で接続を試みた場合の状況です。一致する暗号がない、SNIが必要だけどクライアントが非対応なものにはその旨が出ます。古い端末でも接続性を保ちたい、となればこうした情報も参考になるかと思います。

次に、サーバ設定や脆弱性の対応状況が出ます。BEAST、POODLE、CRIME、Heartbleedなどもカバーしていますし、HSTSやキーピンニングの設定も確認できます。

いちばん下はSSLと関係ありませんが、HTTP接続に関する情報が表示されます。
中級者向け Arduino（組み込み系）コーディング時 リファレンス集

# 概要
私のよく使う、ArduinoでのReferenceの閲覧先を項目ごとにまとめさせていただきました。間違っている部分は、ご指摘いただけると助かります。

# 関数の定義方法
### 関数の定義方法
voidではない型を使う場合は、下記のような記述

```
float output(int input){
   ~hogehoge~
   return 10.222 + 20.5 + input;
}
```


| 上記の文字でいうと | 項目 | 内容 |
|:------------|:-----------|:------------|
| float | 返却値の型 | 関数が返す値の型。関数が返却できる値は0個もしくは1個。2個以上の値を返却することはできない。（もちろん、float以外の型も使用可能。適宜合わせる）| 
| output | 関数名 | 呼び出すときに使う名称。（内容に合わせ適宜合わせる） |
| int |仮引数の型|仮引数の型の定義（もちろん、int以外も使用可能。適宜合わせる）。複数使用可能|
| input |仮引数|関数に渡す入力値。0個以上の入力を指定することができる|
| ~hogehoge~ | 内容 | 関数の実行内容 |
| return | return文 | 呼び出し元に値が返る。普通の式ならば「xxx = 10.222 + 20.5」となるが、そちらの「xxx」を「return」にし、イコールをなくす。そうすると、呼び出し元にこちらの答えが入る。 |

### 関数の呼び出し方法

```
 answer = output(18);
```

このときanswerには「10.222 + 20.5 + 18」の答えが入る。つまり「output(18)」には「10.222 + 20.5 + input」の値が返されている。

※以下を参考にさせていただきました。
[Arduino（C/C++言語)での関数]
(https://garretlab.web.fc2.com/arduino/clang/function/index.html)


# マイコン的ノウハウ・Tips
### 二択での条件分岐の場合、変数はintではなくbooleanを使う

下記のような、二択（0と1）で切り替えわれば十分な場合、このrunをintにするか、boooleanにするかでスケッチ容量がかなり変わる。

```
if (run == true){
   ~hogehoge~
   run = !run
}
```

あるスケッチで、このrunをintとbooleanにした場合の比較では、1回しか使わない変数にもかかわらず、18バイトも容量が変わった。int型自体は2バイトを使って格納するにもかかわらず。

| 型 | スケッチサイズ |
|:------------|:-----------:|
| int | 7800バイト | 
| boolean | 7782バイト | 



[int (整数型) - Arduino 日本語リファレンス]
(http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=1105)

[sketch - Program button to switch between two values - Arduino Stack Exchange]
(https://arduino.stackexchange.com/questions/8647/program-button-to-switch-between-two-values)
> You can set it to __true__ or __false__, or change it to it's opposite (with 
__value=!value__ as shown above). You can also do __if value__ or __if !value__ ("if not value") - these are equivalent to __if value=true__ or __if value=false__.

###   pinMode(hogehoge, INPUT); 利用の場合、INPUT_PULLUPを利用すると便利
スイッチ入力などでオフを判断するには、電圧が0である必要がある。入力するピンの電圧が不安定になり、うっかり1の判断しないよう、入力ピンはグラウンドに接続する。その際、スイッチオンの時もVCCからグラウンドに電流が流れてはOnが判断できないため、抵抗を挟んで利用する。

だが、それだと配線が煩雑になる。

そのときに、INPUT_PULLUPを利用すると、INPUTするピンが電流を流す側になり、電流が流れていないときHighになり、スイッチが導通しgroundにつながるとlowになる。このように、スイッチのオンオフの判定は逆になるが、抵抗を外に挟む必要がなくなり、回路がシンプルになる。


詳細は以下にて
[意外と知られていない？INPUT_PULLUP | スイッチサイエンス マガジン](http://mag.switch-science.com/2013/05/23/input_pullup/)

###   スイッチの意図せぬ瞬間的なオンオフ（チャタリング）対策
オンした時に、5〜10ミリ秒後もオンなら「オンと判定」とするようです。オフも同様。

[Arduino Playground - Bounce](http://playground.arduino.cc/Code/Bounce)
[電子回路で跳ねたり、引っ張り上げたりする話。 - シアトル生活はじめました](http://watanabe-tsuyoshi.hatenablog.com/entry/2015/12/29/152728)

# 資料
[Arduino - ASCIIchart](https://www.arduino.cc/en/Reference/ASCIIchart)

[逆引きArduino]
(https://garretlab.web.fc2.com/arduino/reverse_lookup/index.html)


### 型一覧・データの有効範囲
[Arduino(C/C++言語）でのデータ操作]
(https://garretlab.web.fc2.com/arduino/clang/data/index.html)


### I2C
[How I2C Communication Works & How To Use It with Arduino]
(http://howtomechatronics.com/tutorials/arduino/how-i2c-communication-works-and-how-to-use-it-with-arduino/)

### マイコンの仕組み
Arduinoではないが、マイコンの基本的な仕組みの理解に役立つ
[「マイコン入門!! 必携用語集」最新記事一覧 - ITmedia Keywords](http://www.itmedia.co.jp/keywords/edn_micro_mustvocab.html)
StreamのmapとflatMapの違い

Java 8のStreamに`map()`と`flatMap()`があります。その違いを検証します。

#結論
まず結論から言うと、
　・`map(T -> R)`は、`T`のデータ型を`R`のデータ型に１：１の変換です。
　・`flatMap(T -> Stream<R>)`は、`T`のデータ型から`Stream<R>`に１：Nの変換です。

##Stream#map()

```java
List<String> nameList = Arrays.asList("Tanaka", "Suzuki", "Takahashi");
Stream<Integer> stream = nameList.stream().map(x -> x.length());
System.out.println(stream.collect(Collectors.toList()));
```
上記の実行結果：

```
[6, 6, 9]
```
|    Tanaka    |    Suzuki    |    Takahashi    |
|:------------:|:------------:|:---------------:|
|      ↓       |      ↓       |        ↓        |
|      6       |     6        |       9         |
上記のように文字列(String)から文字列長（Integer）へ１：１の変換です。


##Stream#flatMap()

```java
List<String> nameList = Arrays.asList("Tanaka", "Suzuki", "Takahashi");
Stream<Object> stream = nameList.stream().flatMap(x -> Stream.of(x, x.length()));
System.out.println((stream.collect(Collectors.toList())));
```

上記の実行結果：

```
[Tanaka, 6, Suzuki, 6, Takahashi, 9]
```
|    Tanaka    |    Suzuki    |    Takahashi    |
|:------------:|:------------:|:---------------:|
|      ↓       |      ↓       |        ↓        |
|  Tanaka, 6   |   Suzuki, 6  |   Takahashi, 9  |
文字列(String)から[文字列（String）, 文字列長（Integer）]へ１：Nの変換です。
但し、その場合は２次元配列が生成されるわけではなく、flatなStreamが返却されます。
ご注文はMastodonBotですか？ メディア投稿編

本日誕生日を迎えた記念としてPythonの「Mastodon.py」を使用したAPIで動くBotを作りましょうシリーズを気まぐれに掲載開始です。
![2017-12-04_06.jpg](https://qiita-image-store.s3.amazonaws.com/0/219279/57259afc-e78d-41f5-a922-eb242b81a3da.jpeg)
~~簡易的な導入についてはありふれてますので小難しい話題からになってしまいます。~~
#メディア投稿をしてみましょう☕#
ということでメディアの投稿形式Botさんを作ってみましょう。

```Python:
from mastodon import *
import io, sys

#プロンプト起動向けの処理です。
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,
                              encoding=sys.stdout.encoding,
                              errors='backslashreplace',
                              line_buffering=sys.stdout.line_buffering)

# instanceのアドレス入力をお願いします　例：https://knzk.me
url_ins = open("instance.txt").read()

# クライアントID、アクセストークン取得については
# グーグル先生に聞けば分かりますので割愛します。頑張ってください。
mastodon = Mastodon(
    client_id='client.secret',
    access_token='user.secret',
    api_base_url=url_ins)

"""ここまでがログイン処理のテンプレートです"""

def main():
    # メディア投稿の処理
    # media_post(self, media_file, mime_type=None, description=None)
    media = []  #media_idsはリスト指定になります。
    media.append(mastodon.media_post('test.png'))  # 要素追加の形でmedia_postします。
    print(media)  # png投稿の一例です。
    txl = " ".join(x['text_url'] for x in media)  #生成した短縮URLを繋ぎます。
    post = "メディアテストです" + txl  # くっつけます。
    # status_post(self, status, in_reply_to_id=None, media_ids=None,
    #             sensitive=False, visibility='', spoiler_text=None):
    """status=toot文章　in_reply_to_id=返信宛　media_ids=メディアデータ（ここにメディア情報のリストを入れます）
       sensitive=画像を隠すかどうかです, visibility=公開範囲, spoiler_text=CWで畳むかどうかです"""
    return mastodon.status_post(post, media_ids=media, visibility='unlisted')  # ポストします☕

if __name__ == '__main__':
    main()  # 上記に書いた命令を関数にして実行です！
```
このようなコードになるかと思います。
####メディア投稿の解説☕####
メディアは4つまでアップロードすることが出来ますので、リストを生成して```append```形式で追加するのが望ましいかと思われます。
media_postでメディアをアップロードした後に、データ情報がdict型で生成されます。```'text_url'```キーに短縮URLがありますので、POST内容が空にならない対策に便利ですね。

#####以上となります。　いかがでしたでしょうか？#####
内容が短いですが、画像を投げるBotシステムが欲しかった人の参考になれたらと思います。これをきっかけに、面白く愛嬌のあるBotさんが生まれることを願っております。
qiitaを始めたきっかけとなりました、[神崎おにいさん率いるMastodonのアドベントカレンダー](https://adventar.org/calendars/2225)に参加しております（担当の仕事はもう終わりました）。日々進化する世紀末な最先端に興味がある方は、ぜひとも[knzk.me](https://knzk.me)に来てみてください。
それではMastodonライフをお楽しみください。またのお越しをお待ちしております☕
![2017-11-16_02.jpg](https://qiita-image-store.s3.amazonaws.com/0/219279/ba28b6e0-5994-8d2b-df1b-d2f859889031.jpeg)
ゼロから作るDeep Learning（4章）

#4章 ニューラルネットワークの学習
##学習アルゴリズムの実装
118ページのサンプルプログラムに誤植？があったので、書き残し

```
import numpy as np
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet
```

と書いてあるが、`datasetが見つかりません`エラーが出た。
datasetフォルダは親フォルダにあるので、親フォルダへのアクセスが必要になる。
mnistデータへのアクセスが登場したページ（73ページ）を参考にして書き直すと以下の通り。

```
import numpy as np
import sys, os
sys.path.append(os.pardir)
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet
```
この変更で通すことができた。

***

同サンプルプログラムの中の`np.random.choice(a, b)`は初めて出てきた気がする。
動作は、*0~(a-1)までの数からb個をランダムに取り出す*。
なので、

```
batch_mask = np.random.choice(train_size, batch_size)
```

でやっているのは、`0~783の中からランダムに100個を取り出して、1次元のndarrayを返す`。

***

```
for key in ('W1', 'b1', 'W2', 'b2'):
```

これも一瞬何やっているのかよくわからなかったが、辞書型でforループしているだけ。
すなわち、W1、b1、W2、b2を順に呼び出して処理しているだけである。

***

##過学習の確認方法
学習用のデータの認識精度と確認用のデータの認識精度を比べる。
両方描画してみて、グラフの形に違いがなければ過学習はしていない。（121,122ページ）
多層パーセプトロンと誤差逆伝播法を学んでみた

文系出身のプログラマですが、機械学習が流行っているので、
最初のステップとして大学ぶりに微分積分をちょっと勉強してみました。

---

## 機械学習とは？？

> - ロボットやコンピュータなどの機会が、経験（学習）から行動するためのパラメータを自動的に獲得する方法

> - データの中で見えているものから、見えていないものを予測する方法

とあるように、たくさんのデータを機械に学習させることで、
> - 今後の予測を立てる
> - 似たような問題を与えた時に、機会が自動で答えを出してくれる。

ようにすることです。

んーーーいまいち分からない。。。。。
ざっくり言うと、
機械にたくさんのことを経験させることで、機械にまるで人間のように判断力を獲得することのようです。

---

## ディープラーニング

「ディープラーニング」とは「深層学習」とも呼ばれる機械学習法の１つで、
入力されたデータからクラス分類や、回帰を行う手法です。


またディープラーニングは人の脳における知識獲得に近い仕組みを実現できることがわかっています。
この人に近いハイレベルな学習機能と、パソコン本来の強みである、計算力を生かして、人間でも発見したり、予測できなかったことをしてくれるのがディープラーニングのようです。

今回は機械学習やディープラーニングを学ぶ際に知っておくべき、基本的な仕組みである、
**ニューラルネットワーク**について学ぶため、その元となるパーセプトロン、そして多層パーセプトロンについて
学んでいこうと思います。

---

# パーセプトロンとは

- 視覚や脳神経細胞の機能をモデル化したもの


![パーセプトロン.png](https://qiita-image-store.s3.amazonaws.com/0/190748/aa2f67df-f378-4962-796c-12478958d6c8.png)

上図のように複数の入力から１つの出力を行い、これを繰り返すことでモデルを学習することのようです！

---

# 多層パーセプトロン

パーセプトロンを階層的に構成したものです。

![多層パーセプトロン.png](https://qiita-image-store.s3.amazonaws.com/0/190748/a1ef4818-70f7-644f-963f-07525739599d.png)

こんな感じらしいです笑
上図のように入力層に与えた値を伝播させていきます。

---

# 誤差逆伝播法とは？

得られた出力結果から、教師データとの誤差を算出して、パラメータとしての重みを調整し、調整された値を元にまた後ろのノードへと更新を伝えていきます。

更新量Δwは、以下の式で求められます。


```math
△w = −η\frac{δE}{δw}

```
誤差が大きければ更新量を大きく、誤差が小さければ更新量を小さくするようにするために、
上の傾きを求めます。

途中までですが、今日はここまでで
参考になる三項演算子

どうもこんにちは。専門学校界の旅キチ(自称)です。

最近どうも私の周りで三項演算子の評判がよろしくない(？)ので、せっかくのこの機会に三項演算子の素晴らしさについて伝えていければと思います。

*注：この記法はC, C++, C#, Javaについての説明となります。他の言語環境においての動作は保証しませんので悪しからず。*
*~~筆者がそいつらしかまともに触ったことがない等とは口が裂けても言えない。~~*

## そもそも三項演算子とは何か
三項演算子とはその名の通り、3つの項(式)から成る演算子のことである。


…と言っては身も蓋も無いのでもっと深く説明する。

まず、三項演算子は次のような書式で成り立つ。

```
<条件式> ? <条件式がtrueの場合の式> : <条件式がfalseの場合の式>
```

ここでプログラムを書く上で見慣れない記号があるかもしれない。
そう、"`?`"マークである。
これは**条件演算子**と言い、条件式によって、"`?`"の後に並ぶ2つの項目に処理を分岐させる役割を持つ。

これにより、if文において記述されていた処理を劇的にスッキリさせることが可能になる。
例えば、次のように、bool(Boolean)形の変数`flag`をtrueとfalseで交互に切り替えたい場面があったとする。

```C
if(flag)
{// flagがtrueの場合、falseに

	flag = false;
}
else
{// flagがtrueの場合、falseに

	flag = true;
}
```

なんとも長ったらしい。
しかしこれを三項演算子を利用して記述するとこうなる。

```C
flag ? false : true;
```

なんと、あれだけ長ったらしかった処理がこんなにもスッキリ！
こんな素晴らしいものがあったなんて！明日はきっと快晴に違いない！

…と言いたいところではあるが、そう簡単にはいかないのが世の常。
次のコードをご覧頂きたい。

```C
int num = flag ? flag2 ? flag4 ? 1 : 2 : flag5 ? 3 : 4 : flag3 ? flag6 ? 5 : 6 : flag7 ? 7 : 8; 
```

いかがだろうか？
便利な三項演算子でも、使いどころを間違えるとこのように可読性が地に落ちてしまうのである。

世の中に絶対は無い。それはことプログラミングにおいても同じである。
便利なツールも使いどころを間違えれば石器時代に逆戻りだ。
そしてそのツールの使いどころ、使い方を考えるのは他でもないこの記事を読んでいるあなたである。

使いどころを考えて、良い開発ライフを。