OmniAICreator/Qiita-1.07M huggingface dataset:
MySQLで3億レコード物理削除した話

# MySQLで3億レコード物理削除した話

## はじめに
こんにちは。webエンジニア社会人をしている ningenMe です。
タイトル通り。MySQLで3億レコード物理削除した話。
ちょっとハマったので備忘録。

## はじまりはアラート
はじまりはアラートだった。
僕が運用・保守しているバッチサーバでは、mysqlからちょうど直近1ヶ月分のデータを毎日1回selectする定期処理をしている。  

いつもなら1時間程度で終わる処理のはずが、その日は7,8時間経っても終わらずアラートが鳴り止まない.....。

## 原因追求
とりあえずリトライしたり、ログ見たりしたもののあんまり悪いところがなかった。
クエリもちゃんとindex効いてる。なんでだろうと思ったらDBの容量が結構大きくなっていたことに気づいた。

```
hoge_table | 350'000'000 |
```

3億5千レコード。インデックスちゃんと効いてたので多分普通に遅いだけっぽい。  
必要なデータ取得は1ヶ月分である12'000'000件ほど。このselectクエリが時間かかってトランザクションが長く失敗しているようだった。  


## DB
基本的に毎日400'000件ぐらいinsertされてレコードが増えているこのテーブル。
データ取得は要件的には直近1ヶ月分だけあれば良いので、それだけ持てばよいのだが生憎rotate処理は入っていなかった。  


自分が開発したものではなく引き継いだものだったのだが、その時点では何も言われていなかったので技術的負債のパスをもらってしまった感じである。  

日々のinsertでデータが大きくなり、ついに限界を迎えたときに僕のターンだったというわけだ。  


これだけ大きくなるならパーティション切っててほしかったものの、それも残念ながらなかった。



## 改修
一旦ロジックに手を加えるよりはDB軽くして様子見るほうが工数少ないだろうという方針になった。
3億レコード消せばかなり変わるだろう、ということでdeleteを打つことに......。このときはうまく行くと思っていた......。

  
## 対応その1

バックアップもしっかりとって、意気揚々とクエリを打ち始めた。  
「クエリ打ちまーす」  

```
DELETE FROM hoge_table WHERE create_time <= 'YYYY-MM-DD HH:MM:SS';
```
「...」  
「...」  

なんか反応がない、やっぱ時間かかるかあとか思いつつdbのgrafana眺めてたらdisc busyがめちゃめちゃ上がっていた。  

「yabeeeeeeeee」

とりあえずクエリを止めた。



## 対応その2
一回で削除するには量が多すぎたことを反省した。dbのレプリケーション時間も考慮してこまめに削除することが良さそう。
1'000'000件ずつぐらい削除できるスクリプト書いて処理することにした。  

「実行しまーす」    

これでうまく行くと思っていた......。

## 対応その3
対応その2はどこへ......。処理はうまくいっていたのだが、時間がとてもかかることが判明した。
負荷をかけずに丁寧にやると約2週間必要だった。が、それではサービス要件を満たせず、やむなく中断。  

そして対応その3である。

## テーブルcopyしてrename
なんかdeleteが負荷大きくて良くないのでは。と思いinsertで欲しいテーブルを無から作ろうという方針に切り替えた。

```
| hoge_table     | 350'000'000|
| tmp_hoge_table |  50'000'000|
```

レコード数的には上記のような状態になればよいので、insertするほうがデータ処理も1/7程度になって速いはずである。  

テーブル作ったあとはrenameしてマスターテーブルとして使い、今の3億レコードテーブルはdropすればokなはず。
truncateやdropはdeleteと違い負荷が少ないのは知っていたので、この方針に。


## 実行
「クエリ打ちまーす」  

```
INSERT INTO tmp_hoge_table SELECT FROM hoge_table create_time > 'YYYY-MM-DD HH:MM:SS';
```
「...」  
「...」  
「お...？」  

## 対応その4
うまく行くかと思ったが、insert終わったあとに無限にエラー吐かれた。mysql怖い。
もう本番作業したくねえよ〜って気持ちでいっぱいだった。

まあよく考えると、多分これも1回でinsertしすぎということなんだろう。
とりあえず1日分だけinsertしてみたらうまく行った。  

「おお！」  

このあとは丁寧丁寧に1日分ずつinsert。1ヶ月ぶんあればいいので35回日分を対応。  

## テーブルrename
ここはすんなりいった。めでたし。


## アラート、止まる
バッチ処理の速度も回復した。
今まで1時間かかってたのに2分ぐらいで終わるようになった(は？)  

問題も解決したのを確認できたので、3億レコードテーブルはdropした。
drop tableに爽快感を覚えるのは初めてだった。


## まとめ。
他人のバッチ処理のローテート処理忘れでこんなに苦しむとは、って思った機会でした。
些細な設計の粗さが運用として現れて工数を奪うんだなあ......。  

## DBにくわしく
あなたはdeleteするときレプリケーション負荷など気にしてますか？
mysqlに優しくしましょう。  

まあ今回の内容とか知ってる人は全然困るところじゃないとは思うんですが。
知識がないと難しいねーって。  
  
cassandraでdelete多くて死んだパターンも昔経験したので何か近いものがあるのかなあとか思ったり。  
また勉強したら記事にでもまとめます。


## さいごに

※軽い感じに見えるけど実際はめちゃめちゃ慎重にチームでダブルチェックしながら作業進めてたよ。本番dbって怖いよね。

ではでは。
【Unity2020】Preview版パッケージがPackageManagerから消えた時の対処法

Unity2020.1でPackageManagerからPreview版パッケージ[^1]がリストから消えてしまい、ハマりました。
本記事は**PackageManagerにPreview版パッケージを復活させる**備忘録です。

[^1]: 具体的にはUnityRecorderの事です

## ProjectSettingsにPackageManagerの項目が追加されている

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/0e2705bf-62c3-590d-1fa1-f73086f35ac9.png" width=500 />

`Project Settings > Package Manager > Enable Preview Packages`にチェックを入れるとPreview版のパッケージが復活します。


## 最後に

