OmniAICreator/Qiita-1.07M huggingface dataset:
テレワーク導入で感じたメリデメと課題

# はじめに
このご時世、コロナで皆様色々大変かと思います。
自分が勤めている会社でもテレワークが導入され始め、今週から利用開始しています。
利用して数日で感じたことをユーザ目線で書こうと思い、記事にしました。

初投稿なので稚拙な文章で申し訳ございませんが、最後までご一読いただけますと非常に幸いです。
また、テレワークの導入は初の試みのため、「ほかにもこんなサービスがある」等ございましたら、是非ご共有いただけますと幸いです。

## 1.自己紹介
自身のプロフィールになります。

- 大卒入社で4月で5年目
- システム開発プロジェクトを約4年経験（要件定義～リリースまで一通り）
- 開発職ではなく、マネジメント職のプロジェクトメンバー
- その後開発職もやりたいと思い、今年に入って開発職へ転向（フロント箇所を担当）
- インフラチームではないため、テレワーク導入には関与していない

## 2.テレワークするにあたって必要なもの
テレワーク実施に向けて必要なものをざっと明示します。

#### 必需品
- PC（当たり前ですが、これないと仕事できません）
- マイク（WEB会議で必要。ノートPCに標準搭載いるかも）
- WEBカメラ（同上）
- WEB会議の環境（zoomやTermsがメジャーでしょうか）
- 社内NWにアクセスできるサービス（VPN接続しないとアクセスできないとかあれば必要）

ちなみに、社内NWにアクセスするサービスは、プロパーが「V-Client」、パートナーは「マジックコネクト」を利用しています。
（なぜ使い分けているのかは知らないですが。。。）
他に良いサービスがあればぜひ教えてほしいです。

