OmniAICreator/Qiita-1.07M huggingface dataset:
【SQL】COUNT関数で条件に合致する件数を取得する

SELECTで取得したレコードの件数を取得するCOUNT関数。
特定の条件に合致するレコード数を集計したい時に少し難解な書き方をします。

#テーブル
サンプルで使用するテーブルです。

| 名前 | 性別 |
|:----------------:|:---------------:|
| 田中 | 男 |
| 山田 | 男 |
| 佐藤 | 女 |
| 鈴木 | 男 |
| 武田 | 女 |
| 山本 | 男 |


#SQL
```sql
SELECT COUNT(性別=男 OR NULL) AS 男の数
, COUNT(性別=女 OR NULL) AS 女の数
FROM テーブル
```

#処理の仕組み
上のSQL、`OR NULL`って必要？と思いますよね？

PostgreSQLの公式ドキュメントを見ると、下記の記載があります。
> count(expression) ： expressionが非NULL値を持つ入力値の個数

ですので、上記SQLの`性別=男 OR NULL`の部分が`性別=男`だと、性別=男のレコードはTRUE、性別=女のレコードはFALSEとなり、全レコードが`非NULL値を持つ入力値`としてカウントされます。

`OR NULL`を付けることによって、性別=男のレコードは`TRUE OR NULL`でTRUEとなり、性別=女のレコードは`FALSE OR NULL`でNULLとなり、意図した通りの集計結果となります。

#余談
ちなみに、BOOL値とNULLの論理演算の結果は以下の通りです。
TRUE AND NULL → NULL
TRUE OR NULL → TRUE
FALSE AND NULL → FALSE
FALSE OR NULL → NULL
GooglePlay定期購読でのアップグレード/ダウングレード Part2