(執筆時点)締め切りまで**残り16時間**を切った[Unity1Week](https://unityroom.com/unity1weeks)に参加しようと思っています。その開発中に出会ったトラブルを今回投稿しました(投稿している場合じゃないですが)。

締切に間に合った暁にはプレイしていただけると幸いです。

最新の開発進捗のツイートです。
https://twitter.com/ohbashunsuke/status/1294709487866060802
順列と組み合わせ・確率

# 順列
順列とは、n個の異なるものの中からr個を取り出し、**順序をつけて1列に並べる**ことを言います。

```math
_nP_r=n(n-1)(n-2)…(n+r-1)=\frac{n!}{(n-r)!}
```
```math
_nP_n=n!　0!=1　_nP_0=1
```

# 円順列と数珠順列
円順列とは、n個の異なるものを円形に並べる並べ方のことを言います。
数珠順列とは、n個の異なるもので数珠（輪）を作る順列のことを言います。

※円形のものを裏返すと同じものが2つできるという数珠の特徴に注意します

```math
円順列の総数=(n-1)!
```

```math
数珠順列の総数=\frac{円順列}{2}=\frac{(n-1)!}{2}
```

# 重複順列

重複順列とは、n個の異なるものの中から**重複（同じものを繰り返し取ること）を許して**、r個取り出す順列のことを言います。

```math
_nΠ_r=n^r
```

* n人でジャンケンする時の手の出し方
* 異なるn個のサイコロを投げる時の目の出方
* n人をrつの部屋に入れる方法（空室は存在しても良い）

# 同じものを含む順列
いまn個のものがあり、それらのうちp個は同じもの、q個は別の同じもの、r個はまた別の同じもの、…、である時、これらのn個のものを全て使って1列に並べる順列は、以下のようになります。

```math
同じものを含む順列の総数=\frac{n!}{p!q!r!…}　（ただし、p+q+r+…=n）
```

# 組み合わせ
組み合わせとは、n個の異なるものの中から、**順序を問題にしないで**、r個を取り出して1つの組を作ることを言います。

```math
_nC_r=\frac{_nP_r}{r!}=\frac{n!}{r!(n-r!)}
```

```math
_nC_r=_nC_{n-r}　_nC_r=_{n-1}C_{r-1}+_{n-1}C_r　_nC_0=1
```

# 重複組み合わせ
重複組み合わせとは、n個の異なるものの中から、**重複することを許して**、r個を取り出して1つの組を作ることを言います。

```math
_nH_r=_{n+r-1}C_r
```

# 確率の定義
ある試行の結果、起こりうる全ての場合の数がn(U)通り、事象Aの起こる場合の数がn(A)通りである時、事象Aの起こる確率P(A)は、以下のように定義されます。

```math
P(A)=\frac{事象Aの起こる場合の数}{起こりうる全ての場合の数}=\frac{n(A)}{n(U)}　0\leq P(A)\leq 1
```

# 加法定理
2つの事象AとBについて、「AとBがともに起こる」という事象を、AとBの積事象A∩Bと言い、その確率はP(A∩B)で表されます。「AまたはBが起こる」という事象を、AとBの積事象A∪Bと言い、その確率はP(A∪B)で表されます。

「AとBが決して同時に起こらない」とき互いに排反であると言い、このような事象を排反事象と言います。この場合、AとBの積事象は空事象であり、A∩B=φとなり、P(A∩B)=0となります。

```math
P(A∪B)=P(A)+P(B)-P(A∩B)
```

# 乗法定理
2つの事象AとBが互いに独立（一方の試行の結果が他方の試行の結果に影響を及ぼさない）であるとき、以下の定理が成り立ちます。

```math
P(A∩B)=P(A)P(B)
```

# 条件付き確率
2つの事象AとBについて、**「Aが起こった時にBが起こる」条件付き確率 P(B|A)**は次のように定義されます。

```math
P(B|A)=\frac{P(A∩B)}{P(A)}　P(A∩B)=P(A)P(B|A)
```

# ベイズの定理
ベイズの定理は、ある結果（事象B）が起こった時、その原因（事象A）を推測するのに役立ち、次のように定義されます。

```math
P(A|B)=\frac{P(B|A)P(A)}{P(B)}
```

P(A)は原因として先に知ることができ、事象Bの影響を受けていないので**事前確率**と言い、P(A|B)は結果(B)が分かった後で原因を知るという意味で**事後確率**と言います。またP(B|A)は、想定するパラメーターがある値をとる場合に観測している事柄や事象が起こりうる「もっともらしい」確率である**尤度**と言います。

![145001658286958517179.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663460/7c355bc0-ab2b-750b-cbae-6e92598bac83.jpeg)

> 画像引用：[ベイズの定理のおさらい（３）: T_NAKAの阿房ブログ](https://teenaka.at.webry.info/201512/article_25.html)

# 参考文献
* [例題で学ぶ初歩からの統計学 第2版](https://www.amazon.co.jp/%E4%BE%8B%E9%A1%8C%E3%81%A7%E5%AD%A6%E3%81%B6%E5%88%9D%E6%AD%A9%E3%81%8B%E3%82%89%E3%81%AE%E7%B5%B1%E8%A8%88%E5%AD%A6-%E7%AC%AC2%E7%89%88-%E7%99%BD%E7%A0%82-%E5%A0%A4%E6%B4%A5%E8%80%B6/dp/453555790X)
* [【初心者向け】ベイズの定理とは？ - Qiita](https://qiita.com/ea-yasuda/items/1ffcd518af18c6fa0063)
* [尤度 | 統計用語集 | 統計WEB - BellCurve](https://bellcurve.jp/statistics/glossary/518.html)
iOS13でUICollectionViewCellの大きさがUIImageViewによってSelf-Sizingされてしまう問題

雑ですいません、自分用のメモです
何度もググってるので

ソースはこちら
https://stackoverflow.com/questions/56840665/why-on-xcode-11-uicollectionviewcell-changes-size-as-soon-as-you-scroll-i-alre

Xcode11でってなってますけど、iOS13でですよね？

![スクリーンショット 2020-08-16 3.19.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20784/eb916c9b-cd86-1f70-21db-277efa875a0f.png)

UICollectionViewのEstimate SizeがAutomaticになっていますが、これをNoneにします
これでUICollectionViewDelegateFlowLayoutのsize設定が効きます。

もちろんSelf-Sizingに対応してしまう手もあります（UIImageViewに縦横制約を設定する）
しかしその場合はiOS12でSelf-Sizingを使用できるようにして置かなければならないので注意しましょう。
invalidateLayoutでいけます。

参考
https://qiita.com/usagimaru/items/e0a4c449d4cdf341e152
Google Spreadsheetでハッシュ関数を使う

## やりたいこと
- Google SpreadsheetでMD5やSHA256などのハッシュ関数を使う

## 方針
基本的にこのStackoverflowの質問（[Hash of a cell text in Google Spreadsheet](https://stackoverflow.com/questions/7994410/hash-of-a-cell-text-in-google-spreadsheet)）に従ってやれば良いのだが、非ASCIIの文字列で少しつまずいたので日本人としてメモ。

## 実装
ハッシュ関数を使いたいシートで、`シート＞スクリプトエディタ`を開く。
スクリプトエディタに下記の関数を貼り付けて保存。

```js
function MD5(input) {
  var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, input, Utilities.Charset.UTF_8);
  var txtHash = '';
  for (i = 0; i < rawHash.length; i++) {
    var hashVal = rawHash[i];
    if (hashVal < 0) {
      hashVal += 256;
    }
    if (hashVal.toString(16).length == 1) {
      txtHash += '0';
    }
    txtHash += hashVal.toString(16);
  }
  return txtHash;
}
```
付け加えたのは第3引数の`Utilities.Charset.UTF_8`で、これがないと非ASCII文字は全部同じ文字として扱われてしまう。

`hashVal += 256`しているのは`Utilities.computeDigest`関数が`-128`から`127`までの数値を要素に持つbyte arrayを返すので、マイナスでなくするために足しています。マイナスのまま`hashVal.toString(16)`してしまうと値に`-`がついてしまう（例：`-30.0 -> -1e`）からで、別に256でなく128を足すのでも良いようです。
試しにPythonのhashlibで`hexdigest()`してみたら、上の関数で256を足して作った値と等しかったので、そういうもんなんだな〜とざっくり理解しました。

### SHA256とか他のアルゴリズムを使うなら
`Utilities.DigestAlgorithm.MD5`の部分を好きなアルゴリズムに変えてください。
使えるアルゴリズムは[こちらのリファレンス](https://developers.google.com/apps-script/reference/utilities/digest-algorithm)を参照。

| プロパティ | アルゴリズム |
|:-:      |:-:          |
| MD2     | MD2         |
| MD5     | MD5         |
| SHA_1   | SHA-1       |
| SHA_256 | SHA-256     |
| SHA_384 | SHA-384     |
| SHA_512 | SHA-512     |
まんますぎて何のための表だかわかりません。

## 使い方
普通の関数と同じように`=MD5("hogehuga")`、`=MD5(A1)`のようにして使えます。

MD5は暗号としての目的には使えませんが、`=MD5(A1&B1&C1)`のようにして複数の値を束ねたユニークな値を作りたくて使いました。シートには行を追加したり削除したりするので、番号を振るかわりにそのレコードだと一意に定まる値が得られて便利です。
同じハッシュがあったときに条件付き書式で色が変わるようにしておけば、うっかり同じものを2箇所に書いてしまうことも防げます。

こんな需要がどれだけあるか知りませんが、スプレッドシートでやれることがまた一つ増えましたね。

### 参考文献
[Hash of a cell text in Google Spreadsheet](https://stackoverflow.com/questions/7994410/hash-of-a-cell-text-in-google-spreadsheet)
[Class Utilities - computeDigest(algorithm, value, charset)](https://developers.google.com/apps-script/reference/utilities/utilities#computeDigest(DigestAlgorithm,String,Charset))
[Enum DigestAlgorithm](https://developers.google.com/apps-script/reference/utilities/digest-algorithm)
【Hack The Box】Kali Linuxセットアップ

# はじめに
Hack The Boxを始めるにあたり、Kali Linuxのセットアップを行ったのでログを残しておきます。
ここでは仮想化ソフトとしてVirtual Boxを使用します。

# Kali Linuxイメージのダウンロード
[Offensive Securityの公式サイト](https://www.offensive-security.com/kali-linux-vm-vmware-virtualbox-image-download/)からイメージをダウンロードします。
この記事では`Kali-Linux-2020.2a-vbox-amd64`を使用します。

# キーレイアウトの日本語配列化
[こちら](https://qiita.com/v_avenger/items/c85d946ed2b6bf340a84#%E3%82%AD%E3%83%BC%E3%83%AC%E3%82%A4%E3%82%A2%E3%82%A6%E3%83%88%E3%82%92%E6%97%A5%E6%9C%AC%E8%AA%9E%E9%85%8D%E5%88%97%E3%81%AB%E3%81%99%E3%82%8B)を参考にしましょう。

# タイムゾーンの変更
[こちら](https://qiita.com/v_avenger/items/c85d946ed2b6bf340a84#%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%BE%E3%83%BC%E3%83%B3%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B)を参考にしましょう。

# VirtualBox Guest Additionのインストール
[公式サイト](https://www.kali.org/docs/virtualization/install-virtualbox-guest-additions-kali/)を参考に`Guest Addition`ツールをインストールします。
これは共有フォルダの設定やホスト、ゲスト間のコピペを行うために必要なツールです。

```
kali@kali:~$ sudo apt install -y linux-headers-$( uname -r )
```
次に、[Devices] -> [Insert Guest Additions CD image...]をクリックします。
そして、`/media/cdrom0`にある`VBoxLinuxAdditions.run`を`~/Download`にコピーします。

```
kali@kali:~$ sudo Downloads/VBoxLinuxAdditions.run
```
これでVirtualBox Guest Additionのインストールが完了しました。
再起動して変更を反映させましょう。

# コピペできるようにする
[Machines] -> [General] -> [Advanced] -> [Shared Clipboard]を`Bidirectional`に設定 -> [OK}
![スクリーンショット 2020-08-16 1.54.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326169/126cf970-46af-aebc-b6ec-167d7f13369d.png)

# 共有フォルダを設定する
Virtual Boxで`Kali-Linux-2020.2a-vbox-amd64`を選択した状態で、[設定]をクリック。
![スクリーンショット 2020-08-15 22.25.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326169/dd657247-d07c-f42c-5ca2-cfaef449b9c1.png)

[共有フォルダ]を選択し、[+]をクリック。
![スクリーンショット 2020-08-15 22.26.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326169/bce0df2e-a4e1-9226-b0f5-272397885833.png)

ホスト上でのフォルダのパスを指定し、自動マウントにチェックを入れて、[OK]をクリック。
![スクリーンショット 2020-08-16 2.10.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326169/1080216c-9d4e-367b-bb93-d5f40e02b806.png)

`/media`にフォルダがマウントされます。

```
kali@kali:~$ ls /media
cdrom  cdrom0  sf_Downloads
```

# メモリ割り当て量の変更
VirtualBoxでKali Linuxのマシンを操作していて、挙動が重く感じたのでメモリ割り当て量を変更して対処しました。

Virtual Boxで`Kali-Linux-2020.2a-vbox-amd64`を選択した状態で、[設定]をクリック。
![スクリーンショット 2020-08-15 22.25.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326169/dd657247-d07c-f42c-5ca2-cfaef449b9c1.png)

[システム] -> [マザーボード] -> 任意のメモリ割り当て量を指定 -> [OK]
![スクリーンショット 2020-08-16 2.35.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326169/ceb0cd33-a993-b5a2-0cbb-080d1bef8656.png)


# OpenVPNクライアントの設定
[こちら](https://qiita.com/v_avenger/items/c85d946ed2b6bf340a84#openvpn-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E3%81%AE%E8%A8%AD%E5%AE%9A)を参考にしましょう。

#参考
- https://qiita.com/v_avenger/items/c85d946ed2b6bf340a84
- https://www.youtube.com/watch?v=1VNpW_WBZd8
はじめてのPython3 ~繰り返しのはじまり編~

# はじめに
注意点などは[こちら](https://qiita.com/kashun0410/items/4113051964d5a1cd0bb5)を参照してください。

# 繰り返し処理
歴史は繰り返される。<br>単純なプログラムも繰り返させよう。
## for inによるループ処理
単純な繰り返しの処理。

```
for カウンタ変数 in 繰り返す範囲:
    繰り返し処理
```

※ コロンを忘れぬようお気をつけて

#### 例
```
for i in range(3):
    print("hello world") 

```
============
※ 実行結果

hello world
hello world
hello world

============

#### 繰り返す範囲の range 関数
range 関数は引数に指定した開始数から終了数までの連続した数値を要素として持つ range 型のオブジェクトを作成する。
※ range(a,b,x)：a に指定した数値から順に b に指定した数値だけ足していき、 x に指定した数値を超えない範囲までの連続した数値を要素として持つオブジェクトを作成。<br>・a,x は省略可能。そうした場合 a = 0、x = 1 となる。

```
range(5)
# 0 1 2 3 4

range(0, 5)
# 0 1 2 3 4

range(4,7)
# 4 5 6

range(0, 5, 1)
# 0 1 2 3 4

range(0, 10, 2)
# 0 2 4 6 8

range(10, 0, -1)
# 10 9 8 7 6 5 4 3 2 1

range(0, -8, -2)
# 0 -2 -4 -6
```

##### range関数で指定してみる
```
for i in range(6,11): # 6, 7, 8 ... 11
    print("Hello World:" + str(i)) # 後ろに数値を表示させる
print("last " + str(i)) # 確認用

```
============
※ 実行結果

Hello World:6
Hello World:7
Hello World:8
Hello World:9
Hello World:10
last 10

============

### 数値を繰り返す
数値も繰り返すことができる。

```
for i in range(10):
    print(i)

```

============
※ 実行結果

1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9

============

#### （例題）1月から12月まで表示する

```
for i in range(1,13):
    print(str(i) + "月")
```

============
※ 実行結果

1月<br>2月<br>3月<br>4月<br>5月<br>6月<br>7月<br>8月<br>9月<br>10月<br>11月<br>12月

============

## while による繰り返し処理
条件式が成立している間、何度も繰り返す処理。
カウンタ変数や条件式は自分で用意する必要がある。

```
# while 条件式:
    # 繰り返し処理
    # カウンタ変数を更新
    
```
※ コロンを忘れぬようお気をつけて

#### 例
数値を足していき指定した数以下、ないしは指定した数以上になるまで繰り返す。

```
i = 1   # カウンタ変数の初期化
while i <= 10: # iが10以下なら実行(1,2,3,4...10)
    print(i)   # 繰り返し処理
    i = i + 1  # カウンタ変数を更新。i = i + 1 で10になるまで繰り返す
    print("Next:" + str(i)) # Next: 11
print("Last:" + str(i))
```

※ カウンタ変数の更新文がないと<b>無限ループ</b>と化す(「i = i + 1 」の文)

##### カウンタ変数の更新式(代入演算子)に関して
|演算子|例|意味|別の書き方|
|:-----------:|:------------:|:------------:|:------------:|
|+=|i += 1|変数iの値を1増加させる。|a = a + 1|
|-=|i -= 1|変数iの値を1増加させる。|a = a - 1|

#### 例題
##### 5から15まで表示

```
i = 5
while i <= 10:
    print(i)
    i += 1
 ```

============
※ 実行結果

5<br>6<br>7<br>8<br>9<br>10

============

##### 5から1までカウントダウン

```
i = 5
while i >= 1:
    print(i)
    i -= 1
```

============
※ 実行結果

5<br>4<br>3<br>2<br>1<br>

============

##### モンスターのHPが0になるまで攻撃する

```
import random
hp = 30
while hp > 0:
    hit = random.randint(1,10)
    print("スライムに" + str(hit) + "のダメージを与えた！")
    hp -= hit
print("スライムを倒した")
```

============
※ 実行結果（例）

スライムに2のダメージを与えた！
スライムに9のダメージを与えた！
スライムに7のダメージを与えた！
スライムに8のダメージを与えた！
スライムに4のダメージを与えた！
スライムを倒した

============

##### 体力が完全回復するまで繰り返す

```
import random
hp = 1
while hp <= 150:
    kusa = random.randint(10,30)
    print("薬草を使ってHPを" + str(kusa) + "回復した。" + "現在のHP:" + str(hp))
    hp += kusa
print("体力が完全に回復した")
```
============
※ 実行結果（例）

薬草を使ってHPを18回復した。現在のHP:1
薬草を使ってHPを15回復した。現在のHP:19
薬草を使ってHPを29回復した。現在のHP:34
薬草を使ってHPを15回復した。現在のHP:63
薬草を使ってHPを18回復した。現在のHP:78
薬草を使ってHPを12回復した。現在のHP:96
薬草を使ってHPを15回復した。現在のHP:108
薬草を使ってHPを14回復した。現在のHP:123
薬草を使ってHPを14回復した。現在のHP:137
体力が完全に回復した

============

# 参考
[Paizaラーニング](https://paiza.jp/works/mypage)
Windows 10のシステムフォントをMac風にする

#Windows 10のシステムフォントをMac風にする

Windows 10のシステムフォントは Yu Gothic UIである。
Windows 7では Meiryo UI であった。

###システムフォントを変更する実行ファイル
本記事ではシステムフォントをネットで手に入れたフリーフォントに変更する。

Meiryo UIも大っきらい!! というファイルをダウンロードして解凍する
https://www.vector.co.jp/soft/winnt/util/se500183.html

###Noto Sans フォントをインストール
ヒラギノに似ている Noto Sans JPというフォントがある.
Google, Adobe が共同開発したらしい。

https://fonts.google.com/specimen/Noto+Sans+JP?subset=japanese&sidebar.open=true&selection.family=Noto+Sans+JP:wght@400;500#standard-styles

スタイルがいくつかあるので、気に入ったものをダウンロードしてインストールする。
コンパネ / デスクトップのカスタム / フォント
とすすみ、ここにおいてやる。

###システムフォントの変更
大っ嫌い！！を実行して、
全体設定　すべてのフォント　の項目から、
フォントを選んで適用をおすだけ！

ファイルエクスプローラーの文字が見やすく？なる　（以上）

###おまけ　google chromeのフォントもついでにきれいに
【競プロ基礎パターン】重複のない組み合わせをプログラムで表現する。

# 内容
競プロ、初心者向けの内容
**プログラムで重複のない組み合わせを作り出すにはどうすればよいか。**

# 背景
AtCoder Beginner Contest 175のB問題を提出できなかった弱弱な僕。

[B問題](https://atcoder.jp/contests/abc175/tasks/abc175_b)
この問題の解説というより、その前段階の解説になります。

# 例題.
**問1. 数字が書かれた5種類のカードから3つを選んだ組み合わせはいくつですか？**

高校生なら確実に解けるであろう問題
答えは$  _5C_3$ = 10

しかし、競プロで求められるのは組み合わせの総数より、各組合せが条件に合うかについてということのはず。

**問2. 各組合せのカードの和が10以下になるのは、何通りですか？**
まず、全組み合わせを得る必要があるが、上記公式だけでは、組み合わせの数は分かるが、どんな組み合わせが実際に存在しているのかは分からない。一度中学生に戻って、樹形図を書いてみることにする。

![kumiawase.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628198/56674bcb-1c62-637f-6f69-c6a09d32043d.gif)

これを一つ一つ確かめていけばいいことになる。

**問3.それをプログラムで表してください**
競プロなので当然こうなる

a.そんなの余裕だとプログラムへ変換出来る人
b.まったく分からないという人
c.余裕だと思って書き始めて、止まる人(僕)

a.の人はこれ以上読む必要はありません。

# なぜプログラムへ変換できないのか
樹形図を紙に書くに際には規則性があるため、慣れればシステマチックに書ける。

しかし言葉で説明しようとすると。初めにAを選んだ場合、A以外のB,C,D,Eを組み合わせられる。その次のBに対してはAとB以外を組み合わせられる。・・・・1つ目にDを選んだ場合に組み合わせられるののはEだけど、その次の3つ目に組み合わせられるものがないので、最後の組み合わせはC-D-Eになる。

結構複雑でプログラムでどうやって表現するのか、と呆然とする僕だけではないと思う。


# 解法

### 解法1
全数ループ内を作り、重複しないための条件を追加( if(i>j && j>k)の部分)

```
for(int i = 0; i < 5 ; i++){
  for(int j = 0; j < 5 ; j++){
　　for(int k = 0; k < 5 ; k++){
　    if(i>j && j>k){
　　　　 //重複のない組み合わせが出来上がる
        //和が10以上か確認する
      }
    }
  }
}
```


### 解法2
ループの条件で対応する。(内側のループのj<iとk<jが重要)

```
for(int i = 0; i < 5 ; i++){
  for(int j = 0; j < i ; j++){
　　for(int k = 0; k < j ; k++){
      //重複のない組み合わせが出来上がる
      //和が10以上か確認する
    }
  }
}
```

なるほど、作ってみればとっても簡単。でも、競プロの緊張した中でゼロからこれを考え出せるか。僕には無理。

# 解法以上に大切なこと。

**1つのパターンを身に付けたこと。**

組み合わせから、条件に合うものを探す問題だと気づいたら、上記の解法を思い出し、簡単なループを作れる。これで、樹形図は書けるけどどう表現すれば、とオロオロしていた僕とはおさらば。

実際に上記解法を見ればすごく簡単。人によっては、上記のパターンを事前に知らなくてもいきなりプログラムへ変換できる人はいるかもしれない。でも、みんながみんなそうではないと思う。少なくと僕には難しい、なのでこういった簡単な所からパターンを身に付けていくことが大切だと思う。

# 残る問題
全組み合わせをループで作って解いていいのかどうか、
こっちの方が切実な気がする。

100の3重ループぐらいなら大丈夫、と解説していた。
1000000回だと考えれば、それぐらい大丈夫な気もしてきた。慣れが必要？

# 樹形図的な順番に合っている方法

```
    for (int i = 0; i < n; i++) {
      for (int j = i + 1; j < n; j++) {
```
Amazon Braketで無料の量子コンピュータ・シミュレータを使う

# Amazon Braketには、無料の量子コンピュータ・シミュレータがある

Amazon Braketでは量子コンピュータを利用できますが、料金表のページに記載があるように有料です。

- Amazon Braket Pricing  
  https://aws.amazon.com/jp/braket/pricing/

Amazon Braketには無料枠がないため、「量子コンピュータのことはよく分からないが、お試しで雰囲気を知りたい」という人には、ちょっとハードルが高いです。

Amazonがクラウド上で提供しているSV1というシミュレータは4.50ドル/時なので、本物の量子コンピュータと比べるとかなり安く実行できますが、「1円たりとも課金されたくない」「Amazonのアカウントを持っていないが試してみたい」という人はローカルのPC上で動作するシミュレータを使うのがよいと思います。

本記事では、ローカルのシミュレータ(以下、「LocalSimulator」と呼びます)を動かすまでの流れを紹介します。
(2020/08/16時点の情報にもとづいています)

# インストール

Amazon Braketでは「amazon-braket-sdk」というPython製のライブラリを利用します。
Amazon Braketのノートブックインスタンスを利用すると最初からインストールされていますが、ローカルで動かす場合は自分でインストールします。
pip等を使い、インストールしましょう。

```
pip install amazon-braket-sdk
```

# LocalSimulatorを実行

LocalSimulatorの使い方は、次のページの「Usage」に簡単な記載があります。

- GitHub: amazon-braket-default-simulator-python  
  https://github.com/aws/amazon-braket-default-simulator-python

上記のページに記載されているコードを説明しやすいように少し書き換えたものが次のコードです。

```python
from braket.circuits import Circuit
from braket.devices import LocalSimulator

# LocalSimulatorをインスタンス化
device = LocalSimulator()
# 量子回路を作成
circuit = Circuit().h(0).cnot(0, 1)
# 量子回路を実行(100回実行する)
result = device.run(circuit, shots=100).result()
counts = result.measurement_counts
# 量子回路の実行結果を表示
print(counts)
```

ここでは「量子回路とは何か？」について説明しませんが、自分の好きな量子回路を実行する場合は「量子回路を作成」の部分を目的の量子回路に変更すればOKです。

量子コンピュータの実行結果は確率的に変わるため、ここでは100回実行して結果を表示しています。
「shots」の部分を変更すれば、実行回数を変更できます。

このコードを実行すると、次のような形式の結果が返ってきます。

```
Counter({'11': 52, '00': 48})
```

これで、LocalSimulatorを実行できました。
確率的に動作する量子コンピュータをシミュレートしているため、実行結果にある「52」や「48」の部分は実行するたびに異なる値になります。

数字だけ見ても味気ないため、matplotlibで可視化すると次のようになります。

```python
import matplotlib.pyplot as plt
plt.bar(counts.keys(), counts.values());
plt.xlabel('bitstrings');
plt.ylabel('counts');
```
![histogram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13107/57e60ed1-4211-4530-d900-5323cd8af37c.png)

# まとめ

この記事では、LocalSimulatorを使い、量子コンピュータの動作をシミュレートする流れを紹介しました。
実際に量子コンピュータを利用する前にLocalSimulatorで慣れたり、動作確認してから、本物の量子コンピュータ(有料)を動かすと安くすむので、オススメです。

Qiitaのハッシュタグ「AmazonBraket」で、Amazon Braketに関する記事が少しずつ増えているので、それらの記事も勉強になるかと思います。
名前空間とスコープ、例外処理

#グローバル変数をローカル内で変更
ローカル内ではanimalという変数が存在しないため
animalを出力できないというエラーが発生
![スクリーンショット 2020-08-16 1.02.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/78acf2bc-5c17-bd66-5796-f8ea05b8705a.png)

グローバル変数をローカル内で取得することで書き換え可能
![スクリーンショット 2020-08-16 1.00.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/a729003f-957f-0f97-ed06-0bad60efb794.png)

またはlocalsを使う

#例外処理
何も問題なく抜けた場合、elseが実行
何があってもfinallyは実行
![スクリーンショット 2020-08-16 1.30.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/fc598f4f-531e-229f-77f5-57cbf232e13f.png)

##独自例外の作り方

![スクリーンショット 2020-08-16 1.35.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/1d3e4517-ac11-ff82-1143-8c25ff3e8aea.png)
main.goを複数ファイルに分ける


## コード

```main.go
package main

func main() {
	test()
}
```

```test.go
package main

import "fmt"

func test() {
	fmt.Printf("%s","Hello")
}
```

## 実行
- `main.go`を指定するとエラーというか、test関数を読み込めないでいる

```
yuta:~/func $ go run main.go 
# command-line-arguments
./main.go:4:2: undefined: test
```

## 正しい実行
- `*` で実行しよう！

```
yuta:~/func $ go run *.go
Hello
```

# 参考
https://qiita.com/taqm/items/8eed4371bab199b01b65
最適化コンパイラへのいざない (3) 定数に関する最適化

### 記事一覧
1. [はじめに](https://qiita.com/uint256_t/items/abda5583ce31cd842698)
2. [マルチパスコンパイラ](https://qiita.com/uint256_t/items/32fab9d3678f48b0f03d)
3. 定数に関する最適化 (この記事)
4. [プログラムの構造](https://qiita.com/uint256_t/items/7d4556cb8f5997b9e95c)

### TL;DR

定数畳み込み，定数伝播のお話．

### 対象読者

- コンパイラの内部構造について興味がある方
- コンパイラに関して精通している方（批評お待ちしております）

# 手軽な最適化

突然ですが，次のようなプログラムを見たら何を想像するでしょうか．

```c
seconds_in_day = 1 * 60 * 60 * 24
```

どうやら，1日が何秒なのかを表しているようです．人間にとってはわかりやすいですね．

ですがコンパイラからするとどうでしょうか．仮に上のプログラムを愚直に目的コードへ翻訳すると，実行時に整数に対する掛け算を3回行うことになります．

## 定数畳み込み

上のプログラムは，下のように書き直すと，計算機にとっては嬉しいものとなります．

```c
seconds_in_day = 86400
```

このように，定数式（あらかじめ計算しておくことのできる式）を単純化することを **定数畳み込み** と言います．
実装するのが比較的簡単な最適化手法ですが，次に紹介する定数伝播と組み合わせると，生成される目的コードがグッと短くなるでしょう．

### 具体例

プログラムが木で表されているなら，深さ優先で計算していくことで簡単に定数畳み込みを実現することが出来ます．

![constant folding for tree](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69622/ae8050bf-ee64-4c1d-a746-c64062fec53b.png)


3番地コードのような形式の場合，次に説明する定数伝播の考え方を知っていないと，欲しい動作が得られません．

```
t1 = 1 * 60　
t2 = t1 * 60
t3 = t2 * 24

# 定数畳み込み後
t1 = 60
t2 = t1 * 60 # t1 が定数かわからないと t1 * 60 の結果もわからない
t3 = t2 * 24 # t2 が定数かわからないと t2 * 24 の結果もわからない
```

## 定数伝播

先ほどの具体例で，``t1``や``t2``が定数かわからないと，定数畳み込みできるのかすらわからない場合がありました．

これは，プログラム内で定数（定数畳み込みの結果も含みます）が代入されている変数（その変数への代入は1回のみ行われるとします）を，その定数で置き換えていくことで解決できます．この操作は，どの変数も定数へ置換できなくなるまで，複数回繰り返す必要があります．この一連の操作が **定数伝播** です．

### 具体例

先ほどの具体例に定数伝播を適用して，どうなるか見てみましょう．

```
# 最適化前
t1 = 1 * 60　
t2 = t1 * 60
t3 = t2 * 24

# 定数畳み込み
t1 = 60
t2 = t1 * 60
t3 = t2 * 24

# 定数伝搬(t1消去)
t2 = 60 * 60
t3 = t2 * 24

# 定数畳み込み
t2 = 3600
t3 = t2 * 24

# 定数伝搬(t2消去)
t3 = 3600 * 24

# 定数畳み込み
t3 = 86400
```

いい感じですね．

(迷ったのですが, 疑似コードによる解説は省きました. 疑似コードなどでわかりやすくアルゴリズムを記述してほしいという要望があればお答えします)
【Laravel】型変換をする/$cast

php7以降、型変換ができるよ！っていうのをこの本読んでて学んだので、
https://www.amazon.co.jp/dp/B07Q9PPP2T/ref=cm_sw_r_tw_dp_x_UHaoFbREBEZA2 
laravelのテストサイトに導入してみようとしたところ、laravelではモデル側で型宣言できる機能があるとのこと。
その書き方を試してみました。


###書く場所
モデル.phpの中

###書き方
モデルの中、protected $casts = [ ];の中に設定。
例えば、投稿機能のあるアプリにポスト（Post）モデルがあったとします。


```php
class Post extends Model
{
    protected $guarded = ['id'];

    public function user(){
      return $this->belongsTo(User::class);
    }
//中略
//ーーーーーーーーーー
//この中で、こんなふうに書きます。
//こうすることで、postモデルの中で投稿があった際、またDBからデータを読み込んだときに
//「id」はinteger型で保存、出力のみ許可し、「title」はstring型のみ保存、出力を許可します。
    protected $casts = [
      'id' => 'integer',
      'title' => 'string'
    ];

}

```


###効果
各種データに対して予め型を宣言しておくことで、意図しない型が入ってきたときに早期にエラーなどを発見できるとのこと。
例えば

アプリをつくってく中で、フォームの「時間」の投稿入力欄で
「投稿側」では「数字」ではなく、誤って「テキスト」を受け付けるようにしちゃった場合。

なんかにいいのかも。
モデル側で自動で数字に変換する処理があれば時間的なテキストであれば時間になるし、
全く時間ぽくないテキストであればエラーとして早めに気づける。。。

ということなのかなと思ってます。
LinuC 202「ゾーン情報の管理」を見てBIND9の権威DNSを構築してみた (2)

「2.08.1 BINDの設定と管理」の出題内容については以下をご参照ください。
Version 10.0になって少々内容が変更されているようです。

LinuCレベル2 202試験（Version 10.0）出題範囲 | LPI-Japan
https://linuc.org/linuc2/range/202.html

LinuC レベル 1、レベル 2 の出題範囲改定について
https://linuc.org/docs/linuc_ver10.pdf

## この記事のアジェンダ
- ゾーンファイルの書式について
- named-compilezone, named-checkzoneでレコード追加のテスト
- host, dig, nslookupで名前解決テスト

## ゾーンファイルの書式

+ SOAレコード
   - ゾーンの管理情報についてのレコード
   - @はnamed.confに記載したゾーン名が使われる
   - 末尾に.を付けないと@のゾーン名が自動補完されるので注意
   - レコードを更新したらシリアル番号を変更する (スレーブDNSに通知するため)

```/var/named/example.com.db
$TTL 3H
;名前    IN SOA  <DNSサーバ>       <メールアドレス>
@       IN SOA  example.com. root.example.com. (
                                        ;シリアル番号
                                        2020081500      ; serial
                                        ; スレーブDNSがゾーン情報更新をチェックする間隔
                                        1D      ; refresh
                                        ; スレーブDNSがマスターDNSにアクセスできなかった時に再試行する間隔
                                        1H      ; retry
                                        ; スレーブDNSがマスターDNSにアクセスできなかった時のゾーン情報の有効期限
                                        1W      ; expire
                                        ; ネガティブキャッシュの有効期限
                                        3H )    ; minimum
```

+ NSレコード
   - DNSサーバのFQDNのレコード
   - マスターDNSとスレーブDNSどちらも設定する
   - レコード名を省略すると@の値が使われる

```/var/named/example.com.db
        IN      NS      example.com.
```

+ Aレコード
   - ホスト名とIPの対応レコード

```/var/named/example.com.db
        IN      A       x.x.x.x
www     IN      A       x.x.x.x
```

## named-compilezone, named-checkzoneでレコード追加のテスト

+ named-compilezone
   - 用途: スレーブDNSのゾーンファイルの情報を表示
   - オプションが少々ややこしい
      - named-compilezone -f raw -F text -o - <ゾーン名> <ゾーンファイルパス>
      - -o の部分は - だと標準出力されるけど、出力先ファイルパスを指定することも可

```
# named-compilezone -f raw -F text -o - example.com. /var/named/slaves/example.com.db
```

+ named-checkzone
   - 用途: ゾーンファイルのテスト

```
# named-checkzone example.com. /var/named/example.com.db
zone example.com/IN: loaded serial 2020081500
OK
```

## host, dig, nslookupで名前解決テスト

+ host

```
# host -t mx -v example.com <マスターDNSのIP>
```

+ dig

```
# dig mx example.com @<マスターDNSのIP>
```

+ nslookup

```
# nslookup example.com -type=mx -server <マスターDNSのIP>
```
楽天のラッキーくじをちょっと使いやすくしてみた1

#楽天のラッキーくじをちょっと使いやすくしてみた1
毎日開いてるんですけど、PRとかSPのみが邪魔だなぁと思ったので、JavaScriptで削除してみました。

##作ってみよう
###環境
macOS Catalina ver 10.15.5
GoogleChrome 84
> ぶっちゃけOSは関係ないです
> ChromiumベースのMicrosoftEdgeでもいけると思います

###Chromeの拡張機能をインストール
- [ScriptAutoRunner](https://chrome.google.com/webstore/detail/scriptautorunner/gpgjofmpmjjopcogjgdldidobhmjmdbm)

###ScriptAutoRunnerにJavaScriptを記入
**1. </>のボタンをクリック**
**2. タイトルは自由に**
**3. JavaScriptを記入**

```javascript:jQuery
var pc = "icon_pc",pcsp = "icon_both",pr = "icon_pr",sp = "icon_sp";
var url;
$("#all-kuji-list").children("li").each(function(){
    try{
        url = $(this).children("div.icon").children("img").attr("src");
        if(url.indexOf(sp) > -1 | url.indexOf(pr) > -1 )
            $(this).remove();
        else
            $(this).children("a").attr("target","_blank");
    }catch(e){
        $(this).remove();
    }
});
```

もしくは

```javascript:javascript
var pc = "icon_pc",pcsp = "icon_both",pr = "icon_pr",sp = "icon_sp";
var url;
var el = document.querySelectorAll("#all-kuji-list li");
el.forEach((elem) => {
  try{
    url = elem.children[0].children[0].src;
    if(url.indexOf(sp) > -1 | url.indexOf(pr) > -1)
      elem.remove();
    else
      elem.children[1].target = "_blank";
  }catch{
    elem.remove();
  }
});
```

**4. ホストの入力**
`kuji.rakuten.co.jp`

**5. 左の電源プラグをクリックして入力してるウィンドウが黄色になればOK**

###確認
楽天の[ラッキーくじ一覧](https://kuji.rakuten.co.jp/)にアクセス

多分PCとPC/SPしか表示されていないはず.
自動で実行されない方が良い場合は電源プラグを再度クリックして引っこ抜いてください.

##ちょっと応用
上のコードを応用するとリンク全てを開くスクリプトも作成できちゃいます.
前もって言っておくと私のノートパソコンじゃ重くなるので使ってません（笑）
###コード部分のみ
```javascript
var a = 0;
$("#all-kuji-list").children("li").each(function(){
    try{
        if($(this).children("div.icon").children("img").attr("src").indexOf("pc") > -1 | $(this).children("div.icon").children("img").attr("src").indexOf("both") > -1 ){
            window.open($(this).children("a").attr("href"),"point"+a);
            a++;
        }
    }catch(e){
        ;
    }
});
```
**最初はポップアップで許可するかどうか聞かれるので許可すれば開くようになります.**

## まとめ
遊んでいたJavaScriptでちょっと便利にしてみました.
PCのリンク全て開くスクリプトも作りましたが処理が重くなるので使ってません.

javascriptの方を使ってiphoneのショートカットからも実行できるようになりました.(jQueryじゃ動かなかった)

## 次の記事
[楽天のラッキーくじをちょっと使いやすくしてみた2](https://qiita.com/tasuku_sinsora/items/6bf55e1a51dceda130bf)
【Cloud Functions】Storageに置かれたGZIPファイルを自動解凍

# 前説
* Google Cloud StorageにGZIPファイルが追加（更新）されたタイミングで、自動で解凍させたい
* [Google Cloud Storage APIのリファレンス](https://googleapis.dev/python/storage/latest/index.html)を探しても、GZIPの解凍に関する記述が見当たらない
* 仕方なく、[PythonのGZIPライブラリ](https://docs.python.org/ja/3/library/gzip.html)の活用を模索

## ソース
先人が落としてくれたZipファイルを解凍するコード(参考リンク-3)を改造しました。
Cloud Storageトリガーで起動するCloud Functions(Python 3.7)で、単一ファイルをGzip圧縮している前提です。

```python:main.py
from google.cloud import storage
import io,gzip

def hello_gcs(event, context):

    client = storage.Client()
    bucket_name = event['bucket']
    bucket = client.get_bucket(bucket_name)
    blob_name = event['name']
    blob = bucket.blob(blob_name)

    data = io.BytesIO(blob.download_as_string())
    with gzip.open(data) as gz:
        file = gz.read()
        blob_decompress = bucket.blob(blob_name.replace('.gz',''))
        blob_decompress.upload_from_string(file)
```

## 大きな問題点
* Cloud Functionsに割り当てられる最大メモリは2GB（投稿時点で）
* 処理がメモリの容量を超えると当然エラーになる

⇒ 置かれるGZIPファイルの時点で容量が2GB以上になる可能性があったので、結局ボツになりました。。

## 参考リンク
1. [Cloud Functions ガイド：Google Cloud Storage トリガー](https://cloud.google.com/functions/docs/calling/storage?hl=ja)
2. [GCS にファイルが配置されたらイベント駆動で BigQuery にデータロードするサーバレスなジョブをつくってみた](https://dev.classmethod.jp/articles/cloud-functions-gcs-trigger-load-data2bigquery/)
3. [Googleクラウドストレージで.Zipファイルを解凍するにはどうすればよいですか？](https://www.it-swarm.dev/ja/google-cloud-platform/google%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%81%A7zip%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E8%A7%A3%E5%87%8D%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF%E3%81%A9%E3%81%86%E3%81%99%E3%82%8C%E3%81%B0%E3%82%88%E3%81%84%E3%81%A7%E3%81%99%E3%81%8B%EF%BC%9F/837268170/)
UIPopoverのラベルがiOS13でズレる。

# 概要

訳あって、久しぶりに以前Objective-cで作ったアプリを新しいOSに対応させています。最後の更新はかれこれ2年弱前なのでiOS8だったかな？（確かめようと思ったらapp store connectにつながらない）

その割にはあまり警告もエラーもなくて思ったより作業は早く終わりそうな予感（あまいか？）。

いくつかありますが、結構時間がかかったやつあげておきます。話が古すぎてあまり刺さる人は少ないと思いますが、一人でも参考になればと思っての投稿です。

# 現象

多分、iOS11以降だと思うのですが、シュミレータでios9のipadだと問題ないのに、ios13のipadだとUIPopoverに配置したボタンのラベルがずれて表示されます。


ios9
![iPad_Air_2_—_9_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5336/e1990cfd-2c45-1fd3-9076-800ea72dc62a.png)

ios13
![iPad_Pro__11-inch__—_13_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5336/a1b625c4-5391-089d-a146-e7b48d389348.png)

コードはこんな感じです。

```objective_c
- (id)init
{
    CGRect buttonFrame = CGRectMake(0, 0, 280, 40);
    self.popoverContentSize = buttonFrame.size;
    
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = buttonFrame;
    [button setTitle:NSLocalizedString(@"ADD_TO_STAGE", @"ステージへ追加") forState:UIControlStateNormal];
    [button addTarget:self action:@selector(pushAddStage:) forControlEvents:UIControlEventTouchUpInside];
    
    UIViewController *viewCtrl = [[UIViewController alloc]init];
    viewCtrl.view.frame = button.frame;
    [viewCtrl.view addSubview:button];
    self = [super initWithContentViewController:viewCtrl];
    self.delegate = self;
    
    return self;
}
```

# 解決策

UIPopoverはios11から吹き出しのところまでアイテムを置けるようになったようで、safeAreaLayoutGuideという枠内にコンテンツを配置しないと上記のようにはみ出るようです。

```objective_c
- (id)init
{
...
    self = [super initWithContentViewController:viewCtrl];

    if (@available(iOS 11.0, *)) {
        UILayoutGuide* guide = viewCtrl.view.safeAreaLayoutGuide;
        button.translatesAutoresizingMaskIntoConstraints = NO;
        [button.leadingAnchor constraintEqualToAnchor:guide.leadingAnchor].active = YES;
        [button.trailingAnchor constraintEqualToAnchor:guide.trailingAnchor].active = YES;
        [button.topAnchor constraintEqualToAnchor:guide.topAnchor].active = YES;
        [button.bottomAnchor constraintEqualToAnchor:guide.bottomAnchor].active = YES;
    }

    self.delegate = self;
    
    return self;
}
```

# 参考

時間がかかったのはUIButtonの問題かと思って`UIButton textLabel`などで検索してしまったのが敗因。ボタンのラベルに色をつけたらUIPopoverの問題だとピンときました。

```objective_c
    button.titleLabel.backgroundColor = [UIColor blackColor];
    button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
```

![iPad_Pro__11-inch__—_13_3-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5336/7544defe-5cbb-e0e3-0ad7-14dc8f6993d3.png)

いつも助けてくれる例のサイトで情報発見。

https://stackoverflow.com/questions/57988889/ios-13-uipopoverpresentationcontroller-sourceview-content-visible-in-the-arrow

感謝！！
Scipyでモード解析における一般固有値問題を解く

機械振動学におけるモード解析では、剛性行列Kと質量行列Mから一般固有値問題

```math
K\{\phi_i\}=\omega_i^2 M\{\phi_i\}
```

を解く必要があり、これは両辺に行列が2つある一般固有値問題と呼ばれる。なお、

```math
A\{\phi_i\}=\lambda \{\phi_i\}
```

は標準固有値問題と呼ばれる。一般固有値問題を解くには、両辺に左から$M^{-1}$を掛けて標準固有値問題にして解く方法もあるが、scipy.linalg.eighを使えば、いきなり解くことができる。なお、K,Mは実対称行列なのでscipy.linalg.eigでなくscipy.linalg.eighの方を使う（なぜだかわからないがscipy.linalg.eigだとうまくいかない）

```python
    w, v = scipy.linalg.eigh(K, M)
    print("eigen value:\n", w)

    omega = np.sqrt(w)
    # 昇順にソートする
    omega_v = [[row,list(v[i])] for i, row in enumerate(omega)]
    omega_v.sort(key=lambda x: x[0])
    omega = np.array([row[0] for row in omega_v])
    v = np.array([row[1] for row in omega_v])

    print("eigen vector:\n", v)
    print("omega[rad/s]=",omega)
    f = omega / (2*np.pi)
    print("f[Hz]=",f)
     
    print(v.T @ M @ v)
    print(v.T @ K @ v)
```

正規化は、$\phi_i^T M\phi_i=1$となるようにするが、scipy.linalg.eighでは既にそうなるように出力されるようである。もし自分で計算する場合は$M=diag(m_1,m_2,\cdots,m_n)$なので$\phi_i = \phi_i / \sqrt{m_i}$のように新しい固有ベクトル（固有振動モード）を計算すればよい。

上記により、剛性行列Kも、質量行列Mも固有ベクトルを横に並べた行列[$\Phi$]により対角化され、以下のようになる

```math
[\Phi]^T M [\Phi] = I \\
[\Phi]^T K [\Phi] = diag(\omega_1^2,\omega_2^2,\cdots,\omega_n^2)
```

計算結果：

```
[[1.00000000e+00 0.00000000e+00 3.16285753e-17 0.00000000e+00
  0.00000000e+00 0.00000000e+00]
 [0.00000000e+00 1.00000000e+00 0.00000000e+00 0.00000000e+00
  0.00000000e+00 3.16285753e-17]
 [2.94753911e-17 0.00000000e+00 1.00000000e+00 0.00000000e+00
  0.00000000e+00 0.00000000e+00]
 [0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00
  0.00000000e+00 0.00000000e+00]
 [0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00
  1.00000000e+00 0.00000000e+00]
 [0.00000000e+00 2.94753911e-17 0.00000000e+00 0.00000000e+00
  0.00000000e+00 1.00000000e+00]]


[[3.86469572e-01 0.00000000e+00 1.29304523e-15 0.00000000e+00
  0.00000000e+00 0.00000000e+00]
 [0.00000000e+00 9.66173929e+00 0.00000000e+00 0.00000000e+00
  0.00000000e+00 1.80376128e-14]
 [1.13928941e-15 0.00000000e+00 1.10551030e+02 0.00000000e+00
  0.00000000e+00 0.00000000e+00]
 [0.00000000e+00 0.00000000e+00 0.00000000e+00 4.80769231e+02
  0.00000000e+00 0.00000000e+00]
 [0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00
  1.25000000e+03 0.00000000e+00]
 [0.00000000e+00 2.90139143e-14 0.00000000e+00 0.00000000e+00
  0.00000000e+00 2.76377576e+03]]
```
tarファイル、zipファイルの圧縮展開

##tarファイル
###圧縮
>tarファイル（英：tar file）とは
tarコマンドを使って作ったアーカイブファイル（1つにまとめたよファイル）
であり拡張子（ファイル名の最後に付く、ファイルの種類を表す目印）が「.tar」なファイル
Mac, Linuxで使われる圧縮方法の一つ

モードは"w:gz"とすることで、ひとまとめにして圧縮できる

```python:qiita.py
import tarfile

with tarfile.open('test.tar.gz',"w:gz") as tr:
    tr.add('test_dir')
```

実行すると、test.tar.gzが作成される
pythonの中で展開すると

```python:qiita.py
with tarfile.open('test.tar.gz','r:gz') as tr:
    tr.extractall(path='test_tar')
```
###読み込み
実行するとtest_tarが作成される
extractallを使って全て展開しなくても
extractfileを使ってファイルを指定すればそれだけ読み込める

```python:qiita.py
with tarfile.open('test.tar.gz','r:gz') as tr:
    # tr.extractall(path='test_tar')
    with tr.extractfile('test_dir/sub_dir/sub_test.txt') as f:
        print(f.read())
```

##zipファイル
###圧縮
z.writeではフォルダしか作らない為
さらに自分でテキストファイルを作る必要がある

```python:qiita.py
import zipfile

with zipfile.ZipFile('test.zip',"w") as z:
    z.write('test_dir')
    z.write('test_dir/test.txt')
```

*だけだと同じディレクトリだけ
 **とすると配下にある全てを見ていく

```python:qiita.py
import zipfile
import zipfile
import glob

with zipfile.ZipFile('test.zip',"w") as z:
    # z.write('test_dir')
    # z.write('test_dir/test.txt')
    for f in glob.glob('test_dir/**',recursive=True):
        print(f)
        z.write(f)
```

実行結果
test_dirの配下のファイルが出力される


```
test_dir/
test_dir/sub_dir
test_dir/sub_dir/subsub_dir
test_dir/sub_dir/subsub_dir/subsubu.txt
test_dir/sub_dir/sub_test.txt
test_dir/test.txt
```

###読み込み
全て読み込む
zzz2が作成されている

```python:qiita.py
with zipfile.ZipFile('test.zip', 'r') as z:
    z.extractall("zzz2")
```

指定して読み込み

```python:qiita.py
with zipfile.ZipFile('test.zip', 'r') as z:
    with z.open('test_dir/test.txt') as f:
        print(f.read())
```
【競プロ練習】AtCoder Beginner Contest 175をやってみた(A~C)

AtCoder Beginner Contest 171に参加しました。
A~C問題まで解けました。そのときの思考を記します。

# A - Rainy Season
長さ３の文字列からRの連続する個数を返す。ゴリ押しした。

```Python
S = input()
if 'RRR' in S:
    print(3)
elif 'RR' in S:
    print(2)
elif 'R' in S:
    print(1)
else:
    print(0)
```
# B - Making Triangle
N本の棒の長さリストLが与えられる。このうち３つを選んで、条件をみたす組み合わせの個数を返す。

組み合わせを総当りで調べたが、そのためにitertools.combinationsを使用した。
使い方を競技中に調べるという……。
itertools.combinations(N,r)
リストNからr個選ぶ組み合わせのリストを返します。
例:combinations(range(5),3)→(0,1,2),(0,1,3),(0,1,4),(0,2,3),(0,2,4),(0,3,4),(1,2,3),(1,2,4),(1,3,4),(2,3,4)

```Python
import itertools
N = int(input())
L = list(map(int, input().split()))

count = 0
for i in itertools.combinations(range(N), 3):
    Lx = sorted([L[i[0]], L[i[1]], L[i[2]]])
    if not (Lx[0] == Lx[1] or Lx[1] == Lx[2] or Lx[2] == Lx[0]):
        if Lx[0] + Lx[1] > Lx[2] :
            count += 1
print(count)
```

# C - Walking Takahashi
$X, K, D$ がそれぞれ、初期位置、移動回数、移動距離である。移動方向は正 or 負を選択でき、もっとも0に近づける。

$i$ を正に移動する回数とし、最終的な位置を $d$ とすると、

```math
X + iD - \left((K-i)D\right) = d\\
X/D + (2i - K) = d/D\\
\frac{X/D - K}{2} + i = d/2D\\
```
$d$ の絶対値が $0$ に近い
⇒　$\frac{X/D - K}{2} + i \;(i=0,1,\ldots,K)$ がもっとも $0$ に近づく $i$ を求める。
⇒　$\frac{X/D - K}{2} = {\rm dist}$ と置き、

```
if dist > 0
　⇒ i = 0
else if dist + K < 0
　⇒ i = K
else
　⇒ i = -round(dist)
```
を満たす $i$ のときの $|d|$ を求める。

```Python
X, K, D = list(map(int, input().split()))

dist= (X/D-K)/2

if -dist > K :
    i = K
elif dist > 0 :
    i = 0
else :
    i = -round(dist)

print(abs(X + i*D - ((K-i)*D)))
```

#終わり
D問題以降はまだできていません、、、
Swiftで整数Integerを桁数ごとに配列arrayに変換する方法

アルゴリズム問題を解いている時に、123456のようなIntの各々の桁数を求める方法を調べた際のメモ。
以下のようなExtensionを使えば整数Integerから簡単に桁数ごとに配列Arrayを生成できます。

```Swift
extension BinaryInteger {
    var digits: [Int] {
        String(describing: self).compactMap { Int(String($0)) }
    }
}

let number: Int = 123456
print(number.digits) // [1, 2, 3, 4, 5, 6]

Int(123).digits
Int32(123).digits
Int8(123).digits
```

[BinaryInteger](https://developer.apple.com/documentation/swift/binaryinteger)とは全てのInteger(整数)型が準拠しているprotocolなので、全てのInteger(整数)型で利用可能です。
[HTML/JavaScript] 入力した文字列をJavaScript のコンソール画面に表示させる

# 概要
入力した文字列を JavaScript のコンソール画面で表示する方法を記載する。

![スクリーンショット 2020-08-16 0.02.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663833/d081f4dc-78ba-d28e-4463-0bc7a99f1664.png)


# 前提知識
- [JavaScript で「Hello World」する方法](https://qiita.com/ub0t0/items/f8584f3be322c7fe18fa)
- HTML の基礎知識

# HTML で入力画面を準備
```.html:.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script type="text/javascript" src ="./main.js" defer></script>
    <title>Document</title>
</head>
<body>
   <label> 名前：<input type="text" id="inputname" value=""></label>
   <button onclick="getName()">入力</button>
   <!-- <input> を利用すると以下のような記述 -->
   <!-- <input type="button " onclick="getName()" value="入力"> -->
</body>
```
以下のような画面が表示される。
![スクリーンショット 2020-08-15 23.47.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663833/c66c6f6a-bb18-1d29-3d7b-1d9420326f4b.png)


##### input タグの基本的な書き方

```.html:.html
<input type = "属性" id = "任意の文字列" value = "初期値">
```

・type の記載がない場合、text と認識される。
・`<label>` タグを併せて利用すると、入力ボタンの直前にテキストを配置することができる。


現時点で名前を入力して、コンソール画面を確認すると、`getName`が定義されていないとエラーメッセージが表示される。
![スクリーンショット 2020-08-16 0.05.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663833/f9bb00e3-d23d-884d-41d6-0d99a5502c87.png)

ここから、JavaScript 側でコンソール画面に出力するためのスクリプトを記載する。

# JavaScript で入力された要素を取得
```.js:.js
const getName = () => {
    const yourName = document.getElementById("inputname").value;
    console.log(yourName);
}
```
`document.getElementById`を利用すると、HTMLで定義した id の要素を利用することが可能です。

HTMLの の取得方法

```.js:.js
//要素（input フィールド）の取得
const elem = document.getElementById("id名");
//値
elem.value 

//上記のコマンドをまとめて記載
document.getElementById("id名").value
```
取得した要素を複数回利用する場合は上の記述方法が望ましい。


# 参考ページ
[HTMLとJavaScriptの連携](https://qiita.com/Teach/items/4b0104847be9f2960665)
[`<input>`の使い方とtype属性の一覧をサンプル付きで紹介](https://webliker.info/39533/)
AtCoder Beginner Contest 175 B問題「Making Triangle」解説(C++,Python3,Java)

Ruteです。

AtCoder Beginner Contest 175 B問題「Making Triangle」の解説を行います。

>問題URL:
https://atcoder.jp/contests/abc175/tasks/abc175_b

#問題概要
$N$本の棒のうち、三角形を作ることのできるような<b>長さの異なる</b>$3$本の棒を選ぶ方法は何通りあるかを求めよ。

##制約
・$1 \leq N \leq 100$
・$1 \leq L_i \leq 10^9$
・入力は全て整数

#解法
ans = 0と初期化しておきます。
以下の様な繰返し処理を実装すれば良いです。
・以下の繰返し処理を$(0,n)$の範囲で行う(カウンタ変数を$i$とする)
　・以下の繰返し処理を$(i+1,n)$の範囲で行う(カウンタ変数を$j$とする)
　　・以下の繰返し処理を$(j+1,n)$の範囲で行う(カウンタ変数を$k$とする)
　　　`L[i] == L[j]である` or `L[i] == L[k]である` or `L[j] == L[k]である`を満たしているかを判定する。
　　　・満たしていない場合(<b>長さが異なる</b>条件を満たしている)
　　　　　以下の式が成り立つかを判定し、成り立つ場合はansに1を加算する。

```math
L[i]+L[j] > L[k] \space and \space L[j]+L[k] > L[i] \space and \space L[i]+L[k] > L[j] 
```

ansが求める組み合わせの数なので、これを出力すれば良いです。

計算量は$O(N^3)$で、制約上では間に合います。
以下、Python3,C++,Javaでの解答例を示します。
#各言語解答例
<details><summary>Python3での解答例</summary><div>

```{ABC175B.py}
N = int(input())
L = list(map(int,input().split()))
ans = 0
for i in range(N):
    for j in range(i+1,N):
        for k in range(j+1,N):
            if L[i] == L[j] or L[j] == L[k] or L[i] == L[k]:
                continue
            else:
                if L[i]+L[j] > L[k] and L[j]+L[k] > L[i] and L[k]+L[i] > L[j]:
                    ans += 1
print(ans)

```


</div></details>

<details><summary>C++での解答例</summary><div>

```{ABC175B.cpp}
#include<bits/stdc++.h>
using namespace std;
int main(){
  int n;
  cin >> n;
  vector<long long> L(n);
  for (int i = 0; i < n; i++){
    int l;
    cin >> l;
    L.at(i) = l;
  int ans = 0;
  for (int i = 0; i < n; i++){
    for (int j = i+1; j < n; j++){
      for (int k = j+1; k < n; k++){
        if (L.at(i) == L.at(j) || L.at(i) == L.at(k) || L.at(j) == L.at(k)){
          continue;
        }else{
          if (L.at(i)+L.at(j) > L.at(k) && L.at(j)+L.at(k) > L.at(i) && L.at(i)+L.at(k) > L.at(j){
            ans++;
          }
        }
      }
    }
  }
  cout << ans << endl;
}
```


</div></details>

<details><summary>Javaでの解答例</summary><div>

```{ABC175B.cpp}
import java.util.Scanner;
public class Main{
  public static void main(String[] args){
    Scanner scan = new Scanner(System.in);
    int n = scan.nextInt();
    long L[]; L = new long[n];
    for (int i = 0; i < n; i++){
      long l = scan.nextLong();
      L[i] = l;
    }
    int ans = 0;
    for (int i = 0; i < n; i++){
      for (int j = i+1; j < n; j++){
        for (int k = j+1; k < n; k++){
          if (L[i] == L[j] || L[i] == L[k] || L[j] == L[k]){
            continue;
          }else{
            if (L[i]+L[j] > L[k] && L[i]+L[k] > L[j] && L[j]+L[k] > L[i]){
              ans++;
            }
          }
        }
      }
    }
    System.out.println(ans);
  }
}

```


</div></details>
【Rails】enum で管理されているプロパティについて、属性と DB 上の値との対応表を作る

# やりたいこと

Rails で、`ActiveRecord::Enum` を使ってこのようなモデルを定義したとする。

```app/models/article.rb
class Article < ApplicationRecord
  enum genre: { politics: 0, economy: 10, sports: 20, tech: 30 }
  enum status: { open: 0, closed: 10 }
end
```

このとき、DB 上でたとえば `articles.genre = 0` が何を意味するのかはプロジェクトのソースコードを触れる人間でないとわからない。
それだと開発メンバー以外が DB を分析するときに面倒なので、この手のステータスコード一覧表を自動生成して共有することにした。
また、プロジェクトでは [enum_help](https://github.com/zmbacker/enum_help) を使い下記のようにロケールファイルを定義して enum の日本語化をしていたため（一部）、それもステータスコード一覧表に載せることにした。

```config/locale/ja.yml
ja:
  enums:
    article:
      genre:
        politics: 政治
        economy: 経済
        sports: スポーツ
        tech: 技術
```

# 方針

今回はサクッとやりたかったのでスクリプトを書いて markdown を生成した。
（ちゃんとやるなら管理画面上で動的に生成したほうが更新に追随できてよさそう。）

# やり方

このようなスクリプトを書いて `status_list_generator.rb` として保存する。

```status_list_generator.rb
# モデルを一括で読み込む
Rails.application.eager_load!
# 辞書ファイルを読み込む
I18n.t

i18ns = I18n.backend.translations[:ja][:enums].with_indifferent_access
# クラス名の辞書順に並べる
ApplicationRecord.subclasses.sort_by(&:name).each do |klass|
  # テーブルカラムにない enum は無視
  next if (enums = klass.defined_enums.select { |key| key.in? klass.column_names }).empty?

  puts "# #{klass.table_name}"
  enums.each do |column_name, enum_values|
    puts "## #{column_name}"
    puts '| 値 | 属性 | 日本語訳 |'
    puts '| --- | --- | --- |'
    enum_values.each do |label, value|
      puts "| #{value} | #{label} | #{i18ns.dig(klass.name.downcase, column_name, label)} |"
    end
  end
end
```

このスクリプトを用いて

```
$ rails runner status_list_generator.rb > status_list.md
```

とすると `status_list.md` に markdown でステータスコード一覧表が書き出される。こんな感じ。

```status_list.md
# articles
## genre
| 値 | 属性 | 日本語訳 |
| --- | --- | --- |
| 0 | politics | 政治 |
| 10 | economy | 経済 |
| 20 | sports | スポーツ |
| 30 | tech | 技術 |
## status
| 値 | 属性 | 日本語訳 |
| --- | --- | --- |
| 0 | draft |  |
| 10 | published |  |
```

あとは適当な markdown プレビューを用いて出力すればよい。
筆者は Visual Studio Code の拡張機能 [Markdown All in One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one) を用いて「目次(TOC)の作成 (Create Table of Contents)」機能で目次をつけたあと、「現在のドキュメントをHTMLへ出力 (Print current document to HTML)」機能で出力した。

# 出力結果
このようなものができる。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629590/5890f413-e62f-044c-230b-242d244b27b7.png" alt="status_list_md.html" width="30%"/>
GatsbyでMaterial-UIを適応した際にスタイルが崩れてしまう問題

自分用メモ

CRA(create-react-app)で作成したものをGatsbyに移行した際に， Material UIのスタイルが崩れてしまう問題に遭遇したときに対処した方法


GithubのMateril-UIのissueにありました。
> Gatsby & Material-UI break in production builds #18197
> https://github.com/mui-org/material-ui/issues/18197

## gatsby-plugin-material-uiのインストール

```shell
npm install --save gatsby-plugin-material-ui
```
## gatsby-config.jsに追記
gatsby-config.jsがなければ，トップディレクトリに新規作成

```js:gatsby-config.js
module.exports = {
  plugins: [`gatsby-plugin-material-ui`]
}
```
## 静的ファイル書き出し

```shell
gatsby build
```

以上でスタイルが崩れていた問題を解決できました。
CGPioint,CGSize,CGRect構造体について簡単に説明してみた

長方形オブジェクトの基本についてまとめました。

## origin
長方形の原点座標を指定するインスタンスプロパティ

## size
長方形の高さと幅を指定するインスタンスプロパティ

## CGPoint
２次元座標系の点を指定する構造体です。
CGPointMake()で引数にオブジェクトを表示したい「中心座標x,中心座標y」を指定することにより作成できる。　　

```
// 宣言
var originc: CGPoint
// CGPintの作成
CGPoint point = CGPointMake(x, y)
```

![cgpoint.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595751/6ff24041-e49a-39ce-1c66-b807a6b358f0.png)


## CGSize
長方形の高さと幅を指定する構造体です。  
CGSizeMake()で引数にオブジェクトの「幅,高さ」を指定することにより作成できる。  
距離ベクトルだけでなく、物理的な大きさ（ARとか？）を表すために使用することもあるらしい。

```
// 宣言
var size: CGSize
// CGSizeの作成
CGSize size = CGSizeMake(width, height)
```
![cgsize.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595751/96152ad3-3c9f-fa83-166c-34559997894b.png)


## CGRect
長方形の位置と寸法を含む構造体です。  
CGRectMake()で引数にオブジェクトの「原点x,原点y,幅,高さ」を指定することにより作成できる。  

```
// 宣言
struct CGRect
// CGRectの生成
CGRect rect = CGRectMake(origin.x, origin.y, size.x, size.y)
```
![cgrect.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595751/da72567b-3439-fa86-3965-dc7f056f6b87.png)


# 参考文献
- origin:https://developer.apple.com/documentation/coregraphics/cgrect/1454354-origin
- size:https://developer.apple.com/documentation/coregraphics/cgrect/1455155-size
- CGPint:https://developer.apple.com/documentation/coregraphics/cgpoint
- CGSize:https://developer.apple.com/documentation/coregraphics/cgsize
- CGRect:https://developer.apple.com/documentation/coregraphics/cgrect
シェル(shell)とは何か？

#シェル(shell)とは？

- Linuxカーネル(Linuxの本体で、コマンドを実行する部分のこと)のインタフェース(窓口)となっているソフトウェアのこと。

- ユーザーからコマンドが入力されることで、OSの中核であるLinuxカーネルとやり取りをしてLinuxカーネルのプログラムを呼び出している。つまりシェルの役割は、**「人からの入力とコンピュータからの出力をそれぞれに伝えること」**である。

- shellは英語で「殻」という意味を持っていることから、Linuxカーネルを包み込むように動作するが、イメージとしてはユーザとLinuxカーネルの間を取りもつメッセンジャーの役割をしている。

#カーネルとシェルが別れている理由

主に以下の３つの理由がある。

1. Linuxカーネルには手を入れずに、シェルだけを自分好みのものに変更することができるから

2. Linux以外のOS（FreeBSDやNetBSD、Solarisなど）を利用する際も、シェルが移植されていれば操作を同様に行うことができるから。

3. シェルがエラーや高負荷状態になってクラッシュしたとしても、OS本体であるLinuxカーネルへの影響を最小限に抑えることができるから。


参考サイト：https://blog2.cct-inc.co.jp/blog/os/shell/