OmniAICreator/Qiita-1.07M huggingface dataset:
液漏れを恐れて空冷にこだわっていないか？

1970年頃のホンダでは、エンジンの冷却方法について激しい対立が起きました。

熱力学的には水冷の方が合理的ですが、**創業者社長の本田宗一郎は空冷にこだわりました。**

宗一郎曰く：

- 「砂漠の真ん中でエンストしたときに水なんかあるか！空冷だ」
- 「水冷だってラジエーターを空気で冷やすんだから、最初から空冷のほうが合理的」

実は、宗一郎には、過去に水冷エンジンを開発した際、**液漏れに苦労した体験**がありました。空冷なら信頼性が高いだろうというわけです。

しかし、宗一郎肝いりで開発した空冷エンジン搭載の「ホンダ・1300」は商業的には失敗してしまいます。

宗一郎は技術者としての限界を感じていたのもあり社長を退任し、以後のホンダの四輪車は水冷エンジンを採用します。


# 過去の苦労に囚われる

レジェンド・本田宗一郎と比べるのは恐れ多いのですが、ソフトウェア開発の現場でも**過去の苦労に囚われ判断が歪む**ことがしばしばあります。

- Rubyは遅くて使い物にならないよね！
- Gitは日本語のファイルが文字化けするから怖いよね！
- エンジニアは文章を書けない！ルールを決めても書かない！だからドキュメント無しで開発する！
- ANSI規格が無い言語なんて、いつ開発中止になるか分からない。やっぱりCommon Lispだね！

などなど…。

こういう「判断の歪み」の恐ろしさは**正当化しだす**所にあります。単に「Rubyは遅い」と思いこんでいるだけなら「今のRubyは十分速く、大規模サイトでも利用実績がある」と示せば説得できるはずです。しかし、判断が歪んでる人の場合、「でも、サーバーリソースを使い切る観点ではJavaが優れている」「Javaのライブラリの代替物が全てRubyで見つかるとは限らない」「Rubyは学習コストが高い」などと、新たな理由を持ち出して何がなんでもRubyを避けようとします。

マネージャーやリーダーがこういう判断の歪みを抱えていると大きな機会損失を生んでしまうこともあります。

世間ではこれを「老害」とも言います。でも、私に言わせれば、これは老人特有の話ではなく、若くても何かしら非常な苦労をすると判断の歪みを抱えてしまうことはありえます。

# 追記：主観的な情報にこだわる

「老害」という書き方は、若干エモーショナル過ぎた感じがしました。

「過去の苦労に囚われる」を、もっと具体的に書くと、

**「新しいツールや手法の導入に、主観的な情報（のみ）を根拠に反対する」**

という事だと思います。

Rubyにせよ、Gitにせよ、ドキュメントにせよ、世間には膨大な利用実績があります。メリット/デメリットについても、客観的な情報があるはずです。

それにも関わらず「過去に苦労したから」という**主観的な情報**を根拠に反対するのは、「過去の苦労に囚われている」と言えるでしょう。

もちろん、「おや？これは過去の失敗に似ているぞ？」と勘を働かせ、それをきっかけに慎重に行動するのはいいことです。しかし、勘に「居着いて」しまうのは、生産的ではありません。

# 結論

結論はありません。

本田宗一郎の伝記を読んでいて、ソフトウェア開発に似た現象があると思ったので書いてみました。
【AWS】rootユーザー以外で、AWSの請求金額を閲覧する設定方法　〜IAMユーザー・ロール・IAM Identity Centerユーザー（SSOユーザー）で請求金額を見る方法〜

## 背景
- AWSのアカウントを作成した際、初期設定ではrootユーザー以外ではAWSからの料金の請求情報が見えません。
- AWSを使用していく中で、rootユーザーを使用することは稀（というか[AWSも普段からrootユーザーは使うな](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_root-user.html)と言っている。)だと思います。
- IAMユーザーやIAM Identity Centerユーザー（SSOユーザー）で請求情報を閲覧するためには、簡単な初期設定が必要なので、その設定方法を紹介します。

## rootユーザー以外で、請求情報を見えるようにする設定方法

### rootユーザーでAWSにログインする
- [AWSのマネジメントコンソール](https://aws.amazon.com/jp/console/)画面からログインを選択します。
- スクショのログイン画面でrootユーザーによるログインを行います。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/363f6141-9be6-e21c-b48d-509ed11eb920.png)

### アカウント画面に移動する
- 画面左上の名前が表示されてる箇所をクリックします。
- スクショのような欄が表示されるので、「アカウント」をクリックします。
![02_加工必要.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/3a24dbef-6dbd-db4e-16c8-30f416251120.png)

### 「IAMユーザー/ロールによる請求情報へのアクセス」へ移動する
- アカウントをクリックすると、下記のスクショの画面に遷移します。
- かなり長いですが、スクロールしていくと「IAMユーザー/ロールによる請求情報へのアクセス」という欄があるのでそこまで移動します。
- 「編集」をクリックします。
![03_加工必要.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/48caff61-0a8d-d3e4-b86b-af59e8b17238.png)

### 「IAMアクセスのアクティブ化」を行う
- 「編集」をクリックするとスクショのようなチェックボックスが出現します。
- スクショの通り、「IAMアクセスのアクティブ化」にチェックを入れ、「更新」をクリックします。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/d86fa5dc-e9d6-e22d-c796-3377b589f650.png)

###  「IAMアクセスのアクティブ化」が有効になっているかを確認する
- 正しく更新されると、以下のような表示が出ます。
- これで、請求情報が閲覧できるポリシーがついたIAMユーザーなどでログインした際に、請求情報を確認することができるようになります。
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2651220/8f90968d-6a7f-91bc-9f2c-45bfacf50c05.png)

## 参考資料

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_root-user.html

https://aws.amazon.com/jp/console/

https://docs.aws.amazon.com/ja_jp/awsaccountbilling/latest/aboutv2/control-access-billing.html#grantaccess

## 個人ブログ

https://takuma-tech.com/2022/10/10/315/
[Unity]マーカーを使ってオブジェクトを出そう 

# はじめに

UnityのAR Foundationを使うと写真やロゴなどをマークとして認識し、
そこを基準としてオブジェクトの生成などが行えます。
アイデア次第で色々な表現ができるので是非やってみてください！
### この記事を読むとこんなことができるようになる
![XRecorder_11102022_013549_5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605029/47e8b053-04c7-60b7-c91c-d7aa89c179ef.gif)

![名称未設定_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605029/b062dad0-9011-72e2-8453-78d1ed25ce44.gif)




# 解説

## 環境
- UnityHub 3.0.1
- Unity 2021.3

## 準備
### プロジェクトの作成
 プロジェクトの作成はテンプレート使って簡単に作れますので、こちらを参照してください。

https://qiita.com/Pancetta/items/0dfc0c5bd399f6c63a67

### リソースの準備
マーカーとして必要な画像を1枚用意してください。
身近にあるカード(Suicaとかクレジットカードとか)の画像があると、
そのカードで試せるためおすすめです。

お手頃のものがなければこちらを使用してください。
自分が作った著作権フリーの画像ですので、読みやすいように加工などもしてもOKです。
![icon2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605029/03ff450b-e097-7ee3-afa0-b5f7aa2eb0c3.png)

### シーンの準備
通常であれば、ARを使用するシーンではMain Cameraを削除してARSessonオブジェクトなどを配置する必要があります。
テンプレートには既にそういったシーンの設定が済まされている「BlankAR」というシーンを用意してくれているのでそれを使用します。

## 実装
### 参照する画像の登録

- プロジェクトウィンドウ内で右クリック
- Create > XR > Reference Image Libraryを選択
![スクリーンショット 2022-10-11 0.05.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605029/a99cf54e-9377-5ba8-7f54-8541fb2ccc00.png)

- 作成された`ReferenceImageLibrary.asset`を選択し、インスペクターウィンドウに表示される[Add Image]をクリック
![スクリーンショット 2022-10-11 0.29.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605029/6bf76649-d86a-fb55-f72d-faa3bebd1cfa.png)

- マーカーとして使用する画像をドラッグ&ドロップ
- [Specify Size]にチェック
- マーカーの実物サイズを入力
![スクリーンショット 2022-10-11 0.41.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605029/e6a7c6bd-09dc-57e3-1911-fef300064133.png)

#### 実物サイズとは？
UniyのTransformはメートル表記です。
つまりScaleが1ずつなら、縦・横・奥が１mの物体になります。
![スクリーンショット 2022-10-11 1.00.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605029/c6e679f6-8abd-eac7-c6f6-f8b0e58d3d45.png)

なので10cm*10cmのマーカーを作りたいのであれば0.1と入力してください。

### シーンの設定
- シーン内にある[AR Session Origin]に[AR Tracked Image Manager]スクリプトを追加
- [Serialized Library]に`ReferenceImageLibrary.asset`をドラッグ&ドロップ
- [Max Number of Moving Images]を1に設定
- [Tracked Image Prefab]にマークに表示したいプレハブを設定
![スクリーンショット 2022-10-11 1.09.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605029/f86fcd05-640c-f4f2-99c5-0000f6b00a7e.png)


