OmniAICreator/Qiita-1.07M huggingface dataset:
快適コマンド生活(基本編)

Windows、Mac、Linux(Ubuntu)などの色々な環境でコマンド操作を行うため
よく使うコマンドをまとめてみました。
Qiita右側に表示されるアウトラインから選んで確認してください。

# 対象のOS

- Windows8,Windows10
- MacOSX HighSierra
- Ubuntu 14-18

# このまとめのポイント

- コマンドでファイルが探せる
- コマンドでエディタを起動、編集できる
- ~/でクライアントOSのホームディレクトリを指定可能

# Windows

- 開発用途のマシンであればGit(GitBash)が入っているかと思いましたのでGitBashを入れています。
- WSLについては~/でのWindowsのホームディレクトリの指定が出来ないので入れていません。

## コマンドプロンプト

### 1.ホームディレクトリに移動

```dos
> cd %HOMEPATH%
```

### 2.現在のディレクトリのパスを確認

```dos
> @cd
```

### 3.現在のディレクトリの全ファイルを確認

```dos
> dir /a
```

### 4.ファイルを移動

```dos
> rename "移動元ファイルパス" "移動先ファイルパス"
```

### 5.ファイルを削除

```dos
> del "ファイルパス"
```

### 6.ファイルを編集(メモ帳)

```dos
> notepad "ファイルパス"
```

### 6.ファイルを編集(vscode)

```dos
> code "ファイルパス"
```

### 7.キーワードの含まれたファイルを探す(ファイル名)

```dos
> dir "*ファイル名*" /S /B
```

### 8.キーワードの含まれたファイルを探す(内容)

```dos
> findstr "キーワード" ./*
```

### 9.ファイルマネージャを開く

```dos
> explorer
```

## PowerShell

### 1.ホームディレクトリに移動

```powershell
> cd ~/
```

### 2.現在のディレクトリのパスを確認

```powershell
> pwd
```

### 3.現在のディレクトリの全ファイルを確認

```powershell
> ls -Force
```

### 4.ファイルを移動

```powershell
> mv "移動元ファイルパス" "移動先ファイルパス"
```

### 5.ファイルを削除

```powershell
> rm "ファイルパス"
```

### 6.ファイルを編集(メモ帳)

- 終了はAlt+F4

```powershell
> notepad "ファイルパス"
```

### 6.ファイルを編集(vscode)

- 矩形選択が出来るためこちらを使用したい時があります。
- 終了はAlt+F4

```powershell
> code "ファイルパス"
```

### 7.キーワードの含まれたファイルを探す(ファイル名)

```powershell
> ls -Recurse -Filter "ファイル名の一部"
```

### 8.キーワードの含まれたファイルを探す(内容)

```powershell
> ls -Recurse | Select-String "キーワード"
```

### 9.ファイルマネージャを開く

```powershell
> explorer
```

## GitBash

### 1.ホームディレクトリに移動

```shell
$ cd ~/
```

### 2.現在のディレクトリのパスを確認

```shell
$ pwd
```

### 3.現在のディレクトリの全ファイルを確認

```shell
$ ls -alF
```

### 4.ファイルを移動

```shell
$ mv "移動元ファイルパス" "移動先ファイルパス"
```

### 5.ファイルを削除

```shell
$ rm "ファイルパス"
```

### 6.ファイルを編集(Vim)

- 保存して終了はEsc :wq Enterの順に入力

```shell
$ vi "ファイルパス"
```

### 7.キーワードの含まれたファイルを探す(ファイル名)

```shell
$ find | grep "ファイル名の一部"
```

### 8.キーワードの含まれたファイルを探す(内容)

```shell
$ grep "キーワード" -r ./
```

### 9.ファイルマネージャを開く

```shell
$ explorer
```

# Mac

### 1.ホームディレクトリに移動

```shell
$ cd ~/
```

### 2.現在のディレクトリのパスを確認

```shell
$ pwd
```

### 3.現在のディレクトリの全ファイルを確認

```shell
$ ls -alF
```

### 4.ファイルを移動

```shell
$ mv "移動元ファイルパス" "移動先ファイルパス"
```

### 5.ファイルを削除

```shell
$ rm "ファイルパス"
```

### 6.ファイルを編集(Vim)

- 保存して終了はEsc :wq Enterの順に入力

```shell
$ vi "ファイルパス"
```

### 7.キーワードの含まれたファイルを探す(ファイル名)

```shell
$ find ./ | grep "ファイル名の一部"
```

### 8.キーワードの含まれたファイルを探す(内容)

```shell
$ grep "キーワード" -r ./
```

### 9.ファイルマネージャを開く

```shell
$ open ./
```

# Linux

### 1.ホームディレクトリに移動

```shell
$ cd ~/
```

### 2.現在のディレクトリのパスを確認

```shell
$ pwd
```

### 3.現在のディレクトリの全ファイルを確認

```shell
$ ls -alF
```

### 4.ファイルを移動

```shell
$ mv "移動元ファイルパス" "移動先ファイルパス"
```

### 5.ファイルを削除

```shell
$ rm "ファイルパス"
```

### 6.ファイルを編集(Vim)

- 保存して終了はEsc :wq Enterの順に入力

```shell
$ vi "ファイルパス"
```

### 7.キーワードの含まれたファイルを探す(ファイル名)

```shell
$ find | grep "ファイル名の一部"
```

### 8.キーワードの含まれたファイルを探す(内容)

```shell
$ grep "キーワード" -r ./
```

### 9.ファイルマネージャを開く

```shell
$ pcmanfm
```

## 所感

コマンドプロンプトでも意外と色々出来る！
ええ加減、ちょっとずつでもScalaの基礎を理解する　implicitによる拡張メソッド　（enrich my library パターン）

<font color="Red">※2019/06/06追記
本の続きを読んだら、暗黙の型変換によるメソッドの拡張は、冗長で非推奨とのことでした。代わりに奨められていた暗黙クラスによる拡張メソッドについて、追記をしました。</font color>

# ええ加減、理解しないと
あんま分かってない概念を咀嚼して、理解したことをまとめていきます。
だいぶざっくりなので、間違いがあれば指摘をいただけると大変ありがたいです。

基本的には、『技術評論社　実践Scala入門』に沿って、気になる点を適宜記事にしていく方向です。

# 環境
Java: 11.0.2
Scala: 2.12.7

# はじめに
implicit には別の使い方もある
http://kmizu.hatenablog.com/entry/2017/05/19/074149 こちらのブログが非常にわかりやすかったです。
今回は、このブログでいうところの「拡張メソッド」の使い方ですね。ほかについては、学習が進み次第まとめていきます。


# 「拡張メソッド」とは

既存のクラスの、メソッドを拡張すること。
実際に行っているのは、クラスの改変ではなく、「このメソッドが呼ばれたときには、別のクラス扱いにしてね」という取り決めを暗黙に行っているだけ。

# 例
開発中のプロジェクトにおいて、String型の末尾に"----"と表示する場面が頻繁にある。毎回書くのはもちろん大変なので、String型のオブジェクトに、「自分自身の末尾に"----"を加える」というメソッドを加えることにした。

「与えられたString型の引数の末尾にハイフンを加えて返す」関数を作って毎回使用するパターンも考えられる
（`appendBorder("foo")` の返値が `"foo----"`になるみたいな感じで）
場合によるのかな。コード書く量はどっちもどっちな気が。あまりいい使いどころの例が思いついておりません。


やることは、

1. 新たなクラス`RichString`を作り、そこに加えたいメソッド`appendBorder`だけ実装する
2. `implicit`を使い、Stringオブジェクトに対してappendBorderが呼ばれたときは、その時だけRichStringとして扱うようにするように宣言。
「String型は、いざとなればRichStringになれるよー」と暗黙に宣言しておく。
「いざとなれば」というのは、RichStringにしか存在しないappendBorderをString型に対して呼んだ場合、ということ。


#　実際に書いてみる

```RichStrng.scala

import scala.language.implicitConversions // implicitで拡張メソッドを利用する際は、これつけないと警告が出る。エラーにはならない

object RichString extends App {

  class RichString(val self: String) {

    def appendBorder: String = self + "----"

  }
  implicit def enrichString(self: String): RichString = new RichString(self)

  println("test".appendBorder) // "test----" String型だが、appendBorderが呼ばれているので一時的にRichString型に変換される
  println("test".getClass) // java.lang.string あくまでも、普段はString型
  
}

```


個人的には、あまり使いどころというか、便利さが分かっていないが、人のコードで見かけたこともあり、理解しておいたほうがよいのかな。
はじめにも書いたけど、implicitについては、型クラスなど、ほかの使い方がかなり重要っぽいので、そっちも次回やる。

↑　正しい感想だった笑

Scala2.10以降では、クラスを暗黙に定義することで、メソッドの拡張ができるようになったので、こっちを使いましょう。

# 暗黙クラスによる拡張メソッド

先ほどのコードは、以下のように書けます。

```scala
import scala.language.implicitConversions

object RichString extends App {

  implicit class RichInt(val self: String) {
    def appendBorder: String = self + "----"
  }

  println("test".appendBorder) // "test----"
  println("test".getClass) // java.lang.String
}

```

暗黙にするものが、型変換ではなく、クラス定義そのものになったということですね。

こっちの方が全然すっきりしますね。

ただ、それでもやっぱりコードの可読性が落ちるというか、専用のメソッドを作って逐一String型に使う方が自分的にはいい気がしますが。