GooglePlay定期購読のアップグレード/ダウングレードの仕様についてPart2です。
サーバ側でアップグレード/ダウングレードしたのかをどうやって判断するのかについてのまとめとなります。
Part1はこちら :arrow_right: [GooglePlay定期購読でのアップグレード/ダウングレード Part1](https://qiita.com/natty420/items/1da53952202e9bc5e7bb)

# サーバ側での課金状態取得

GoogleAPIを利用して現在の課金状態を取得します。
https://developers.google.com/android-publisher/api-ref/purchases/subscriptions/get

#### 前提知識
<font color="Pink">Googleではアップグレード/ダウングレード時または再購読時にはpurchaseTokenとorderIdは新たに発行されます。
</font>

結果取得できるレスポンスの一部は以下の通りです。
(すべてのレスポンス内容は[公式ドキュメント](https://developers.google.com/android-publisher/api-ref/purchases/subscriptions#resource-representations)を参照)

|Key       |詳細      |
|:-----------|:------------|
|startTimeMillis           |商品が購入された時間を1970年1月1日から始まるミリ秒で表す。     |
|expiryTimeMillis           |期限切れになるまでの時間(ミリ秒)。   |
|autoRenewing           |自動更新が有効かどうかを表す。trueの場合は自動更新購読が有効で、次の課金日に自動的に更新されます。falseの場合はユーザーが自動更新購読をキャンセルしたことを示します。     |
|paymentState           |注文の購入状況。<br>0：支払保留中<br>1：支払い済み<br>2：無料トライアル<br>自動更新がOFF(autoRenewing:false)かつ有効期限も切れている場合はKey自体ない。     |
|orderId           |購入に関連付けられた最新の定期注文の注文ID。     |
|cancelReason           |自動更新購読をキャンセルした or 有効期限が切れた理由。<br><br>0： ユーザーが定期購入をキャンセルした<br>1：システムによってキャンセルされた(請求ができなかった等)<br>2：新しいサブスクリプションに置き換えられた(アップグレード/ダウングレードや、再購読した等)<br>3：開発者によってキャンセルした<br>     |
|userCancellationTimeMillis           |cancelReasonが0の場合のみ入る。自動更新をキャンセルしたときの時間(ミリ秒)。 |
|linkedPurchaseToken          |この購読に紐づく購読情報となる。パターンは2つ。<br>1. アップグレード/ダウングレードした場合、アップグレード/ダウングレード前のpurchaseTokenとなる。<br>2. ある購読を有効期限内にPlayストアでキャンセルする。その購読の有効期限内に再購読をするとキャンセルした購読のpurchaseTokenとなる。     |

## アップグレード/ダウングレードかどうかを見極めるには

|金額       |アイテム      |期間　　　　　　|
|:-----------|------------:|:------------:|
|300円           |アイテムA     |1ヶ月 　　　　　|
|600円           |アイテムB     |1ヶ月 　　　　　|

アイテムAからBに変更した場合とします。
:one: Aを4/1に登録すると、次の更新日は5/1となる。このときの課金状態は以下となる(purchaseTokenをAAAとする)

|Key       |詳細      |
|:-----------|:------------|
|startTimeMillis           |2018/4/1 xx:xxをミリ秒で表す。     |
|expiryTimeMillis           |2018/5/1 xx:xxをミリ秒で表す。   |
|autoRenewing           |true     |
|paymentState           |1     |
|orderId           |購入に関連付けられた最新の定期注文の注文ID。     |

:two: 4/10にBに乗り換える。この時点でBに変更となる。次の更新日は4/20となる。(Bで購入したpurchaseTokenをBBBとする※)
このときのAの課金状態は以下となる

|Key       |詳細      |
|:-----------|:------------|
|startTimeMillis           |2018/4/1 xx:xxをミリ秒で表す。     |
|expiryTimeMillis           |2018/4/10 xx:xxをミリ秒で表す。乗り換えを実施した時間となる。   |
|autoRenewing           |false     |
|cancelReason           |2     |

このときのBの課金状態は以下となる

|Key       |詳細      |
|:-----------|:------------|
|startTimeMillis           |2018/4/10 xx:xxをミリ秒で表す。乗り換えを実施した時間となる。     |
|expiryTimeMillis           |2018/5/20 xx:xxをミリ秒で表す。   |
|autoRenewing           |true     |
|paymentState           |1     |
|linkedPurchaseToken          |アップグレード前のpurchaseTokenとなるので「AAA」となる。     |

linkedPurchaseTokenがある時点で、再購読かアップグレードかダウングレードは確定となる。
あとはlinkedPurchaseTokenとサーバ側で保持しているデータを参照してどのアイテムからどのアイテムへの変更なのかを検証できればよさそう。またlinkedPurchaseTokenの課金状態のcancelReasonを見てもわかりそうですね。

## まとめ

linkedPurchaseTokenを使えばどういった課金の変更なのかを追えて便利ですね:sparkles:
Inception V3　モジュール 実装

#構造

![image.png](https://qiita-image-store.s3.amazonaws.com/0/315063/9a49abc0-2fb4-fbf1-e57f-5232d45caeed.png)



#実装
```python
def InceptionV3_block1():
    def f(x):
        b1 = Convolution2D(64, (1,1), strides=2, padding='same')(x)
        b1 = BatchNormalization()(b1)
        b1 = Activation('relu')(b1)

        b2 = Convolution2D(48, (1,1))(x)
        b2 = BatchNormalization()(b2)
        b2 = Activation('relu')(b2)
        b2 = Convolution2D(96, (3,3), strides=2, padding='same')(b2)
        b2 = BatchNormalization()(b2)
        b2 = Activation('relu')(b2)


        b3 = AveragePooling2D(pool_size=(3, 3), strides=2,  padding='same')(x)
        b3 = Convolution2D(64, (3,3), padding='same')(b3)
        b3 = BatchNormalization()(b3)
        b3 = Activation('relu')(b3)

        b4 = Convolution2D(64, (1,1))(x)
        b4 = BatchNormalization()(b4)
        b4 = Activation('relu')(b4)
        b4 = Convolution2D(96, (3,3), padding='same')(b4)
        b4 = BatchNormalization()(b4)
        b4 = Activation('relu')(b4)
        b4 = Convolution2D(32, (3,3),strides=2, padding='same')(b4)
        b4 = BatchNormalization()(b4)
        b4 = Activation('relu')(b4)

        output = concatenate([b1, b2, b3, b4], axis=-1)
        return output
    return f

```
```python
def InceptionV3_block2():
    def f(x):
        b1 = Convolution2D(64, (1,1), strides=2,  padding='same')(x)
        b1 = BatchNormalization()(b1)
        b1 = Activation('relu')(b1)

        b2 = Convolution2D(48, (1,1))(x)
        b2 = BatchNormalization()(b2)
        b2 = Activation('relu')(b2)
        b2 = Convolution2D(96, (3,3), strides=2,  padding='same')(b2)
        b2 = BatchNormalization()(b2)
        b2 = Activation('relu')(b2)


        b3 = AveragePooling2D(pool_size=(3, 3), strides=2,  padding='same')(x)
        b3 = Convolution2D(64, (3,3), padding='same')(b3)
        b3 = BatchNormalization()(b3)
        b3 = Activation('relu')(b3)

        b4 = Convolution2D(64, (1,1))(x)
        b4 = BatchNormalization()(b4)
        b4 = Activation('relu')(b4)
        b4 = Convolution2D(96, (3,3), padding='same')(b4)
        b4 = BatchNormalization()(b4)
        b4 = Activation('relu')(b4)
        b4 = Convolution2D(64, (3,3),strides=2, padding='same')(b4)
        b4 = BatchNormalization()(b4)
        b4 = Activation('relu')(b4)

        output = concatenate([b1, b2, b3, b4], axis=-1)
        return output
    return f
```
```python
def InceptionV3():
    inputs = Input(shape=(32, 32, 3))
    x = Convolution2D(32, (1,1), strides=2)(inputs)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = MaxPooling2D((3, 3), strides=(2,2), padding='same')(x)
  
    x = InceptionV3_block1()(x)
    x = InceptionV3_block2()(x)
  
    x = GlobalAveragePooling2D()(x)
    x = Dense(10, kernel_initializer='he_normal', activation='softmax')(x)
  
    model = Model(inputs=inputs, outputs=x)
    return model

model = InceptionV3()
adam = Adam()
model.compile(optimizer=adam, loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()
```
大きな素数（かもしれない）

# はじめに

大きな素数(1024bitより大きい)を求める必要がある場合を考えました。
[RSA暗号 - Wikipedia](https://ja.wikipedia.org/wiki/RSA%E6%9A%97%E5%8F%B7)などをみると、乱数を生成して、それが素数かどうか調べるのが速いそうです。
ただし、ガチ計算だと時間がかかりすぎるので、[確率的素数判定法](https://ja.wikipedia.org/wiki/%E7%B4%A0%E6%95%B0%E5%88%A4%E5%AE%9A#%E7%A2%BA%E7%8E%87%E7%9A%84%E7%B4%A0%E6%95%B0%E5%88%A4%E5%AE%9A%E6%B3%95)で素数判定をおこないます。

## ミラー–ラビン素数判定法（Miller–Rabin primality test）

[ミラー–ラビン素数判定法 - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%9F%E3%83%A9%E3%83%BC%E2%80%93%E3%83%A9%E3%83%93%E3%83%B3%E7%B4%A0%E6%95%B0%E5%88%A4%E5%AE%9A%E6%B3%95)によると、内部で仕様している$k$から$4^{-k}$の確率で合成数を素数と誤認識してしまうようです。
$k$をある程度大きくしておけば、黙認できるレベルになるそうです。


```golang
func isProbablyPrime(n *big.Int) bool {
	ONE := big.NewInt(1)
	TWO := big.NewInt(2)
	if n.Cmp(ONE) <= 0 {
		return false
	}
	// if n == 2 then prime
	if n.Cmp(TWO) == 0 {
		return true
	}
	// odd check
	if n.Bit(0) == 0 {
		return false
	}
	// n-1 = 2^s * d
	d := new(big.Int).Sub(n, ONE)
	s := big.NewInt(0)
	for d.Bit(0) == 0 {
		d.Rsh(d, 1)
		s.Add(s, ONE)
	}
	k := 1024
	nm1 := new(big.Int).Sub(n, ONE)
	for i := 0; i < k; i++ {
		// a in [1,n-1]
		a := Rnd(nm1)
		a.Add(a, ONE)
		// a^{d} mod n == 1
		t := new(big.Int).Exp(a, d, n)
		if t.Cmp(ONE) == 0 {
			continue
		}
		flg := false
		// r in [0,s-1] , a^{2^rd} mod n == -1
		// a^{2^0 * d} , a^{2^1 * d} , a^{2^2 * d} , .... , a^{2^(s-1) * d}
		for r := big.NewInt(0); r.Cmp(s) < 0; r.Add(r, ONE) {
			if t.Cmp(nm1) == 0 {
				flg = true
				break
			}
			t.Exp(t, TWO, n)
		}
		if !flg {
			return false
		}
	}
	return true
}

// Rnd returns a random number less than n
func Rnd(n *big.Int) *big.Int {
	tmp := make([]byte, len(n.Bytes()))
	rand.Read(tmp)
	return new(big.Int).Mod(new(big.Int).SetBytes(tmp), n)
}
```

## 素数生成

bit数の素数を生成するプログラムを作成します。
単純に乱数生成して、それが素数かを判定するだけのプログラムです。

```golang
func probablyPrime(bits int) *big.Int {
	max := new(big.Int).Exp(big.NewInt(2), big.NewInt(int64(bits)), nil)
	p := big.NewInt(0)
	for !isProbablyPrime(p) {
		p = Rnd(max)
		for p.BitLen() != bits {
			p = Rnd(max)
		}
	}
	return p
}
```

# さいごに

RSAの乱数生成とか、どうやってたか調べたら案外単純な方針だったことに驚きました。
そして、確実でないってことも・・・
Encrypted SNI / TLSハンドシェイクの暗号化

# SNI とは

一つのIPアドレスと一つのTCPポートで、複数のWebサイトをホスティングする技術の一つに、`virtualhost`があります。
これは、HTTPリクエスト内で指定するドメイン名から、同じIPに対するアクセスをドメインごとに振り分ける機能です。

たとえば、以下のコマンドを実行すると、こんな出力がされます。

（ちなみに、vがリクエストヘッダの表示、 Iがボディの非表示のオプションです。）

```bash
$ curl -v -I example.com

*   Trying xxxxx...
* TCP_NODELAY set
* Connected to example.com (xxxxx) port 80 (#0)
> HEAD / HTTP/1.1
> Host: example.com
> User-Agent: curl/7.62.0
> Accept: */*
>

…（省略）
```

真ん中の行に、`Host: example.com`という行があるのが見えます。HTTP通信はTCPの上で行われる通信ため、通信内容にドメイン名は必要ないのですが、HTTP/1.1対応のブラウザだとこのようなリクエストが投げられます。

Nginxなどのサーバーは、このHostを見分けて、同じIPアドレスへのリクエストでも、異なる処理ができるように
なります。格安レンタルサーバーなどではこの手法を取っています。

>今HTTP/2.0はどうなんだろうなーと調べてみましたが、やはりHostフィールドはあるようです。 
 [RFC 8.1.3章](http://http2.github.io/http2-spec/index.html#rfc.section.8.1.3)


そしてここからが本題です。HTTPSを使う場合、Hostはどうなるでしょう。
はい、そこのあなた、正解です。HTTPヘッダごと暗号化されます。

なので、もし判別しようと思った場合、TLSハンドシェイクの時点で、どのサーバーにアクセスしたいのかをリバースプロキシにあたるサーバーが知る必要が有ります。
また、そのときにクライアントはサーバー（virtualhost）のTLS証明書を取得します。

このために、拡張TLS通信のハンドシェイクの一番最初の段階である`ClientHello`では、__SNI(Server Name Indication)__と呼ばれる技術を使います。
これはClientHelloの中で、`server_name`の項目にドメイン名を入れて、接続するホスト先を指定してあげることができます。

```
      enum {
          server_name(0), max_fragment_length(1),      ←これ
          client_certificate_url(2), trusted_ca_keys(3),
          truncated_hmac(4), status_request(5), (65535)
      } ExtensionType;
```
( https://www.ipa.go.jp/security/rfc/RFC6066JA.html より )

また、このSNIは、RFCの中で
>「クライアントは、あるサーバをサポートされている名前種別によって見つけ出す（locate）ときはいつでも、その client hello 中に種別が "server_name" の拡張を含むこと」が推奨される（RECOMMENDED）。」


と定められています。どういうことかというと、ChromeやFirefoxといった、モダンなブラウザは基本的にこのserver_nameを使用しています。

つまり、HTTPS通信を使う場合でも、最初のコネクション時に、接続するドメインを指定することになります。


ということは、HTTPSを使っても、__どのドメインに接続しているかはネットワーク上の機械が確認できてしまう__ということになります。

このため、HTTP bodyやパスだけを暗号化したところで、ネットワーク側である程度の検閲やブロッキング、ログ収集ができてしまいます。

この対策として考えられたのが、Encrypted SNIです。

# Encrypted SNI とは

__Encrypted SNI__(以下、ESNI)は、その名前の通りSNI、つまりClientHelloの中のserver_nameを暗号化してしまう技術です。

パケットを割り振ったり、Hostによって処理を変えるサーバー（リバースプロキシ、Nginxなど）が、SNIを解釈できればその後TLS暗号が使えるわけです。
初回接続時だけ、HostやTLSによらない暗号化を行います。

# 暗号化とDNS

具体的な暗号化についてです。

server_nameを暗号化し、ClientHelloを送信します。
それを受け取ったサーバーは、復号化したのち、server_nameを見て、ホスト振り分けを行うことになりますね。

では、TLS通信のハンドシェイクの暗号化につかう鍵は、どうやって手に入れるのでしょう。ここまで来ると卵が先か鶏が先か、の気分になってきます。

この方法ですが、DNSを使用します。DNSのレコードの中に、鍵交換に使うための公開鍵をサーバーが埋め込んでおきます。
クライントは、まずTLSハンドシェイクの中で、DNSクエリーで取得した鍵で暗号化を使えるわけですね。

DNSクエリーの中身を覗かれる心配、改ざんされる心配ですが、前者はDNS over HTTPSやDNS over TLS、後者はDNSSECによって解決できます。

いや、またTLS使うんならそこのESNIはどうなんだよ…と言いたくなりますが、まあ1.1.1.1などはvirtualhostを使っていないようなので、SNIをあえて使わないようにすれば大丈夫な様子です。（これ僕も思いました。）

# ESNI の実用例

今の所、ESNIはTLS 1.3の拡張提案でしかないため、実際にブラウザで利用することはできません。
ただ、Firefox Nightlyに追加している途中という噂もあります。 

ESNIを使うことで、先程の問題点などを解決することができ、より安全にインターネットが使えるようになるのはそう遠くないことだと思います。
もちろん、IPアドレスの逆引きなど、最後の穴はいくつか残っています。これからのESNIの動向に注目したいです。

（参考: https://blog.cloudflare.com/encrypted-sni/ ）
（また、使っているブラウザがDNSSECやTLS1.3に対応しているかどうかはここで確認できます。 https://www.cloudflare.com/ssl/encrypted-sni/ ）
IT企業が狙う新たな自動車ビジネス

【自動運転とカーシェアリング】
■特許分析から何がわかる
・研究開発活動にもとづく技術視点の情報のため、最先端の情報になる。
　（ただし、特許申請から更改まで１年半かかるので古い可能性も否めない）
■Ｔｅｓｌａかの戦略を特許から読み解く
前提
車は製品から部品から流通まで技術の結晶であり、知財観点とすると特許の塊になる。
→それに対しTeslaはかなり少ない特許数で販売にいたっている

特許申請の動き　
・2011年のModelS発売までに特許が増えるが、以降減る
・2015年のオートパイロット導入の際に少し増えるが、減少の一方
・2005～2011年にバッテリ、電圧制御に関する特許を積極的に出願
・オートパイロットは1件のみ（技術研究をしていない？）
・Teslaの特許の中にSolarCityと共同開発の特許もある
（SolarCityの特許）
・ModelSとオートパイロット導入以降も特許が増えている。（2015年から急増）

⇒Teslaのコア技術はバッテリと電圧制御
　オートパイロットは公知技術の利用が主であり、積極的な研究開発を行っていない
　開発投資は自動車から太陽電池へ

■IT企業が進める次世代自動車技術の動向
▼特許の動向
　・過去、年100件ほどの特許申請があったが、2017年は700件ほど申請があった。
　・ただし、自動車関連企業（Waymo、Uber）以外は1％ほどしか自動車関連の特許申請がない。
　・Googleの自動運転技術の研究が始まり、Waymo（Google）の出願が急増。
　　その流れに合わせてIT企業の車関連の特許申請が増える。（2016～2017に急増）
▼MicroSoft
　・ここ数年で特許申請している内容に大きな差異はない
▼Apple
　・2014年ころまでは車でApple製品を使うための特許が多い
　・2015年以降は自動運転向けの制御系技術の特許が増え始めている

■総括
自動運転の技術はかなり注目され成熟期に入ろうとしている。
ライドシェアの技術がまだまだ進められていない。これから伸びていく分野

【MaaS分野】
個々の技術は既にある。MaaS技術の新しさはなに？
⇒例：マルチモーダル交通体系を一括で検索、予約できる最適化サービス（Whim）
ALB（Application Load Balancer）を導入する

## 概要
ALB（Application Load Balancer）を導入し、サービスの冗長化を行う。
今回は、HTTPでの通信とし、SSL証明書の設定は行いません。

本番運用を想定したものではないので、ご注意ください。

## 環境
- Amazon Linux 2

## 前提条件
- VPCが作成されていること
- Webサーバインスタンス作成してあること
- インターネットゲートウェイがアタッチされたサブネットが作成されていること

## ALBの作成
### ロードバランサーの設定

`EC2` > `ロードバランシング` > `ロードバランサー`　を選択し、`ロードバランサーの作成`をクリックします。
<img width="1433" alt="スクリーンショット 2018-11-26 18.59.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/206741/af494ade-15d4-3538-f122-2f128dfc77bd.png">

`Application Load Balancer`を選択します。
<img width="1431" alt="スクリーンショット 2018-11-26 19.01.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/206741/70ac03fe-2859-2cfd-5737-29b70065db59.png">

任意の名前を入力。
`スキーム`には、`インターネット向け`を選択し、インターネットからの接続を許可します。
<img width="1421" alt="スクリーンショット 2018-11-27 15.34.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/206741/144d94ea-3148-ecb4-3f52-4987ca2b1e89.png">

`リスナー`には、`HTTP`を選択し、HTTPリクエストをロードバランサーで処理できるよう設定します。
<img width="1426" alt="スクリーンショット 2018-11-27 16.24.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/206741/604f0585-0f9d-3a52-1ca7-cd64a813ff09.png">


アベイラビリティゾーンの設定を行います。

作成済みのVPCを選択します。
ここで指定するサブネットは外部からのリクエストを想定しているので、インターネットゲートウェイがアタッチされている必要があります。
今回は、東京リージョンの`ap-northeast-1a`、`ap-northeast-1c`、`ap-northeast-1d`にそれぞれサブネットを作成してあるので、それを設定します。
![スクリーンショット 2018-11-26 19.12.57.png](https://qiita-image-store.s3.amazonaws.com/0/206741/0cecdb65-f19a-e5da-f375-927a9c93e564.png)


後で、識別がしやすいようにタグの設定を行います。

- キー : Name
- 値 : わかりやすい名前(今回は、dev-api-albを指定)
<img width="1425" alt="スクリーンショット 2018-11-26 19.17.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/206741/54fb72dd-e31c-38e1-5844-69841ff54ef1.png">


### セキュリティ設定の構成
今回は、リスナーに`HTTP`を設定しているため、特に設定は必要ありません。

### セキュリティグループの設定
セキュリティグループは事前に作成していないので、`新しいセキュリテイグループを作成する`を選択します。
80ポートであれば、全てのアクセスを受け付ける設定です。
<img width="1428" alt="スクリーンショット 2018-11-26 19.31.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/206741/45ec3924-8a9c-821e-3067-930cd0ff7cc1.png">

### ルーティングの設定
ターゲットグループは事前に作成していないので、`新しいターゲットグループ`を設定します。
ターゲットグループへのインスタンスの登録は次のステップで行います。
EC2インスタンスへHTTPアクセスする設定を行なっています。

<img width="1432" alt="スクリーンショット 2018-11-26 19.35.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/206741/5578e70a-483a-6be6-584b-7e0458b82981.png">

### ターゲットの登録

ロードバランサーの配下で起動するインスタンスを登録します。

確認画面で問題がなければ、`作成`をクリックしてALBの作成は完了です。

## 動作確認
作成済みのロードバランサーを選択すると、説明タブよりDNSを確認できます。
![スクリーンショット 2018-11-27 16.41.18.png](https://qiita-image-store.s3.amazonaws.com/0/206741/10a44e13-f7ef-2a84-6633-a81074624c90.png)

DNSへのアクセスを確認し、ALBが動作していることを確認します。
SOQL の数値リテラルに対する暗黙的な型変換

SOQL で数値リテラルを条件としてクエリする際には暗黙的な型変換に気をつけましょう。

##暗黙的な型変換
例えば、以下の様なクエリを実行すると `Unknown error parsing query` とエラーになります。

```sql
SELECT Id FROM Asset WHERE Price < 9999999999
```

SOQLは暗黙的に `9999999999`　を Integer 型に変換しようと試みます。
しかし、`9999999999` は Integer 型で表現できるサイズを超えているためエラーとなってしまいます。

## 回避方法
回避策は、下のように Double 型として記述する方法になります。

```SQL
SELECT Id FROM Asset WHERE Price < 9999999999.0
```
UiPath Community Edition ダウンロード＆インストール

**はじめに**
仕事でUiPathを触ることになったので
UiPath Studio Community Edition(無償版)を個人のPCにインストールして
動作検証をしてみることにした

**１．UiPathをダウンロード**
UiPathのサイトからCommunity Editionをダウンロード
https://www.uipath.com/ja/

「リリース」　→　「UiPath Community エディション」を選択
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/286799/dcb191a2-0fc6-01c3-95dc-d052738adef7.png)

「COMMUNITYエディションのダウンロード」を選択
![無題2.png](https://qiita-image-store.s3.amazonaws.com/0/286799/c1664df1-c2cf-7b8e-24de-4bac934a631e.png)

個人ユーザ様による利用　画面で「姓」「名」「Eメール」を入力
プライバシーポリシーを確認し、チェックをいれて「COMMUNITYエディションのダウンロード」を選択
![無題3.png](https://qiita-image-store.s3.amazonaws.com/0/286799/aebfe451-0be3-b1ea-336a-f939b133c9e5.png)


「こちらから」を押下するとダウンロードが開始します
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/286799/483ebcf5-73ad-ff79-d82e-2c818acb8884.png)

バージョン18.3.3.0がダウンロードできました。（2018/11/27現在）

因みに
先に登録したメールアドレス宛にUiPathからメールが1通飛んでおり、本文にもダウンロード用のリンクがある
そちらからダウンロードするとバージョン18.4.0が入手できます

**２．インストール**
ダウンロードしたUiPathStudioSetup.exeを実行
「Communityエディションのアクティベーション」を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/286799/0b7f0f47-7390-0204-8f15-48612042d7ea.png)

先に登録したメールアドレスを入力、「アクティベーション」を実行する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/286799/d2851130-9d18-01d8-b273-3affc130a052.png)

これで終了です。

尚、デスクトップにUiPath.Studio.exeのショートカットはできませんでした
必要であればC:\Users\%ユーザ名%\AppData\Local\UiPath\UiPath.Studio.exeのショートカットを配置します
画像ファイルの作成日時をExifの撮影日時で更新するワンライナー

# はじめに
iPhoneからMacに画像をjpeg形式で保存すると、ファイルの作成日時がこの保存操作日時となるため、Exifの写真撮影日で上書きする。

# 環境
- Mac OX
- bash

# 準備
homebrewでexiftoolをインストール。

`$ brew install exiftool`

CommandLineToolsをインストールしていない場合（setfileコマンド実行時に'xcrun: error: invalid active developer path'などが表示される）、こちらもインストール。

`$ xcode-select --install`

# ワンライナー
```bash
$ for file in `ls *.jpeg`; do date_str=`exiftool -DateTimeOriginal $file`; date_str=`date -j -f "%Y:%m:%d %H:%M:%S" "${date_str#*: }" +"%m/%d/%Y %H:%M:%S"`; setfile -m "$date_str" $file; echo -e "$file\t$date_str"; done
```

-lsコマンドのファイル拡張子は、適宜jpgなどに変更。
-日付のフォーマット変換（dateコマンド）は、使用環境により不要な可能性あり。

#　解説
- `exiftool -DateTimeOriginal $file`
    -  撮影日時を取得
-  `${data_str#*: }`
    -  左端から最初に': 'にヒットする部分までを削除
-  `date -j -f "%Y:%m:%d %H:%M:%S" "${date_str#*: }" +"%m/%d/%Y %H:%M:%S"`
    -  日付のフォーマットを変換
-  `setfile -m "$date_str" $file`
    -  ファイルの変更日を上書き（変更日が作成日より古い場合、作成日も変更日で上書きされる）
    -  作成日を変更したい場合は-dオプション
Treasure DataとHadoopについて

#Treasure Data
2011年 日本人が米国で創業
2018年 ソフトバンク傘下のARM社が買収(https://jp.techcrunch.com/2018/08/03/arm-treasure-data/)

どんなサービスを提供しているかというと、百聞は一見にしかずということでこちら。
<img width="1197" alt="treasureData.png" src="https://qiita-image-store.s3.amazonaws.com/0/318521/e5932e4b-7d62-25f3-49d9-cb8aaa655300.png">

要は、「様々なデータソースをよしなに使いやすく整理して、分析まで実施し、ユーザーへ連携」といったかんじかと思います。
ここでいう機会学習はどこまでできるのか個人的には気になる。
また、通常オンプレミスだと、データ量のピークに合わせて巨大なデータストレージを確保する必要がありました。
その為システム投資や運用費が必要になります。
一方Treasure Dataはクラウドを使用している為、必要な分だけ使用する為、そういった投資や運用コストが不要になります。

#Treasure DataとHadoop
##概要
Treasure DataはHadoopも一部に使いつつ、Hadoopでの問題点を解決してトータルで使いやすくしたサービス
https://qiita.com/Lewuathe/items/95961787a151ba4d1ae2

Hadoopは大量のデータを扱うにあたって、分散処理を可能にしデータ分析をより身近なものにした画期的発明でした。
しかし、それでもやはりHadoopにも問題点はありました。そこでHadoopの利便性を向上させより使いやすくしたのがTreasure Data Serviceです。

#Treasure Data特徴
(引用元 https://sios.jp/products/bigdata/treasuredata/hadoop-treasuredata-04.html)

|内容|Hadoop|Treasure Data|
|:-------------------:|:----------------------|:------------------|
| 処理速度|データを参照する場合には一旦全データを呼び出すため処理速度が遅くなってしまうという問題を抱えています。|「カラムナ×タイムインデックス」という独自技術を採用。通常の「Apache Hadoop」とは異なり必要なファイルのみを呼び出すため、高速でのデータ参照が可能です。|
|インターフェース|HDFSやMapReduceといった独自のインターフェースに慣れる必要があります。そしてHDFSやMapReduceの取り扱いに慣れるまでには、相応の時間を要することとなります。|HDFSではなくAmazon Simple Storage Service（Amazon S3）を利用してストレージを実装。また計算処理機能については、Amazon Elastic Compute Cloud (Amazon EC2)を活用しています。そして「Treasure Data Service」は、さまざまなインターフェースも装備。そのためデータベースへの接続、データマートとの連携、CSV形式やTSV形式でのエクスポートなどを容易に行うことが可能です。そのため通常の「Apache Hadoop」を導入した場合と比べて、ユーザーは短時間で必要な機能を利用できるようになります。|
|クエリー|-|多くのエンジニアに親しまれているSQLスタイルのクエリーインターフェースが提供されます。そしてSQLスタイルのクエリー文はシステム上でMapReduce形式に変換され、並列処理を実行。そのためユーザーは、たとえプログラミングスキルを有していなくとも「Apache Hadoop」を利用することができるのです。|
|データ・コレクター|-|データ・コレクターである「Treasure Agent」を搭載。この「Treasure Agent」のおかげで、ユーザーはデータベースの構造やデータの格納形式を設計することなくデータを投入することができます。具体的には「Treasure Agent」を利用して、ストリーミングでログ収集を行う場合には、ユーザーのアクションから分析を開始するまでに必要な時間は約5分程度であり、短時間で処理することが可能です。（※また、この処理方法が適さない場合においても、「Embulk」というバッチ処理専用のツールを利用することで、同様のログ収集を行うことが可能となります。）|
|オンプレ/クラウド|「Apache Hadoop」をオンプレミスで導入する場合、サーバ環境の構築やシステム設定などにかなりの時間がかかります。したがって「Apache Hadoop」を導入して、実際にビッグデータの分析などを開始できるまでには通常半年から1年程度はかかってしまうと言われているのです。|Treasure Data Service」はクラウド型の統合サービス。そのため「Apache Hadoop」と同等の分散処理環境を、クラウド環境によって利用することが可能です。したがって、わずか数日程度でビッグデータ分析を開始することができます。|
|スケールアウト|オンプレミス型サービスのひとつとして「Apache Hadoop」を利用する場合にはシステム停止が懸念されるため、安易にスケールアウトを行うことはできません。|クラウド環境で実現される「Treasure Data Service」であれば、無停止でスケールアウトを実現することができます。そのためシステムを稼働させたまま、データ量に応じた適切な環境を常に維持することができます。|

#追記
>ここでいう機会学習はどこまでできるのか個人的には気になる。

上記について少し調べたので追記。

##[Hivemall]
https://www.treasuredata.co.jp/press_release_jp/20160218_hivemall_machine_learning/
https://qiita.com/onunu/items/69beeed32a8e852674f0
https://dev.classmethod.jp/hadoop/hadoop-advent-calendar-10-introduction-hivemall/

**Open source**
https://www.treasuredata.co.jp/opensource/

**ML**
https://support.treasuredata.com/hc/en-us/categories/360001001934-Machine-Learning

**Introduction TD ML**
https://support.treasuredata.com/hc/en-us/articles/360011818033-Introduction-to-Treasure-Machine-Learning
Djangoのサーバ起動


# とりあえず起動する

```
$ python manage.py runserver 8000
```

# 外部アクセスできる状態でサーバ起動する

アクセス制限がかかっているので、settings.pyの`ALLOWED_HOSTS`を修正する必要がある。
フルオープンにするときは'*'を入れればいい。

```settings.py
ALLOWED_HOSTS = ["*"]
```

サーバを起動するときは0.0.0.0で起動する

```
$ python manage.py runserver 0.0.0.0:8000
```
Bootstrap Dual Listboxを使おうとして詰まりかける

Bootstrap Dual Listboxを読もうとしてエラーになる。

```js
window.jQuery = window.$ = require('jquery');
require('bootstrap');
require('bootstrap4-duallistbox/src/jquery.bootstrap-duallistbox');
```

古いバージョンだと大丈夫

```js
window.jQuery = window.$ = require('jquery');
require('bootstrap');
require('bootstrap-duallistbox/src/jquery.bootstrap-duallistbox');
```

こうしたら動いた

```js
window.jQuery = window.$ = require('jquery');
require('bootstrap');
require('bootstrap4-duallistbox/src/jquery.bootstrap-duallistbox')($);
```

htmlはこんな

```html
<form id="demoform" action="#" method="post">
<select multiple="multiple" size="10" name="duallistbox_demo1[]" title="duallistbox_demo1[]">
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
<option value="option3" selected="selected">Option 3</option>
<option value="option4">Option 4</option>
<option value="option5">Option 5</option>
<option value="option6" selected="selected">Option 6</option>
<option value="option7">Option 7</option>
<option value="option8">Option 8</option>
<option value="option9">Option 9</option>
<option value="option0">Option 10</option>
</select>
<br>
<button type="submit" class="btn btn-default btn-block">Submit data</button>
</form>
<script>
var demo1 = $('select[name="duallistbox_demo1[]"]').bootstrapDualListbox();
$("#demoform").submit(function() {
alert($('[name="duallistbox_demo1[]"]').val());
return false;
});
</script>
```

わからない事がまだまだある。
AWSマネージドサービスのみでリダイレクトさせる

http通信をhttpsにリダイレクトしたり、またゾーンアペックスからサブドメインへのリダイレクト (google.com -> www.google.com のような)は一般だとNGINXやApacheで設定…となりますが、AWSのサービスを駆使すれば必要ありません。
それぞれ説明します。

## http通信をhttpsにリダイレクト

ALBを使います。
80番のターゲットグループでリダイレクトの設定を行えばOK.

<img width="1210" alt="スクリーンショット 2018-11-27 16.00.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/27674/fafd1cfb-25e8-7296-ce31-d042df0cc92c.png">

## ゾーンアペックスからサブドメインへのリダイレクト

Route53とS3を使います。もしhttpsもリダイレクトしたい場合はCloudFrontも使います。

### S3

ゾーンアペックス名でバケットを作った後、Static website hostingでリダイレクトの設定を行います。
※バケットポリシー等の設定は不要です。

### CloudFront (httpsも使う場合）

S3をオリジンとしたCloudFrontを用意します。わざわざCloudFrontを利用する理由は、S3だとカスタムのhttps証明書が入らないからです。
なのでCloudFrontではhttps証明書も設定します。
**※オリジンの設定にはリストで出てくるS3ではなく、Static website hostingで出てくるエンドポイントのドメイン部分をコピペして設定します。**

### Route53

ゾーンアペックスのAレコードのエイリアスとしてCloudFront　(CloudFrontを使用しない場合はS3)　を指定します。
料理を記述するプログラミング言語を作る

# とつぜんですが、料理できるエンジニアってかっこよくないですか。

でもエンジニアって料理下手ですよね(偏見)。

これって、掛け算用の処理ユニットを持っているため掛け算は得意だけど、でも割り算は苦手なIC(本当にそんなものは無いとは思うが)と同じだと思いませんか？

何が言いたいかと言うと、エンジニアはコードを書くユニットや設計をするユニット、レビューをするユニットを持っていても、料理をするためのユニットを持っていないと考えられます。
なので汎用処理用のユニットで料理をする必要があります。反対に、料理が得意な人は料理をするためのユニットが脳の中にあるんですよね、たぶん。
じゃあこう考えるわけです。料理を、ある程度エンジニアが普段慣れている処理系に変換しといてあげれば、エンジニアは料理をそこそこの性能で実行できるのではないか、と。

つまりこれは、**料理のレシピを厳格なプログラミング言語として定義すれば、みんな料理ができるようになるのでは？**というネタ系プロジェクトです。

# 料理を表現するために必要なことを考えよう

## 定義
まず、料理とは何かを最初に決めておきましょう。ぼくの場合は以下のようになりました。

> 複数の食材に対して、「なんらかの調理」と「混ぜる・載せる。盛り付けるなど組み合わせる」を適用させて最終的に目標の料理をつくること

今回は、この情報を文字だけで表現できることを目標とします。

## 必要な要素

そして、今度は料理をする上で必要な情報を以下のように抜き出してみました。
また、名前が複数あるものは、今後一番右(料理・おかずなら料理)で呼び方を統一しようと思います。

|要素|簡単な定義|
|:-:|:-:|
|料理・おかず|最終的に作りたいオブジェクト群|
|食材・調味料|おかずを作るために必要なオブジェクト群|
|調理器具|レシピの中で使用する道具群|
|汎用資源|ガス、電気など調理器具が必要なエネルギー|
|レシピ|おかずを作る一連の手順|

これさえあれば、料理を表現できそうですね。

それでは、要素ごとにどんな情報を保持しているか、考えてみましょう。

## 料理

最終的に出来上がる料理ですね。
料理自体は何かに使用するものでは無く、むしろその料理に対して他の要素がぶら下がる形になるでしょう。言うなれば構造体やクラスの名前みたいなものです。

ココらへんで飽きてきた‥
【AWS re:Invent】Monday Night Liveで発表されたAmazon SageMaker Neoについて

11/27 6:24 AWSのYoutubeアカウントからプレゼン動画がリリースされたのでリンクを張りました．

----

[docomo Developer support](https://dev.smt.docomo.ne.jp/)の赤塚です．

[AWS re:Invent 2018](https://reinvent.awsevents.com/)の**Monday Night Live**で下記のリリースがアナウンスされました．[AWS News Blog](https://aws.amazon.com/jp/blogs/aws/aws-previews-and-pre-announcements-at-reinvent-2018-monday-night-live/)でも早速記載されていますが，現時点では本投稿で記載のAmazon SageMaker Neoの記載はありません．

* AWS Global Accelerator
* AWS Transit Gateway
* Amazon EC2 A1 Instances
* 100 gigabit networking
* Amazon EC2 C5n Instances
* Amazon EC2 P3dn Instances
* Elastic Fabric Adaptor
* Amazon SageMaker Neo
* Firecracker

![001.png](https://qiita-image-store.s3.amazonaws.com/0/262328/342b15e1-f28a-4e89-ef4a-d0e5b7402c34.png)

発表された**Amazon SageMaker Neo**について記載いたします．

# Amazon SageMaker Neo

**Train models once, and run/deploy them anywhere**

Youtube動画 
[AWS re:Invent 2018 - Announcing Amazon SageMaker Neo](https://www.youtube.com/watch?v=RjhrugELYW8)  *←追加(11/27 6:24)*

Amazon SageMaker Neoはディープラーニングのモデルコンパイラです．一回の学習で複数のハードウェアに最適化されたモデルを作成することができます．ハードウェアごとに最適化されることにより，パフォーマンスが従来の最大2倍まで改善されます．パフォーマンスが指しているのが認識時間，学習時間，認識精度のどれを指しているのかがわからないです．

今週リリースされるようです

![002.png](https://qiita-image-store.s3.amazonaws.com/0/262328/c18032d2-d8e8-7a96-56a1-5bda5bc15a34.png)

以下に簡易的な処理フローが記載されています．利用可能なフレームワークとしては①AWSが公式サポートしている**mxnet**，②デファクトの**Tensorflow**，③Deep Learningの利用者から最近人気が高い**PyTorch**がサポートされる予定．

![005.png](https://qiita-image-store.s3.amazonaws.com/0/262328/7a4c0be3-3c42-3fcc-c9a8-865c68f7afed.png)

ハードウェアパートナー

![004.png](https://qiita-image-store.s3.amazonaws.com/0/262328/b09aa86f-1c02-3e7b-826b-db9694fe495b.png)

Amazon SageMaker Neoはオープンソース化されるようです．

![003.png](https://qiita-image-store.s3.amazonaws.com/0/262328/c21ceb2e-a62c-dbe7-53cc-5680f42695ab.png)

ハードウェアの最適化をAWSが実施してくれることで，データサイエンティストはハードウェアを意識せずに学習アルゴリズムの開発に専念できること，様々なデバイスに対する機械学習の適応が容易になることにより，今後Amazon SageMakerを利用したサービスの範囲が拡充するように思いました．

どうでもいいことですが，日本語だとNeoはネオと発音しますが，英語だとNeoはニオと発音します．

---

参考までに，[[AWS re:Invent 2018] Registration と SWAG と 会場の雰囲気](https://qiita.com/akatsukaha/items/4553eb619ccc80c7ecd8)を見て頂ければre:Inventの会場の雰囲気がわかると思います．
Ruby 2.6 で Hash#to_h が便利になった

# はじめに

2018/11/06 (火) に Ruby 2.6.0-preview3 がリリースされました。Ruby 2.6.0 で [Hash#to_h](https://docs.ruby-lang.org/ja/latest/method/Hash/i/to_h.html) をブロック付きで呼んだ場合の挙動が新しく追加されていたのでご紹介します。

# Hash#to_h について

例として Hash のそれぞれのキーと値に同じ処理を施したい場合、例えば

```rb
{ a: 1, b: 2, c: 3 }
```

を

```rb
{ A: 1, B: 4, C: 9 }
```

に更新したい場合を想定します。

従来であれば Enumerable#map と Array#to_h を使って

```rb
# Ruby 2.5.3 or Ruby 2.6.0-preview3
{ a: 1, b: 2, c: 3 }.map { |k, v| [k.upcase, v ** 2] }.to_h
#=> {:A=>1, :B=>4, :C=>9}
```

と書けました。Enumerable#map の返り値が Hash オブジェクトではなく Array オブジェクトなので、再度 Hash オブジェクトに変換する必要がありました。

ところが、Ruby 2.6.0 は同じことを Hash#to_h だけで行えるようになりました。

```rb
# Ruby 2.6.0-preview3
{ a: 1, b: 2, c: 3 }.to_h { |k, v| [k.upcase, v ** 2] }
#=> {:A=>1, :B=>4, :C=>9}
```

なお、Ruby 2.5.3 では Hash#to_h をブロック付きで呼んだ場合の挙動が特に定義されていないので、ただレシーバを返すだけです。Hash#to_h はもともとダックタイピングのためだけに用意されたメソッドなのでしょうね。

```rb
# Ruby 2.5.3
{ a: 1, b: 2, c: 3 }.to_h { |k, v| [k.upcase, v ** 2] }
#=> {:a=>1, :b=>2, :c=>3}
```

地味ですが、またひとつ便利になりました :v_tone2:
IE,Edgeで勝手にスクロールバーがついてしまった時の対処

### 現象
IE11、Edgeで意図しないところにスクロールバーがついてしまった

```HTML
<li class="list">
  <a title="title" class="scroll" href="#introduction01">
    <div class="introduction_tab_content">
      <p class="introduction_title">hoge</p>
      <p class="introduction_name">fugafuga</p>
    </div>
  </a>
</li>
```
このHTMLを6つ作ってカード形式に並べていたのだが、テストをしている方から

「IE11とEdgeでスクロールバーが出てます」

とのこと。

要素にoverflow:scroll;がついているはずもなく（だとしたらChromeやFirefoxでも表示されるはず）なんだこれは。。。と思っていたところ

```HTML
<a title="title" class="scroll" href="#introduction01">
```

この一行が原因でした。

どうやらIE11では

```
class="scroll"
```
を勝手にスクロールバーを出すと解釈するようです。

無駄な解釈をしないでください、、、笑

無事にクラス名を変更して、動作するようになりました。
Wordpressのhttps化をDB直接変更で強引に行う

Wordpressをhttps化したものの、一部ページ内の画像がhttpのままのため、ブラウザのアドレスバーに警告が出ていました。

1ページずつ修正するのは論外だし、プラグインを使うのも後々トラブルになりそうだったので、DBを直接弄って解決しました。

```sql

UPDATE wp_options SET option_value = replace(option_value, 'http://ドメイン', 'https://ドメイン') WHERE option_name = 'home' OR option_name = 'siteurl';
UPDATE wp_posts SET post_content = replace(post_content, 'http://ドメイン', 'https://ドメイン');
UPDATE wp_postmeta SET meta_value = replace(meta_value,'http://ドメイン','https://ドメイン');
UPDATE wp_usermeta SET meta_value = replace(meta_value, 'http://ドメイン','https://ドメイン');
UPDATE wp_links SET link_url = replace(link_url, 'http://ドメイン','https://ドメイン');
UPDATE wp_comments SET comment_content = replace(comment_content , 'http://ドメイン','https://ドメイン');
UPDATE wp_posts SET post_content = replace(post_content, 'http://ドメイン', 'https://ドメイン');
UPDATE wp_links SET link_image = replace(link_image, 'http://ドメイン','https://ドメイン');
UPDATE wp_posts SET guid = replace(guid, 'http://ドメイン','https://ドメイン');
```
pandasのoption設定変更方法

# 表示行数の設定
```python3:python3
import pandas as pd
import numpy as np
df=pd.DataFrame(np.random.rand(20,20)) #20行x20列のDataFrameを作成
pd.options.display.max_rows=5 #最大表示行数=5に設定
pd.options.display.max_columns=5 #最大表示列数=5に設定
df
```
```text:出力結果
          0         1     ...           18        19
0   0.680790  0.653840    ...     0.136195  0.548428
1   0.544310  0.385327    ...     0.292293  0.043041
..       ...       ...    ...          ...       ...
18  0.122189  0.928378    ...     0.905592  0.159815
19  0.052095  0.079974    ...     0.559600  0.287442
```

# 小数点以下の表示桁数の制御
```python3:python3
pd.options.display.float_format='{:.2f}'.format #小数点以下2桁まで表示する
df
```
```text:出力結果
     0    1  ...    18   19
0  0.68 0.65 ...  0.14 0.55
1  0.54 0.39 ...  0.29 0.04
..  ...  ... ...   ...  ...
18 0.12 0.93 ...  0.91 0.16
19 0.05 0.08 ...  0.56 0.29
```
```python3:python3
pd.options.display.float_format='{:.2%}'.format #%表示にして、小数点以下2桁まで表示する
df
```
```
       0      1   ...       18     19
0  68.08% 65.38%  ...   13.62% 54.84%
1  54.43% 38.53%  ...   29.23%  4.30%
..    ...    ...  ...      ...    ...
18 12.22% 92.84%  ...   90.56% 15.98%
19  5.21%  8.00%  ...   55.96% 28.74%
```
AWS Transfer for SFTP を試そうとして料金を見て断念

S3へのオブジェクトの操作はコンソールからだと手間がかかるので、頻繁にバケット間を移動したり、ファイルの移動・コピー・ダウンロードなどが必要な場合は[CloudBerry Explorer](https://www.cloudberrylab.com/explorer/amazon-s3.aspx)を使ってきました。

で、、、本日「AWS Transfer for SFTP発表 [（公式サイト）](https://ap-northeast-1.console.aws.amazon.com/transfer/home?region=ap-northeast-1#/)」の報をみて、「おーーやっと来たー。どれどれ」と思ったのですが、料金を見て愕然。高額すぎて使えません。。。

例えば常に利用できる状態にしておくと、1ヶ月216ドル？！（0.3ドル/時間 x 720時間）
さらにS3へのデータアップロードは無料ですが、本機能を使ってWinSCPなどからアップロードすると課金されてしまいます。（0.04ドル/GB)

| 課金項目	 | 料金 |
|:--|:-:|
| Time your SFTP endpoint is provisioned   | $0.30/hour  |
| SFTP data uploads and downloads  | $0.04/GB  |

AWS CLIを使って利用するときだけエンドポイントを作成するという使い方なのかなと思いましたが、エンドポイント作成して、ユーザを作成してまではいいですが、SSH-KEYをダウンロードしてSFTPクライアント（例えばWinSCP）に割り当てるということを考えると手間が多すぎる感じ。

そもそも冒頭に記載したようなユースケース（=S3に格納済のオブジェクトの各種操作）を支援するものではないのですね。

# 補足

念の為ですが、本機能が使えないと主張しているわけではありません。当方が想像というか期待した機能と違っただけです。
Nuxt.jsをHerokuへデプロイする手順

## 事前準備
- Nuxt.jsインストール
- git導入

## アカウント作成
[Heroku Sign up](https://signup.heroku.com/login)

## Heroku Toolbeltの導入
コマンドにて

```
brew install heroku/brew/heroku
```

## Herokuへログイン
```
heroku login
```

## heroku上にアプリを作成
```
heroku create
```

## herokuへデプロイ
```
git push heroku master
```

## .envがある場合は、herokuへ反映
```
heroku plugins:install heroku-config
heroku config:push
```

## Nuxt.jsのデプロイに必要な設定
```
heroku config:set NPM_CONFIG_PRODUCTION=false
heroku config:set HOST=0.0.0.0
heroku config:set NODE_ENV=production
```

```package.json
"scripts": {
    "dev": "nuxt",
    ...
    "heroku-postbuild": "npm run build"
},
```
heroku に npm run build を実行してもらうために　`"heroku-postbuild": "npm run build"` を追記


## 作成したアプリを開く
```
heroku open
```

## ログ確認
```
heroku logs --tail
```

## アプリの更新
```
git push heroku master
```
PowerApps コミュニティ プランでCDS（Common Data Service）を試そうとしたら「予期せぬエラー」が発生する件

# 概要
PowerAppsでデータ統合を試そうとした際に予期せぬエラーに困ったので解決してみました。(2018/11/27時点)

# 現象
新規にデータ統合プロジェクトを作り接続先を選択していくと予期せぬエラーが発生するユーザーと発生しないユーザーが存在する。

# 調査結果

MSDocsに回答がありました。

>Common Data Service でのアプリケーションの作成と実行	はい**
>Common Data Service でのデータのモデル化	はい**

>**現在、Common Data Service でのデータベースの作成は個人用環境では利用できませんが、この機能はまもなく再開されます。 前にデータベースを作成している場合は、問題なく引き続き使用できます。

つまり、以前から作っている人は引き続き使用できるけど、今作ろうとしてる人は予期せぬエラーが発生するよ！ということでした。
[PowerApps コミュニティ プラン: 個人用の無料開発環境](https://docs.microsoft.com/ja-jp/powerapps/maker/dev-community-plan)


# 回避策
プラン2の試用版を使いましょう。

# まとめ
コミュニティプランはCommon Data Service、および Microsoft Flow の学習とスキル習得を目的としているので、できる限り早く使えるようにしてほしいですね。
webpackerでtest環境でもgzip圧縮する

## はじめに

webpackerはデフォルトではproductionのときしかgzip圧縮しません。

test時にもgzip圧縮したかったので設定しました。

## 環境

rails 5.0.6
webpacker 3.2.2

## コード

設定ファイルを修正すればOKです。
productionの設定を参考にしました。
 [webpacker/production.js at 227661b546701e107213aa9b6f83451bc89cf7d5 · rails/webpacker](https://github.com/rails/webpacker/blob/227661b546701e107213aa9b6f83451bc89cf7d5/package/environments/production.js)

```diff:config/webpack/test.js
const environment = require('./environment')
const CompressionPlugin = require('compression-webpack-plugin')

+ environment.plugins.append(
+   'Compression',
+   new CompressionPlugin({
+     asset: '[path].gz[query]',
+     algorithm: 'gzip',
+     test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/
+   })
+ )

module.exports = environment.toWebpackConfig()
```

## 動作確認
test環境でcompileして、output先にgzipファイルがあればOK。

```sh
RAILS_ENV=test bundle exec rake webpacker:compile
```

以上です :hugging: 

## 参考
- [rails/webpacker: Use Webpack to manage app-like JavaScript modules in Rails](https://github.com/rails/webpacker)
- [Webpacker 3.0 でのWebpackの設定カスタマイズ - upinetree's memo](http://upinetree.hatenablog.com/entry/2017/09/21/084448)
ActiveRecord::Relationのメソッドが何を返すのか

ツッコミ大歓迎です

# 記事のターゲット

Railsを触り始めたばかりの人（僕）
ActiveRecordをなんとなくで触ってた人（僕）
ActiveRecordのメソッドが何を返すのか知らなくて知りたい人（僕）

# ORMの勘所

ActiveRecordは言わずと知れたORMです
ORMは使い方を知らないと
「不要なクエリを発行したり（無駄なクエリ発行）」「N+1問題が発生したり（無駄なクエリ発行）」「全件取ってきてしまったり（無駄なクエリ発行）」
とりあえず無駄だらけになってしまいます

なぜ無駄なクエリが発行されているか深掘りするために必要な観点は
**いつクエリ発行されるか**だと思います
それは`ActiveRecord::Relation`が`配列やオブジェクト`に変わるとき！
と言い換えることができますね

* ActiveRecord::Relationを返す = クエリは発行されていない
* 配列やオブジェクトを返す = クエリが発行されている

# 本題

まずはActiveRecordのメソッド群が何を返すか？を調べます
[Railsガイド](https://railsguides.jp/active_record_querying.html)を眺めると以下のように記載してありますね
> 検索メソッドはwhereやgroupと行ったコレクションを返したり、ActiveRecord::Relationのインスタンスを返します。また、findやfirstなどの１つのエンティティを検索するメソッドの場合、そのモデルのインスタンスを返します。

なるほど。わからん

…自力で潜ってみましょう

## ActiveRecord::Relationを返すメソッド

* all
* scope (実装でnilを返すとallと同様になる)
* select (使い方次第)
* group
* order
* reorder
* unscope
* joins
* where
* rewhere
* having
* limit
* offset
* lock
* none
* readonly
* create_with
* from
* distinct
* extending
* reverse_order
* includes
* eager_load
* preload
* references
* uniq
* merge
* except
* only
 
## 配列やオブジェクトを返すメソッド（多すぎるので一部割愛）

* select (使い方次第)
* find
* find_by
* take
* first
* last
* second
* third
* fourth
* fifth
* forty_two
* exists?
* ids
* pluck
* sum
* maximum
* minimum
* average
* count
* find_each
* find_in_batches
* to_a etc...
* 各種delegateされているArrayメソッド

# まとめ

ActiveRecord::Relationを返すメソッドは`SQL元来使えるもの`に近しい名前だった
配列やオブジェクトを返すメソッドは「見つける」とか「取る」みたいなアクションが多かったり集計関連だったりした
また、配列のメソッドを呼び出すとクエリが発行されるのはまさに**結果が必要になったタイミング**なのだろう

> 検索メソッドはwhereやgroupと行ったコレクションを返したり、ActiveRecord::Relationのインスタンスを返します。また、findやfirstなどの１つのエンティティを検索するメソッドの場合、そのモデルのインスタンスを返します。

要約するとRailsガイドの言い方になりました

# 参考

[ActiveRecord::Relationとは一体なんなのか](https://doruby.jp/users/whale/entries/ActiveRecord--Relation%E3%81%A8%E3%81%AF%E4%B8%80%E4%BD%93%E3%81%AA%E3%82%93%E3%81%AA%E3%81%AE%E3%81%8B)
[Railsガイド Active Record クエリインターフェイス](https://railsguides.jp/active_record_querying.html)
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb
kaminariの日本語対応

ページネーション用のgem、[kaminari](https://github.com/kaminari/kaminari) の日本語化。
kaminari用のファイルを新たに作ると管理しやすいかと。

```yml:config/locales/kaminari_ja.yml
ja:
  views:
    pagination:
      first: "&laquo; 最初"
      last: "最後 &raquo;"
      previous: "&lsaquo; 前"
      next: "次 &rsaquo;"
      truncate: "..."
  helpers:
    page_entries_info:
      one_page:
        display_entries:
          zero: ""
          one: "<strong>1-1</strong>/1件中"
          other: "<strong>1-%{count}</strong>/%{count}件中"
      more_pages:
        display_entries: "<strong>%{first}-%{last}</strong>/%{total}件中"
```

参考
- [kaminariのpage\_entries\_info はデフォルトだと英語環境でしか使えないので対応 \- Qiita](https://qiita.com/m-shin/items/7f31fc81fdd2ebc0fe8c)
- [【Ruby on Rails】gem\(Kaminari\)でページネーション機能を追加してBootstrapを適用する。 \- Qiita](https://qiita.com/residenti/items/1ae1e5ceb59c0729c0b9)
VPS上のubuntu 18.04 LTSにVNC接続するまで

##目標
Microsoft AzureやGoogle Cloud Platform、AWSなどのVPS上にあるssh接続しかできない状態のubuntu 18.04 LTSに対して、VNCで接続することでGUIでの操作を可能にする
![Kobito.BjLehG.png](https://qiita-image-store.s3.amazonaws.com/0/190719/8bc0ff5c-1aed-c294-8369-f8f0044945c0.png "Kobito.BjLehG.png")
(完成イメージ)

##VPSへの初回アクセスから初期設定まで
$に続く文字列は入力内容、その他は出力内容
[]内は任意の値を入力([]は入力不要))

初回アクセス

```初回アクセス
$ ssh [ユーザー名]@[IPアドレス]

Are you sure you want to continue connecting (yes/no)? 

$ yes

ユーザー名@IPアドレス's password:[初期パスワード]
```
ログイン完了

```ログイン完了
You are required to change your password immediately (root enforced)
Welcome to Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-1031-azure x86_64)
 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
```
初期パスワードの変更

```初期パスワードの変更
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for ユーザー名.
(current) UNIX password: [現在のパスワード]
Enter new UNIX password: [新しいパスワード]
Retype new UNIX password: [新しいパスワード]
passwd: password updated successfully
Connection to IPアドレス closed.
```
再度アクセス

```再度アクセス
$ ssh [ユーザー名]@[IPアドレス]
ユーザー名@IPアドレス's password:[新しいパスワード]
```
パッケージを最新に

```パッケージを最新に
$ sudo apt-get update
$ sudo apt-get upgrade -y
```

##X Window System(デスクトップ環境)の導入
インストール

```インストール
$ sudo apt-get install ubuntu-desktop -y
```
処理には10分近くかかるので待機

## ディスプレイマネージャー(gnome)の導入
インストール

```インストール
$ sudo apt-get install -y gnome-core gnome-panel gnome-settings-daemon metacity nautilus gnome-terminal
```
##VNCサーバ(vnc4server)の導入
インストール

```インストール
$ sudo apt-get -y install vnc4server
```
VNCパスワードの登録

```VNCパスワードの登録
$vncpasswd
Password:[パスワード]
Verify:[パスワード]
```
初期ファイルの生成

```初期ファイルの生成
$ vncserver :1
$ vncserver -kill :1
```
xstartupの設定

```xstartupの設定
$ vi ~/.vnc/xstartup
```
xstartupの初期状態

```xstartupの初期状態
#!/bin/sh
  
xrdb $HOME/.Xresources
xsetroot -solid grey
#x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
#x-window-manager &
# Fix to make GNOME work
export XKL_XMODMAP_DISABLE=1
/etc/X11/Xsession
```
xstartupの下部に追記

```xstartupの下部に追記
exec gnome-session &
gnome-panel &
gnome-settings-daemon &
metacity &
nautilus -n &
gnome-terminal &
```
再起動

```再起動
$ sudo reboot
```

##VNCサーバの起動
ssh接続でポートフォワーディング

```ssh接続でポートフォワーディング
$ ssh -L 1234:localhost:5901 [IPアドレス] -l [ユーザー名]
ユーザー名@IPアドレス's password:[パスワード]
```
vncserverの起動

```vncserverの起動
$ vncserver
```
##vncserverへの接続(Mac編)
前編でのポートフォワーディングが有効な状態でファインダーを開き、`⌘+K`
`vnc://localhost:1234`を入力、接続ボタンを押す
![Kobito.2txYVg.png](https://qiita-image-store.s3.amazonaws.com/0/190719/2ddf3f4f-d55b-8320-65aa-848969a3c564.png "Kobito.2txYVg.png")
パスワードが要求されるので、VNCパスワードを入力して接続する
![Kobito.vxCrQm.png](https://qiita-image-store.s3.amazonaws.com/0/190719/e9fcf8f4-d771-e08d-4e35-d005521aa7f2.png "Kobito.vxCrQm.png")

接続が完了し、ubuntu18.04 LTSのデスクトップが表示される
![Kobito.TElxzk.png](https://qiita-image-store.s3.amazonaws.com/0/190719/b48f9389-1ca2-acd1-1868-3ccd121d856e.png "Kobito.TElxzk.png")
Intel Realsense D435 とNuitrackを使ってみたので インストール方法まとめてみました。

環境：
Windows10 64bit
Intel Realsense D435
Nuitrack SDK 1.3.6
intel Realsense SDK-2.16.3.312


##1.Realsense D435のファームウェアアップデートとSDKのインストール
(2018/11/20)

####ファームウェアのアップデート
この二つをダウンロード
・アップデートツール
Windows* Device Firmware Update Tool for Intel® RealSense™ D400 Product Family
https://downloadcenter.intel.com/download/27514/Windows-Device-Firmware-Update-Tool-for-Intel-RealSense-D400-Product-Family

・最新ファームウェア bin
Latest Firmware for Intel® RealSense™ D400 Product Family
https://downloadcenter.intel.com/download/28237/Latest-Firmware-for-Intel-RealSense-D400-Product-Family

更新方法
上記のダウンロードリンクと同じですけど、インストール方法が記述されています。
https://downloadcenter.intel.com/download/27514/Windows-Device-Firmware-Update-Tool-for-Intel-RealSense-D400-Product-Family

簡単にインストールを説明すると
・ダウンロードしてきたアップデートツール(DFU Tool)  intel-realsense-dfu.exeを管理者で実行します。
・メニューが表示されて2番で更新可能なカメラが一覧で表示されます。ここでD435を確認
・メインメニューに戻り1番を選択 ファームウェアbinのパスを入力して実行します。
・3分ほどかかります。終了後メニューの4番でバージョンを確認して終了します。


![sample1.jpg](https://qiita-image-store.s3.amazonaws.com/0/11402/ee76dadf-7b03-fd26-7a2d-2015a9f2b542.jpeg)


####ドライバーは自動にインストールされてるはずだったのですが、なぜかうまくカメラが動かなかったりしていたので下記のドライバーインストールで解決しました。
Intel® RealSense™ D400 Series Universal Windows Platform (UWP) Driver for Windows® 10
https://downloadcenter.intel.com/download/27799/Intel-RealSense-D400-Series-Universal-Windows-Platform-UWP-Driver-for-Windows-10

インストール方法
解凍して"RS400Camera.inf"右クリックしてインストール


####intel Realsense SDK2.0のインストール
https://github.com/IntelRealSense/librealsense/releases

Intel.RealSense.SDK-2.16.3.312.exeをインストール
ここのリンクにUnityのパッケージも公開されているので
https://github.com/IntelRealSense/librealsense/releases/download/v2.16.5/Intel.RealSense.unitypackage

UnityにImportして動きを確認


##Nuitrackのインストール

Nuitrackをダウンロード
nuitrack-win32.zip (for Windows 32-bit) 
http://download.3divi.com/Nuitrack/platforms/nuitrack-win64.zip

nuitrack-win64.zip (for Windows 64-bit) 
http://download.3divi.com/Nuitrack/platforms/nuitrack-win64.zip

公式 
http://download.3divi.com/Nuitrack/doc/Installation_page.html

インストール方法
1． OpenNI 1.5をインストール　<install-folder>\OpenNI-Win64-1.5.7-Dev.msi for 64-bit.
2．環境変数を設定
・"NUITRACK_HOME"変数名  パス"<install-folder>\nuitrack"
・PATHに "<install-folder>\nuitrack\bin"を追加

オプション
OpenNI-1.5 Primesense/ORBBEC driver をインストール
<install-folder>\Primesense-Sensor-5.1.6.6-Win-x64.msi for 64-bit).
[Optional] OpenNI 1.5 API使用する場合は
Nuitrack dynamic mudleを設定

"C:\Program Files\OpenNI\Bin64\niReg64.exe" -r <install-folder>\nuitrack\bin\libnuitrack_ni.dll <install-folder>\nuitrack\data


###Nuitrackのアクティベーション
アクティベーションしていない場合はトライアルになります。トライアルバージョンは3分しか試せません。

ラインセンスを入力
1.<install-folder>\nuitrack\activation_toolを実行 Realsesneが起動数秒後にラインセンスが入力できるinput fieldが出ます。
![sample2.jpg](https://qiita-image-store.s3.amazonaws.com/0/11402/eb6283a1-6644-2449-5639-6a92d62f4ef6.jpeg)


Activationはこのビデオ見るとわかりやすい
https://www.youtube.com/watch?time_continue=2&v=Rk_1eCZz94M


あとは公式からSDKをダウンロードして
Unityの場合は
Nuitrack SDK: Unity 3D → NuitrackSDK.unitypackage
公式
http://download.3divi.com/Nuitrack/doc/UnityBasic_page.html
田舎のエンジニア事情 2018

#前置き
東京で7～8年、Webアプリケーションの開発を行ってきました。
いろんな会社に委託に行ってたこともあり、結構色んな環境に触れてきたつもりです。
気が付けば社内のグループウェアや生産管理システムをスクラッチ開発できるようにもなり、ある程度スキルはついてきたかなーとか思いながら転職活動をしていました。

もう東京も満足したし、地元企業のSEとして働いてみよう！と思い立ち、社内にシステム開発部を持つ地元の企業に転職しました。
一年ほど経ちましたので、いろいろと記事にしてみたいと思います。

#転職先のシステム開発環境
転職先の会社では、社内で開発した会計システムやグループウェアを使っていました。
不具合対応をしてほしいとのことでしたので、さっそくソースを見てみたところ、その内容に結構衝撃を受けました。

1. HTMLにて「div」タグではなく、「frame」タグを使っている。もちろんBootstrapは使っていない。
2. MavenもGradleも使わずに、ライブラリはjarファイルをプロジェクトに突っ込んでいる。ビルドはEclipse上で行う。
3. JQuery等のライブラリを使っていない。値はdocument.getelementbyidで取得。
4. IEのみ対応。社内ではIEのアップデートを禁止している。IEの古いバージョンしか「frame」タグが動かないとのこと。
5. IISにwarファイルをデプロイして運用している。
6. java6を使っている。

こんなところでしょうか。
なかなかレガシーな環境で、いろいろと懐かしさを感じながら、この一年間で多少はモダンな環境に置き換えました。
（5に関しては特にレガシーではない？）

###行ったことは下記
- フレームワークを「struts」から「spring boot」に変更
- java6からjava8に変更
- Node.js・npmの導入
- Gradleの導入
- IDEをEclipseからintellijに変更
- Bootstrapの導入
- Gitにてソースを管理するよう変更
- サーバーにubuntuを入れて、dockerにてwebアプリケーションを運用するよう変更

まだまだ古いシステムは残っていますが、新しく導入したシステムに関してはある程度、レガシーから脱したかなというところです。
ある程度落ち着いてきたところで、なぜ、このようなレガシーな環境になってしまっていたかを考えてみました。

#都会のエンジニア事情
まずは、都会でのエンジニア事情を書いてみようと思います。
私が東京で開発していた際は、とにかく周りの従業員が「モダンな開発」に心が奪われていました。
自分がクライアントサイドの開発に困っていると、先輩方が「お前まだこんな古いライブラリ使ってるのかよ。
今はこんな便利なライブラリあるんだぜー」と流行りのライブラリを**自慢げ**に教えてくれたり、「Qiitaにかっこいい記事載せたから読んでおいてよー。いいね押してね！」と**自慢げ**にチャットワークに自分の記事のURLを貼ってくれたりしました。
業務中に少し時間が空くと、java・Pythonなどの勉強会への参加や、ビッグデータ・AIに関する書籍、IT系の雑誌の購読、stackoverflowへの回答など行い、スキルアップへの関心が高かったように思います。
そんな環境にいるうちに、自分もQiitaの記事を読むことや、いろんな勉強会に参加するようになり、いつしか、**モダン**というキーワードが超かっこよく聞こえてくるようになりました。

「周りが常に新しい情報を求め、いろんな場所にアンテナを張っている状態」の中に身を置くことができていました。


#田舎のエンジニア事情
対して、田舎のエンジニア事情ですが、地元企業に転職してから一年間、なぜ、レガシー環境のまま、業務が行われてしまうのか、少しわかったことがあります。

まずは、地元にてIT関連の勉強会・セミナーの開催が無く、新しい技術に対する興味を持つような場がないということが大きいのではないかと思います。
書籍やインターネットで新しい技術というのはいくらでも手に入るとは思いますが、やはり勉強会・セミナーの熱量とは大きく差が開いてしまいます。
また、通常業務の観点から見てみると、田舎のお客さんにとっては「新しい技術」よりも「昔からの付き合い」のほうが圧倒的に信頼度が高いため、おなじみの受注先において革新的な技術で対抗してくるような競合他社もいません。
そのため、今の技術をどうこうするといった話にならず、「実績があって動作する環境」であればそれでいいのです。

このような閉鎖的な環境が続いてしまえば、レガシーな状態になってしまうのかなとも思ってしまいます。

#結論
もしかしたら私のように、都会に飽きて田舎に戻ろうと考えている方がいらっしゃるかもしれません。
その時、あまりの技術の差に直面して後悔することが無いように、田舎のエンジニア事情を伝えてみようかなと思った次第です。
もちろん、田舎のIT企業がすべてこんな状態かというと、そうではなく、最先端技術を駆使したサービスを提供している企業もいっぱいあると思います。
ただ、私の転職先はこうでした。ということです。

都会のメリット・田舎のメリット。いっぱいあります。
仕事においてのそのギャップがなくなれば最高ですね。
二値文字列の転倒数が従う群構造

#概要
二値文字列の転倒数が従う群構造を紹介します。これによって範囲転倒数クエリが、累積和やSegment Treeで計算できます。Segment Treeでできます、という言及は[今までに見たことがありましたが](http://yosupo.hatenablog.com/entry/2015/03/31/000740)、累積和もできるという話は聞いたことがなかったのでまとめます。

二値文字列の転倒数とは、`0`と`1`からなる二値文字列 $s$ が与えられて、$s$ をソートするために必要な隣り合った`0`と`1`のswap数 $f(s)$ のことです。例えば、$s=101011$ を $001111$ にソートするためには、 $3$ 回のswapが必要なので、$f(101011) = 3$です。

長さ $n$ の二値文字列に対する転倒数は、ここで紹介する群構造によって、

- $O(n)$で計算できます。
- 二値文字列 $s$ の任意の部分連続文字列 $s[l, r)$ の転倒数を計算するクエリは、前処理 $O(n)$ クエリ $O(1)$ で計算できます。
- 二値文字列 $s$ の一箇所を変更する更新クエリ、および任意の部分連続文字列 $s[l, r)$ の転倒数を計算するクエリを、ともに $O(\log n)$ で計算できます。

#二値転倒数の代数構造
二値文字列 $s$ に含まれる`(0の個数, 1の個数, 転倒数)`を $g_s = (x_s, y_s, z_s)$とします。この時、二つの二値文字列 $s, t$ が与えられて $g_s, g_t$ が既知である場合、連結された二値文字列 $s+t$ の転倒数 $g_{s+t}$ は、二項演算子$\otimes$を用いて、$g_{s+t} = g_s \otimes g_t = (x_s + x_t, y_s + y_t, z_s + z_t + x_t y_s)$と表されます。第三成分は、$z_s, z_t$ 回のswapを行って、$00001111100000011111$のような形状にした後、真ん中の`11111000000`をswapする回数を足すので、このような形になっています。$g_{s+t}$のマージ則が定める二項演算は結合的であり、以下の性質を満たすため、この二項演算が定めるモノイドは群をなします。

- 単位元: $(0, 0, 0)$
- 逆元: $g^{-1} = (x, y, z)^{-1} = (-x, -y, -z + xy)$

#利用可能なデータ構造
群をなす長さ $n$ データ列 $g_i\ (0 \le i < n)$ に対して、区間 $[l, r)$ のデータを二項演算によってかけあわせる効率的操作は、累積和によって可能です。具体的には、$g_i$を始めから $i$ 個掛けあわせたデータを $x_i$ とした時、$g_l \otimes g_{l+1} \otimes \cdots \otimes g_{r-1} = x_l^{-1} \otimes x_r$と簡便に計算できます。そのため、累積和によって構築 $O(n)$, クエリ $O(1)$ で二値転倒数が計算できました。

群は結合法則を満たすので、Segment Treeを利用することもできます。これによって、二値文字列の添字 $i$ を変更するクエリ、および区間 $[l, r)$ のデータを二項演算によってかけあわせる操作を、ともに $O(\log n)$ で計算することができます。

#Verify
`Dwacon 2019 Qual D - k-DMC` では、各 $i$ について、区間 $[i, i+k)$ の二値転倒数を足し合わせる必要があります。静的二値文字列に対する転倒数は、前処理に $O(n)$ をかけることで、累積和で各 $i$ につき $O(1)$ で計算できるので、全体で $O(q n)$ の計算量で解くことができました。この群構造を利用することで、シンプルなコードで解答することができます（[提出](https://beta.atcoder.jp/contests/dwacon5th-prelims/submissions/3675284)）。

#一般の転倒数
置換の転倒数の計算は文字列の長さ $n$ に対して、[BITやマージソートを用いて](http://antimon2.hatenablog.jp/entry/2013/09/04/225924) $O(n\log n)$ で計算できます。現在の最速は[前原氏のスライドによると](https://www.slideshare.net/tmaehara/inversion-counting) $O(n \sqrt{\log n})$ だそうです。