## 出力

Pasmoをマークにして線路図を表示してみる
![XRecorder_11102022_013549_5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605029/60055d3a-41db-092a-8fb0-3b504ba2fea8.gif)

Unityちゃんをだしてみる
![名称未設定_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605029/d5add17a-a1f6-015e-5aca-bf644a5b9ef5.gif)

:::note alert
うまくいかない場合は以下の項目をチェックしてみてください
:::
- 表示するプレハブのPositionやScaleが正しく設定されているか
- マーカーに登録した実物サイズは適正であるか


## おわり
ARグラスなどが普及してきてそろそろAR用のUIがあるアプリとか出てくると思います。
そう考えると色々なアイデアが出てきてワクワクします。


参考させて頂いたURL
https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@2.2/manual/tracked-image-manager.html
Tomcat の ホットデプロイ (リロード) 設定（起動時にJava変更を反映）

Tomacat を使って開発してるときに起動時に Java の変更を即時で反映できるようにする設定
ホットデプロイをよく使ってたけど一般的にはどれなんだろ．．．

- servlet.xml を設定
    1. Servers - 対象の Tomcat - server.xml を開く
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/7cb7f62d-dff7-fd3f-ab8e-99ea290cd89a.png)
    1. エディタの左下にある [ソース] をクリック
    1. 下の方にある `Context doxBase="プロジェクト名"` になってる行の `reloadable` を `true` にする
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/6a0d68d3-ec97-c325-7189-f6cd11a54a15.png)

- 設定後のコンソール（Java変更したときのログ）
    再ロード開始, 完了 が出れば反映OK（こんな感じのログが出る）
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/c9b410fa-d372-be98-a683-292b77533696.png)
【Python】プログラミング問題　文字と整数の組のソート2 　を自分なりに解説【paiza】

# はじめに
paizaラーニングはプログラミング学習が出来るプラットフォームです。
問題はランク付けしてあり、ランクが上がると難易度がアップします。
paizaラーニングのレベルアップ問題はユーザー同士で解答を教え合ったり、コードを公開することが可能です。
自分が難しいと感じた問題のコードを解説することでスキルアップをする事が今回の目的でした。

誤りや改善点がありましたらご指摘頂けますと嬉しいです。

# お題　
## お題のリンク
https://paiza.jp/works/mondai/prob60/sort_add_9

## 問題文

>1行目に行数を表す整数 n、続く n 行の各行で「文字」と「整数」の組が空白区切りで入力されます。
>n 個の組について、「文字」の値が同じ組同士の数値を足しあわせてまとめ、まとめた数値の降順で
>文字とまとめた数値の組を出力してください。
>この際、まとめた数値は重複しません。

## 入力される値
入力は以下のフォーマットで与えられます。

n
S_1 D_1
S_2 D_2
...
S_i D_i
...
S_n D_n

S_i は「文字」で、D_i は「整数」です。


入力値最終行の末尾に改行が１つ入ります。
文字列は標準入力から渡されます。

## 期待する出力
文字とまとめた数値の組を各行で出力してください。
文字と数値は半角スペースで区切ってください。

# お手本コード

```python
num = int(input())
inputs = {}
result = {}

for i in range(num):
    tmp = input().split()

    exist = False
    for (key, value) in inputs.items():
        if key == tmp[0]:
            exist = True

    if exist:
        inputs[tmp[0]] = inputs[tmp[0]] + int(tmp[1])
    else:
        inputs[tmp[0]] = int(tmp[1])

# ソート用にkeyとvalueを反転させた辞書を作る
for (key, value) in inputs.items():
    result[value] = key

result = sorted(result.items(), reverse=True)

for i in result:
    print(i[1] + " " + str(i[0]))
```
# 解説

## 考え方
以下の考え方で実現します

1. 標準入力が何回行われるかという値を取得してfor文の繰り返し回数に指定する。2~5を繰り返す
1. 標準入力で受け取った値を辞書のキーとバリューとして使う値に分割する
1. 2で取得したキーの値が既出かどうかを確認する
1. 既出の場合は１で取得したバリューを辞書内の同キーのバリューに足算する
1. 未出の場合は１で取得したキーとバリューを辞書に追加する
1. 2~5で作成した辞書をソートするためにキーとバリューを反転した辞書を作成する
1. 6で作成した辞書をsorted関数で降順にソートする。キーと値のタプルのリストになる
1. 7で作成したリストからキー、バリューに使用していた値を繰り返して出力する

## 2~5のコードの詳細
初見で考え方は思い付いたのですが、お手本を見るまでは実現させるイメージがつきませんでした。
お手本コード内の以下の箇所にあたります。

```python
for i in range(num):
    tmp = input().split()

    exist = False
    for (key, value) in inputs.items():
        
        if key == tmp[0]:
            exist = True

    if exist:
        inputs[tmp[0]] = inputs[tmp[0]] + int(tmp[1])
    else:
        inputs[tmp[0]] = int(tmp[1])
```
*取得したキーの値が既出かどうかを確認する*　の判断は
毎回、作成段階のリストからキーを一つずつ取り出して、今回のキーと同じであるか比較します。
初期値をFalseに設定しておき、同じであればTrueを返します。

Trueの場合は作成中辞書の今回のキーのバリューを今回のバリューと足算した値にします。
False、未出の場合は今回のキーとバリューを辞書に追加します。

# コードの改善箇所
@shiracamus　さんに改善点をご教示頂いたのでシェアしたいと思います。
ありがとうございます！

## 前述の2~5のコード箇所の簡略化
**取得したキーの値が既出かどうかを確認する** 箇所を
if tmp[0] in inputs: の一行で行うことが出来ます。
```python
for i in range(num):
    tmp = input().split()

    if tmp[0] in inputs:
        inputs[tmp[0]] = inputs[tmp[0]] + int(tmp[1])
    else:
        inputs[tmp[0]] = int(tmp[1])
```

## 前述の6~7のコード箇所の簡略化
反転した辞書は不要で、キーを対象としてソートを行うことが可能です。
以下一行で実現出来ます

```python
result = sorted(inputs.items(), key=lambda x: x[1], reverse=True)
```
処理速度が向上したり、視認性が良くなるのでより良いコードを知れる事はすごく嬉しいです。

# おわりに
競技プログラミングな問題は「考え方」と「実現方法」の理解が大切ですね。
今は問題を一つでも多くといて自分の中に吸収していきたいです。
WSL2でのWindows Terminal強制をやめたい

各WSLの実行ファイルを起動すると、`WindowsTerminal`が最近強制になってしまったので解除する方法を記載する。
勝手にデフォルト動作を変更するのは良くないよMS

「設定」でターミナルを検索すると
「ターミナルの設定」と「対話型コマンドラインツール用のホストアプリを選択します」がでるので（どちらでも飛び先は同じ）
ターミナル設定箇所の「Windowsに決定を許可する」から「Windows コンソールホスト」に選択を変える。保存ボタンはない

で通常のcmd画面が出ます
取引履歴のスリッページ情報を配列に取得する関数

　MQL5には取引履歴より、注文価格と約定価格を取得することができます。この仕様により注文価格と約定価格の差に注文の売り買いに応じて符号±をつけてスリッページを求めます。ここでは指定した期間の取引履歴からスリッページを各取引で求め、配列で返す関数を作成しました。

　スリッページはブローカーによっては結構でかいマイナス要因となるので日ごろからチェックしておきたい項目ですね。また、__注文価格を取得できないブローカーもあるので（注文価格＝0になる）__、うまくスリッページが取得できないときは残念ながらそういうことです…


## 関数の説明
|引数|型|種類|説明|
|:-:|:-:|:-:|:--|
|1|double|out|スリッページが入るdouble型の配列|
|2|ulong|in|マジックナンバー( -1は全マジックナンバーを指定 )|
|3|ENUM_DEAL_ENTRY|in|DEAL_ENTRY_INまたはDEAL_ENTRY_OUT。取得したい方。|
|4|datetime|in|取得したい期間の開始日時|
|5|datetime|in|取得したい期間の終了日時|

|戻り値|型|説明|
|:-:|:-:|:--|
||bool|処理が成功ならtrue|