今後、使いどころを見つけていきたいと思います。
SSH接続について調べた

SSHについて大まかな流れだけでも知っておきたいので、調べたことをまとめておきます。

## まずSSHっと何？
SSHはHTTPとかと同じプロトコルの一つです。ただ通信中の情報は暗号化されていて中身を覗かれることがないから安全だね！というやつ。サーバーやネットワーク機器に接続し何か操作したいとき、サーバーとのやりとり(パスワードとか個人情報とか)が第三者に見られたら大変なことになるから、暗号化して見られても中身がわからないようにしておくために使う。

## SSHの仕組み
SSHは公開鍵認証方式が主に使われています。これは公開鍵と秘密鍵という二つの鍵を用意し、公開鍵とペアになる秘密鍵がないと暗号化された通信の中身を知ることができないという仕組みになっています。二つの鍵の中身は意味不明な文字列が並んだファイルです。
公開鍵はサーバー側に秘密鍵は自分で所持します。サーバーは公開鍵からユーザーの認証を行った後、公開鍵と乱数から暗号を作成してくれます。この暗号をPCに送り、ユーザーは自分がもつ秘密鍵で暗号を複合します。するとサーバー側で作られた乱数が出てきます。この乱数からハッシュ値をサーバー側に送り、サーバーはハッシュ値を比較し、合っていたら認証されます。これで接続先が正しいことが分かり、SSH接続ができるようになります。
IntelliJ IDEA 2019.1 で Kotlin で mobile project を新規作成したら sync でエラー

# TL;DR

- IntelliJ IDEA 2019.1 で Kotlin で Mobile アプリでも作ろうかと思ったら新規プロジェクト作っただけでエラー
- gradle 4.7 が悪いらしい
- gradle をバージョンアップしたらいけたのでメモ
- PROJECT_HOME/gradle/wrapper/gradle-wrapper.properties の distributionUrl を https\://services.gradle.org/distributions/gradle-4.7-bin.zip から https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip にする

# log

- IntelliJ 2018.3 を 2019.1 にバージョンアップ（なんか勝手に飛んできたから
- Kotlin を薦められたのでハロワした。うまくいった
- じゃあ次はモバイルアプリかってんで new project
- sync ってところでエラー

```
Gradle sync failed: Cause: sun.misc.Unsafe.defineClass(Ljava/lang/String;[BIILjava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class; Consult IDE log for more details (Help | Show Log) 
```

- そのままぐぐると https://github.com/gradle/gradle/issues/4860
- https://intellij-support.jetbrains.com/hc/en-us/community/posts/360001797360-New-project-on-IntelliJ-idea-Kotlin-Native-Unable-to-find-method
- https://youtrack.jetbrains.com/issue/KT-28552
- わからぬ。。。
- gradle のバージョンが4.7とかだとエラーになるらしい
- 設定的には gradle ラッパーを使っている
- バージョン設定どこだよ（プラグインの設定等にはないっぽい）
- https://pleiades.io/help/idea/gradle.html
- PROJECT_HOME/gradle/wrapper/gradle-wrapper.properties か！確かに4.7とか書いてある
- 最新のURLはどこよ
- https://gradle.org/releases/
- むう。なんかURIがちょっと違う気がする
- https://gradle.org/install/
- お、これっぽい
- https://docs.gradle.org/5.4.1/userguide/gradle_wrapper.html
- あった。これだ。

``` gradle-wrapper.properties
# distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
```

- 保存したところ自動で再度syncが実行されてダウンロードが始まりしばらく待ったら成功になった

# note

- 普段から使い慣れてる人には大したことではないのかもだけど不慣れだと何かなんだか
- qiita ならメモっておけばそのうちどっかで検索にひっかかるようになるかと思ってメモ
- ブログ書けよって話ｗ
Fork 元とローカルのレポジトリを同期するエイリアスを考える

## 概要

題名の通り。 Fork 元との同期は忘れがちであり、かつコマンドもよく忘れてしまう。 `git fetch upstream` -> `git rebase upstream/master` みたいな形ではあるが、どうも忘れがち。

そこでエイリアスに登録してしまおう、というのが主目的となる。

## 私の環境

* OS: MacOS 10.14
* Git version: 2.21.0
* Shell: zsh 5.7.1-dev-0

以降については、この環境で検証しているため、特に他の OS 、 Shell の場合は動作保証ができない。（特殊なコマンドを使っていないので、 grep コマンドの動作だけ怪しいが、少しいじれば動くものとは思われる）

## 生成物
### 前提条件

`git remote add upstream` で upstream に Fork 元のリポジトリを登録しておく。

不安なら Git リポジトリのルートで `cat .git/config` とかで見とくと安心。こんな感じのものがあるはず。( `yumechi` を自分のユーザー名、 `kashikoma` を Fork 元、 `mirei` をリポジトリ名として見てください)

```config
# （前略）
[remote "origin"]
	url = git@github.com:yumechi/mirei.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[remote "upstream"]
	url = git@github.com:kashikoma/mirei.git
	fetch = +refs/heads/*:refs/remotes/upstream/*
# （後略）
```

また、 upstream の同期したいブランチ名と、ローカルのブランチ名が一致していることを確認する。一致してない場合は checkout する。（ master に同期したい場合は `git checkout --track origin/master` とかで一旦ローカルを master にしておく）

### alias

```shell
    upstream-pull = "!f () { if git remote | grep upstream -q; then b=$(git rev-parse --abbrev-ref HEAD); git fetch upstream; git rebase upstream/"$b"; unset b; else echo '** error: set upstream !! **'; fi }; f"
```

https://www.shellcheck.net/ で異常がないか確認しつつ、整形したので多分問題ないはず。

### 使用してる関数を整形したもの

見づらいので、整形版を張っておく。

```shell
    upstream-pull = !"f() { \
    if git remote | grep upstream -q; then \
        b=$(git rev-parse --abbrev-ref HEAD); \
        git fetch upstream; \
        git rebase upstream/"$b"; \
        unset b; \
    else \
        echo '** error: set upstream !! **'; \
    fi \
    }; \
    f"
```

現在のブランチを upstream に同期するようにしているが、 master ブランチだけでもよかったのでは？ という考え方もある。しかし、デフォルトブランチが master でない場合も自分が関わっている範囲でたまにあるため、現在のブランチを同期するようにしている。そのため、同期したいブランチはこのコマンドを打つ前に checkout しておく必要がある。

## あとから見た記事

基本的に自分でコマンドを書いていたので、 Qiita 上で探していなかったが、とりあえず良さそうだと思ったのを貼る。

* フォークと本家を同期させる Git エイリアス
    * https://qiita.com/ybiquitous/items/bc1af6655e340ff853e8
    * 公式リファレンスを引いて、コマンドをベタでつなげてるだけっぽいが、 GitHub のドキュメントを私は探しに行かなかったので参考になった
* よく使うgitコマンド一覧
    * https://qiita.com/suzukihi724/items/3fcfb891f5768293404c#3-%E3%83%8F%E3%83%9E%E3%82%8A%E7%B3%BB
    * ハマり系がすごいわかりやすい（今日書いた alias も適当に書いたものなので、ハマり系になりそうな気はする（が、それもまた経験ということでハマってなれたらササッと解決したいと思う））
numpyを使わずにリストの転置

わざわざnumpyをimportするまでもない時は以下の手順で転置できる。
(shiracamusさんにコメントを頂き、より簡潔に修正致しました。ありがとうございます。)

~~~Python
>>> A = [[1,2],[3,4],[5,6]]
>>> AT = [*zip(*A)]

>>> A
[[1, 2], [3, 4], [5, 6]]
>>> AT
[(1, 3, 5), (2, 4, 6)]
~~~

タプルになるのが気に入らないなら以下。

~~~Python
(1)
>>> AT = [[*a] for a in zip(*A)]
>>> AT
[[1, 3, 5], [2, 4, 6]]

(2)
>>> AT = [*map(list, zip(*A))]
>>> AT
[[1, 3, 5], [2, 4, 6]]

(3)
>>> *AT, = map(list, zip(*A))
>>> AT
[[1, 3, 5], [2, 4, 6]]
~~~

サクッと転置してfor文回したいときにオススメ。

余談。
以下が等価なのは凄い勉強になった。

~~~Python
>>> [*A]
[[1, 2], [3, 4], [5, 6]]
>>> list(A)
[[1, 2], [3, 4], [5, 6]]
~~~
Pythonでギルブレスシャッフル

このごろ他のことが忙しかったので久々の投稿です．

# ギルブレスシャッフル
52枚のトランプカードを，例えばダイヤ・クローバー・ハート・スペード・ダイヤ・クローバー…　のように4種のスートが繰り返されるように並べて重ねる．
束の上から一枚とって裏向きのまま机の上に重ねることを何回か(10~30枚程度)繰り返す．
できた二つの束をリフルシャッフル(マジシャンがよくやる，二つの束を交互に重ねるシャッフル)すると，
一見スートの並びはランダムに見えるが，その実4枚ごとに4種類のスートを必ず含むような並びになる．

……というもの．
もちろん，手元にトランプがあればそれで試すことが出来ますが，**スートが繰り返されるようにトランプを並べ替えるのが面倒**なので，退屈なことはPythonにやらせます．

# Pythonで実装
まずはトランプを用意します．0~51の52個の数字をそれぞれ4で割った余りをリストに入れて，0,1,2,3をそれぞれスートに対応させることにしましょう．
余りというのは周期性があるので，この時点で既にスートが繰り返されるような束ができているわけです．素晴らしい．