以下、サイトのリンクです。
[V-Client](https://www.amiya.co.jp/solutions/verona/v-client.html)
[マジックコネクト](https://www.magicconnect.net/)


#### あると嬉しいもの
- チャットツール（Slackとか。後ほど記載しますが、電話だけだとコミュニケーションロスが起こりやすいので）

## 3.テレワークのメリット
#### 通勤時間がない
出社・退社時の時間を有効活用できるのは、かなりのメリットです。
自分の場合、通勤時間が往復約1時間半なので、1か月稼働だけで30時間も別のことに時間が割けます。

#### 好きな音楽を流しながら作業ができる
このメリットは個人差がありますが、音楽を流すと人によっては生産性が向上します。（自分もこのタイプです）

## 4.テレワークのデメリット
#### コミュニケーションロスの発生
直接対面でないため、やっぱり発生します。（Slackで話が2転3転することも）
その時は、関係者へSlackの通話ツールを用いて話すことでコミュニケーションロスのリカバーを行っています。

#### サボりがち
自宅での作業なので、オフィスと違いどうしても色んな誘惑があります。
回避策として、朝自分がやることを人が見える場所に公開することかなと思います。随時更新できればなおよし。
業務終了時に作業実績を日報として上司へ報告しています。
自分の場合、Slackを使っているので、パブリックチャンネルにやることを明示し、随時更新しています。

#### 社内NWへアクセスできなくなる
トラフィック増加でアクセス不可、もしくはすごく重たくなる事象がパートナーさんから報告がありました。
使用するサービス次第では業務影響が発生するものもあるようです。
アクセス不可になった場合、早急にインフラチームへ連絡するよう運用をとっています。（それでも、事態が解決するわけではないですが。。。）

## 5.テレワーク導入に向けた課題
導入時に色々あった課題を共有します。導入時の参考にさせて頂ければ幸いです。

#### 勤怠管理
テレワーク運用に向けて、出社時間と退勤時間の報告ルールを決める必要があります。（特にパートナーさん）
PCのログイン時間とか管理できればそれでよいのですが、自分のところはExcelで勤怠を自己申告制です。（ほんとにIT会社か）

#### パートナーさんとの契約内容
自分は一番ここで揉めました。
テレワークというリモートワーク上、どうしても成果物出してナンボになります。
加えてセキュリティが落ちるのは必至なので、リモートワークにあたっての合意書が必要になりました。
書面内容によっては契約元の会社と揉めることになるので、リーガルチェックを通した上で合意をとりましょう。

以下、揉めた時の悪い例
悪い例①
>労働者は、在宅勤務における始業、休憩の取得と終了、並びに終業の際に原則としてメール等の手段で所属長に報告するものとする。なお、終業時の報告には、その日の作業内容についても追記する。

運用方法を契約内容に書くのはナンセンス（普段Slackで勤怠報告してるけど、メールでの報告？で揉めました）

悪い例②
>在宅勤務の遂行において、万一、損害が発生した場合、労働者は直ちに所属長に報告する。また、その責については原則として労働者が負うものとする。

情報漏洩した場合、契約元の会社ではなく、パートナーさんに責任負えってこと？で揉めました。
極端な話、「1000万の損害出たら、あなたが1000万払ってね」と同じ内容。なんとひどい話。。。

## 6.最後に
テレワークの導入は、本記事で掲載したメリデメ以外にもあると思いますが、緊急事態宣言が発令された以上、テレワークが推奨になってくると思われます。
特にパートナー・派遣社員を雇用している多くの企業は、契約元との契約内容にも関与してくる話なので、契約元へ確認を取りつつテレワークの導入を進めていただければと思います。

また、リモートワーク初めての方へGoogle様より在宅勤務のコツが掲載されているので、そちらも参考にしていただければと思います。
[在宅勤務のコツ](https://cloud.google.com/blog/ja/products/productivity-collaboration/make-work-from-home-work-for-you)

本記事が少しでもテレワーク導入の際の一助になれば幸いです。
最後まで読んでくださり、ありがとうございました。



4/12 追記
導入して1週間経ったので、金曜日にリモートでパートナーさんとお酒飲みながら色々話しました。

- 普段してた他愛ない雑談ができないのはキツい（特に一人暮らしの人は話し相手がいなくなるのでキツく感じる）
- 対策として、来週以降からおやつタイムを導入（他愛ない会話をするブレイクタイム。仕事の話はあまりしない）

おやつタイムがリモートワークにどれだけ効果をもたらすのか、色々やり方を試行錯誤していきます。
（導入して間もないこともあって、色々試行錯誤できるのもいいですね）
Laravel PassportでPersonal Access Tokenを使う場合の有効期限設定

## 概要
LaravelでAPIを構築する場合の認証基盤として、Laravel Passportを使用するケースもあると思います。Laravel Passportの認証方法の一つであるPersonal Access Tokenでの認証について、取り上げます。

## Laravel Passportの概要とPersonal Access Tokenに関して
@zaburoさんの[Laravel Passportの使い方まとめ](https://qiita.com/zaburo/items/65de44194a2e67b59061)の記事にざっくりとした概要と、Personal Access Tokenの実装サンプルが紹介されています。
Personal Access Tokenは認証後にユーザに対し、アクセストークンを発行しこのトークンを用いて、認証済みかの判定を行います。

## Tokenの有効期限に関して
[Laravel Passportのクライアント認証を試してみる](http://kayakuguri.github.io/blog/2017/10/20/laravel-passport-sample/)の記事にある通り、AuthServiceProviderにtokenの有効期限を設定することが可能です。
ただ、上記記事の設定だけだとPersonal Access Tokenの有効期限はデフォルトのままです。

## 対応
こちらのStack Overflowの記事[Laravel Passport token lifetime](https://stackoverflow.com/questions/42609436/laravel-passport-token-lifetime/56695300#56695300)によると、Personal Access Tokenに対しては、

```
Passport::personalAccessTokensExpireIn(Carbon::now()->addDays(1));
```
のように設定しないとダメとのこと。
また、Passportが7.0.4以上のバージョンから使用できます、おそらくLaravelは5.8以上からではないと使えないと思います。（[Laravel 5.8 Laravel Passport
](https://readouble.com/laravel/5.8/ja/passport.html)）
ちなみに、`oauth_access_tokens`の`expires_at`を直接更新しても、実際に使用している期限はtokenで暗号化されているものらしく、更新しても無意味だそうです。。
NuxtでTrianglifyを使う

# 概要

Nuxt(とvuetify)で作成しているページの背景にTrianglifyを利用しようとしたところ、ドキュメントが見つかりませんでした。
なんとか実装できたため、メモとして残しておきます。

# Trianglify

Trianglifyとは美しいポリゴンっぽい画像を生成してくれるライブラリです。
CDNとnpm両方で提供されています。

<img width="1280" alt="スクリーンショット 2020-04-07 23.55.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202481/11bbdfec-2b44-3b45-8ff4-f8745f4af41f.png">
http://qrohlf.com/trianglify/

# CDN

CDNから呼び出す際は`nuxt.config.js`の`head`に書き込みます。

```nuxt.config.js
head: {
  script: [{ src: 'https://cdnjs.cloudflare.com/ajax/libs/trianglify/2.0.0/trianglify.min.js' }]
},
```

背景に当てたいので、`layout/default.vue`で利用します。

```layout/default.vue
<template>
  <v-app id="background">
    <v-content>
      <v-container>
        <nuxt />
      </v-container>
    </v-content>
  </v-app>
</template>

<script>
export default {
  mounted() {
    this.addTriangleTo(document.getElementById('background'))
  },
  methods: {
    addTriangleTo(target) {
      const dimensions = target.getClientRects()[0]
      const pattern = Trianglify({
        width: dimensions.width,
        height: dimensions.height
      })
      target.style['background-image'] = 'url(' + pattern.png() + ')'
    }
  }
}
</script>
```
これでもできたのですが、`Trianglify is not defined`と怒れることが時々あったり、、、。
多分よくない書き方だと思います。

# npm

npmで落とした物を利用する際は一度pluginにします。

```shell

npm install trianglify --save
```

```plugins/trianglify.js
import Vue from 'vue'
import Trianglify from '../node_modules/trianglify/dist/trianglify.min.js'

Vue.prototype.$addTriangleTo = (target) => {
  const dimensions = target.getClientRects()[0]
  const pattern = Trianglify({
    width: dimensions.width,
    height: dimensions.height
  })
  target.style['background-image'] = 'url(' + pattern.png() + ')'
}
```

pluginを有効化します。

```nuxt.config.js

plugins: ['~/plugins/trianglify.js'],
```

同じく`layout/default.vue`で当てます。

```layouts/default.vue

<template>
  <v-app id="background">
    <v-content>
      <v-container>
        <nuxt />
      </v-container>
    </v-content>
  </v-app>
</template>

<script>
export default {
  mounted() {
    this.$addTriangleTo(document.getElementById('background'))
  }
}
</script>
```

これでいい感じの背景を設定することができました。

# Trianglifyを背景にして作成したサービス

https://nvimc-generator.web.app/
(作成中)

# 参考

https://github.com/qrohlf/trianglify
https://github.com/qrohlf/trianglify/blob/master/examples/basic-web-example.html
https://hacknote.jp/archives/26679/
.gitignoreでフォルダに対してホワイトリストで管理する方法。特定階層以降を許可

#◆ 対象
.gitignoreで、ホワイトリスト型にするのはよく見かけますが、
特定のフォルダの中身全てを許可したい人向けになります。

複数人で利用するときに、担当者ごとに特定のフォルダ内のみ追加変更を許可する。
などしたいときに利用できます。

#◆ 書き方
ホワイトリスト型にするには、まず全てをブラックリストとして禁止して
必要なファイルやフォルダを許可（!をつける）する順番で書きます。


```gitignore:.gitignore
# 【1】 最初に全ファイル禁止
# すべてのファイルをignoreするがフォルダはしない
# gitは空フォルダは無視されるので影響はない
*
!*/

# 【2】 次に任意のファイルやフォルダを許可
# このファイルと同階層のフォルダ階層以降を許可
!/lib/**
# このファイルと同階層以降の「??？_m」というフォルダ階層以降を許可
!**/*_m/**
# このファイルと同階層のファイルだけ許可
!/README.md
!/.gitignore


# 【3】 最後に常に除外するファイルやフォルダを禁止
# OSが自動で作るファイル
.DS_Store
Thumbs.db

```

#◆ 解説

フォルダに関する定義

| 記号 | 意味 |
|:-----------------|:------------------|
| 先頭に / | このファイルと同階層のみ |
| 先頭に */ | このファイルと同階層よりも下（同階層を含まない） |
| 先頭に **/ | このファイルと同階層以降（同階層を含む） |
| 末尾に / | 指定のフォルダのみ（意味がない） |
| 末尾に /* | 指定のフォルダ直下のファイルのみ |
| 末尾に /** | 指定のフォルダ以降全てのファイルとフォルダ |

上記を踏まえて、
`!**/*_m/**`
の意味は、
「`**/`」 このファイル（.gitignore）を記述した階層を含む以降の階層に対して
「`*_m/`」 末尾が 「*_m*」 で終わるフォルダがあったら
「`/**`」 このフォルダ以降のファイルとフォルダを全てを
「`!`」 許可する
となります。

#◆ 参考
GitHubが公式で出している、プロジェクト毎のテンプレート
https://github.com/github/gitignore

この中身を見た方が勉強になるかもしれません。

一部抜粋
> Android
> C++
> Dart
> Go
> JENKINS_HOME
> JAVA
> Kotlin
> Laravel
> Lua
> Node
> Objective-C
> Peal
> Processing
> Python
> Rails
> Ruby
> Sass
> Swift
> Symfony
> Unity
> VisualStudio
> WordPress

などなど
SEIRモデルの実装

※私は感染症に関しては全くの素人です。記事に誤りがあれば指摘をお願いします。また、この記事で生じる損害に関して、私は一切責任を負うつもりはありませんので、あくまで個人利用の参考にお使いください。
# はじめに
東京大学理学系研究科生物科学専攻のWebサイトに掲載されていた[新型コロナウイルス感染症の流行予測](http://www.bs.s.u-tokyo.ac.jp/content/files/SEIR%E3%83%A2%E3%83%87%E3%83%AB%E3%81%AB%E3%82%88%E3%82%8BCOVID-19%E6%B5%81%E8%A1%8C%E4%BA%88%E6%B8%AC%20200331ver3.1.pdf)がとても興味深いものだったので、そこで紹介されていたSEIRモデルをRで実装してみました。モデルの詳細はリンク先をご覧ください。R以外の言語でも実装は容易だと思います。

```R:SEIR.R
R0 <- 2.5; l <- 5.0; i <- 10.0; dt <- 1.0
daymax <- 400
Su <- numeric(daymax) # Susceptible
Ex <- numeric(daymax) # Exposed
In <- numeric(daymax) # Infectious
Re <- numeric(daymax) # Recovered
N <- 1.0*10^5 # 10万人
Su[1] <- N; Ex[1] <- 0.0; In[1] <- 1.0; Re[1] <- 0.0
for (day in 1:(daymax-1)) {
  print(day)
  Su[day+1] <- Su[day] + (-(R0/i)*(Su[day]/N)*In[day])*dt
  Ex[day+1] <- Ex[day] + ((R0/i)*(Su[day]/N)*In[day] - (1.0/l)*Ex[day])*dt
  In[day+1] <- In[day] + ((1.0/l)*Ex[day] - (1.0/i)*In[day])*dt
  Re[day+1] <- Re[day] + ((1.0/i)*In[day])*dt
}
plot(1:daymax, Su, type="l", xlab="日数", ylab="人数", ylim=c(0,N))
par(new=T); plot(1:daymax, Ex, type="l", xlab="", ylab="", ylim=c(0,N))
par(new=T); plot(1:daymax, In, type="l", xlab="", ylab="", ylim=c(0,N))
par(new=T); plot(1:daymax, Re, type="l", xlab="", ylab="", ylim=c(0,N))
```
結果の図は以下の通り。
![Rplot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282333/0ce1abc4-8abc-b0c8-95bc-f104a08586be.png)

# その他
時間があれば、上のSEIRモデルを使って色々考察していこうと思います。
東京都の場合の考察（執筆予定）
スプレッドシートから書き出したxlsxが破損しているとき

# はじめに
今やgoogleのドキュメントやスプレッドシートは仕事をする上でなくてはならない存在になっています。インターネットさえあれば無料で使うことができ、さらに他人とのリアルタイム編集や共有によって取り回しも非常に良いです。

しかし、全ての企業がドキュメントやスプレッドシートを導入できる訳ではなく、スプレッドシート⇄エクセルファイルでのやりとりが発生してきます。そこで、やはりスプレッドシートで作ったものがエクセルでは正しく表示されない、またその逆も然り。

今回は、何ら難しい数式も入れていない情報をまとめただけのスプレッドシートをxlsxに書き出した時におきたことについてまとめておきます。

# スプレッドシートのxlsx書き出し
スプレッドシートへ書き出すには、左上のメニュー→ダウンロード→xlsxを選択します。
![書き出し](https://gyazo.com/415b39dfb52e0dce6d2eba10cf1cc4a6.raw)

# ファイルが破損していた
さて、書き出したxlsxをExcelで開いてみると・・・
![破損](https://gyazo.com/b421b10711a3614310b28c6a2e7e01e1.raw)
何やらファイルが破損している様子（もちろんwindows機やteams上でもxlsxの破損警告は出た）

# 検証結果
![検証結果](https://gyazo.com/40c71b444057774f28f19bcd199d0f80.raw)
つまり、シートの名前に全角でも半角でもクエスチョンマークは使ってはダメということです。
すごく単純なところでしたが、仕事で提出したファイルに対して「破損して開けません」は肝を冷やしますね・・・
オンライン文章校正支援サービスまとめ

# はじめに

## 背景

Qiitaをはじめとして、さまざま場面で文章を書くかと思います。良い記事の条件として、文章が日本語として正しいというものがあるかと思います。正しい誤解のない、認知不可の低い文章を書くために、最低限の誤字脱字や表記ゆれを防ぎたいですよね。今回はそのようなときに役に立つオンライン文章校正支援サービスについて、いくつかを紹介します。

## オンライン文章校正支援サービスとは

ウェブブラウザ上で文章を入力（ペースト）することで、文章校正を実施し指摘箇所を洗い出してくれるサービス。

# オンライン文章校正支援サービスまとめ

## オンライン文章校正支援サービスPRUV（プルーフ）

URL: https://pruv.jp/

英語の“proof”（校正）から由来。文法や固有名詞、送り仮名の誤り、誤入力、だけでなく表記ゆれの検出も可能。

## 文章校正ツール

URL: https://www.value-press.com/proofreader/

対象テキストを直接入力する方法に加えて、URLを指定して対象ページのテキストを校正する。

## プレスリリース校正ツール - プレスリリース配信サービス | valuepress

URL: https://www.value-press.com/proofreader/

校正結果を左右に表示され確認が容易。

## 日本語校正サポート
URL: https://www.kiji-check.com/

「基本」、「難読」、「品質」の3つに分類される項目の細かい設定が可能。（※最大1万字まで）

## 日本語の文章のタイポ/変換ミス/誤字脱字エラーをチェック/校正

URL: http://enno.jp/

いくつかの文章校正ツールはYahoo!デベロッパーネットワークより提供されている[テキスト解析:校正支援](https://developer.yahoo.co.jp/webapi/jlp/kousei/v1/kousei.html)によって実装されている。それに対して独自のアルゴリズムで誤字・脱字を判断してくれるサービス。他のサービスと併用して使用するとよいだろう。

## 文の長さを計測して度数分布を表示するWebサービス - 文長さ計測[αテスト中]

URL: http://drupa.jpn.org/measure-sentence-length/

文の長さを計測するサービス。他のサービスと毛色は異なるが、読みやすい文章にするための参考になる。併用して使用するとよいだろう。

# おわりに

「オンライン文章校正支援サービス」をいくつか紹介しました。Qiitaをはじめとする文章を書く人は使ってみてください。
RTX830とWLX313で作る自宅超快適ネット環境！

# はじめに
某ELECOM社製無線LANルータを今まで使っていました。
そのところ、無線LANがめっちゃブッチブッチ切れるわ、電波が弱いところに入るとなんかよくわからないけどTCPのセッション止まるやら切れるわで、エクスペリエンスは最悪でした。

# ルータがあるなら無線も揃えちゃえば？
という発想は誰でもすると思います。
なので買っちゃった！＆WXL313はめっちゃ良いぞ！という話です。
機能についてもいくつか触れます。
自宅のスマホをRADIUS認証できるの本当に良いし、怪しいバックドアを持っていそうな中華製の電源タップとかは別途VLAN切った別のSSIDに繋げてやれば、ネットワークレベルで分離できるわけですよ。
（盗聴器on IoTやネットワークカメラに付けられたバックドアのようなネットワーク分離だけじゃ片付けられないな問題になると流石に無理ですが。）

さいこうですね。

# RTX830につなげてみた
わーい認識したよー！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/521fc2be-6040-4d1f-83ce-a69189fca35f.png)

※この画像は色々設定を終わったあとに撮ったので、VLAN切ってあります。
VLANとかの説明は後回しにして、WLX313の機能をいくつか紹介します。

### 使用する帯域とアンテナの話
四角い筐体を、地面と垂直に置くと上と下にアンテナがあります。
こんなん。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/919f0b50-8a62-3667-895f-1d7213723dec.png)
この5GHz(2)というのが、FastDFSでレーダー探知に使えるアンテナです。
逆に言うと、FastDFSを有効にすると、探知をしなきゃいけないので、上二本のアンテナは通常の通信には使えなくなります。

### FastDFS
というわけでFastDFSの説明から。
5GHz帯を使ってると、気象レーダーとかいろいろなレーダー波と干渉するので、それを事前に察知して回避するアクティブなDFSのこと。
でも最近の無線ルータには結構ついているイメージはあるけど違うかな。

### VAP(Virtual Access Point)
一般的なルータにおけるSSID設定のこと。最大16個のSSIDを設定できます。
こんな感じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/5a22483f-061d-11fb-5ffb-790131f70708.png)

ただですね、なんと、SSIDのパスワードとか名前だけを変えられるだけではない！！！！
VLAN IDもSSID毎につけられちゃうわけですよ。
ここで設定したVLAN IDとSWX2200で設定したVLAN IDを合わせれば、いい感じにVLAN切れます。ヤマハすごくないですか？


※VLANの設定は、[ゲスト用の無線ネットワークを設定 : ルーター Web GUI設定 + WLX313 Web GUI設定](https://network.yamaha.com/setting/wireless_lan/airlink/guest_access-wlx313-rtx#vlan)を見ながら頑張った。


### 簡易RADIUSサーバ（証明書の発行・管理もできる！）
これが一番推してる内容なんですが、ユーザ毎・マシン毎に証明書を発行できるんですね。
なので、パスワード（プレシェアード）とか入れなくていい！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/f41dc75c-f9ff-4a42-c50a-ed34987a6c34.png)

更に！複数ユーザが居て、ちまちまユーザ追加とかしんどいよ！
なんて場合には、CSVで一括登録、一括証明書生成、一括証明書送信機能があります！
便利ですねー！！！！！！！！

もちろんこれらの証明書の失効操作なんかもできます！
個人ユースには十分な性能ではないでしょうか！

### 周りのご家庭のAPの状況が見える
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/e15906e9-6d60-d04c-b105-10450e3c4255.png)

なんかWEP使ってるAPあるぞ・・・まじかよ・・・

# 導入後のスマホでのスループット
たまらん！！！！スマホで出る速度とは思えん
Ooklaのテスト
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/40aad9a3-7905-926b-1b9d-b85056dd8be5.png" width=50%>
Googleのほう
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/55bcfb72-b529-1b89-81df-4200204c9efd.jpeg" width=50%>
実際の速度はこんなもん。
リンク速度は・・・？
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/0dfadd35-0795-d765-4b0a-358be587c4f7.jpeg" width=50%>
650Mbpsってなんやねんみたこと無いぞ。（もちろんこんなに出るわけはない）

# いかがでしょう？WLX313良いですよ！
是非買いましょう、今買いましょう。悩んでるくらいなら買っちゃいましょう！

# 関連記事
[RTX830を使ってバックアップ回線をUSBモバイルルータで作る](https://qiita.com/segfo/items/600d87015c77a63bde75)
言語処理100本ノック2020年版が公開！どこが変わったの？

# はじめに
自然言語処理の基礎を楽しく学べる問題集として長らく親しまれてた言語処理100本ノック、その[2020年版](https://nlp100.github.io/ja/)が4/6に公開されました！これは5年振りの改訂です。
[2015年版](http://www.cl.ecei.tohoku.ac.jp/nlp100/)をやったけど興味ある人、15年版のQiita記事が役立たなくなって残念に思ってる人、15年版を途中までやってたけど20年版が出て心が折れそう、という人のために、どこが変わったのかをまとめていきます。もちろん非公式なので変更箇所の見逃し等はあるかもしれません。


# 改訂の概要
4/7現在、公式の[更新履歴](https://nlp100.github.io/ja/about.html)によると、次の3点が大きく変わったようです。

- 深層ニューラルネットワークに関する問題を追加
    - 第8, 9, 10章が全て新規に作成された問題になっている
- 英語版の公開（39番まで）
    - 40番以降も順次公開予定とのこと（[著者Twitter](https://twitter.com/chokkanorg/status/1247312205671874561)）
- 旧第6章（英語テキストの処理）が英語版に移動
    - 該当する英語版は未公開。作成中のようだ（[Github](https://github.com/nlp100/nlp100.github.io/blob/master/en/ch05.md)）。

後述しますが、日本語版を私が見比べた限りでは**2015年版の第1～5章は変更無し、第8章はタスクが変更、第9・10章は簡易化、残りは削除**という感じです。それ以外では、ダウンロードするファイルのURLが全面的に変更されています（文字コードやリンク先の問題を気にしてのことでしょうか？）。

(6/10 追記)
Rev 1がリリースされました。日本語版は問題文の表記が微修正され、英語版も10章まで完成したようです。

# 具体的にどこが変わったか
## 旧第1章: 準備運動
- 変更無し
- 英語版も"パタトクカシーー"が"schooled"になった以外の違いは無さそう

## 旧第2章: Unixコマンドの基礎
- タイトルが「Unixコマンド」に変更
- tsvファイルが変更。行数も増えた。
- 問題文に変更無し

## 旧第3章: 正規表現
- 問題文に変更無し
- 日本語Wikipediaデータが更新された
- 英語版では英語版Wikipediaのデータを使う

## 旧第4章: 形態素解析
- 旧33番「サ変名詞」は削除され、代わりに新37番「『猫』と共起頻度の高い上位10語」追加
- テキストファイルのURLが更新された
- 英語版は"POS tagging"で、Alice’s Adventures in Wonderlandをダウンロードするスクリプトが付属している
    - 日本語版ではMeCabが指定されているが、英語版でPOS taggerの指定は無い

## 旧第5章: 係り受け解析
- 問題文に変更無し
- (6/10追記) Rev 1でテキストファイルが変更され、またCaboCha縛りが無くなった。

## 旧第6章: 英語テキストの処理
- 概要に書いた通り、英語版に移動

## 旧第7章: データベース
- 削除
    - 旧第7章だけNLP感が無かったので妥当な変更だと思います

## 旧第8章: 機械学習
- 新第6章に移動
    - ただし細かい変更点が多い
        - 後半の、深層学習を用いた手法への導入を意識したのかもしれません
- タスクが極性分析（2値分類）からカテゴリ分類（多クラス分類）に変更
    - 新版のダウンロード先を開こうとすると、証明書が期限切れの可能性という警告が出る
- 旧78番では分割交差検証を行っていたが、新版では代わりにホールドアウト検証を行う
    - データセットのサイズが大きくなったので妥当な変更だと思います
    - これに伴い、新版では50番でデータを学習データ・検証データ・評価データに分割する
- 旧71番「ストップワード」は削除
- 旧72～75, 77はほぼそのまま新版に移動
    - 素性→特徴量など、細かい変更は有り
    - ストップワードに続きステミングもオミットされた
        - 時の流れの影響かと...
- 旧76番「ラベル付け」は削除され、代わりに新55番「混同行列の作成」追加
    - 元々存在意義が微妙な問題ではあった
- 旧79番「適合率-再現率グラフの描画」は削除され、代わりに新58番で正解率-正則化パラメータグラフを描画する
- 新59番「ハイパーパラメータの探索」が追加

## 旧第9・10章: ベクトル空間法
- 新第7章「単語ベクトル」に移動
    - 旧版では単語ベクトルを自力で学習していたが、新版では学習済みのものを利用することになった
    - それ以外でやることは旧10章と同じ
- 評価データがリンク切れになっていたが、更新された

## 新第8章: ニューラルネット
- PyTorch, TensorFlowなどを用いて単層（フィードフォワード）ニューラルネットワークを作成する
- 行列作成→予測→損失と勾配の計算→ミニバッチ化→GPU化→多層化、という具合に、段階的に実装していく構成

## 新第9章: RNN, CNN
- 自然言語処理の研究でかつてよく使われていたRNN・CNN（の簡易なモデル）を実装する
- 89番はBERTなどの事前学習済み言語モデルを用いて転移学習してみよう、というものになっている
    - 現在自然言語処理の様々なタスクで採られているアプローチである
    - ライブラリをサンプル通り動かすだけになりそうだが、それも重要な経験だと思います

## 新第10章: 機械翻訳
- 既存のツールを活用してニューラル機械翻訳を行う
    - 機械翻訳は自然言語処理の中心的な分野であり、ツールを使うだけでも重要な経験になると思います
- 99番では機械翻訳の結果がブラウザ上で表示されるデモを作成する
    - 旧69番「Webアプリケーションの作成」は何も知らない人にとっては難問でしたが、妥当な形になったと思います

# 個人の感想
最新の自然言語処理研究の潮流が反映されており、研究室の学生の新人研修に使われる問題集として、よりふさわしいものになったと思います！

# 余談
- Pythonをほとんどに知らずに100本ノックに取り組みたい人におすすめの記事はこちら→[言語処理100本ノックでPythonに入門](https://qiita.com/hi-asano/items/02d82cc1e89fc663b4e6)
- 新10章を解くとき何を使えば良いか迷った人におすすめの記事はこちら→[ニューラル機械翻訳ライブラリのざっくりとした紹介](https://qiita.com/hi-asano/items/27f6f9cdac9972fae464)
rbenvを利用している場合、VSCodeで[Ruby Solargraph]をインストールするとエラーが出る

# 問題
VSCodeでRubyの拡張機能である[Ruby Solargraph](https://github.com/castwide/vscode-solargraph)をインストールしたところ、以下のエラーが出て利用できませんでした。
<img width="456" alt="スクリーンショット 2020-04-07 23.09.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567216/94dbbb8e-a014-a27b-8328-9af37b3d3146.png">

インストール失敗したかと思いましたが、ターミナルからSolargraphを見に行くことはできています。

```zsh:
$ solargraph -v
0.38.6
```
調査した結果、解決できましたので、その方法を記載します。

### 参考にさせていただいた記事
- https://qiita.com/tequila0725/items/8e93dc894e0ab67d322f
- https://qiita.com/neko_the_shadow/items/87bb06cb73b01177a851

## 環境
- macOS Catalina
- Ruby version(2.7.1)
- rbenv version(1.1.2）
- VisualStudioCode version(1.43.2)
- Ruby Solagraph version(0.38.6)


## 解決方法
どうやらVSCodeからSolargraphが見に行けていないようでした。
以下の手順で`Setting.json`にSolargraphのパスを設定することで解決しました。

１． VSCodeの左下の歯車をクリックし、[設定]を開く 
<img width="305" alt="スクリーンショット 2020-04-08 0.10.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567216/c9908fcc-882d-5e8d-0620-8db5c762a94c.png">

２． タブの右上のボタンから`Setting.json`を開く
<img width="162" alt="スクリーンショット 2020-04-08 0.19.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567216/f787e67b-7c21-a84d-4401-e3c87e5e80f8.png">

3． `Setting.json`に以下を記入する

```json
"solargraph.commandPath": "solargraphのPATH"
```
※SolargraphのPATHは以下のコマンドを実行すると分かります。
 私の場合だとこちら。

```zsh
$ which solargraph
/Users/momonga11/.rbenv/shims/solargraph
```

４． VSCodeを再起動する

以上まで行うと、エラーが出なくなり、Solargraphの機能であるインテリセンスが動くようになりました。


## まとめ
rbenv等でRubyのバージョン管理をしている場合、こちらの設定が必要になるようです。
aws-cliでCogtnitoが発行したIDトークンを使い一時クレデンシャルを発行する

## 概要

aws-cliでCogtnitoが発行したIDトークンを使い一時クレデンシャルを発行する。

※ ↓の `外部プロバイダーの認証フロー` の `拡張（簡略化）認証フロー` を使う
https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/authentication-flow.html

## コマンド

### １．まず GetId を叩く。

```bash
aws cognito-identity get-id --cli-input-json file://get-id.json
```

get-id.jsonの中身

```json-doc
{
    "IdentityPoolId": "ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // IDプールのID
    "Logins": {
        // ↓リージョン/ユーザプールID : 取得したIDトークン
        "cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_xxxxxxxxx": "ey..."
    }
}
```

※
* IDプールの設定で、認証プロバイダーとしてIDトークン発行時に使用している、ユーザープールID、アプリクライアントID が設定されている必要あり。

https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetId.html
https://docs.aws.amazon.com/cli/latest/reference/cognito-identity/get-id.html

### ２．次に、GetOpenIdTokenForDeveloperIdentity を叩く

```bash
aws cognito-identity get-credentials-for-identity --cli-input-json file://get-credentials.json
```

get-credentials.jsonの中身

```json-doc
{
    "IdentityId": "ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // GetIdのレスポンスの値
    "Logins": {
        // GetIdで使ったものと同じ値
        "cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_xxxxxxxxx": "ey..."
    }
}
```

* https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdTokenForDeveloperIdentity.html
* https://docs.aws.amazon.com/cli/latest/reference/cognito-identity/get-credentials-for-identity.html
[Ruby] 時間フォーマット変換（"HH：MM"）

##やりたいこと

**注意：コメント指摘によるコードの改良も行っているので、ぜひ最後までみてください〜**


```ruby

8時間30分 + 10時間 + 10時間
=> 28時間30分
```

   ↓↓↓ 秒数計算

```ruby

30600 + 36000 + 36000 / 60 / 60
=> 28.5
```

**↑この数値を→「28:30」に直したい**


##合計値が24時間以内の場合

```ruby

Time.at(seconds).utc.strftime('%R')

Time.at(30600).utc.strftime('%R')
=> "08:30"
```

これは問題なく動く！

しかし、、、

##合計値が２４時間超えるとき(今回の問題)

```ruby

Time.at(102600).utc.strftime('%R')
=> "04:30" # ← 一周回った値しか返してくれない（Time.atを使用しているので当たり前だが。。。）
```

#本題
##「28:30」のように表示させたい

```ruby

seconds = 102600
days = seconds / 86400
# days = 1
```

↑ まずは何日分かを取得する

```ruby

time_at = Time.parse("1/1") + seconds - days * 86400
# 2020-01-01 04:30:00 +0900
```

↑ secondsから先程のdayをひくことで24時間を超える値は取得されない

```ruby

hours = sprintf("%02d", days * 24 + time_at.hour)
# "28"
```

↑ 日 × 24 + 時間

```ruby

min = sprintf("%02d", time_at.min)
# "30"

"#{hours}:#{min}"
# "28:30" となる
```

####補足

```ruby

days = seconds / 86400
time_at = Time.parse("1/1") + seconds - days * 86400
↓↓↓↓ # 一行に
time_at = (Time.parse("1/1") + seconds - (day = seconds / 86400) * 86400)
```

#参考
https://qiita.com/riocampos/items/2c4e4a9b45ad83a0bdc7
ありがとうございます。


####結局は、hourとminを別々の文字列をとし、最終的には文字列にそれぞれの変数を埋め込むように書いただけなので、一発でできるものがあれば教えていただきたいです。

##コメント指摘による改良コード

```ruby

def hhmmss(sec)
  sec_i = sec.to_i # 念の為に整数にしておく（小数点以下切り捨て）
  hours = sec_i / 3600
  mins = (sec_i - 3600 * hours) / 60
  secs = sec_i - 3600 * hours - 60 * mins
  sprintf("%d:%02d:%02d", hours, mins, secs)
end
```

```ruby
hhmmss(102600)
# => "28:30:00"
```

`sprintf("%d:%02d:%02d", hours, mins, secs)`
ここの書き方とか初めて知りました。本当にありがとうございます。
＋qiita 書くこと大事だなと実感。。。

なので、今回の場合は

```ruby
def hhmm(sec)
  sec_i = sec.to_i # 念の為に整数にしておく（小数点以下切り捨て）
  hours = sec_i / 3600
  mins = (sec_i - 3600 * hours) / 60
  sprintf("%d:%02d", hours, mins)
end
```

```ruby
hhmm(102600)
# => "28:30"
```

こうなりますね！
わかりやすくて良きですね！
Eclipse 拡張子を追加する

# はじめに
CakePHPで開発をしている時、.ctpファイルを開いたらPHPファイルとして認識してくれませんでした。.ctpファイルを開いたらPHPファイルとして認識させる方法を紹介します。

# やりかた

### メニューバー
ウィンドウ > 設定

### 設定
一般 > コンテンツ・タイプ

### コンテンツ・タイプ
テキスト > PHPコンテンツ・タイプ
→ファイルの関連付けに.ctpが登録されていない！！

### ファイルの関連付け
* 追加ボタンを押す
* .ctpと入力してOK
* 適用して閉じる

# おわりに
以後、.ctpファイルを開くとPHPファイルとして認識してくれるようになります。
SpreadSheetからCloudSQL(MySQL)に接続する方法

# メリット
サーバ側APIやクライアント側を作る必要がないので、とりあえず手っ取り早く管理画面を作りたい時に便利。

# 向いてない点
* あまりにもデータ量が多いと、GASやSpreadSheetが耐えられない。
* 処理速度の改善は難しい。

# 元ネタ
https://developers.google.com/apps-script/guides/jdbc
こちらを日本語にして、自分が躓いたところを補填しています。

# 準備
* 一度ぐらいGASを書いたことある。
* CloudSQLでDBを作成しておく。
* CloudSQLのユーザ名とパスワードとDB名は把握しておく。
* 何件かデータが入っている

# IPアドレスを許可する
以下のアドレスをCloudSQLにアクセスするのを許可します。

```
64.18.0.0/20
64.233.160.0/19
66.102.0.0/20
66.249.80.0/20
72.14.192.0/18
74.125.0.0/16
173.194.0.0/16
207.126.144.0/20
209.85.128.0/17
216.239.32.0/19
```
GCPコンソールからだと一つずつしか出来なくて、とても面倒なので、gcloudコマンドを使います。

```
sql instances patch [インスタンスID] --authorized-networks=64.18.0.0/20,64.233.160.0/19,66.102.0.0/20,66.249.80.0/20,72.14.192.0/18,74.125.0.0/16,173.194.0.0/16,207.126.144.0/20,209.85.128.0/17,216.239.32.0/19 --project [プロジェクト名]
```
インスタンスIDはこれです。
![CloudSQL_instance.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/b34778b5-9a3a-4ca6-ec55-fa079b6dca2a.png)

プロジェクト名は、GCPのプロジェクト名になります。

うまく行けば、GCPコンソールのCloudSQLから「接続」を選べば、以下のような画面になります。
![許可IPアドレス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/90309977-7426-e65d-985f-54ffcaea87b8.png)

# GASを書く
SpreadSheetからツール- スクリプトエディタから書きます。
詳しい内容は割愛します。

```js
/**
 * Read up to 1000 rows of data from the table and log them.
 */
function readFromTable() {
  
  var connectionName = 'インスタンス接続名';
  var user = 'ユーザ名';
  var userPwd = 'パスワード';
  var db = 'DB名';
  
  var dbUrl = 'jdbc:google:mysql://' + connectionName + '/' + db;
  var conn = Jdbc.getCloudSqlConnection(dbUrl, user, userPwd);

  var start = new Date();
  var stmt = conn.createStatement();
  stmt.setMaxRows(1000);
  var results = stmt.executeQuery('SELECT * FROM テーブル名');
  var numCols = results.getMetaData().getColumnCount();

  while (results.next()) {
    var rowString = '';
    for (var col = 0; col < numCols; col++) {
      rowString += results.getString(col + 1) + '\t';
    }
    Logger.log(rowString);
  }

  results.close();
  stmt.close();

  var end = new Date();
  Logger.log('Time elapsed: %sms', end - start);
}
```

インスタンス接続名はこちらを参照する。
![インスタンス接続名.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/3853078a-2b5f-e891-c00f-cea17c1c7932.png)

時間がないけどどうしても管理画面が必要！という時は向いてますね。
BraveでAmazon Prime Music/Video・NHKプラスなどが再生できないときの対処法

Amazon Prime Music で「再生が無効になっています。ブラウザの再生設定を有効にしてください。」と出たり、Amazon Prime Video や NHK プラスなどが再生できないときの対処法です。

1. 設定 → 拡張機能 → 「Widevine」をON
![Widevine](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155587/0ab74155-dca9-a5f5-a4b9-f96a74101046.png)

2. サイトにアクセスし、Widevine のインストールを求められるのでインストールする

※ Widevine は Google が開発したもので、DRM (Digital Rights Management, デジタル著作権管理) で保護された楽曲が映像の再生に必要なものですが、デフォルトでは Brave にインストールされていません。


追記 (2020/12/31)
M1チップ搭載のMacではarm64バージョンのBrave Nightlyを使用している場合Widevineが正常に動作しない模様です。
https://github.com/brave/brave-browser/issues/12950
文字列に変数を埋め込む【Ruby/PHP/Swift】

## 概要
RubyとPHPをざっくり学び、現在Swift学習中の筆者の備忘録です。
よくある「文字列に変数を埋め込む（変数展開）」ことについて
言語間で微妙な違いがあり、すぐ分からなくなるのでまとめました。

## 記述する内容

変数「name」に文字列「田中」を代入する。
この変数を埋め込む形で「こんにちは、田中さん」という文字列を出力する。

## Ruby

```ruby
"#{変数}"

name =  "田中"
puts "こんにちは、#{name}さん"　
```


## PHP
```php
"${変数}"

<?php
$name = "田中";
echo "こんにちは、${name}さん";
?>
```

## Swift
```swift

"\(変数)"

var name: String = "田中"
print("こんにちは、\(name)さん")
```

## 最後に
以上、簡単ですが変数展開についてでした。
こういう細々した違いは、新しい言語に挑戦していると
すぐにこんがらがってしまいます。。。
まとめておくと安心ですね。
Vue CLI 4+Vagrant HMR有効化

HMRを有効にする設定。

```ruby:Vagranfile
Vagrant.configure("2") do |config|
  config.vm.box = "generic/ubuntu1804"
  config.vm.provision "shell", inline: <<-SHELL
    apt-get -y update
    echo "set grub-pc/install_devices /dev/sda" | debconf-communicate
    apt-get -y dist-upgrade
    apt-get -y autoremove
    apt-get install -y nodejs npm
    npm install n -g
    n stable
    cd /home/vagrant/app
    npm install
    npm rebuild node-sass
  SHELL
  config.vm.synced_folder "./", "/home/vagrant/app", SharedFoldersEnableSymlinksCreate: true
  config.vm.network "forwarded_port", guest: 8080, host: 8080
end
```

プライベートIPにwebsocketをはろうとするので、ループバックアドレスに修正。

```javascript:vue.config.js
module.exports = {
    devServer: {
        public: '127.0.0.1:8080',
    }
}
```

Vagrantの共有フォルダではファイルの変更を検知できないため、vagrant-notify-forwarderConnectionプラグインを入れる。

```shell-session
$ vagrant plugin install vagrant-notify-forwarder
$ vagrant reload
```
iOS app開発 習得日記 (4)

(https://qiita.com/nori0620/items/66ebc623f63fc3f0ca20)

こちらのサイトをみて勉強中

サーバーサイドのAPIというのを初めて作った。
json　webサーバーにphpファイル送れるだけで作れるとは。

本チャンのios app

```
import UIKit
import Firebase
import GoogleMobileAds

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var myNavigationController: UINavigationController?
    var json_string:String?
    var selected_id: Int?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        FirebaseApp.configure()
        GADMobileAds.sharedInstance().start(completionHandler: nil)
        
        let first: ViewController = ViewController()
        myNavigationController = UINavigationController(rootViewController: first)
        let n_bar_rgba = UIColor(red: 240/255, green: 240/255, blue: 10/255, alpha: 1)
        UINavigationBar.appearance().barTintColor = n_bar_rgba
        self.window = UIWindow(frame: UIScreen.main.bounds)
        self.window?.rootViewController = myNavigationController
        self.window?.makeKeyAndVisible()
        
        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }


}
```

だが、わからないぞ。
let first: 行こうなにをやっているか不明
また、appdelegata.swiftが起動前起動後動きを書いて行くのはわかったが、
なぜここでfirebaseの設定などを行うのか？？


今日はここまで
C#　メモリ上の数値の改ざんを防ぐ

#成果物
C#のコンソールテスト用です
https://github.com/Oinary/SecureValue/blob/master/Program.cs

#1.やりたいこと
・改ざんされちゃマズい数値を守りたい！（ゲーム内のHPやお金など）
・ファイルだけではなくメモリ上の数値も保護したい。(今回はInt型とFloat型)
#2.何を使えば出来るか
XOR（排他的論理和）で解決。
https://qiita.com/kuuso1/items/778acaa7011d98a3ff3a

簡単に言うと2進数で2つの数を演算したとき
片方がTrue(1)ならTrue。　　　　　　0 xor 1 → 1
両方がTrue又はFalse(0)ならFalse。　 0 xor 0 → 0

これって同じ値で演算しなおすと元の値に戻るんです。
1010 xor **0110** → 1100
1100 xor **0110** → 1010

科学の力ってすげぇ（てきとう
#3.実装してみた
まずXORを使うのには、元の値とそれを**合わせる値**が必要。
C#でランダムな整数をもらってきます。(これはちゃんと保存しましょう)

**Random.Next()**
https://docs.microsoft.com/ja-jp/dotnet/api/system.random.next?view=netframework-4.8

あとは **^** 演算子で保存、復元すれば解決！

```C#:SecureInt.cs
private int Seed;
private int Value;
public int _Value
 {
    get
    {
        return Value ^ Seed;
    }
    set
    {
        Seed = new Random().Next()//ランダムなInt
        Value = value ^ Seed;//あとはお好きに
    }
}
```

##3-1.そうは上手くいかなかった
Int型は何も問題なく実装できましたが…。
Float型ってXORを直接は使えない。（馬鹿には分からなかった。

##3-2.じゃぁどう回避しようか
ヒントがここにあった…。
https://qiita.com/nia_tn1012/items/d26f0fc993895a09b30b

Floatで後ろ23ビットは仮数部と呼ばれる、我々が目にする数が格納されているところがあります。
例　2.345 → 2345　（小数点を無くした値になります）
その仮数部を隠せば良さげです。
※これはイメージです

```C#:Sample
float F = 1.55f;//得たfloat
var I = BitConverter.ToInt32(BitConverter.GetBytes(F),0);//これをbyte[]にして、Int型にさせる
var SignificandPart = I << 9;//左に9ビットシフトすると仮数部だけ残る
var SecureValue = SignificandPart ^ Seed;//あとは煮るなり焼くなり
//戻すときはこの逆で
```

で出来上がりなのですが、まぁ操作多いんですよ。
なんかこう、もっとサクッとFloatをIntにできないんですかね…。

**・・・あったわ**

その参照記事の下に別の方法が書かれています。
ポインタを扱うこと ~~がポイント♪~~ で内部値をInt型で取得できます。

```C#:SecureFloat.cs
private int SecValue;
private int Seed;
public unsafe float _Value
{
   get
   {
       var result = SecValue ^ Seed;
       return BitConverter.ToSingle(BitConverter.GetBytes(result), 0);//戻すときは一度byte[]にしてからFloatに変換。
   }
   set
   {
      CalculatingSeed();
      int v = *((int*)&value);//&valueでvalueのポインタを取得、(int*)でInt型のポインタを格納、最初の*でそのポインタの値を指す。
      SecValue = v ^ Seed;//あとはお好きに
   }
}
```

ポインタの使用は、本来はバグなど意図しない動作を防ぐために制限されています。
それを解除するため、**unsafe** を明示します。**([VisualStudioの設定もお忘れずに][link-1])**
[link-1]:https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/compiler-options/unsafe-compiler-option

これで守りたい値の保護方法が実装できそうです。

#4.さいごに
不正の種類はいくつもあるので、それ相応の対応をしなければなりません。
が、あの手この手で不正してくるはずです。
実装するコストと見合っているかどうかも検討しないと、クオリティや製作時間に響いちゃいます。

僕みたいな初級の個人ゲームクリエイターならお遊び程度でいいんじゃないでしょうかね。

では初記事をご覧いただきありがとうございました。



**※ってか一番大事なメモリエディタの画像なくね？**
【今日のアブストラクト】Image-to-Image Translation with Conditional Adversarial Networks【論文 DeepL 翻訳】

1 日 1 回 論文の Abstract を DeepL 翻訳の力を借りて読んでいきます.

この記事は自分用のメモみたいなものです.
ほぼ [DeepL](https://www.deepl.com/home) 翻訳でお送りします.
間違いがあれば指摘していだだけると嬉しいです.

翻訳元
[Image-to-Image Translation with Conditional Adversarial Networks](https://arxiv.org/abs/1611.07004)

# Abstract

### 訳文

本研究では, 画像から画像への変換問題の汎用的な解決法として, 条件付き逆説ネットワークを検討している. このネットワークは, 入力画像から出力画像への写像を学習するだけでなく, この写像を学習するための損失関数も学習する. これにより, 従来は全く異なる損失定式化を必要としていた問題にも, 同じ汎用的なアプローチを適用することが可能となる. このアプローチは, ラベルマップからの写真の合成, エッジマップからの物体の再構成, 画像の色付けなどに有効であることを示す. 実際, この論文に関連したソフトウェア pix2pix が公開されて以来, 多くのインターネットユーザー (多くはアーティスト) が私たちのシステムを使った実験を投稿しており, パラメータを調整する必要がなく, 適用範囲が広く, 導入しやすいことが実証されている. コミュニティとして, 我々はもはや写像関数を手作業で設計する必要はなく, さらに本研究では, 損失関数を手作業で設計することなく妥当な結果を得ることもできることを示唆している.

### 原文

We investigate conditional adversarial networks as a general-purpose solution to image-to-image translation problems. These networks not only learn the mapping from input image to output image, but also learn a loss function to train this mapping. This makes it possible to apply the same generic approach to problems that traditionally would require very different loss formulations. We demonstrate that this approach is effective at synthesizing photos from label maps, reconstructing objects from edge maps, and colorizing images, among other tasks. Indeed, since the release of the pix2pix software associated with this paper, a large number of internet users (many of them artists) have posted their own experiments with our system, further demonstrating its wide applicability and ease of adoption without the need for parameter tweaking. As a community, we no longer hand-engineer our mapping functions, and this work suggests we can achieve reasonable results without hand-engineering our loss functions either.
Excelの機能を200%使ってRPAする方法とは？

# 対象読者

RPAでたくさんショートカットキーを使うよりも、いい方法が知りたい。
しかし、Excelファイルを直接読み書きするなどの高度なテクニックを使うとなると、勉強コストが掛かりすぎて手に負えない。
そんな絶妙な状況にいる人向けの記事として書きました。

（※ただし、超絶技巧Excel関数を使っています。）

# これぞジャンプメソッド

いきなりジャンプメソッドを紹介しますが、
これがなかなか便利でして。ご覧になっていただきたいと思います。

```py:
def jumpTo(WhereYouWannaGo):
	type("g",Key.CTRL)
	wait("JumpDialog.png",30) #ジャンプダイアログが出たことが確認できる画像

	paste(WhereYouWannaGo)
	type(Key.TAB*2,Key.SHIFT)
	type(Key.SPACE)
```

移動先のExcel内アドレスをジャンプ機能に渡しているだけです。
ただこの`WhereYouWannaGo`にゴリゴリにネストしたワークシート関数を仕込めば、
縦横無尽に好きなところにジャンプできてしまうのです。これは便利。


# ジャンプのバリエーション

このジャンプメソッドの何がおいしいかというと、
知っているワークシート関数の数だけ移動選択のバリエーションが豊富になるというところ。
普通にショートカットキーで移動していては、空白に制限されます。

例えば、`Ctrl`+`Shift`+`↓`で表の下まで選択するときに、
途中で未入力のセルがあると選択できないとかですね。

「それは`Ctrl`+`Shift`+`End`で解決するのでは？」
という声が聞こえてきそうですが、
表の下に別の表があったりしたら詰みです。

# ジャンプとは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/e3b748fd-c721-6024-6f4c-42c1853a909d.png)
これが噂のジャンプ機能のダイアログ画面です。
「ジャンプってなんだよ。そんなの使わないよ。」というのが普通だと思います。
わたしもRPAをSikuliXで始める前はそう思っていました。
その考えはRPAによって打ち砕かれました。以下の例をご覧ください。

```py
# 冒頭のジャンプメソッドを利用して

# 冒頭のジャンプメソッドを利用して

jumpTo("INDIRECT(\"R1C\"&TEXT(COLUMN(),\"@\")&\":R20C\"&TEXT(COLUMN(),\"@\"),FALSE)")

# 同じことをショートカットキーで行う場合のコード

# 同じことをショートカットキーで行う場合のコード

type(Key.UP*100, Key.CTRL)
type(Key.DOWN*20, Key.SHIFT, Key.CTRL)
```
すでに`Key.UP*100`とかやってしまっているので、
100行目より下にカーソルがいかない前提も必要なことがわかると思います。

***「でもジャンプならそんな心配りは要らない！！」***


# 環境

冒頭のジャンプメソッドは、こんな構成で使用できます。
- Sikulix 2.0.4
- Open JDK 12
- Excel 2013
- Windows 10 64bit
- AAAシステム
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/49b98d12-248e-1c25-260f-17341d0add99.png)
- Excel
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/85d73743-5f34-e5f6-8c66-191ffcbf4005.png)

# 実現すること

- ExcelファイルからAAAシステムへ複数項目をコピーペーストする
- できる限り効率的に行う

# さあコピペを自動化しましょう

Aさん「これを使うとRPAができるんですね」
Bさん「さっそく今日から自動でAAAシステムにExcelからコピペしてください」
Aさん「わかりました、わたしちょっとできる子なのでショートカットキーとか使ってスマートにできますよ！」
Aさん「Excelを開くコマンドの後に`↓`キーで、次に`Ctrl+C`で…」
Aさん「AAAシステムを開くコマンドの後に`↓`キーで、次に`Ctrl+V`で…」

```py:
for i in range(2):
    App.focus(ExcelApp)
    type(Key.DOWN, Key.CTRL)
    type("c", Key.CTRL)
    App.focus(AAAApp)
    type(Key.DOWN, Key.CTRL)
    type("v", Key.CTRL)
```

# 荷物はまとめて持っていこう

Bさん「なんだか、ウィンドウの切り替えが目まぐるしいですね」
Aさん「それに、コピーのタイミングで再描画処理が発生するから`wait()`を入れないと不安定なんですよね。」
Aさん「これだと端末のスペックに影響を受けるから別端末に移植もできないです。」
Bさん「うーん、一気にコピーしてみてはどうでしょう」
Aさん「それいいですね」
Aさん「Excelを開くコマンドの後に`Ctrl+Shift+↓`キーで、次に`Ctrl+C`で…」

```py:
type(Key.DOWN*20, Key.SHIFT, Key.CTRL)
type("c", Key.CTRL)
```

# まとめた荷物を切り分ける

Aさん「あれ？貼り付けるときどうするんですか？」
Bさん「`split()`して配列として扱うと順番に貼り付けできますよ」

```py:
App.focus(AAAApp)
fromExcel=App.getClipboard()
Ecells=fromExcel.split("\n")
paste(Ecells[0])
```

# ジャンプメソッドの出番

Aさん「あれ？セルの選択位置が`B1`ならいいけど、`M68`だったり、ずれてると上手くいかないですね」
Aさん「しかも、選択したいセル範囲の中にランダムに空白セルが混ざっているとしたら」
Aさん「`Ctrl+Shift+↓`を何回実行したらいいのかわからないですね」
Aさん「どうしたらいいんでしょう？」
Bさん「ジャンプしてみてください」
Aさん「ぴょんぴょん」
Bさん「いやいやジャンプメソッドを」

```py:
jumpTo("B1:B2")
```

**Excelsior!**
マルチプラットフォーム対応のターミナル「Hyper」

![hyper_plugin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81919/807b8c51-5814-6514-cc48-d27aecf2200d.png)


# 「Hyper」ターミナル
　マルチプラットフォームなターミナル「Hyper」がなかなかよさそうだったのでメモ。Win/Mac/Linuxで使えます。

## インストール方法
### Windows
　Windowsの場合は、サイトから`.exe`をダウンロードして、ダブルクリックしましょう。

https://hyper.is/#installation

### Mac
　Macの場合は、Homebrewが入っていたら、以下コマンド実行するだけでOKです。

```sh
$  brew install hyper
```

　Homebrewを知らない方は、以下記事参照下さい。

[Macのパッケージ管理ソフトウェア 「Homebrew」「Homebrew Cask」でソフトウェアを簡単にインストール・管理しよう](https://karaage.hatenadiary.jp/entry/2016/05/13/073000)

### Linux
　Linuxの場合は、以下サイトから`.deb`パッケージをダウンロードして、ダブルクリックしてインストールしましょう。

https://hyper.is/#installation

　アップデートの場合は、一旦削除してからインストールになります。

　`.AppImage`をダウンロードして、`chmod 755`で実行権限与えて、実行しても動きます。

## Hyper起動
　以下コマンドで動きます。

```sh
$ hyper
```

　起動画面は以下です。おしゃれ。

![hyper_normal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81919/6f24ffda-a881-2da4-a563-a69bd68ce4ef.png)


## テーマの変更
　以下のように実行します。

```sh
$ hyper i hyper-solarized-light
```


![hyper_solarized.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81919/c12e312f-1d7d-10bb-5ba5-38e48690bdd0.png)

　テーマは、以下の公式サイトで探すことができます。

[Hyper](https://hyper.is/)

## プラグイン
 テーマと同じように`hyper i xxx`と実行していけば良いのですが、`~/.hyper.js` の設定ファイルのpluginに以下のように書いて、Hyperを「View -> Reload」でリロードするか、起動しなおせば記載したプラグインがインストールされます。

```
plugins: ["hyper-solarized-light", "hyper-statusline", "hyper-search", "hypercwd", "hyper-opacity", "hyper-pane", "hyper-tab-icons-plus"],
```

　色々プラグインを入れると以下のようにオシャレになります（.bashrcも変更の必要あり、参考リンク参照）。

![hyper_plugin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81919/807b8c51-5814-6514-cc48-d27aecf2200d.png)

## 設定ファイル（`.hyper.js`）のコマンドでの反映
　GitHubに設定ファイルアップしておけば、コマンド一発で設定を反映できます。以下は、自分の設定ファイルの例です。Mac/Linuxで共通です（Windowsは未検証）。

```sh
$ curl https://raw.githubusercontent.com/karaage0703/mac-dotfiles/master/.hyper.js > ~/.hyper.js
```

　古いバージョンだと、設定ファイルの場所が`~/.config/hyper/.hyper.js`かもしれません。

　また、curlコマンドが入っていない場合は、あらかじめインストールしておきましょう。

# まとめ
　「Hyper」ターミナルおしゃれなので使ってみようかなと思います。自分の設定ファイルは、以下のGitHubリポジトリにアップしました。

[karaage0703/mac-dotfiles](https://github.com/karaage0703/mac-dotfiles)


　さらに仮想ターミナルを使いたい場合は、以下記事参照下さい。

[byobuで仮想端末入門（Mac/Linux/Raspberry Pi）](https://karaage.hatenadiary.jp/entry/2016/04/22/073000)

# 関連記事
[Macの.bashrcセットアップ](https://karaage.hatenadiary.jp/entry/2016/03/30/073000)

# 参考リンク
- https://qiita.com/ucan-lab/items/ed0687e9cd4a8ea7c76c

# 変更リンク
- 2020/08/10 設定ファイルのコマンドでの反映に関して追記
テレワークで役立つAmazon Workspacesをちゃんと監視できるのか？

# 概要
- 2020/04/07、緊急事態宣言が発令したこともあり、どこの企業もテレワークや在宅勤務
- AWSの「Workspaces」で環境をサクッとバリッと作成
- ちゃんとCloudTrailで監査ログ見れることを確認

# 対象読者
- テレワーク・在宅勤務を推奨している会社の情報システム部などの人
- テレワークするための論理武装したい人
- Workspaces好きで推進したい人
- CloudTrail好きな人

## 事の発端
ずっと前々から騒がれていたことですが、2020/04/07にとうとう緊急事態宣言が発令しました。これに伴い、どこの企業もテレワークや在宅勤務が発動しています。
筆者の周りでも強烈な動きが巻き起こっており、一斉に環境構築がなされています。

## Workspacesでやっちゃえば？
筆者はクラウドサービスのなかでAWSに最も慣れており、AWSが最も好きです。そう、AWSにはリモート環境が用意されています。それが「[Amazon Workspaces](https://aws.amazon.com/jp/workspaces/)」です。Amazon Workspacesを使うと、Windows または Linux のデスクトップが数分でセットアップできちゃいます。加えて、**追加コストを払えばOfficeソフトをつけたWindowsもセットアップできます**。

他のソリューションでもいいのですが、かんたんにスケールして多くの企業で使われているOfficeを使わなきゃいけないという要件は意外と辛いのですが、これなら解決できそうです。

## ちゃんとログとれるよね？
ここからが本題です。使うはいいけど、誰が使ったか情報システムとかに関わる人は気になりますよね。上から、本当に大丈夫とか言われて、ログもとってるんで大丈夫って言えたら楽ですよね。
となったのでちゃんと確認しとこうとなりました。

AWSでサービスを利用したログを確認となったら「[AWS CloudTrail](https://aws.amazon.com/jp/cloudtrail/)」です。

[こちら](https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudtrail-track-api/)を見ていただいたら分かる通り、CloudTrailの情報を確認する経路はたくさんあります。サポートされるサービス種類は下記のとおりです。

https://docs.aws.amazon.com/ja_jp/awscloudtrail/latest/userguide/cloudtrail-aws-service-specific-topics.html#cloudtrail-aws-service-specific-topics-integrations

よし。Workspaces入ってるから問題ない。

## CloudTrail dashboardから確認
ログ取れていることみたいだけなのでダッシュボードから確認します。なお、CloudTrailで気をつけるべきはログ転送までに15分程度かかることです。[よくある質問](https://aws.amazon.com/jp/cloudtrail/faqs/?nc1=h_ls)にも記載があります。WorkSpacesにアクセスして、ダッシュボードから確認してみましょう。

<img width="1199" alt="Screenshot 2020-04-07 23.27.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123578/73bf9b5e-f65f-761d-3974-ce0b8c626e86.png">

問題なく取れてますね。よかったよかった（なんか時間が少し古いような・・・）。

## ダッシュボードにログが出てこないときは・・・
当方最初ダッシュボードから検索しても何もHITしませんでした。もちろん15分以上時間を撮ってアクセスしています。あれーー？ってなっててS3にストアされているログをあさりにいきました。S3から復元するのはめんどくさいので、Amazon Athena（S3に対してSQL文を発行してインタラクティブにログ検索できるサービス）を使いました。CloudTrailログをAthenaで検索することは割と簡単です。CloudTrailの画面上にある「探していたものが見つからない場合は、 Amazon Athena で高度なクエリを実行します」の手順に沿ってS3のバケットの設定などをしていくと利用できます。

Athenaを使うとごそっとログが抽出でき、最近の時間のものまで取得ができました。極力リアルタイムにすべてのログを抜き取るときはCloudTrailダッシュボードではなく、Athenaを利用して、Workspacesのログを取得したほうがよいことがわかりました。

<img width="1431" alt="Screenshot 2020-04-07 23.38.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123578/7da1be05-4d46-a171-be52-bca8e1185606.png">


# まとめ
- こんな状況なので、できる限りテレワークや在宅勤務をしましょう。
- Workspacesを使えば比較的カンタンにサクッとリモート環境構築できます。
- CloudTrailでWorkspacesのログを見るときはダッシュボード、見つからなくて急ぎのときはAthenaを使いましょう。
Azure VNET における同一サブネット周りの簡単な動作確認

# はじめに

Azure の VNET 周りの動作で、下記のようなポイントを改めて確認したので、残しておこうと思います。

1. 同一 VNET のサブネット間は、既定ではルーティングされる
2. 特に NSG を設計しなくても、相互に通信ができる
3. 逆に、ある程度制限したい場合は NSG を作れば対応できる

### 構成図

<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218221/900ed479-4d48-8446-0e76-0215f51b7f86.png">

## 1. 同一 VNET のサブネット間は、既定ではルーティングされる

問題なくいけました。

```shell
$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         _gateway        0.0.0.0         UG    100    0        0 eth0
10.0.3.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
168.63.129.16   _gateway        255.255.255.255 UGH   100    0        0 eth0
169.254.169.254 _gateway        255.255.255.255 UGH   100    0        0 eth0

$ ping 10.0.4.4
PING 10.0.4.4 (10.0.4.4) 56(84) bytes of data.
64 bytes from 10.0.4.4: icmp_seq=1 ttl=64 time=1.17 ms
64 bytes from 10.0.4.4: icmp_seq=2 ttl=64 time=1.37 ms
64 bytes from 10.0.4.4: icmp_seq=3 ttl=64 time=1.09 ms
^C
--- 10.0.4.4 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 1.094/1.212/1.370/0.116 ms
```

## 2. 特に NSG を設計しなくても、相互に通信ができる

上記は ping ですが、HTTP なども問題なく通信できます。

```shell
$ curl http://10.0.4.4/

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xh
tml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <!--
    Modified from the Debian original for Ubuntu
    Last updated: 2016-11-16
    See: https://launchpad.net/bugs/1288690
  -->
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Apache2 Ubuntu Default Page: It works</title>

以下略
```

## 3. 逆に、ある程度制限したい場合は NSG を作れば対応できる

下記のような NSG を作成し、それぞれの Subnet に割り当てます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218221/af941c12-51eb-f078-42a3-57391fa053d5.png)

```shell
$ curl http://10.0.4.4/
curl: (7) Failed to connect to 10.0.4.4 port 80: Connection timed out
```

ということで、通信制限ができました (DROP ですね)。

# 最後に

ちょっと話はそれますが、[Draw.io](https://app.diagrams.net/) 良いですね。冒頭のネットワーク図はコレで作成しました。

-----
Perl List::Util::pairs で解く AtCoder Judge System Update Test Contest 202004 B

# はじめに
いつもお世話になっております *[AtCoder](https://atcoder.jp/home)* で、新しいジャッジシステムの負荷テストを兼ねたコンテストが行われました。
*[Perl AtCoderのアップデートを先取りしてライバルに差をつけよう(List::Util他)](https://qiita.com/superrino130/items/eeec1fe627e934262042)* にて下準備をしていましたので、それを使用し動作の確認をしてみました。

# B - Picking Balls
*[AtCoder Judge System Update Test Contest 202004 B - Picking Balls](https://atcoder.jp/contests/judge-update-202004/tasks/judge_update_202004_b)*
従来環境（すなわち、List::Util::pairs 等が無い）でしたら、赤ボール・青ボールそれぞれの配列を準備して、解答します。

```before.pl
use v5.18; # strict say state
use warnings;

chomp (my $n = <STDIN>);
my (@r, @b);
for my $i (0..$n-1) {
  chomp (my @a = split / /, <STDIN>);
  if ($a[1] eq 'R') {
    push @r, $a[0];
  } else {
    push @b, $a[0];
  }
}
@r = sort {$a <=> $b} @r;
@b = sort {$a <=> $b} @b;
say $_ for (@r, @b);
```
# リファレンス
配列のリファレンスを使用した解法

```ref.pl
use v5.18; # strict say state
use warnings;

chomp (my $n = <STDIN>);
my @p;
for my $i (0..$n-1) {
  chomp (my @a = split / /, <STDIN>);
  $p[$i] = [$a[0], $a[1]];
}
my @q = map {$$_[0]} sort { $$b[1] cmp $$a[1] || $$a[0] <=> $$b[0] } @p;
say $_ for @q;
```
2次元配列として処理をしています。
# pairs の使用例１
先頭の **use v5.26** が光っていますね。

```after1.pl
use v5.26; # strict say state biwise
use warnings;
use List::Util qw(pairs);

chomp (my $n = <STDIN>);
my @p;
for my $i (0..$n-1) {
  chomp (my @a = split / /, <STDIN>);
  push @p, $a[0];
  push @p, $a[1];
}
my @q = map {$$_[0]} sort { $b->value cmp $a->value || $a->key <=> $b->key } pairs @p;
say $_ for @q;
```
配列 @p = (10, 'B', 6, 'R', 2, 'R', 4, 'B'); を
pairs @p とした場合、下記の状態として扱うことができます。

|keys|values|
|:--:|:--:|
|10|B|
|6|R|
|2|R|
|4|B|
ハッシュと異なり、**keys** の値が重複していてもそのまま使用可能です。
# pairs の使用例２
```after2.pl
use v5.26; # strict say state biwise
use warnings;
use List::Util qw(pairs unpairs pairkeys pairvalues pairfirst pairgrep pairmap);

chomp (my $n = <STDIN>);
my @p;
for my $i (0..$n-1) {
  chomp (my @a = split / /, <STDIN>);
  push @p, $a[0];
  push @p, $a[1];
}
my @r = sort {$a <=> $b} pairkeys pairgrep {$b eq 'R'} @p;
my @b = sort {$a <=> $b} pairkeys pairgrep {$b eq 'B'} @p;
say $_ for (@r, @b);
```
pairkeys や pairgrep 等も使用可能です。

仮に仕様が変更され緑ボールや黄ボールが追加されても、最小限の修正で対応できます。
# まとめ
+ *AtCoder* の新環境は *Perl v5.26.1* となり、*List::Util* が拡張された
+ *pairs* を使用することにより、データ構造が簡易に構築できるようになった


参照したサイト
*[List::Util](https://perldoc.perl.org/5.30.0/List/Util.html)*
*[Perl AtCoderのアップデートを先取りしてライバルに差をつけよう(List::Util他)](https://qiita.com/superrino130/items/eeec1fe627e934262042)* *
期間限定無料の Unity Learn Premium の ML-Agents: Penguins が良かった

Unity Learn Premium が無料で提供されているものの、たくさんあるし、英語だしと怯んでいましたが、その中の一つをやってみたらとても良かったというお話です。

# 良かった理由

1. わずか5時間で、
2. 環境構築から始まって強化学習させたモデルを利用した、
3. 魚を採って子どもに与えるペンギンを作って動かす体験ができます

![ml-penguin.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/6f63cf6a-6c96-1997-cac3-c75b281bf728.gif)

どうやって学習するの？なにこの数値？とか、
なんかわからないから難しい、怖いというところから脱することができます。


## 5時間
頑張れば1日でできるぐらいの量なのが良いと思っています。長いと疲れるし、途中でき飽きちゃいますが、やるぞって決めてやり切れるぐらいの量。間延びしても2日あればやり切れるぐらい。

## 強化学習させたモデル
環境構築から始めたにもかかわらず、終わるときには学習した結果（モデル）が手元に残ります。Unity と python の繋ぎこみや、Machine Learningに必要な知識がある程度のレベルに隠蔽されているので、詰まることもありません。

## 動くペンギン
学習させた数値だけ見ていても実感はわきませんが、これは実際に魚を捕まえるのがうまくなったペンギンを見ることができます。Unity の良さでもあり、そしてその Unity の良さをきちんと体験できるものだと思いました。

# どういう人にオススメ？
* Machine Learning に興味があるけど、まだ知識がない人
* Unity やってるけど、単純なのに飽きてきた人
* 無料でやりたい人
* 英語できなくても、google 翻訳でなんとかなります（自分はなった）
* [ちょっと厳しい人](https://qiita.com/matchyy/items/3bfa0d6d2f30b9391034#%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E5%8E%B3%E3%81%97%E3%81%84%E4%BA%BA)

# 時間はどれぐらい？
サイトでは約2.5時間となっていますが、ダウンロードとか、間に色々挟まったりして5時間程度かかりました。
（Unity や IDE はインストールした状態から開始しています。）

# 肝心の講義はこちら
* [ML-Agents: Penguins](https://learn.unity.com/project/ml-agents-penguins)

### 注意
一番ハマったのが ML-Agents のバージョンです。更新が順次入っているので、このサイトのバージョン（0.13.x, 私は0.13.1でやった）に合わせてやったほうが良いです。そうでないとプログラムとかをいちいち最新バージョンに合わせて修正しないと動きません。

# 補足
## これだけでは足りない（当たり前）
* ハイパーパラメーターや学習モデルの話とかは、良くも悪くも出てこないので、そういうところは全く理解できません
* 横展開したくても、現状のバージョンはペンギン専用らしいです

## Unity Learn Premium が無料
[「Unity Learn Premium」を3か月間無料化(6月20日まで)](https://twitter.com/unity_japan/status/1247358435735359488)　
<img width="604" alt="スクリーンショット 2020-04-07 22.14.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/14d70289-7082-1de0-7a04-e5b97df15c04.png">

## ちょっと厳しい人
体験はできると思うけど、意味があるかは？が付くという意味で、ちょっと厳しい。

* プログラムほとんど書けない人
    * 基本的な構文（if/for)とかが何か見ないと書けない人
* Unityほとんど知らない人
    * Start/Update/FixedUpdate/rigidbody/GameObject を知らないレベルの人