## ソースコード（コピペしたい方どうぞ）
```.cpp
//+------------------------------------------------------------------+
//| 取引履歴のスリッページ情報を配列に取得する
//+------------------------------------------------------------------+
bool GetHistorySlippage(double &results[], const ulong magic_number, const ENUM_DEAL_ENTRY EDE, const datetime start, const datetime end)
  {
//--- 指定期間の取引履歴をリクエストする
   if(!HistorySelect(start, end))
      return (false);

   const ulong check_ma = 18446744073709551615; // magic_numberが-1だったとき
   
   uint  total_deals = HistoryDealsTotal(); // 履歴総数
   int   counter             = 0;           // 取引回数カウンター
   ulong ticket_history_deal = 0;           // ディールチケット
   
   ENUM_DEAL_ENTRY deal_entry;
   long            deal_type;
   long            deal_order;
   double          deal_price;
   double          order_price;
   double          slippage = 0;
   ulong           deal_magic;

//--- 配列を、履歴の取引数にリサイズ
   ArrayResize(results, total_deals);

//--- 全ての取引を配列に取得
   for(uint i = 0; i < total_deals; i++)
     {
      //--- 取引を選択する
      if((ticket_history_deal = HistoryDealGetTicket(i)) > 0)
        {
         deal_entry  = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket_history_deal, DEAL_ENTRY);
         deal_type   = HistoryDealGetInteger(ticket_history_deal, DEAL_TYPE);
         deal_order  = HistoryDealGetInteger(ticket_history_deal, DEAL_ORDER);
         order_price = HistoryOrderGetDouble(deal_order, ORDER_PRICE_OPEN);
         deal_price  = HistoryDealGetDouble(ticket_history_deal, DEAL_PRICE);
         deal_magic  = HistoryDealGetInteger(ticket_history_deal, DEAL_MAGIC);

         //--- 取引操作以外はスルー
         if((deal_type != DEAL_TYPE_BUY) && (deal_type != DEAL_TYPE_SELL))
            continue;
         
         //--- マジックナンバーの確認
         if( (deal_magic != magic_number)&&(check_ma != magic_number) )
            continue;

         //--- ENUM_DEAL_ENTRYで指定した情報のみ
         if(deal_entry == EDE)
           {
            if(deal_type == DEAL_TYPE_BUY){
              slippage = order_price - deal_price;
            }
            else if(deal_type == DEAL_TYPE_SELL){
              slippage = -(order_price - deal_price);
            }
            
            //--- 取引結果を配列に書き込み、取引のカウントアップ
            results[counter] = slippage;
            counter++;
           }
        }
     }
//--- 配列の最終サイズを設定する
   ArrayResize(results, counter);
   return (true);
  }
```
Yolov7でエラーが出た時の解決法

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/a8890ddc-af86-0576-1ba6-c6ceb0a673e0.jpeg width=400>

大丈夫です。すぐ解決できます。

# エラー１："_pickle.UnpicklingError: STACK_GLOBAL requires str" 

Yolov7で、「さあ、トレーニングしよう」というときにこのエラーが出てがっかりすること、ありますよね。

>"_pickle.UnpicklingError: STACK_GLOBAL requires str" 

**datasetのcacheファイルを削除すればいいだけです。**

```python
os.remove('my_dataset/labels/train.cache')
os.remove('my_dataset/labels/val.cache')
```

これでもう一度train.pyを実行すれば、うまくいくはずです。

# エラー２："Command 'git tag' returned non-zero exit status 128."

>Command 'git tag' returned non-zero exit status 128.

**models/experimental.py の251行目をコメントアウトしましょう。**

```python:models/experimental.py
#  attempt_download(w)
```

きっと解決します。

# エラー３："RuntimeError: CUDA out of memory. Tried to allocate XXX GiB ..."

>RuntimeError: CUDA out of memory. Tried to allocate XXX GiB ...

GPUのメモリが不足すると出ます。特に、img-size　1280のモデルを使うと、メモリが不足しやすいです。
**--batch-size　を小さくしてtrain.pyを再実行しましょう。例えば32→16**
小さくしても出る場合は、さらに小さくして、トレーニングが開始されるまで試してみましょう。**16→8→4→2**

理力があなたと共にありますように。

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

機械学習、ARアプリ（Web/iOS）を作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
javascript1・2終了

大学でC言語を習っているため、文法は違うものの考え方は一緒なのでサクサク進むことができる。
progateは非常によくできているサービスなので普通に進めていればエラーになることはなく、正直つまらないので早く自分で構想したものをコーディングしたい。
<br>pythonの自動化も興味があるし、kaggleに出場してスコアを競い合いたい欲もある。機械学習や深層学習も勉強したい。やりたいことを絞って取り組んでいきたい。
【pytorch】DataLoader を触ってみる

# はじめに

pytorch の DataLoader や function の使い方が分からないので、手元でガチャガチャ動かしてみました。
メモです。

# 内容

IRIS dataset を使ってみます。

```python
from sklearn import datasets
iris = datasets.load_iris()
```

ここでdata にndarray で値が収められています。

```
In [11]:  iris.data.shape
Out[11]: (150, 4)

In [12]: type(iris.data)
Out[12]: numpy.ndarray
```

正解ラベルが target に収められているようです。

```
In [15]: iris.target
Out[15]:
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
```

これらを学習で利用するために、pytorch ではDataLoader というクラスを使うらしい。

https://pytorch.org/docs/stable/data.html

DataLoader を使う上でのポイントとして、まずDataset の用意があります。

DataLoader のコンストラクタで dataset が必要。dataset は　map-style と iterable-style がある。map-style は __getitem__() と __len__() とが実装されていて、多くの場合 dataset[idx] で idx番目の要素を参照するように使うらしい。典型的な例では、torch.utils.data.Dataset を継承したクラスを作り、__getitem__() と __len__() を実装する例をよく見ます。

ただし、もっと簡単には TensorDataset を使うことができるようです。今の場合、


```python
tgts = torch.tensor(iris.target, dtype=torch.int64)
inps = torch.tensor(iris.data, dtype=torch.float32)
dataset = torch.utils.data.TensorDataset(inps, tgts)
```

最初の要素には、dataset[0]でアクセスできます。inps と tgts の二つのテンソルがそのまま tensors で参照できます。

```
In [27]: len(dataset.tensors)
Out[27]: 2

In [28]: dataset[0]
Out[28]: (tensor([5.1000, 3.5000, 1.4000, 0.2000]), tensor(0))

In [29]: len(dataset)
Out[29]: 150
```

バッチサイズを３にすると、最初の３個のデータがまとめて取得できます。

```
In [34]: data_loader = torch.utils.data.DataLoader(dataset,
    ...:                        batch_size=3, shuffle=False)

In [35]: for v in data_loader:
    ...:     print(v)
    ...:     break
    ...:
[tensor([[5.1000, 3.5000, 1.4000, 0.2000],
        [4.9000, 3.0000, 1.4000, 0.2000],
        [4.7000, 3.2000, 1.3000, 0.2000]]), tensor([0, 0, 0])]

In [36]: dataset[0:3]
Out[36]:
(tensor([[5.1000, 3.5000, 1.4000, 0.2000],
         [4.9000, 3.0000, 1.4000, 0.2000],
         [4.7000, 3.2000, 1.3000, 0.2000]]),
 tensor([0, 0, 0]))
 ```


バッチサイズが１（default) でも配列で与えられることは変わりないようです。

```
In [38]: for v in data_loader:
    ...:     print(v)
    ...:     break
    ...:
[tensor([[5.1000, 3.5000, 1.4000, 0.2000]]), tensor([0])]

In [39]: for d,t in data_loader:
    ...:     print(d.shape, t.shape)
    ...:     break
    ...:
torch.Size([1, 4]) torch.Size([1])
```

data_loader をtrain, validation で分けるために、dataset を分ける機能もtorch.utils.data.random_splitで提供されています。

ところで、ここで Cuda memory pinning について書かれていましたが、何のことだろう。
https://pytorch.org/docs/stable/notes/cuda.html#cuda-memory-pinning
GPUのメモリコピーは早いが、CPUで使う場合も非同期処理ができるようにほげほげ。。。

# まとめ

とりあえず、DataLoader については、ざっと目を通してみた。次はloss を計算する所を調べてみようかな。
Migrationファイル　備忘録

# Migrationファイルとは?
データベースの設計図の役割を持つ。
例えばroomsというテーブルに、nameというカラムを追加して下さいねと記述。
作成したmigrationファイルは rails db:migrateで実行する。

# Migrationファイル中身詳細
```ruby
#class Createテーブル名でMigrationファイルを定義
#[7.0]はRails7系を使っていることを示す
class CreateRooms <ActiveRecode:Migrate[7.0]
  def change
    #create_table：テーブル名でテーブルを作成するように宣言
    #ここではroomsというテーブル名でテーブルを作成
    create_table :rooms do |t|
        #t.テーブルのカラム型：カラム名、オプションの意味
        #string型のnameカラムを作成し、オプションとしてnullにはできないと指定
        t.string :name, null:false
        #integer型のfeeカラムを作成し、オプションとしてnullにできないようにし、デフォルトで0を設定
        t.interger :fee, null:false, default:0
        #自動的にcreated_atとupdated_atの２つのカラムを作成
        t.timestamps
    end
  end
end
```
【競プロ典型90問】004をPythonで解説

# はじめに
最近競プロを始めたので，[競プロ典型90問][1]の★1~★3を解いて典型問題へのアプローチ方法を学んでいます．
公式のソースコードがC++で困っているPython勢の方も多いと思うので，自分の解答をシェアしたいと思います！
初心者の解答なので，もっといい方法があれば教えていただけると嬉しいです！