```python
#52枚
cards=list(range(52))
#4つのスート
cards=[i % 4 for i in cards]
```

続いて，適当な枚数分束の上から一枚ずつ取って重ねていき別の束を作ります．
あまり極端な枚数だと面白くないので，10~30あたりの数字をランダムに出し，その数字の位置でトランプを二分割します．
新しくできた束は順番が逆になるのでreversedをかけます．

```python
import random 
rand=random.randrange(10,30)
#print("rand:"+str(rand))
cards_taken = cards[:rand]  #新しく作られる束
cards_remain = cards[rand:]  #残る束

#逆向きに重ねられていくのでreversed
cards_taken = list(reversed(cards_taken))
```

いよいよ二つの束をリフルシャッフルします．
二つの束は基本的に枚数が異なるため，交互に入れられるのは少ない方の束の枚数分だけということになります．

実際にリフルシャッフルする様子を思い浮かべてみましょう．
まずどちらかの束がなくなるまで，下から交互に束が混ざっていきます．
そして，余った方の束が上に重なり，シャッフルが終了します．

これをコードに落とし込むことを考えます．
二つの束のうち，少ない方の枚数分だけ二つの束(リスト)からpopし「交互に混ざる部分」を作ります．
そして，残ったカードは「混ざらない余り」となります．

現実世界でシャッフルを行うと
【上】
混ざらない余り
交互に混ざる部分
【下】
といった具合になります．

リストの一番左をトランプの一番上に対応付けることを考えると
「混ざらない余り」に「交互に混ざる部分」をextendで加えることになります．

最後に「交互に混ざる部分」をreversedしていますが，これはpopで束を後ろから取ってきているためです．
ちなみに，extendの際どちらの束が残っているか確認する必要はありません．すでに片方は空だからです．

```python

riffle=[]
#リフルシャッフル
for i in range(min(len(cards_remain), len(cards_taken))):
    riffle.append(cards_remain.pop())
    riffle.append(cards_taken.pop())

#混ざる部分と混ざらない部分を合体
output = []
output.extend(cards_remain)
output.extend(cards_taken)
output.extend(list(reversed(riffle)))
```

最後に，outputを見てみましょう．

```python
print(output)
#[1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 0, 3, 3, 0, 2, 1, 1, 2, 0, 3, 3, 0, 2, 1, 1, 2, 0, 3, 3, 0, 2, 1, 1, 2, 0, 3, 3, 0, 2, 1, 1, 2, 0, 3, 3, 0, 2, 1, 1, 2, 0, 3]
```

確かに，4つごとに0~3が一回ずつ現れていますね．
また，4つごとの塊に着目すると，何種類かのパターンが何回か現れていますね．
面白いですね．

#さいごに
ギルブレスシャッフルについては数か月前，アニメで知りました．
当時コード書いてこうなることを確認してそのままにしていたので今更ですが上げてみました．
Slackに投稿されたファイルを自動削除する方法

# はじめに

中規模のチームでSlackを無料枠で使っていると、ストレージが５GBまでという制約に苦戦することになるかと思います。特に、Slackの仕様についてあまり理解していない人は、サイズが大きいAIファイルなどをチャンネルで送ったりします。(Slack管理者としてはやめてーと言ってるんですが、、)

そこで、今回はSlackに投稿されたファイルを自動削除するスプリクトを作成しました。


# 環境
- [GAS(Google Apps Script)](https://script.google.com/home)


# Slack
## Tokenの取得


- https://qiita.com/ykhirao/items/3b19ee6a1458cfb4ba21
- https://qiita.com/komiya_____/items/0e988239ed3f5145a22c

推奨Tokenの取得については、上記記事を参考にしました。


### スコープの設定

![スクリーンショット (223).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430946/8bd0733c-25ce-918f-974b-a2f7721a792d.png)

![スクリーンショット (224).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430946/8d9b5fd2-a120-e709-6dd6-3435f887ce98.png)

今回必要なスコープは、

- `files:read`
- `files:write:user`

の二種類です。

設定が完了したら、「Install App」をクリックして、`OAuth Access Token`を取得しましょう。


# GAS

```js

var SLACK_TOKEN = PropertiesService.getScriptProperties().getProperty("SLACK_TOKEN");

function DaysToUnixTime(days){  
  var date = new Date();
  var now = Math.floor(date.getTime()/ 1000);
  return now - 8.64e4 * days + '';
}

function getFileList(day){
  var count = 100 //一度に削除できるファイル数
  var params = {
    'token': SLACK_TOKEN,
    'ts_to': DaysToUnixTime(day),
    'count': count
  }
  var options = {
    'method': 'POST',
    'payload': params
  }
  var url = 'https://slack.com/api/files.list';
  var res = UrlFetchApp.fetch(url,options);
  var FileList = JSON.parse(res.getContentText());
  FileList.files.forEach(function(val){
    var del = fileDelete(val.id);
  });
}

function fileDelete(id){
  var url = 'https://slack.com/api/files.delete?token='+SLACK_TOKEN+'&file='+id;
  var res = UrlFetchApp.fetch(url);
  return res;
}

function OneWeekDelete(){
  var day = 7 //指定した日数以前のファイルを削除する
  getFileList(day);
}

function ImmediateDelete(){
  var day = 0 //指定した日数以前のファイルを削除する
  getFileList(day);
}
```

## スプリクトのプロパティ

先ほど取得した、SlackのTokenを「スプリクトのプロパティ」に追加します。

https://qiita.com/0Delta/items/7d8303eebbff4062069e


↑追加方法

- プロパティ： `SLACK_TOKEN`
- 値： 先ほど取得したToken


## 実行

関数`OneWeekDelete`や`ImmediateDelete`を実行すると、ファイルが削除されます。なお、前者は投稿から一週間経過したファイル、後者はすべてのファイルを消します。
僕は、前者を１日ごとにトリガーで実行させています。(後者は使いたいときに手動で実行するようにしている)


# まとめ
- Slackに投稿されたファイルを無差別に削除する。
- このチャンネルの投稿は消したくないというのがあれば、下記参考サイトを見れば実装できるはず。
- ただし、プライベートチャンネルやDMは(自分が参加しているものを除き)対象外。


## 参考サイト

http://lyncs.hateblo.jp/entry/2017/06/04/191421
Metabase で変数を含んだクエリ

Metabase では、クエリに変数を入れることができる。

カスタムSQLを作成する際に、日付指定を柔軟に行えたりするのが利点。また一つ便利になった。

下記は、ユーザーの登録日を期間で絞って見る例。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103885/5d1cfa04-ae0f-763e-012b-ac49a958d795.png)

`Required` を ON にすれば、デフォルトで10日、などの設定もできる。神。

ドキュメント: https://metabase.com/docs/latest/users-guide/13-sql-parameters.html
Pythonでソートアルゴリズムの再発明をしてみる: バブルソート

# 概要
* Pythonでソートアルゴリズムを再発明してみるだけ
* 今回は最も簡単と思われるバブルソートについて再発明する
* 参考サイトのサンプルコードをできるだけ見ずに実装する
* とりあえず昇順ソートのみの対応とする

# バブルソートの概要
* あんまり速くないので実用面ではあまり使われない
* シンプルなアルゴリズムなので再発明が容易。勉強目的にはよく使われる
* 安定ソート

## 基本的な手順
1. リストを走査して隣り合う要素の大小関係を比較し、逆だったら入れ替える
2. 上記手順をリストの終端まで繰り返す
3. 一通り走査が完了したらリストの終端の要素は位置が確定するので処理対象から除外し、上記手順を繰り返す
4. 全ての要素の位置が確定したら完了

# ソース
```python
import random

def bubble_sort(lst):
    # 手順全体を繰り返すためのループ。全要素の位置が確定したら抜ける
    # max_indexはリストの終端要素の添字
    # step として-1を指定することで、位置が確定した末尾の要素を除外しながら処理を繰り返す
    for max_index in range(len(lst) - 1, 0, -1):
        # リストを走査するループ。ループ内でi+1 を指すので、ループ回数はリストの要素数より1回少ない
        for i in range(max_index):
            if lst[i] > lst[i+1]:
                # 大小関係が逆なので入れ替え
                lst[i], lst[i+1] = lst[i+1], lst[i]


lst = list(range(10))
random.shuffle(lst)

print("ソート前: " + str(lst))

bubble_sort(lst)

print("ソート後: " + str(lst))
```

# 参考サイト
* https://www.codereading.com/algo_and_ds/algo/bubble_sort.html
はじめてのC++ 【48日目】

# はじめに
C++の勉強に加えて、Webアプリケーションの勉強も始めることになりました。同時並行は良くないといいますが、諸事情により仕方がないことなので、２つともしっかりとやろうと思います。
Webアプリケーションの学習方法としては、実際に作りながら覚えていく形式で行おうと思います。
## Atcoder ABC128
ABC128では、A問題しか解けなかった。まじめに復習していこうと思う。
### B問題
いまAtcoderのサイトがメンテ中なのであとで問題は追記します。レストランを並び替える問題。

これが私が書いたコードです。さっぱりわかんなかったです。辞書順ソートとかのやり方がさっぱりわかりませんでした、、、。