# 004 Cross Sum（★2）
https://atcoder.jp/contests/typical90/tasks/typical90_d

## 問題文
$H$ 行 $W$ 列のマス目があります。上から $i$ $(1≤i≤H)$ 行目、左から $j$ $(1≤j≤W)$ 列目にあるマス $(i,j)$ には、整数 $A_{i,j}$ が書かれています。 すべてのマス $(i,j)$ $(1≤i≤H,1≤j≤W)$ について、以下の値を求めてください。

- マス $(i,j)$ と同じ行または同じ列にあるマス（自分自身を含む）に書かれている整数をすべて合計した値

## 制約
- $2≤H,W≤2000$
- $1≤A_{i,j}≤99$
- 入力は全て整数

# 解法
各マス $(i,j)$ について第 $i$ 行と第 $j$ 列の整数の合計を求めていくだけなので，やること自体は簡単です．しかし，愚直に実装しようとすると，第 $i$ 行の合計を求めるために $O(W)$，第$j$ 列の合計を求めるために $O(H)$ の計算量がそれぞれかかってしまい，これをすべてのマスについて計算するので $O((H+W)HW)$ の計算量になり `TLE`　してしまいます．
そこで，各マスについての個別の計算は必ず必要だと思われるので，各行と各列の合計を先に求めておくことを考えます．
まず，各行の合計を記録するためのリスト `sum_row` と 各列の合計を記録するためのリスト `sum_col` を用意し，第 $i$ 行の合計を `sum_row[i]` に，第 $j$ 行の合計を `sum_col[j]` に入れることにします．
このとき，「マス $(i,j)$ と同じ行または同じ列にあるマス（自分自身を含む）に書かれている整数をすべて合計した値」を `ans[i][j]` とすると以下の式で表されます．

```math
ans[i][j] = sum\_row[i] + sum\_col[j] - A[i][j]
```

ただし，`sum_row[i]` ，`sum_col[j]` にはそれぞれ `A[i][j]` が1回ずつ足されているため，重複している分を引いています．
`sum_row` を作るための計算量を考えると，1行の合計を求めるための計算量は $O(W)$ で，それを $H$ 行分計算するので，$O(HW)$．`sum_col` についても同様です．
したがって，各マスについての計算と，行，列ごとの合計の計算を分離したため，全体の計算量が $O(HW)$ になりました．制約は $2≤H, W≤2000$　なので，十分間に合いそうです.

# 実装
解法の部分で説明した内容をそのままコードにすればよいので，それほど難しいところはないと思いますが，`sum_col` の計算が複雑になってしまう人がいるかもしれません．そこで，今回は `map` を使うことで1行で実装できるようにしています．少し見慣れない書き方かもしれませんが，2次元配列の列ごとの合計を求める際に非常に便利なので，覚えておくとよいと思います． 

↓↓↓ 2次元リストの合計の求め方です ↓↓↓

https://knuth256.com/2021/05/06/python3-%E3%80%802%E6%AC%A1%E5%85%83%E3%83%AA%E3%82%B9%E3%83%88%E3%81%AE%E5%90%88%E8%A8%88%E8%A1%8C%E3%83%BB%E5%88%97%E3%83%BB%E5%85%A8%E8%A6%81%E7%B4%A0%E3%82%92%E6%B1%82%E3%82%81%E3%82%8B%EF%BC%81/


```Python: answer.py
import sys
input = sys.stdin.readline


H, W = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(H)]
# 行, 列ごとの合計をリストに入れる
sum_row = list(map(sum, A))
sum_col = list(map(sum, zip(*A)))
# Aのすべての要素を更新
for i in range(H):
    for j in range(W):
        A[i][j] = sum_row[i] + sum_col[j] - A[i][j]
# 出力
for i in range(H):
    print(*A[i])
```

# さいごに
今回はやること自体はそれほど難しくないものの，計算量を減らす工夫が必要な問題でした．同じ計算や値を何度も使う場合には，それらをはじめに求めておくと上手くいくことが多いと思います． 
よく分からないことやコードの改善点などありましたら，気軽にコメントしてください．

最後までお付き合いいただきありがとうございました！

<!-- リンク集 -->
[1]: https://atcoder.jp/contests/typical90
ball sort puzzleを作ってみた

# はじめに
そのままなんですが、ball sort puzzleを作ってみました。
作ったきっかけは、妻が広告がうざいというから、そんなの簡単に作れるわとうっかり言ってしまい、３連休がつぶれました。

こんな画面のものです。広告は出ませんｗ
ボールの色と深さ、空きの数を指定して、開始します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/8f5e4d3e-8a51-441d-e1c3-d3dbd7bb69ea.png)

実行環境はこちら
http://ball-sort-puzzle-yo16.herokuapp.com/

ソースはこちら

https://github.com/yo16/ball_sort_puzzle


# 技術的なこと
いつものとおり、JavaScriptでやってしまいました。新しいことを身に着けたいと言いながら、いつも同じパターンに戻ってしまう。

d3.jsを使って、ボールを描いたり移動させました。d3.jsともだいぶ仲良しになってきましたが、もう一歩というところか。SVGでのお絵描きは、とにかくコード量が多くなります。パラメータ１つで１行かかるので。ほんとはソースをうまく分割するとよいと思います。

# 仕様のこと
技術的なことよりも、ball sort puzzleは仕様が意外と難しい。ボールを動かすルールではなく、適度に難しい問題を作ることが難しいです。

最終的なゴールは、それぞれの箱（フラスコ？私のソースではboxとしましたが）に同じ色のボールがすべて入れば終了なので、↓こんな感じがゴールです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/340f9b9b-48a5-36d6-bc51-7403399bb48d.png)
そこで私のball sort puzzleは、ゴールから遡って問題を作ることにしてみました。

まず上の図から遡って、まず１歩遡って、これ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/983cdebc-7ee4-a93d-5b5e-c679722cad9f.png)

もう１歩遡ってこうする・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/73a642de-38b6-7e52-5d5a-9c3f801316a0.png)

そうすると、もう左から２番目の箱は、遡るためにいじれないです。
なぜかというと、２番目のトップの水色を遡って動かすことは、逆に通常のプレイの時間でいうと、黄色の上にどこからか水色を乗せるということになり、ゲームのルールに沿わないためです。（説明が難しい・・・）
そんなわけで、この２番目の箱はもう手を付けられず、終了。

これが起こると同じ色の塊ができてしまい、難易度が一気に下がります。問題を作るときに工夫しないといけないです。この問題をどう回避するのかがわからないです。とりあえず、この問題が起きると動かせる回数が著しく減るので、動かす回数が少ないときは最初から作り直し、みたいにしています。

よくあるアプリでは、完全に空の箱が１個か２個あって、それ以外の箱にはみっちりバラバラで入ってます。それやりたかったんだけど、ロジックがよくわかりません。手で問題作るとできるから、もうちょっと考えればできるかも。

もしかしたら、ランダムでボールが並んでいるときに、並び替えることが可能かどうか、判定する方法があるかもしれない。

今回はひとまず作ったところまで。

# 今後の課題
- 問題作成モードを完成させる
    - 手で問題を作るモード
    - いちおう作ったけど、動きが怪しいので非表示にしてある
- 適切な問題を作れるようにする
- 終わったら「終わり」的なメッセージを出すようにする
    - 達成感がいまいち
Google UXデザイン：ユーザーストーリーを作る

# はじめに

わたしが[Google UX Design Certificateで得られた素晴らしい体験][google]を、特に重要だと思われるポイントを小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ Google UX Design Certificateを受講してみてください。

[google]: https://qiita.com/mapami/items/7a0d0a3d4661c50f8bec

https://www.coursera.org/professional-certificates/google-ux-design

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/3729adea-8dba-b2a3-6127-9b0bf6886e54.png" width="800">

# ユーザーストーリーとは

ユーザーストーリーとは、ペルソナの視点から語られる1文の架空の物語です。これはペルソナを発展させ、ユーザーグループに対する理解を深めてくれます。

***<font color="MediumVioletRed">『ユーザーストーリーは、デザイン上の意思決定にインスピレーションを与え、情報を提供するもの』</font>***

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/924d7421-e92e-7b7b-8144-a5e88f3c6516.jpeg" width="700">

# ユーザーストーリーができること

- デザインゴールに ***<font color="Teal">優先順位</font>*** をつけます。検討すべきユーザーニーズがたくさんある場合、ユーザーストーリーは、どのニーズを解決することが最も重要であるかを決定します。
- 明確な目標のもとに ***<font color="Teal">チームを団結</font>*** させます。
- 私たちのアプローチをユーザー中心にすることで、***<font color="Teal">共感できるデザイン決定を促す</font>***　こともできます。
- ステークホルダーへの説得力ある売り込みのための ***<font color="Teal">パーソナライズ</font>*** ができます。あなたは、単に最新デザインのアイデアを提示するだけではなく、特定のタイプの人々をどのように助けるかを示すのです。

# ユーザーストーリーの書き方

ユーザーストーリーを書くには、次のようなシンプルな公式を用います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/a958c711-5d04-4d3b-ac63-d4daf7527cda.png" width="600">

- ***type of user***： 私たちがデザインする対象者
- ***action***: ユーザーが何を望んでいるか
- ***benefit***: ユーザーがその行動を起こしたい理由

このフォーマットを使うことで、ユーザーストーリーがペルソナについて知っておくべきことを全て伝える明確な方法となります。

:::note info
ユーザーストーリーのベストプラクティスは、短く、インパクトがあり、要点を押さえていて、明確な行動と利益があることです。
:::

作成したユーザーストーリーは、ユーザーが製品に関わる際に直面する可能性のある重要な問題に対処し、解決するための「チェックリスト」としても機能します。

# サンプル（犬の散歩アプリ）

- 旅行が多いので、旅行中のペットの安全について安心できるように、一貫したドッグウォーカーを雇いたい。
- 犬の飼い主として、私は定期的に犬の散歩のためにそれらを雇うことができるように、私の犬の散歩を信頼したい。
- 忙しい経営者なので、ドッグウォーカーを信頼し、安心して仕事ができるようにしたい。
- 優柔不断な学生なので、たくさんのドッグウォーカーを試してみて、その中から定期的に散歩に行ける人を選びたい。
- 2児の母として、家族の安全を守るために、自宅への出入りを制限したい。
- 元警察官として、ペットの安全を確保するために、犬の散歩を追跡したい。
- 未亡人の経営者として、私のペットがふさわしいケアを受けることができるよう、常駐のドッグウォーカーを見つけたい。

このようなユーザーストーリーを念頭に置くことで、作成するデザインに反映させることができます。例えば、犬の散歩アプリでは、次のことを検討できます。
- ユーザーは、犬の散歩の日時をリクエストできる
- ユーザーは、特定の犬の散歩者を選択できる
- ユーザーは、犬の散歩者のバックグラウンドを確認できる


ユーザーによってニーズは異なるので、ユーザーストーリーを書くときは、必ず共感し、彼らのユニークなニーズを心に留めておいてください
Three.jsでおみくじアプリを作りました

# はじめに

最近占いに興味が出てきたのとThree.jsで何かアプリ作りたいな～とずっと思っていたんですが、
そうだ！おみくじアプリ作ればいいんや！ということでおみくじアプリをサクッと簡単に作ってみました

では早速作ったアプリを紹介します
こんな感じのアプリです！

![omi.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2275128/04fcaeb6-331b-126f-b95c-1c10c41abcfa.gif)

おみくじの木箱と棒をイメージして、棒を出し入れすることで運勢を占うという非常にシンプルなWebアプリを作りました!!
スクロールで棒が動きます


# 使用技術

[言語]
・JavaScript

[ビルドツール]
・Vite
-> Vanilla

[アプリでメインで利用するライブラリ]
・Three.js


# リポジトリ

コードはGitHubにあげています
こちらです
https://github.com/orekyo/omikujidaikicchi


# 使ってみたい人

https://omikujidaikicchi.vercel.app/


# おわりに

今回はざっくり簡単に作ってみました
今後気が向いたら作り込んでいこうと思います

木箱のテクスチャとかちゃんと作り込みたいですね
RPi + CHIRIMEN + Node-REDの環境づくり

# はじめに
Web IoT MakersというIoTの演習＋ハッカソンイベントでCHIRIMENというJavaScriptでRPiを動かせるフレームワークを学びました。
Web系のエンジニアの方はJavaScriptですいすいコーディングできるのだと思うのですが、すこしでも楽をしたいのでNode-RED環境も作って併用する環境を作ってみます。
少々回りくどいですが、CHIRIMENのコア部分はWeb I2C APIとWeb GPIO APIです。htmlでUIを使ってJSのAPIでセンサやGPIO制御してMQTTでデータをNode-REDに投げてごにょごにょするイメージです。


# CHIRIMEN用のマイクロSDを作る

CHIRIMENの基本的な情報は次のサイトを参考にしてください。
https://chirimen.org/
https://tutorial.chirimen.org/pizero/#chirimen--1
https://chirimen.org/chirimen/gc/top/examples/

起動用のmicro SDカードの作り方はこちらです。
https://tutorial.chirimen.org/raspi/sdcard

基本的な流れは次の通り
①OSイメージファイルを[ダウンロード](https://r.chirimen.org/sdimage)
②イメージファイルを解凍
③[balena Etcher](https://www.balena.io/etcher/)で書き込み


# Node-REDをインストール
先ほど作ったmicroSDでRaspberry Piを立ち上げ、Node-REDをインストールします。
インストール方法はNode-RED公式の通り、terminalから次のコマンドを実行します。

```shell
bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
```
途中で2回ほど[y/N]を聞かれるのでどちらも[y]。

インストールには数分かかります。

# Node-REDを起動する

Node-REDを起動するコマンドは次の通り。terminalから実行します。
```shell
node-red-pi --max-old-space-size=256
```

シェルスクリプトを使って自動起動
```
sudo vim $home/Workspace/node-red-start.sh
```
スクリプトの中身
```
node-red-pi --max-old-space-size=256
```
crontabにコマンド追加
```
crontab -e
```
初めて起動するときはエディタに何を使うか聞いてくるのでお好みで。
よくわからない人はnanoを選んでおくとよいかな。
設定ファイルの一番最後に一行追加して保存
```
@reboot /home/airpocket/Workspace/node-red-start.sh
```
airpocketのところは自分のuser名を。


# Node-REDを自動起動する
毎回起動コマンドを入力するのはめんどくさいので、自動実行させておきましょう。
```shell
sudo systemctl enable nodered.service
```


自動実行をやめるのは次のコマンドです。
```shell
sudo systemctl disable nodered.service
```



# Node-REDにアクセスする
Node-REDはブラウザでアクセスして、フロー（プログラム）を編集します。
Raspberry Piのブラウザでアクセスする場合は、ブラウザを立ち上げて「http://localhost:1880」を読み込みましょう。初めてアクセスするとチュートリアルが表示されます。消してOK。
Raspberry Piと同じLANに接続しているPCからもブラウザで簡単にアクセスできます。
アクセス先のアドレスは「http://***.***.***.***:1880」です。***にはRaspberry PiのIPアドレスを指定します。


# Node-REDの使い方をちょっとだけ

Node-REDの画面構成はこのようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/0fd4ce17-a180-e33e-db84-2268f96d0eb3.png)

パレットには、様々な昨日を持った「ノード」がならんでいます。試しに「inject」と「debug」 ノードをワークスペースにドラッグしてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/de81f72d-bd4f-7d3f-19d1-a6d962b4b8aa.png)

「inject」が「タイムスタンプ」、「debug」が「msg.payload」に変化します。①から④の操作を続けてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/38809eb4-6d63-7ffe-f58a-c9f5663f0c3f.png)

画面右のサイドバーの虫のマークのアイコンをクリックして、デバックタブを表示すると、タイムスタンプノードで取得した現在時刻のデータがmsg.payloadノードからデバッグウィンドウに出力されています。数字はUNIX時間で表示されていますがデバッグウィンドウ内の▶をクリックすると表示フォーマットを変更できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/b93be7cc-c8d6-5656-04a3-c58c5d07088d.png)

次に、時刻データではなく、テキストメッセージを出力してみます。下図の通り、「inject」ノードのプロパティを変更すると時刻ではなく、テキストが表示されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496179/7d72744e-c33b-64f8-600e-84a2f92f30cb.png)
Node-REDは、ノードをつなげるて、msg.payroadなどのデータを次のノードに送りながら様々な処理を行うフロー形式のプログラミングツールであることがなんとなくイメージできたでしょうか。

# まとめ
CHIRIMENにNode-RED環境をインストールしました。
2022年10月現在、CHRIMENはDebian Busterベース、インストールされているNode.jsはVer14ですがNode-REDのインストールは可能でした。
C/C++で #defineは #include の後に書く理由？

## はじめに

こんなコードを見た。
``` C++
#include <iostream>

int main(int, char**) {
    std::cout << "Hello, world!\n";
}
```

あれっ？main()の引数に名前がないぞ？これ使えるの？答えは「使えない」である。ではなぜ引数名を省略するのか？

## ググってみた

いくつか理由はあるらしい。

* 将来のために引数を予約しておきたい
* 関数をオーバーロードしたときに引数の数で動作を変えたい

その他に「プロトタイプの宣言では引数を省略する」というのが出てきた。どういうことだ?

次のコードを考えてみよう。

``` main.cpp
#define hoge 1
#include "func.hpp"

int main()
{
    func1(3);
    return 0;
}
```

``` func.hpp
int func1(int hoge);
int func2(int fuga);
```

このコード、コンパイルが通らない。では、これをプリプロセッサにかけてみよう。