```cpp:B問題(不正解)
#include <iostream>
#include <vector>
#include <string>
int main()
{
  int N = 0;
  std::cin >> N;

  std::vector<std::string> S;
  std::string s;
  std::vector<int> P;
  int p = 0;
  for(int i = 0; i < N; i++)
  {
    std::cin >> s;
    S.emplace_back(s);
    std::cin >> p;
    P.emplace_back(p);
  }
  for(int i = 0; i < N; i++)
  {
    printf("_______________________\n" );
    std::cout << "S[" << i << "] の値は" << S[i]<< std::endl;
    std::cout << "P[" << i << "] の値は" << P[i]<< std::endl;
  }
  return 0;
}
```

youtubeのAtcoder公式チャンネルの解説を観てみると、 `tuple` という機能を使っていました。
`tuple` を簡単に説明すると、 `std::pair` の従兄弟みたいな感じです。 `std::pair` は組み合わせを２つしか作れなかったけど、 `std::tuple` では、いくつでも組み合わせを作ることができます。
また、辞書順ソートは `std::sort` できるみたいです。 動的配列に `std::tuple` のソートをしたときは、第一引数みたいなところから順にソートするようになっています。しかし、この問題では、第二引数の `p （int型）` においては降順にしなければなりません。この場合は、汚いやり方になってしまいますが、値を動的配列に格納するときに、符号を逆転させることで第二引数のソート部分だけを降順にさせることができました。