```
$ cpp main.cpp
# 1 "./func.hpp" 1
int func1(int 1);
int func2(int fuga);

# 3 "main.cpp" 2

int main()
{
    return 0;
}
```

あれっ？関数のプロトタイプがおかしくなっってる?はい、そのようである。

これは、main.cppの1行目の #define が、問題を起こしてしまった。'hoge'という識別子と競合してしまったのだ。通常ライブラリを使うときにはヘッダファイルを隅々まで読んで使うことはない。たまたま自分が使ったマクロ展開がライブラリ内の識別子とぶつかってしまうことは可能性としては起こりうる。

今回の例ではそもそもコンパイルが通らないのでまだ問題は発見しやすいが、

```
#define hoge []
```

なんて書いてしまったら、文法上は正しいことになる。もちろん呼び出してみればエラーにはなるが、もうその理由は意味不明であろう。

## そういえば？

おそらくC言語系を学んだ皆さんは、習慣的に#defineは#includeとかが一通り終了した後に書いているのではなかろうか。また、特別な理由がない限りソースコードの途中でなにかのファイルをインクルードすることはしないはずだ。それはほとんど習慣だったかもしれない。

私もなぜそうしているのかを深く考えたことはなかった。ひょっとしたら当時の師匠には理由を説明されたかもしれないけれど、初心者な私はマクロ展開なんてわかっちゃいなかった。

## では解決してみよう。

``` main.cpp
#include "func.hpp"
#define hoge 1
int main()
{
    func1(3);
    return 0;
}
```

めでたい！解決である。

## セキュリティ上の問題

JPCERTのページにこんなのがある。

[関数プロトタイプでは引数に名前をつけない](https://www.jpcert.or.jp/sc-rules/c-api08-c.html)

なるほど、場合によってはセキュリティ上のリスクになるのか、それは気が付かなかった。

ということで、普段コードを書くときは #define は後ろに、ヘッダファイルを書くときは引数名は書かないように、ということなのだろう。
wsl --import が一向に終わらない

# 概要

PC 引っ越しのために `wsl --export` した tarball を別の PC で `wsl --import` したところ、数時間経ってもインポートが終わらなかった。

tarball のサイズは 20GB 程度とそこまで大きいわけでもない。

# 原因

タスクマネージャーを見ると「bsdtar」というプロセスが動いていた。おそらく tarball を展開しているのだと思われる。
しかしディスクのスループットが「0.5MB/s」前後しか出ていなかった。仮に 20GB を 0.5MB/s で展開するとなると 10 時間ほどかかる計算になる。

このとき「Antimalware Service Executable」がやけにメモリとディスクのリソースを食っていることに気付き、Windows Defender の「リアルタイム保護」を一時的に無効化させた。
すると「bsdtar」のディスクスループットが増大し、20MB/s 程度まで出るようになった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49525/598324c8-2b42-36cb-6b2f-18c5c65802c5.png)

Windows Defender によって速度が出なかった可能性が高い。
【Ruby】ファイルのタイムスタンプを参照したい時

# 概要　
内容が更新されていた場合のみファイルを処理したいなど、
タイムスタンプ情報を元にしてファイルを処理したい場合などがあります。
その場合は、
`File.mtime`メソッド,`File.atime`メソッド,`File.ctime`メソッド
を使って取得することができます。

## 使用例

|  定義  |  動作  |
| ----- | ---- |
| File.mtime | 最終更新時刻を返す。 |
| File.atime | 最終アクセス時刻を返す。 |
| File.ctime | 状態が最後に変更された時刻を返す。状態の変更とは chmod などによるもの |

### File.mtime
```ruby
File.mtime(__FILE__) # => 2017-12-03 03:16:22 +0900
```

### File.atime
```ruby
File.atime(__FILE__) # => 2017-11-28 22:38:44 +0900
```

### File.ctime
```ruby
IO.write("testfile", "test")
File.ctime("testfile") # => 2017-11-30 22:40:49 +0900
File.chmod(0755, "testfile")
File.ctime("testfile") # => 2017-11-30 22:42:12 +0900
```

# 参考
* File.mtime
https://docs.ruby-lang.org/ja/latest/method/File/s/mtime.html

* File.atime
https://docs.ruby-lang.org/ja/latest/method/File/s/atime.html

* File.ctime
https://docs.ruby-lang.org/ja/latest/method/File/s/ctime.html
wavファイルの作成

何故か急にwavファイルを作りたくなったので作成してみましたので、その際に覚えた知識をメモとして残します。

# ライブラリ
本投稿では下のライブラリを使います。
* math（正弦波を作成するため）
* numpy（1次元配列を扱うため）
* scipy（wavファイルの作成のため）
* playsound（wavファイルの再生のため）

# 波形を作る
サンプルとして100Hzの正弦波を作成します。なお、サンプリングレートを44100Hzとするため、441個で1周期となる正弦波を100個（つまり1秒分）作成しています。
```python:
import math
data = [ math.sin(2 * math.pi * i / 441) for i in range(44100) ]
```

# データを整数化する
wavファイルにするには`int16`にしないといけないので、波形の最大値で割り、`int16`の正の最大値である`32767`を掛けてから、`int16`にしています。
```python:
import numpy as np
data2 = np.int16(data / np.abs(data).max() * 32767)
```

# wavファイルとして保存
ファイル名を`test.wav`、サンプリングレートを`44100`として保存します。
```python:
from scipy.io.wavfile import write
write('test.wav', 44100, data2)
```

# wavファイルの再生
保存したwavファイルを再生します。
```python:
from playsound import playsound
playsound('test.wav')
```

# おまけ
逆に保存したファイルを高速フーリエ変換(FFT)してみました。ファイルの読み込みにはwaveライブラリを使います。上記で作成したwavファイルであれば、下のようなプログラムになります。（モノラル16bitの場合だけです。bit数が違っていたりステレオ等だと、データフォーマットが違うので使えません）
```python:
import wave
import numpy as np
f = wave.open('test.wav', 'rb')
data = f.readframes(f.getnframes())
f.close()
data2 = np.frombuffer(data, dtype = 'int16')
data3 = np.fft.fft(data2 / np.abs(data2).max())
```
twitter API(投稿)使って困ったところ

自分のサービスの告知などでTwitterに自動でツイートするシステムを作ろうと思っていろいろ試して、詰まった点などを書こうと思います。

## ・前提
以下二つの記事を見れば一通りできると思うので読んでみてください。

https://codechacha.com/ja/nodejs-twitter-api/
https://qiita.com/kzthrk/items/84acb969dc0b23aeae58


## ・自分が詰まったところ1
実行するとエラーがかえってきてエラーのメッセージを確認してみました。
you’ll need to apply for Elevated access.
ただ単に登録だけだとレベルのようなものがEssentialだからだめと言われ、Elevatedにランクアップみたいなのをしないといけませんでした。
これのためには、簡単なアンケートようなものに答えるだけです。
（どのような使い方するのか、データをアナライズする予定はあるか、など5分もあれば終わります。
）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2092476/d53ecadf-379a-2fb4-a57c-97e9a3c10b26.png)

エラーメッセージ本文
```
[ { message: 'You currently have Essential access which includes access to Twitter API v2 endpoints only. If you need access to this endpoint, you’ll need to apply for Elevated access via the Developer Portal. You can learn more here: https://developer.twitter.com/en/docs/twitter-api/getting-started/about-twitter-api#v2-access-leve',
    code: 453 } ]
```
## ・自分が詰まったところ2
Linkを載せたかったので、"attachment_url"のパラメータで投稿しようとするとこれもエラーが返ってきました。
そこでリファレンス記載の概要を確認しました。
要はふつうのURLリンクを記載する場合にはattachment_urlは使わないでstatusの中に含んでね、ということでした。

コード的には以下の形で無事tweet出来ました。タグ追加も無事にできました。
```
tweet = message + " " + attachUrl + " " + tagList.join(" ")

client.post('statuses/update', { status: tweet }, function (error, tweet, response) {
    if (error) {
        console.log(error);
        throw error
    };

    console.log(tweet);  // Tweet body.
    console.log(response);  // Raw response object.
});
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2092476/39465099-3727-34bb-025b-a9c4528cbcf8.png)


本文
```
In order for a URL to not be counted in the status body of an extended Tweet, provide a URL as a Tweet attachment. This URL must be a Tweet permalink, or Direct Message deep link. Arbitrary, non-Twitter URLs must remain in the status text. URLs passed to the attachment_url parameter not matching either a Tweet permalink or Direct Message deep link will fail at Tweet creation and cause an exception.
```

Google翻訳
```
URL が拡張ツイートのステータス本文にカウントされないようにするには、URL をツイートの添付ファイルとして提供します。この URL は、ツイートのパーマリンクまたはダイレクト メッセージのディープ リンクである必要があります。 Twitter 以外の任意の URL は、ステータス テキストに残す必要があります。ツイートのパーマリンクまたはダイレクト メッセージのディープ リンクのいずれとも一致しない attachment_url パラメーターに渡された URL は、ツイートの作成に失敗し、例外が発生します。
```

リファレンス（https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/post-statuses-update）

## ・最後に
google翻訳ってほんとに便利。
【Ruby】ファイル名がパターンにマッチするか調べたい時

# 概要　
File.fnmatchメソッドを使用すると、与えられたファイル名がパターンにマッチするか確認できます。
特定のファイル名のみ受け付けるなどの処理に有効です。（特定の文字から始まるファイル名しか受けつけないなど）

## 記載方法
* fnmatch(pattern, path, flags = 0) -> bool
* fnmatch?(pattern, path, flags = 0) -> bool

例
```ruby
%w(foo foobar bar).each {|f|
  p File.fnmatch("foo*", f)
}
# => true
#    true
#    false

p File.fnmatch("ruby*", "rubytest.txt") # => true
p File.fnmatch("ruby*", "javatest.txt") # => false
```

## 注意事項
パターンで使用できるワイルドカードの一覧は以下の通りです。
正規表現ではないため注意が必要。

|  指定方法  |  動作  |
| ----- | ---- |
|  *    |  任意の0文字以上にマッチ  |
|  ?    |  任意の1文字にマッチ  |
|  []   |  []で囲んだ文字のいずれかにマッチ  |

またflagsを指定することにより、パターンマッチの動作を変更可能となる

|  定数  |  動作  |
| ----- | ---- |
|  FNM_NOESCAPE    |  エスケープ文字 「\」 を普通の文字とみなす  |
|  FNM_PATHNAME    |  ワイルドカード 「*」, 「?」, 「[]」 が 「/」 にマッチしなくなる |
|  FNM_CASEFOLD   |  アルファベットの大小文字を区別せずにパターンマッチを行う  |
|  FNM_DOTMATCH   |  ワイルドカード 「*」, 「?」, 「[]」 が先頭の 「.」 にマッチする  |
|  FNM_EXTGLOB   |  {} 内のコンマで区切られた文字列の組合せにマッチするようになる。例えば、foo{a,b,c} は fooa, foob, fooc に展開されそれぞれに対してマッチ判定を行います。  |

# 参考
* File.fnmatch
https://docs.ruby-lang.org/ja/latest/method/File/s/fnmatch.html
GitHubからAWSにOIDC認証するときのIAM信頼ポリシーではStringLikeとStringEqualsに気をつける

# 概要

今までGitHub ActionsでAWSにOpenID Connect認証する設定を2回して、2回ともハマった設定ミスを今後はもう繰り返さないためにメモ。

# 内容

設定の過程で、認証先のIAMロールに信頼ポリシーを設定する必要がある。
https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#configuring-the-role-and-trust-policy

そのConditionに次のようなものを書いてしまうと失敗する。

```
"Condition": {
  "StringEquals": {
    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
    "token.actions.githubusercontent.com:sub": "repo:octo-org/octo-repo:*"
  }
}
```

マネジメントコンソールから編集する場合は、ワイルドカードを使っているのにStringEqualsを使っていることに警告が出るが、Terraformを使っていたためになかなか気付けなかった。

なんでこんなことが起きてしまったかというと、最初に
```
"token.actions.githubusercontent.com:sub": "repo:octo-org/octo-repo:ref:refs/heads/octo-branch"
```
のように具体的なブランチの指定をStringEqualsで書いたあとで（別の理由でうまくOIDC認証が成功せず、もしやここのミスじゃないかと思うなどして）ワイルドカードに書き換えたからである。本当は、ワイルドカードにするならStringLikeに変える必要がある：
```
"Condition": {
  "StringEquals": {
    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
  },
  "StringLike": {
    "token.actions.githubusercontent.com:sub": "repo:octo-org/octo-repo:*"
  }
}
```

# ちなみに

OIDC認証がうまく成功しなかった場合、GitHub Actionsの実行ログを見てもあまり情報が得られないことが多い。このときは、CloudTrailからAssumeRoleWithWebIdentityイベントの中身を見ると上記信頼ポリシーのaudやsubにあたる値も見ることができるため、これらの設定でミスっていないか、予期せぬ値がGitHub Actionsから渡っていないか調べることができる。

他にも、pull requestをトリガーにしたGitHub Actionsから来る場合には、subが `repo:octo-org/octo-repo:pull_request` になることもCloudTrailから分かる。
Dockerを用いてLabelImgを使用する on Ubuntu

# やり方

下記の内容を記述したDockerfileを用意します。

```docker
FROM ubuntu:20.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y pyqt5-dev-tools python3-pip git
RUN git clone https://github.com/tzutalin/labelImg.git && \
    cd labelImg && \
    pip3 install lxml && \
    make qt5py3