```cpp:B問題（正解）
#include <iostream>
#include <string>
#include <tuple>
int main()
{
  int n = 0;
  std::string s;
  int p = 0;
  std::vector< std::tuple< std::string, int , int > > a;

  std::cin >> n;

  for(int i = 1; i <= n; i++)
  {
    std::cin >> s >> p;
    p = -p; // <-重要！！
    a.emplace_back( std::tie(S,P,i) );
  }

  std::sort( a.begin(), a.end() );

  for(int i = 0; i < N-1; i++)
  {
    std::string s;
    int p;
    int id;
    tie( s, p, id ) = a[i];
    std::cout << id << std::endl;
  }

  return 0;
}
```
(注意)私の環境が悪いのかわかりませんが、コンパイルエラ- がでます。原因はまた明日調べようと思います。
##ロベールのC++
みなさまコメントありがとうございます！
明日また読ませていただきます。
### 静的メンバ変数の使い所
静的メンバ変数は、必ず一つしか生成されない。これは、変数を共有するのには便利だがクラスのモジュール性を大きく低下させてしまう。クラスのモジュール性とは、簡単に言ったらクラスごとに役割を独立させて部品のように扱うってことかな（あんまり理解してないのでリンク貼らせてもらっています）
[詳しくはこちら](https://qiita.com/hirokidaichi/items/591ad96ab12938878fe1)

では、どういうときに静的メンバ変数を使うのかというと、クラスの実体の数を数えるときにとても便利に働いてくれます。
とりあえずコードを書いてみます。

```cpp:B.cpp
#include <iostream>

class B {
public:
  B();
  virtual ~B();
  void show();
private:
  static int m_count;
};

int B::m_count;//静的変数は0で初期化される

B::B()
{
  m_count++;
}
B::~B()
{
  m_count--;
}

void B::show()
{
  std::cout << m_count << std::endl;
}

int main()
{
  B a;
  a.show();
  {
    B b;
    a.show();
    b.show();
  }//bのデストラクタを呼んでいる
  a.show();
}
```
```:実行結果
1
2
2
1
```
# 終わりに
ロベールもいつのまにか半分過ぎてた！頑張ろ！
Webは明日からやる！
MetaMask x Ganacheで作るEthereum Private Net環境

# Ganacheのインストール

[公式サイト](https://github.com/trufflesuite/ganache)に沿って、インストールを行っていきます。
※Windowsの方は、事前に[windows-build-tools](https://www.npmjs.com/package/windows-build-tools)のインストールが必要です。

- 1. Source codeをCloneする

```bash:clone
git clone https://github.com/trufflesuite/ganache.git
```

- 2. 必要なライブラリをインストールする

```bash:install
npm install
```

- 3. Ganacheを起動する

```bash:start
npm start
```

- 4. 起動したら、`QUICKSTART`をクリックして、完了です。

<img width="1197" alt="スクリーンショット 2019-06-05 2.29.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65794/69ce6633-b439-b054-6f50-3504243239f3.png">


# MetaMaskのインストール

Google Chromeのプラグインで、MetaMaskをインストールします。
Google Chromeで以下のURLにアクセスして、「Chromeに追加」をクリックします。
https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=ja

<img width="1209" alt="スクリーンショット 2019-06-05 2.34.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65794/5e27a078-9669-9efc-33eb-1fa3a311543e.png">

## Networkを変更する

ネットワークから`カスタムRPC`を選択

<img width="360" alt="スクリーンショット 2019-06-05 2.39.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65794/c08ce9ba-a8dd-fca0-641c-08a70102129d.png">

## 必要情報を入力する

Ganache環境に接続するための情報を入力し、保存ボタンをクリックします。

|項目名|値|
|:-:|:-:|
|Network Name|Ganache|
|New RPC URL|http://127.0.0.1:7545|

<img width="360" alt="スクリーンショット 2019-06-05 2.44.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65794/75180c3f-d944-62a3-5131-edfc125d4162.png">


## アカウントを追加する

Ganacheからプライベートキーの取得します。

<img width="1199" alt="スクリーンショット 2019-06-05 2.45.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65794/77fa5b1d-61f6-2fbe-9693-c207b27b4a3d.png">

プライベートキーからMetaMaskにアカウントをインポート

<img width="359" alt="スクリーンショット 2019-06-05 2.47.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65794/7f178789-135f-0f18-7b62-79a42071dd4c.png">

プライベートキーを入力して、追加ボタンをクリックします。

<img width="361" alt="スクリーンショット 2019-06-05 2.50.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65794/97d4a588-f428-733f-2f71-0b8bf29d5b46.png">

これで、アカウントの追加は完了です。
このアカウントは、生成時に100ETHを持っているので、いつでもテストができる状態です！
さぁ、開発を楽しみましょう！！
MicroPythonの中でエディタを使う

#免責
この記事に従って発生した如何なる損害も筆者は負うことができません。ご免なさい。

#はじめに
使い勝手が良いのでMicroPythonがお気に入りです。
でも、REPLの中では、\*.pyファイルの編集が大変です。
MicroPythonをUbuntuなどにインストールするには[こちら](https://qiita.com/tab4moji/items/c22279ff397c7f2782cc)を参考にしてみて下さい。

#目的
MicroPythonの中でエディタを使いたいです。
robert-hhさんの「[Small Python Text Editor](https://github.com/robert-hh/Micropython-Editor) (以降、pye)」を使わせてもらいます。

#準備
pyeが使うパッケージを用意しておきます。os、signal、ttyを使えるようにしておきます。

```shell-session:pyeが使うPythonパッケージをインストール
$ micropython
MicroPython v1.11-37-g62f004b on 2019-06-05; linux version
Use Ctrl-D to exit, Ctrl-E for paste mode
>>>
>>> import upip
>>> upip.install("os")
>>> upip.install("signal")
>>> upip.install("tty")
>>>
```

#pyeを使う
色々なバージョンがありますが、試しにpye.pyをダウンロードしてみます。
デバイスの場合はmpy-crossで小さくしたものを使いましょう。

```shell-session:pyeを使う
$ # UNIX版MicroPythonの場合
$ mkdir -p ~/.micropython/lib
$ wget -O ~/.micropython/lib/pye.py https://raw.githubusercontent.com/robert-hh/Micropython-Editor/master/pye.py
$
$ micropython
MicroPython v1.11-37-g62f004b on 2019-06-05; linux version
Use Ctrl-D to exit, Ctrl-E for paste mode
>>>
>>> import os
>>> os.listdir()
<ファイル一覧>
>>>
>>> import pye
>>> pye.pye("hello.txt")
<CTRL-Q:終了>
<CTRL-S:保存>
<CTRL-Z:戻す>
```

#参考
 * mpy-crossの参考 : [MicroPythonでBlynk](https://qiita.com/tab4moji/items/8c1f9fdbb170738b3630)
 * [internal editor in Micropython](https://forum.micropython.org/viewtopic.php?t=3550)
GoogleMapの住所追加が早くて感動した話

GoogleMapの地図データがゼンリンのものからgoogle独自に切り替わったようですね。
https://www.itmedia.co.jp/news/spv/1903/22/news067.html
この影響や、もともとの地図情報が間違っている、一戸建てを新築した等の理由でGoogleMapで住所を検索してもヒットしなかったり間違った場所にピンが立つことがあります。

----

UberEatsが届かないトラブルがあったので
住所の追加を申請してみました。

思いのほか早く対応していただいて感動したので
この嬉しさの勢いでキーボードを叩いています。

----

#ゼンリン時代

実は以前にも住所の追加申請を行っていました。
2年前に引っ越しましたが、その住所がGoogleMapにありませんでした。
友達やタクシーが迷子になって困るので住所の登録を申請しました。
※この時はまだゼンリン時代です。

----

- 申請
- 数日後ゼンリンから電話が来る
- いろいろ確認される
- 「調査員が現地調査をして、しかる後にデータが更新されます。時間はかなりかかります」
- 現在まで音沙汰なし

まだ反映されていません😢

----

#google独自時代(現在)

----

#こんな風に申請しました

##GoogleMapで自宅の住所を検索します。
「●丁目○○番△△番」を検索しても「●丁目○○番」までしか出ません。
やはり私の自宅住所は登録されていないようです。

----

##「問題を報告」します
<img width="375" alt="IMG_2984.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301/425e3fa7-a018-5f00-ce37-a4c01ae73aa5.png">

----

##正しい住所を入力します
<img width="375" alt="IMG_2985.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301/e1752b20-96cc-c275-708c-4154bca45905.png">

----

## 必要に応じてピンの位置を微調整します
<img width="375" alt="IMG_2985_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301/339eb327-5381-df03-e8f9-966ed667cde3.png">
<img width="375" alt="IMG_2986.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301/eee76cbb-e7b4-ebf6-81a7-512616c0082a.png">

----

##送信

もう一度住所を確認しましょう
<img width="375" alt="IMG_2985_3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301/78fd445b-80ec-c9fc-b33e-c3a8d2b560c4.png">

----

#確認メールが届きます
![ss 2019-06-05 23.50.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301/11f73086-449e-4eca-33e6-2c4251d396cf.png)

----

##ストリートビューカー

翌日、近所でストリートビューカーとすれ違いました。
…偶然かな？🤔

----

#公開のお知らせ

5/31に申請して6/5に公開のお知らせメールが届きました🎉
早い！

早速「●丁目○○番△△番」で検索してみます。
我が家の住所がヒットしましたやったね！

----

![ss 2019-06-06 0.02.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301/11a77405-a680-dd09-c504-2ac8e2911588.png)

----

##おまけ

----

ピンがお隣さんの家に立ってしまいました。
ピンの微調整大事です。
もう一回申請してきます。。。
【個人用メモ】WindowFormアプリつくります

新しいフォームを表示する
http://dobon.net/vb/dotnet/form/showform.html

コンボボックス周り
http://hanatyan.sakura.ne.jp/dotnet/combo01.htm

ダイアログ周り
https://dobon.net/vb/dotnet/form/openfiledialog.html

Zip展開周り
・単純な開き方
https://dobon.net/vb/dotnet/file/zipfile.html#extract

・パスワード周りも載っている
これでの解凍を求められてそう
https://dobon.net/vb/dotnet/links/sharpziplib.html

・悪くない
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1133580201

・良いですね
http://xn--p8jj1g.com/excel-vba-passzip-776

・わりと答えそう
http://help.jp.infragistics.com/Help/doc/Silverlight/2010.3/CLR4.0/html/InfragisticsSL4.Compression.v10.3~Infragistics.Compression.ZipFile~Password.html
【コスト削減】AWS のインスタンス料金をばっさり1/3にした

## 目的

AWS のサーバー費を少しでも安くする

## 概要

例えば m5.large の場合、0.124USD/時間、年間約 1086.24USD (約12万円)、リザーブドインスタンスで年額前払いだと 706USD (約8万円)です。（※純粋なインスタンス料金のみの計算）

土日祝を除く 2019年の平日は244日、その内営業時間(営業時間の前後1,2時間もプラス)のみを動かせばいいと考えると 年間 244日 * 12時間 = 2688時間 稼働させればOKという計算になる。約 333USD （約3 〜 4万円） が年間費用となるため、約 1/3 に金額が抑えられます。 リザーブドインスタンスよりはるかに安い！


やすくするためにはリザーブドインスタンスを買うという方法もあるが、以下の課題があり、たまたま [定期的に EC2・RDS インスタンスを停止・起動する仕組みの CloudFormation テンプレート](https://dev.classmethod.jp/cloud/aws/state-scheduler-cloudformation/) という記事を見つけ、これをカスタマイズして導入してみた。

- 開発用の環境で全く使っていないタイミングがある
- 適宜インスタンスタイプやインスタンスファミリーを変更して検証するケースがある
- 1年も使い続けない一時的なインスタンスである
- リザーブドインスタンスの購入タイミングに神経を使う対象のインスタンスを少しでも減らしたい

使っている上で更に以下のような欲がわいてきた。

- 祝日も動かしたくない
- AutoScaling 対象の EC2 インスタンスも 0 台にして、無駄なコストをおとしたい

これらを満たすために、もともと参考にしていた記事の CloudFormation をカスタマイズしてみました。


## 修正した箇所

### 土日祝対応

- Google カレンダー 提供の祝日リストから祝日一覧を取得し、lambda 上で本日が祝日であるか判定処理を追加した
  - [該当ソースコード:Lambda](https://github.com/oz-urabe/CloudFormationSample/blob/master/StateScheduler/src/lambda/holiday/holiday.py#L26)


### AutoScaling グループ対応

- Lambda の IAM role に AutoScaling の設定参照、更新権限を追加
    - [該当IAM定義:CloudFormation](https://github.com/oz-urabe/CloudFormationSample/blob/master/StateScheduler/StateScheduler-CloudFormation.yml#L111)
- AutoScaling グループの設定に対して、インスタンス数を 0 <> 1 と切り替わるようにした 
    - [該当ソースコード:Lambda](https://github.com/oz-urabe/CloudFormationSample/blob/master/StateScheduler/src/lambda/index.py#L48)

### 該当ソース

[Github に公開](https://github.com/oz-urabe/CloudFormationSample/tree/master/StateScheduler) していますので、使ってください。使い方は README.md に書いています。
※ fork & PR 歓迎
preg_replace 正規表現　後読み先読み　数字を3桁ずつで「,」(カンマ)で区切る

```
preg_replace("/正規表現/", 置き換え文字列, 対象文字列)
```

置き換え文字列には、\$1や\$2、\\1や\\2などを使うことができます。\$1と\\1は、同じ意味で、$2と\2も同じ意味で、正規表現のパターンと一致した文字列を分けて扱うことができます。<b>\$のほうが推奨されており、${1}もいいです。</b>
/(スラッシュ)には特別な意味がなく、正規表現のパターンの範囲を表しており、スラッシュを使うことが多いですが、何の文字でもいいです。

###$1・\1例

```:php
$beforeText = 'apple:banana:lemon:3つで、100000000円します。';
$afterText  = preg_replace("/(apple)/", '$1[りんご]', $beforeText);

------結果---------
"apple[りんご]:banana:lemon:3つで、100000000円します。"

```

appleという文字列の後ろに、日本語訳をつけてみました。\1を使います。

```:php
$beforeText = 'apple:banana:lemon:3つで、100000000円します。';
$afterText  = preg_replace("/(apple)/", '\1[りんご]', $beforeText);

------結果---------
"apple[りんご]:banana:lemon:3つで、100000000円します。"
```

同様の結果が得られました。それでは、\$1と\$2と\$3を使ってみましょう。

###$1・$2・$3例

```:php
$beforeText = 'apple:banana:lemon:3つで、100000000円します。';
$afterText  = preg_replace("/(apple)(:)(banana)/", '$1[りんご]$2$2$2$2$3[ばなな]', $beforeText);

------結果---------
"apple[りんご]::::banana[ばなな]:lemon:3つで、100000000円します。"
```

一致する文字列は、「apple:banana」を探すことにしました。そのうえで、一致した場合にその文字列を分けて、扱いたかったため、「(apple)(:)(banana)」としました。そして、置換後の文字列では、分けた効果を使用しています。

##後読み先読み
| パターン | 解説 |
|:-----------|------------:|
| 肯定的先読み(?=文字列) | apple(?=banana) 直後にbananaがあるappleのみに一致 |
| 否定的先読み(?!文字列) | apple(?!banana) 直後にbananaがないappleのみに一致 |
| 肯定的後読み(?<=文字列) | apple(?<=banana) 直前にbananaがあるappleのみに一致 |
| 否定的後読み(?<!文字列) | apple(?<!banana)直前にbananaがないappleのみに一致 |

さっそく肯定的先読みを使ってみましょう。

```:php
$beforeText = 'apple:banana:lemon:3つで、100000000円します。apple';
$afterText  = preg_replace("/(apple)(?=:banana)/", '$1[りんご]', $beforeText);

------結果---------
"apple[りんご]:banana:lemon:3つで、100000000円します。apple"
```

後ろが「:banana」がある場合の、appleのみ置換しています。
[正規表現後読み先読み参考にさせていただいた記事](https://abicky.net/2010/05/30/135112/)

##数字を3桁ずつで,で区切る

```
$beforeText = 'apple:banana:lemon:3つで、100000000円します。apple';
$afterText  = preg_replace("/(\d)(?=(\d{3})+(?!\d))/", '$1,', $beforeText);

------結果---------
"apple:banana:lemon:3つで、100,000,000円します。apple"
```

正規表現のパターンの説明をします。
・「(\d)」は、半角数字
・「?=(\d{3})」半角数字の直後に、半角数字が3つ続いたもの(肯定的先読み)
・「(?!\d)」は、半角数字が3つ続いたものを1回以上繰り返した文字の直後に、半角数字じゃないもの(否定的先読み)

つまり、<b>半角数字の直後に、半角数字が3つ(1回以上)続き、その直後は、半角数字じゃないものがあれば、「,」を足す。</b>

「100000000円」->「100,000,000円」

[正規表現サンプル集](https://www.megasoft.co.jp/mifes/seiki/)
[数字を3桁で区切る参考にさせていただいた記事](http://programmer-toy-box.sblo.jp/article/15013518.html)
最新の Python を入れても古い Python はアンインストールしない方が良い（たぶん）

# やってしまいました

Raspberry Piに最新のPython 3.7.3をインストールした後、ログイン出来なくなってしまいました。

パスワードを入力してエンターを押すと途中で突然画面が黒くなって、もう一度パスワードを求められ... の無限ループです。

試しに、わざと間違ったパスワードを入れると「不正なパスワード」と表示されるので、パスワードは合っています。

# 原因（たぶん）

Python 3.7.3をインストールした後、SDカードの残量が少なくなってしまっていたので、元々入っていたPython 3.5.3をアンインストールしました。

たぶん以下のコマンドだったはずです（覚えていないですし、ログインできないので確認もできません）

```powershell
$ sudo apt-get --purge autoremove Python3.5.3
```

このとき、Thonnyなど、いくつかのソフトもアンインストールされてしまいました。そのため、もしかしたらシステムの重要なファイルも削除されてしまったのかもしれません。実際、この後の作業でバックアップしておいたデータをRaspberry Piに戻すときコマンド関連のファイルが初期状態よりも幾つか少なかったです。

GUIではログインできないのに、なぜかCUIではログインできます。しかし、元々入っていたバージョンのPythonをインストールしようにも、やはり重要なファイルが失われたらしくインストールできません。

また、ログインできなくなる前

```powershell
$ sudo rpi-update
```

も行ったので、こちらが原因かもしれません。

どちらにしても、特に理由がなければデフォルトでインストールされているPythonは入れたままにし、 rpi-updateは行わないほうが良いでしょう。ただし、ログインできなくて確認できないので本当にこの2つのどちらかが原因だと言い切ることはできません。

# 解決策

何度も言うように、ログインできないので正確な原因を突き止めることはできません。そこで、とりあえずOSを入れ直すことにしました。

# データのバックアップ

OSの再インストールをするとデータが全て削除されてしまいます。そこで、WinSCPというソフトを使ってRaspberry PiにWindows PCを接続、バックアップを取っておきたいデータをWindows側にコピーしました。

今まで使っていたソフトの再インストールが面倒だという場合は、ここでそれらのデータのバックアップも取っておきましょう。

ちなみに、WindowsにSDカードを直接接続しても、ほとんどデータを見られません。~~どうやらWindowsが認識しない領域を使っているようです。~~素直にWinSCPを使いましょう。

**2019.06.06 追記:**

WindowsでSDカードの内容が見られないのは、使っているファイルシステムが違うからのようです。[c-yan](https://qiita.com/c-yan)さん、ご指摘ありがとうございました。

# OS再インストール

Raspberry Piを起動するとき、途中で画面に大きくRaspberry Piロゴが表示されます。ロゴが消える前にShiftキーを押すと、OS再インストールのメニューが出てくるので画面に従って再インストールを行います。

インターネット接続は、Wi-Fiではなく有線LANのほうが多少速いはずです。環境によりますが、私の場合は30分程度で完了しました。

無事再インストールできたら、初期設定を済ませます。

# データを戻す

WinSCPを使って、WindowsにコピーしておいたデータをRaspberry Piに戻します。

ただし、データを戻すとき、ディレクトリ内を全削除→データをコピー　ではなく、データをコピー→既に存在するものは上書きしない　という方法を使ってください。ディレクトリ内を全削除→コピー　だと、結局また元の状態に戻ってしまいます。

# 最後に

気軽に古いPythonをアンインストールしないようにしましょう。

また、

```powershell
$ sudo apt-get dist-upgrade
```

で十分なので、rpi-updateは行わないようにしましょう。
exercism.ioでプログラミングを勉強する

# はじめに
最近、exercismでTypeScriptを勉強してみて、結構良かったので紹介となります。

# exercismとは
<img width="1144" alt="スクリーンショット 2019-06-05 21.47.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/99b63fe4-6f5f-71ae-a8c0-ed0cef4b8cd1.png">

[exercism](https://exercism.io) はオンラインで無料で勉強できるサービスです。

下記のような特徴があります。

- 無料 (**Exercism is 100% free forever**)
- 50個言語があり、2856のエクササイズがある
- メンターが存在する
- テンプレートプロジェクトをダウンロードし、実装は自分のPCで行う
- テストコードをクリアするように実装していく
- 他の人が書いたコードもみれる


# How to use
#### ログインして、言語を選択する
[exercism](https://exercism.io) からsinginしてください

#### exercismのCLIをインストール
exercismのCLIをインストールしてテンプレートフォルダのインストールや解答の送信を行います。

<img width="1141" alt="スクリーンショット 2019-06-05 21.48.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/91863ed0-df08-36c4-0b14-a2ef898604a2.png">

記載されている手順に沿って設定しておけば問題ないです。
1点、デフォルトのワークスペースは下記のように変更可能です。

```bash

$ exercism workspace
/Users/suzuki_naoto/Exercism
$ exercism configure -w /Users/suzuki_naoto/private_project/Exercism
/Users/suzuki_naoto/private_project/Exercism
```

#### テンプレートをダウンロード
Downloadのスクリプトをコピペして、実行するとテンプレートをダウンロードできます。
<img width="1143" alt="スクリーンショット 2019-06-05 21.54.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/8f2321c0-e3d0-9ded-8a5f-8708b8eaabfd.png">

#### チュートリアルを見ながら実装
初回はHello Worldでチュートリアルを見ながら進めます。
テストコードがあるので、それを通すような形で実装になります。

雰囲気はこんな形です。
<img width="1053" alt="スクリーンショット 2019-06-06 0.13.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/2d8d786a-99f6-abc2-b324-0d1c60aaa7a3.png">


#### 課題をアップロード
実装が完了したら、exercismのCLIから提出します。(テストが通っていない状態でも提出可能です)
提出すると他の人の実装を見ることができ、またフィードバック依頼をお願いできるようになります。

<img width="1153" alt="スクリーンショット 2019-06-05 22.07.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/7ce2e68c-bd64-2f00-d6c8-4aa62517d614.png">

# 最後に
50もの言語があるので新しい言語学ぶ時などにいいと思います。
日本語ではありませんが、読みやすい簡単な英語で書かれています。プログラミングと英語を一緒に学べて一石二鳥です！！
ポインタとは？

# 概要
　最近、アルバイト先や趣味でGolangを書いたり、学校の講義や課題でC言語を書いたりする中でやっぱりポインタって分かりにくいな〜と思い、その話をいろんなエンジニア学生とすると、やっぱりみんなわかりにくいと思っていたので今回はC言語でのポインタ(GolangはC言語を参考に作られた)をまとめてみました！！！

# ポインタとは
　コンピュータというのはプログラム内の変数をメモリ上に確保して、その場所を特定するためのアドレスを記憶しています。プログラムでそのアドレスを取り扱いたい時に使用するのがポインタです。つまり、ポインタというのはアドレスを取り扱う変数のことを言います。

# 構文
　C言語でポインタを使用する際の構文についてみていきます。

## ポインタの宣言
　```データ型 *ポインタ変数名;```

(例)int型変数のポインタを宣言する
　```int *p;```

## アドレスを代入
- 変数に"&"をつけるとそのアドレスが取得できる。
```&変数名```

(例) 

```c

#include<stdio.h>
int main() {
    int x = 1;
    int *p;
    p = &x;
    printf("「&x」のアドレス: %p\n", &x);
    printf("「p」が示すアドレス: %p\n", p)

    return 0
}
```
(実行結果)

```

「&x」のアドレス: 00A2EE76
「p」が示すアドレス: 00A2EE76
```

## ポインタが示すアドレス内の値を表示
- ポインタに"*"をつけるとポインタが示すアドレス内の値が取得できる。
```
*ポインタ変数名;
```

(例)

```c
#include<stdio.h>

int main(){
    int x = 1;
    int *p = &x;
    printf("「p」が示すアドレス内の値: %d\n", *p);

    return 0;
}
```
(実行結果)

```

「p」が示すアドレスの値: 1
```

## 注意すべきこと
### 注意点 １
　混乱しやすく注意が必要だと考えるのが、"*"の解釈の仕方についてです。
　ポインタの宣言時にアドレスを代入する場合、「int *p = &x」となっているので、「*p」に「&x」を代入しているかのように見えるが、意味的には「p = &x」となるのです。つまり、以下の二つは同義です。

```
int x = 1;
int *p;
p = &x;
```
```
int x = 1;
int *p = &x;
```
### 注意点 ２
　二つ目の注意すべき点としては、初期化についてです。ポインタ変数の宣言をするだけでは、そのポインタ変数が示すアドレスは不定となるのです。そのためポインタ変数を初期化しないで使用すると不特定のアドレスにアクセスすることになり、バグが発生する原因になります。

```c
#include<stdio.h>

int main() {
    int x = 1;
    int *p;
    // 以下の一行は p を初期化していないのでバグの原因になります
    *p = x;
}
```

## 配列とポインタ
　配列の先頭アドレスをポインタ変数に代入することによりポインタ演算を使って配列を取り扱うことができるのです。以下のサンプルを見るとわかるように、 `&num[0]` と `num` は同じである。
また、 `*(p + i)` と `num[i]` は同じである。

```c
#include<stdio.h>

int main() {
    int *p;
    int i;
    int num[3] = {1, 5, 10};
    // 以下の一行は配列の先頭アドレスをポインタ変数に代入
    p = num;
    for(i = 0; i < 3; i++) {
        printf("%d\n", *(p + i));  //ポインタを要素数分進めて値をとる
    }
    return 0;
}
```
(実行結果)

```c
1
5
10
```

#まとめ
　今回はC言語でのポインタについての基本的な勘違いしやすい点を中心にまとめました。次回は、Golangのポインタについての勘違いしやすい点についてまとめていこうと思います。！！！
Jetson Nanoの実験環境のまとめ

# はじめに

Jetson Nanoを購入してから幾度となくSDカードにインストールを繰り返している。構築方法もほぼ固まりつつあるので紹介する。

# ネットワーク関連

- 無線LANのIPアドレスをDHCPから固定IPアドレスに変更する
- 画面ロック時にネットワークが切断されないように「All users may connect to this network」にチェックを入れる
- aptの接続先をミラーサーバに変更する[^1]

[^1]: 詳細は「[apt関連コマンドが遅い原因の調査](https://qiita.com/yamamo-to/items/5b7fef75b4cabad51e25)」を参考。ただし接続先がミラーリングしている最中は更新ができなくなる。

```bash:ターミナル
sudo sed -i.org -e 's|ports.ubuntu.com|jp.archive.ubuntu.com|g' /etc/apt/sources.list
```

- ~~IPv6を無効化するために`/etc/sysctl.conf`の最後に以下の3行を追加(IPv6が有効にされているとネットワークトラブルがあったため無効化)~~ Ubuntu 18.04では下記の設定は無効らしいためWifi設定のIPv6 SettingsからMethod:Ignoreを選択した。

```:/etc/sysctl.confの最後
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
```

- wifiの電力モードを3から2に変更(3は省電力あり、2は省電力なし)、対象ファイルは`/etc/NetworkManager/conf.d/default-wifi-powersave-on.conf`

```:/etc/NetworkManager/conf.d/default-wifi-powersave-on.conf
[connection]
wifi.powersave = 2
```

# 開発環境関連

## スワップ領域

```bash:ターミナル
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
```

このままでは起動時に有効にならないので`/etc/fstab`に次の行を追加する。

```:/etc/fstabの一部
/swapfile  swap        swap           defaults 0 0
```

## Pipenvのインストール

```bash:ターミナル
sudo apt update
sudo apt upgrade
sudo apt install python3-pip
pip3 install pipenv --user
```

## 環境変数の設定

~/.bashrcの最後に次の3行を追加する。

```:~/.bashrcの一部
export PATH=/usr/local/cuda-10.0/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64:$LD_LIBRARY_PATH
export PYTHONPATH=/usr/lib/python3.6/dist-packages
```

## リソース使用状況の監視

jtopコマンドを使うためにjetson-statsのインストール[^2]。

[^2]: 詳細は「[Jetson NanoのGPUモニタリング](https://qiita.com/yamamo-to/items/161f7dcf96704b07a1f9)」を参照

```
sudo -H pip3 install jetson-stats
```

最後に再起動して完了。
文字コードがShift-JISのファイルを再帰的に抽出する

残念ながら、現実はこうなってる。

```shell
$ tree
.
├── dir1
│   ├── sjis.txt
│   └── utf8.txt
└── dir2
    ├── dir3
    │   └── sjis.txt
    └── euc.txt
```

このディレクトリからsjisで書かれたファイルだけ抽出したい。 `nkf` の `--guess` オプションを使えばできるとは思ってたけど、意外と面倒だった。なんかもっといい方法ある気もする。

```shell
$ IFS=$'\n'; for file in `find . -type f`; do nkf --guess "$file" | grep Shift_JIS >/dev/null 2>&1 && echo "$file"; done;
./dir2/dir3/sjis.txt
./dir1/sjis.txt
```

`nkf` はコマンドの中でも好きな方。`echo`のところ例えば `nkf -w --overwrite` にすれば、SJISをUTF-8にしちゃえる。
micro:bitでモーター制御(6円コース)

micro:bitでモーターを制御する方法です。

現在でmicro:bitでモーターを制御するための製品が多く発売されていますが、こちらではトランジスタを利用する方法を紹介しています。

20個入りで110円のトランジスタを利用しますので1個6円でモーター制御ができます。

■接続
E - GND
C - モーター - VCC
B - P0

・トランジスタの配置について
 https://detail-infomation.com/transistor-ecb/

■コードサンプル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71746/46733962-7ea4-b451-9354-12984d97bd6b.png)

■モータードライバー
トランジスタ　２ＳＣ２１２０－Ｙ　（２０個入）@110円
http://akizukidenshi.com/catalog/g/gI-13829/

■モーター
円筒形　振動モーター　ＬＡ４－４６６ＦＢ
http://akizukidenshi.com/catalog/g/gP-06785/
VSCodeでGo言語の開発環境を構築する

# はじめに
一身上の都合によりGo言語を使うことになりましたので、
[VSCode](https://code.visualstudio.com/)でGo言語の開発環境を構築してみました。

Go言語のIDEとしては、他に[Goland](https://www.jetbrains.com/go/)がありますが、フリートライアルが30日間なので却下。
あとは[Eclipse](http://mergedoc.osdn.jp/)も検討しましたが、環境構築が大変なので却下。

ということで、簡単に環境構築ができる無料の[VSCode](https://code.visualstudio.com/)にしました。

# 検証環境
・Windows7 64bit
・Visual Studio Code 1.６２.２
・Go 1.1７.3

# 前提
OSがWindowsであること。
(後日、この記事をMac用に読み替えてMacでも環境構築できました)

# 開発環境構築
必要なソフトを順番にインストールしていきます。
どれもインストール時のオプションは変更していません。

## Visual Studio Code
VSCodeをインストールします。
⇒[Download Visual Studio Code](https://code.visualstudio.com/Download)

## Go言語
Go言語をインストールします。
⇒[The Go Programming Language - Downloads](https://go.dev/dl/)

# Go言語の拡張機能をインストール
VSCodeでGo言語での開発をするにあたり、インストール必須の拡張機能です。
予測変換などが使えるようになるので開発スピードが上がります。

VSCodeを起動し、拡張機能(Ctrl+Shift+X)を開いて`Go`で検索します。
様々な拡張機能がヒットしますが、以下を選択してインストールします。
![VSCode_Go.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406684/d7a1d5da-e8fa-e6da-51ee-67efaba1f466.jpeg)

## 拡張機能の依存パッケージをインストール
最後にGo言語の拡張機能が依存するパッケージをインストールします。
デバッガなどもこちらで入りました。
>You can access all of the above commands from the command pallet (Cmd+Shift+P or Ctrl+Shift+P).
>引用： https://github.com/Microsoft/vscode-go

VSCodeでコマンドパレット(Ctrl+Shift+P)を開いて`GO: Install/Update tools`で検索します。
![compalet.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406684/659a5e17-3736-1b81-001b-07ccfd942c17.jpeg)
全ツールを選択し、OKボタンを押下してインストールします。
![vscode_kakucho.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406684/b6c2213c-5bea-6b8e-0c2f-c15787950b5d.jpeg)

インストール結果です。
拡張機能をアップデートした場合は依存パッケージもアップデートすることをオススメします。
![goget.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406684/881f0fa2-d374-3b02-b82e-de6620f0daa4.jpeg)

# プロジェクトをセットアップ
## プロジェクトを作成する
VSCodeでGo用のプロジェクトを作成してください！

## プロジェクトを初期化する
コマンドプロンプトを開いて先ほど作成したプロジェクト直下にcdし、
以下のコマンドを実行してGo環境を初期化してください。
Goモジュールのパスが書かれたファイル（`go.mod`）が自動生成されます。

```bat
cd [プロジェクト直下]
go mod init [プロジェクト名]
```

# 動作確認
VSCodeの動作確認を一通り行ってみます。

## Go言語のソースを実行
作成したプロジェクトに以下のソース「main.go」を作成してVSCodeで動かしてみます。
<font color="red">**F5キーで実行できます。**</font>

```go:main.go
package main

import "fmt"

func main() {
	fmt.Printf("Hello world\n")
}
```
実行完了し、デバッグコンソールに「Hello world」と出力されました。
![vscode_hello.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406684/336f076d-8573-ef5d-ed76-6de4f435ede2.jpeg)

## デバッグ
ソースの6行目にブレークポイントを立て、F5実行でデバッグできました。
![vscode_degub.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406684/798a0c31-d2dc-bb36-57dd-bb3d4e87a34d.jpeg)

## メソッド補完
「Ctrl+スペース」でメソッド補完ができました。
![hokan.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406684/a6608e33-7d10-a858-c191-a473fcd1df35.jpeg)

# 参考にしたサイト
[【レッツカスタマイズ】Visual Code StudioにGo言語の開発環境を整えてみよう！](https://blogenist.jp/2018/03/11/2201/)

# おわりに
お手軽にGo言語の開発環境を構築することができました。
特につまずいた箇所も無かったです。

次回は、Go言語で開発したWebアプリをローカルサーバーでデバッグする方法について投稿します。
Pythonのenumと実用例

#enumは何
列挙型とは、コンピュータプログラミングにおいて、...実際のコンパイル時あるいは実行時には、列挙型は整数で実装されることが多い -- ウィキペディア

**個人的な見解としては、ラベルみたいなものです**
#pythonで実施してみます
```python:enum_1.py
# モジュールをインポート
from enum import Enum

# クラスのパラメータにEnumを与えればok
class LANGUAGE(Enum):
      PYTHON = 1
      JAVA = 2
      PHP = 3
      GO = 4 
print(LANGUAGE.PYTHON) # LANGUAGE.PYTHON
print(LANGUAGE.PYTHON.name) # PYTHON
print(LANGUAGE.PYTHON.value) # 1

#ループさせることもできる
for x in LANGUAGE:
    print(x)
# LANGUAGE.PYTHON
# LANGUAGE.JAVA
# LANGUAGE.PHP
# LANGUAGE.GO

# enumのvalueも別に数字である必要はありません
class LANGUAGE(Enum):
      PYTHON = 'python'
print(LANGUAGE.PYTHON.value)  
# python

# 数字でvalueを固定したい場合
# IntEnumモジュールをインポート
from enum import IntEnum
class LANGUAGE(IntEnum):
      PYTHON = 'python'
      JAVA = 2
      PHP = 3
      GO = 4 
#下記のエラーが出ます
ValueError: invalid literal for int() with base 10: 'python'

# 同じ値が存在することもできる
class LANGUAGE(Enum):
      PYTHON = 2
      JAVA = 2
      PHP = 3
      GO = 4
# ただし、この場合、ニ個目の定義は基本無視される(表示させる方法もあるけど)
for x in LANGUAGE:
    print(x)

# 同じ値を定義させない方法もある
# uniqueモジュールをインポート
from enum import unique
@unique
class LANGUAGE(Enum):
      PYTHON = 2
      JAVA = 2
      PHP = 3
      GO = 4
#下記のエラーが出ます
ValueError: duplicate values found in <enum 'LANGUAGE'>: JAVA -> PYTHON
```
#実用例を見てみます
enumの実用例としてはデータベースの連携にあると私は考えています。
例えば、よくあるユーザーテーブルを例として見てみます...
####User
| name      |       age |    status  |
|:-----------------|------------------:|:------------------:|
| python            |             29(意外と長い) |      1      |
| go|             10 |      -1      |

statusカラムに注目しましょう 、1と-1の値がそれぞれ入ってます、意味としては

 - 1が正常にログイン出来る
 - -1はブロックされてログイン出来ない

でも数字だけ見ても意味が分からないし、更に2、3、4、5と増えて行くので推測すら難しい:point_up:
###ここでenumの登場です
```python:enum_2.py
# モジュールをインポート   
from enum import Enum
#例えばaはuser表のstatusカラムの値
a = 1
class STATUS(Enum):
      NORMAL = 1
      BLOCK = -1

print(STATUS(a).name) # NORMALが出力される、わかりやすいでしょう
```
`Explicit is better than implicit(暗示するより明示するほうがいい。).`--pythonの哲学
[Intel SGX] sgx_rijndael128GCM_encrypt/decryptをやってみた。

## 本記事の背景
SGXでrijndael encryptionができるみたいなのでやってみた。
インターネットの海を彷徨っても（英語でも、日本語でも）文献があまり見当たらなかったのでまとめた。

## 本記事の対象
- Intel SGXについて知っていること。
- rijndael(AES)暗号化について知ってること。
- Enclave.edl/Enclave.cpp/App.cppで何をやっているかわかること。

## サンプルコード
`sgx_rijndael128GCM_decrypt/encrypt`をやってみるサンプルです。

#### Enclave.edl 

user_checkが大事なようです。まず最も大事なことは、ポインターで渡そうがなんだろうが、enclave内ではすべて値コピーされます。なので、参照渡しは不可能です。ではどうやって書き換えるかですが、[out]というのを変数の前につけてあげます。[out]をつけると、非Enclave領域に値コピーして書き込んでくれます。このとき、非Enclave側で確保した配列の大きさをsizeで指定してやるのがよさそうです。

```
public sgx_status_t enclave_enc([in, size = plain_len] unsigned char * plain, 
size_t plain_len, [out, size=cipher_len] unsigned char * cipher, 
size_t cipher_len, [in, out] sgx_aes_gcm_128bit_tag_t * tag);

public sgx_status_t enclave_dec(
  [in, size = cipher_len] unsigned char *cipher, size_t cipher_len,
  [out, size=plain_len] char *plain, size_t plain_len, [in] sgx_aes_gcm_128bit_tag_t *tag);
```

#### Enclave.cpp
ポイントはaadにNULLを、ivに12byteの配列を入れること。本サンプルでは定数を用いていますが、ivは必ずランダムに生成してください。

```
sgx_status_t enclave_enc(unsigned char * plain, size_t plain_len, 
    unsigned char * cipher, size_t cipher_len, sgx_aes_gcm_128bit_tag_t * tag)
{
	sgx_status_t ret;
	sgx_key_128bit_t mk = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
	uint8_t iv[12] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; // 96bit(12byte)?

	ret = sgx_rijndael128GCM_encrypt(&mk, plain, plain_len, cipher, iv, 12, NULL, 0, tag);
    return ret;
}

```

```
sgx_status_t enclave_dec(unsigned char * cipher, size_t cipher_len, 
char * plain, size_t plain_len, sgx_aes_gcm_128bit_tag_t * tag)
{
	sgx_key_128bit_t mk = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
	sgx_status_t ret;
	uint8_t iv[12] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; // 96bit(12byte)?

	ret = sgx_rijndael128GCM_decrypt(&mk, cipher, cipher_len, (unsigned char *)plain, iv, 12, NULL, 0, tag);
    return ret;
}
```




#### App.cpp
まず暗号化から。ポイントは、App側で領域確保を行うこと。[out, size]設定により、Enclave側でも自動で領域の確保を行ってくれる。暗号化後の文字列のサイズはstrlenで取得できる。

```
sgx_status_t status, sgxrv;
sgx_aes_gcm_128bit_tag_t tag;
char text[32] = "fizzbuzz";
unsigned char cipher[60] = {};
status = enclave_enc(eid, &sgxrv, (unsigned char*)text, strlen(text), cipher, 60, &tag);
int cipher_len = strlen((char *)cipher);
```

続いて復号。長さは同様にstrlenで復号できるし、%s使って出力も可能。

```
char plain[60] = {};
status = enclave_dec(eid, &sgxrv, cipher, cipher_len, plain, 60, &tag);
int plain_len = strlen(plain);
printf("%s\n", plain);
```
AtCoderのC問題を解く：一筆書きグラフ問題

##AtCoderのC問題を解く：一筆書きグラフ問題
ABC054のone stroke problemを解いてみました。
ようするに無向グラフで一筆書きできる経路の数を求めよ、というものです。

ちなみに参考にしたのは以下のブログでほぼ同じことが書かれてしまっています

>再帰を使った無向グラフの経路全探索
>>https://tx-driver.hatenablog.com/entry/2019/01/08/233242


##問題設定：
以下、atcoderのスクショを貼ります。
こちらからも見れるかな？
> C- one stroke path
>> https://atcoder.jp/contests/abc054/tasks/abc054_c

![屏幕快照 2019-06-05 下午10.45.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/3425fb7e-02f6-d481-dedb-0898d414865c.png)
![屏幕快照 2019-06-05 下午10.45.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/e4a02391-3300-7cf2-eec1-3628bd4a8a67.png)
![屏幕快照 2019-06-05 下午10.45.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/677e6dd7-5271-75fd-47e6-d093a4a200ba.png)
![屏幕快照 2019-06-05 下午10.45.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/0208876d-edf9-cf3e-70bf-7d226196c906.png)


この問題を解いていきましょう！

##流れ

グラフの情報はinputから読み取ることとします。以下が流れです。

1.無向グラフを表す行列を作り、inputから読み込んだ情報をもとに初期化する
2.訪問したことのあるノードについての情報を入れるvisitedリストをつくる
3.グラフ上にいる位置、深さをループごとに更新し、一番深いところまで来たら、探索終了とする

3では再帰関数を使うのですが、これがちょっと最初は理解しにくいかもしれないです。


コードは以下です。

```python
#Nはノード数、Mはエッジ数
N, M = map(int, input().split())

path_matrix = []

#無向行列の初期化
for n in range(N):
    path_matrix.append([False] * N)

#まず無向グラフを表す行列を作る
for m in range(M):
    line = map(int, input().split())
    paths = [x - 1 for x in line]
    path_matrix[paths[0]][paths[1]] = True
    path_matrix[paths[1]][paths[0]] = True

#最初はvisited、つまり訪問したことのあるノードはひとつもないので、Falseにする
visited = [False] * N


#再帰関数、ここが難しいかもしれない。
def dfs(now, depth):
    if visited[now]:
        return 0
    if depth == N - 1:
        return 1
    
    visited[now] = True
    total_paths = 0
    for i in range(0, N):
        if path_matrix[now][i]:
            total_paths += dfs(i, depth + 1)
    
    visited[now] = False

    return total_paths

print(dfs(0, 0))


```


###再帰関数dfsのやろうとしていること
再帰関数dfsでやろうとしていることは要するにもし飛べる先があるのなら、その飛んだ先のノードで今いる位置と深さを更新した上で、もっと掘り下げてみる、ということです。
・これでもし更新された深さが一番深ければ、そこで経路は全探索されたものとしてtotal_pathsに1が足されます。
・もしもうすでに訪問したノードに再びたどりついてしまったら、total_pathsに0が足されます。（つまり、何も足されない）

最後に一応これ以降引き続き処理を行う場合のために現在位置のvisitedをFalseに戻しています。


##検証

実際にデータを入力してみましょう

Input:

3 3
1 2
1 3
2 3

Output:
2


Input:
7 7
1 3
2 7
3 4
4 5
4 6
5 6
6 7

Output:
2


##最後に

2ヶ月前に競技プログラミングをはじめたのですが、まったくC問題が解けないので、ここでどんどんアウトプットしていこうと思います。再帰関数、深い！