CMD ["python3","labelImg/labelImg.py"]
```

イメージをビルドします

```bash
$ docker build -t labelimg .
```

GUI表示ができるように設定します

```bash
$ xhost +
```

コンテナを作成・実行します

```bash
$ docker run -it --rm -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix -v <共有元パス>:<共有先パス> labelimg
```
ウィンドウが表示されます。
![example.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/785720/78c81bbf-1a26-3e2f-2a97-84600881ebb7.jpeg)
HGW配下のYAMAHA RTX1210でIPv4通信を行う最低限のコンフィグ

## 1. はじめに

学習のために実験的に行った構成です。IPv6を使わずに、IPv4のみでHGW経由で通信します。
HGWでBIGLOBEのIPv6オプションを使用しています。

IPv6通信も行う場合は、下記ページのコンフィグからL2TPv3/IPsec等を削ればできます。

YAMAHA RTX1210 2台を使用したフレッツ網折り返し通信によるL2TPv3/IPsec通信 - Qiita
https://qiita.com/mayo00/items/774b650215959925d89c

## 2. ネットワーク構成

![20221010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534247/033c7cea-2c79-028e-b6f4-a7096df20655.png)

|機器|IPアドレス|備考|
|---|---|---|
|HGW(PR-500KI)|192.168.1.1||
|RTX1210 LAN2|192.168.1.254|うちではRTX1300が254を使用しているので253を使用していたけど書き換えました|
|RTX1210 LAN1|192.168.100.1||
|PC|192.168.100.100||

## 3. コンフィグ

```
ip route default gateway 192.168.1.1
ip lan1 address 192.168.100.1/24
ip lan2 address 192.168.1.254/24
ip lan2 secure filter in 1000 2000
ip lan2 secure filter out 3000 dynamic 100 200 300 400 500 600 700 800
ip lan2 nat descriptor 1
ip filter 1000 pass * * icmp
ip filter 2000 reject * * * * *
ip filter 3000 pass * * * * *
ip filter dynamic 100 * * ftp
ip filter dynamic 200 * * domain
ip filter dynamic 300 * * www
ip filter dynamic 400 * * smtp
ip filter dynamic 500 * * pop3
ip filter dynamic 600 * * submission
ip filter dynamic 700 * * tcp
ip filter dynamic 800 * * udp
nat descriptor type 1 masquerade
nat descriptor address outer 1 primary
nat descriptor address inner 1 auto
dhcp service server
dhcp server rfc2131 compliant except remain-silent
dhcp scope 1 192.168.100.2-192.168.100.50/24
dhcp scope option 1 dns=192.168.100.1
dns host lan1
dns server 8.8.8.8 8.8.4.4
dns server dhcp lan2
```

## 4. 説明

IPアドレス、デフォルトゲートウェイ設定。

```
ip route default gateway 192.168.1.1
ip lan1 address 192.168.100.1/24
ip lan2 address 192.168.1.254/24
```

外から内はICMP(ping)のみ。本当はLANのアドレス範囲を指定したりしたほうがよいらしい。

```
ip lan2 secure filter in 1000 2000
ip filter 1000 pass * * icmp
ip filter 2000 reject * * * * *
```

内から外は通す。FTP、domain(DNS関連)、WWW、SMTP、POP3、submission(SMTP関連)、TCP、UDPの応答は通す。
UDPを入れておかないとChromeリモートデスクトップが使えない。

参考：
NVR500 GUI「プロバイダ情報の設定」で設定されるIPフィルターの解説
https://network.yamaha.com/setting/router_firewall/security/wan_side/ip_filter_wizard_explain-nvr500

```
ip lan2 secure filter out 3000 dynamic 100 200 300 400 500 600 700 800
ip filter 3000 pass * * * * *
ip filter dynamic 100 * * ftp
ip filter dynamic 200 * * domain
ip filter dynamic 300 * * www
ip filter dynamic 400 * * smtp
ip filter dynamic 500 * * pop3
ip filter dynamic 600 * * submission
ip filter dynamic 700 * * tcp
ip filter dynamic 800 * * udp
```

NAT設定。

```
ip lan2 nat descriptor 1
nat descriptor type 1 masquerade
nat descriptor address outer 1 primary
nat descriptor address inner 1 auto
```

DHCP。範囲はアドレス末尾2～50。

```
dhcp service server
dhcp server rfc2131 compliant except remain-silent
dhcp scope 1 192.168.100.2-192.168.100.50/24
dhcp scope option 1 dns=192.168.100.1
```

DNS。Google DNS使用。

```
dns host lan1
dns server 8.8.8.8 8.8.4.4
dns server dhcp lan2
```
「多次元の分布関数の不連続点は高々可算」とは限らない

# はじめに
以下の記事で述べた通り、多次元の分布関数の連続点は稠密です。
一方で「多次元の分布関数の不連続点は高々可算」ではない場合があります。
これは一次元の場合と決定的に異なる点ですがあまり強調して述べられることがありません。
そこでこの記事では、多次元の分布関数で不連続点が高々可算でない例を紹介します。

https://qiita.com/mochimochidog/items/a5091dda350fb00f6086

# 準備
まず、以下の補題を証明しましょう。これはFubiniの定理の証明（の前段階）で使われたりします。

> **補題1**
$2$ 次元の Borel 集合 $E \in \mathscr{B}_{\mathbb{R^2}}$ と $y \in \mathbb{R}$ に対して、
$$
E^y := \\{x \in \mathbb{R} \mid (x, y) \in E \\}
$$
と定めると、$E^y \in \mathscr{B}\_{\mathbb{R}}$ となる。

**証明**
以下のように置きます。
$$
\mathscr{F} = \\{ F \in \mathscr{B}\_{\mathbb{R^2}} \mid \forall y \in \mathbb{R},\~ F^y \in \mathscr{B}\_{\mathbb{R}} \\}
$$
すると、$\mathscr{F}$ は $\mathbb{R}^2$ 上の $\sigma$-加法族となります。実際、$\emptyset^y = \emptyset$ より $\emptyset \in \mathscr{F}$ です。また、$(F^c)^y = (F^y)^c$ より $\mathscr{F}$ の元の補集合はまた $\mathscr{F}$ に属します。さらに、$\\{E_n\\}\_{n \in \mathbb{N}} \subset \mathscr{F}$ に対して、 
$$
(\bigcup_{n \in \mathbb{N}} E_n)^y =\bigcup_{n \in \mathbb{N}} (E_n)^y \in \mathscr{B}\_{\mathbb{R}}
$$
となります。そして、$ A, B \in \mathscr{B}\_{\mathbb{R}}$ とするとき、$F = A \times B$ とおくと、$F \in \mathscr{F}$ となります。なぜなら $y \in B$ ならば $F^y = A \in \mathscr{B}\_{\mathbb{R}}$ となり、$y \notin B$ ならば $F^y = \emptyset \in \mathscr{B}\_{\mathbb{R}}$ となるからです。よって、
$$
\\{ A \times B \mid A, B \in \mathscr{B}\_{\mathbb{R}} \\} \subset \mathscr{F}
$$
となり、$\mathscr{B}\_{\mathbb{R^2}}$ は左辺を含む最小の$\sigma$-加法族であるため $\mathscr{B}\_{\mathbb{R^2}} \subset \mathscr{F}$ がわかります。

# 反例の紹介
$a \in \mathbb{R}, A \in \mathscr{B}\_{\mathbb{R}}$ に対して、以下のようにおきます。
$$
\mu_a (A):= 
\begin{cases}
1 & (a \in A) \\\\
0 & (a \notin A)
\end{cases}
$$
すると、$\mu_a$ は $\mathbb{R}$ 上の確率測度となります。次に、$a,b \in \mathbb{R}, E \in \mathscr{B}\_{\mathbb{R^2}}$ に対して
$$
\mu_{a,b}(E) := \mu_a(E^b)
$$
と定めます。すると、$E \cap F = \emptyset$ ならば $E^b \cap F^b = \emptyset$ となることから $\mu_{a,b}$ は $\mathbb{R}^2$ 上の確率測度となることがわかります。 
さて、$\mu_{a,b}$ の分布関数 $F(x,y) = \mu_{a,b}((-\infty, x] \times (-\infty, y))$ は 
$$
E = \\{ (a, y) \in \mathbb{R}^2 \mid y \geq b \\}
$$
の上の点で不連続です。実際、$y \geq b$ とするとき、任意の $\varepsilon > 0$ について、
$$
\begin{align}
&F(a-\varepsilon, y) = \mu_{a} ((-\infty, a-\varepsilon]) = 0, \\\\
&F(a, y) = \mu_{a} ((-\infty, a]) = 1, \\\\
&F(a+\varepsilon, y) = \mu_{a} ((-\infty, a+\varepsilon]) = 1,
\end{align}
$$
となり、これは $(a, y)$ で $F$ が不連続であることを意味します。$E$ は連続濃度であり、これで反例が構築できました。
Elixir IO dataとChardataの違い



## IO data

- [Elixir]言語では、[IO data]は文字列を効率よく連結する目的でよく活用される
- バイト(`0..255`)のリスト

> IO data is a data type that can be used as a more efficient alternative to binaries in certain situations.

> Building IO data is cheaper than concatenating binaries. Concatenating multiple pieces of IO data just means putting them together inside a list since IO data can be arbitrarily nested, and that's a cheap and efficient operation. 

[IO data]: https://hexdocs.pm/elixir/IO.html#module-io-data
[Elixir]: https://elixirschool.com/ja

## Chardata

- [IO data]と非常に似ている
- Unicodeの符号点(`0..0x10FFFF`)のリスト

> Chardata is very similar to IO data: the only difference is that integers in IO data represent bytes while integers in chardata represent Unicode code points. 

[Chardata]: https://hexdocs.pm/elixir/IO.html#module-chardata
[符号点 - Wikipedia]: https://ja.wikipedia.org/wiki/%E7%AC%A6%E5%8F%B7%E7%82%B9

## 論よりラン

[IO.iodata_to_binary/1]と[IO.chardata_to_string/1]を使って検証してみます。

[IO.iodata_to_binary/1]: https://hexdocs.pm/elixir/IO.html#iodata_to_binary/1
[IO.chardata_to_string/1]: https://hexdocs.pm/elixir/IO.html#chardata_to_string/1

> 迷わず行けよ行けばわかるさ（アントニオ猪木）

> 人は実行が第一である。書物の如きは心がけさへすれば、実務に服する間には、自然読み得るに至るものなり。（吉田松陰）

https://note.com/awesomey/n/n4d8c355bc8f7

### 似ている点

バイナリのリストを扱うのであれば挙動が全く同じの様子。入れ子になってもOK。

```elixir
bin1 = <<1, 2, 3>>
bin2 = <<4, 5>>
bin3 = <<6>>

## IO data

IO.iodata_to_binary(bin1)
<<1, 2, 3>>

IO.iodata_to_binary([bin1, 1, [2, 3, bin2], 4 | bin3])
<<1, 2, 3, 1, 2, 3, 4, 5, 4, 6>>

## Chardata

IO.chardata_to_string(bin1)
<<1, 2, 3>>

IO.chardata_to_string([bin1, 1, [2, 3, bin2], 4 | bin3])
<<1, 2, 3, 1, 2, 3, 4, 5, 4, 6>>
```


### 異なる点

ASCII文字でないUnicode文字を扱う場合に、IO dataでは対応できない。

```elixir
## Unicode文字

IO.chardata_to_string('闘魂')
"闘魂"

IO.iodata_to_binary('闘魂')
** (ArgumentError) errors were found at the given arguments:

  * 1st argument: not an iodata term

    :erlang.iolist_to_binary([38360, 39746])
    iex:12: (file)

## ASCII文字

IO.chardata_to_string('fighting spirit')
"fighting spirit"

IO.iodata_to_binary('fighting spirit')
"fighting spirit"
```

>「闘魂」とは己に打ち勝（克）ち、闘いを通じて自分の魂を磨くことである（アントニオ猪木）


## 符号点の値を探す

豆知識として符号点の値を探す方法をいくつか挙げます。

```elixir
"闘魂" |> to_charlist
[38360, 39746]

'闘魂'
[38360, 39746]

?闘
38360
?魂
39746

38360 |> IO.inspect(base: :hex)
0x95D8
```

https://codepoints.net/U+95D8

## CJK統合漢字

たまに微妙に変な漢字が出現するのはこれが原因かも？知らんけど。

> また収録において、元の各文字集合内で分離されている文字は尊重するが、異なる文字集合に同一の文字が収録されているとみなされるものは、同じ符号位置に割り当てる方針を取っている。この際に集合が膨大であるという理由で、漢字について、中国、日本、韓国の各規格の漢字を統合しCJK統合漢字としたことは大きな議論となった。

https://ja.wikipedia.org/wiki/Unicode

https://ja.wikipedia.org/wiki/CJK%E7%B5%B1%E5%90%88%E6%BC%A2%E5%AD%97

## ご参考までに

https://qiita.com/piacerex/items/e0b6e46b1325bb931122

https://qiita.com/torifukukaiou/items/1edb3e961acf002478fd

https://qiita.com/piacerex/items/e5590fa287d3c89eeebf