OmniAICreator/Qiita-1.07M huggingface dataset:
自己紹介とレーティング検討の経緯【クイズレーティング#1】

#自己紹介
　皆さま、先日公開したレーティングにたくさんの反応を頂き、ありがとうございました。「こいつ急に人の成績評価し始めて、誰やねん！」といった感じかと思いますので、遅ればせながらまずは自己紹介をしたいと思います。
　わたくし、rufiyaa（るふぃや）というHNでクイズをしております。初めて参加した第25回高校生クイズで県ベスト５に残ったため、調子に乗ってクイズを始めてはや17年[^1]。これまでに所属したのはMino-ten、TEQ、常陽一族[^2]。好きな傾向はMono-series。昨年10月あたりからは月末にみんはやで自作をたれ流したりしています。
　いわゆる一つのエンジョイ勢で、クイズに強くなるための勉強は特にしていません。そのため目立った戦績もなく、稀に大会に参加してクイズを楽しんでいます。

[^1]: えっ17年！？　もう人生の半分以上クイズやってるのか・・・
[^2]: なんかpeace quiz connectionとやらにも一時期呼ばれた気がするが、所属はしていない。いや、所属していたのかな？

#モチベーション
　大学生の頃、頻繁に大会に参加していましたが、それほど強くはないので、前半あたりで敗退。実はクイズ観戦には興味がないので、敗退すると比較的無為な時間を過ごしていました。
　そのころから一部大会ではレギュレーションを設けて参加者のレベルを限定しようと試みていました。しかし評価のために用いられたのはクイズ歴[^3]、オープン大会の参加経験[^4]、獲得☆数[^5]や、⛩数[^6]といった値であり、特にボリュームゾーンのプレイヤーを階級分けできていない現状がありました[^7]。
　かくして、2012年ごろには「クイズにレーティングがあればいいのに・・・」という想いを抱き、所属サークルでテスト運用したりしていました。しかし当時の実力不足もあり実現には至らず、お蔵入りしてしまいました。

[^3]: 歴は必ずしも強さとは比例しない
[^4]: どちらかというと未経験者に来てもらうためのレギュレーション
[^5]: [abc](https://ja.wikipedia.org/wiki/Abc_(%E3%82%AF%E3%82%A4%E3%82%BA%E5%A4%A7%E4%BC%9A))の戦績に応じて与えられる強さの指標。6倍～10倍の倍率を勝たないと手に入らなかった(当時)ので、☆１でもだいぶ強い。
[^6]: abc対策大会のひとつ、STUにおける☆。☆程ではないが、⛩持ちも割と強い。
[^7]: 新人王・早押王では複数のクイズ部屋を設け、対戦結果に応じて次の試合がダイナミックに変化するシステムを組み、同等プレイヤーの対戦を実現しています。レーティングとは違いますが、素晴らしいシステムです。

#クイズへのレーティングの適用
　先日公開したレーティングのベースにあるのはELOレーティングという考え方です。元々チェスのために開発されたレーティングシステムで、開発者のアルパド・イロさんはハンガリー生まれのアメリカ人物理学者だそうなので、覚えたい人は覚えてください。
　1対1の勝負を前提としており、勝敗に応じてレーティングが変動します。敗者の減少分と勝者の増加分は同量で、勝敗が番狂わせであるほどその変化量は大きくなる仕組みです。
　今回のMegalomaniaTokyo2への適用においては、4名の戦いを6試合の1対1対戦に分解し、計算しています。

#過去の適用例(AQL)
　実はレーティングを計算して公開したのはMegalomaniaTokyo2が初めてではありません。以前AQLに対して計算したことがあり、Twitterでかる〜く流してみましたが、反応はあまり得られませんでした。
　当時AQLのレーティング計算において困難だと感じていたのは、試合数の少なさと、トーナメント構造です。レーティングはさまざまな強さのプレイヤーを相手に何度も何度も試合をすることにより、より正確な強さを推定するシステムです。年間1大会、一回の大会で30試合程度しか行われないAQLでは、収束スピードに難があるように見えました。また、地方大会→全国大会というシステムの処理も課題でした。全国進出チームの強さが全国大会でやっと評価されることになるため、その結果が地方大会にフィードバックされるには次大会の開催を待つことになります。このことは時間的な問題にとどまらず、同一のチームが何年も何年も継続して大会に参加することを求めているように見えました。要は、レーティングの収束スピードと大会頻度との間に食い違いがあったのです。
　今回MegalomaniaTokyo2に対して提案した計算方法であれば、この困難を乗り越えられたかもしれません。しかし当時はこれを思いつくことはできず、実用的なレーティングの算出は先送りとなりました[^8]。

以上、これまでの経緯でした。次回に続きます。

[^8]: 今回の方法もまだ完璧な方法と決まったわけではないのですが。
jQueryのhoverで離れたmenuを出現させるのにつまづいたこと

# jQueryのhoverで離れたmenuを出現させるのにつまづいたこと

## やりたいこと
ヘッダーにhoverを使ってヘッダーから少し離れた下部にメニューをドロップダウンしたい

## つまづいたこと①
ヘッダーとメニューの間が空いているため、矢印がヘッダーから外れるとhoverが外れて表示されているメニューが消える。
<img width="1026" alt="quita_1" src="https://user-images.githubusercontent.com/61651779/150142455-9e056d75-2dd0-4be9-927f-2c52a91fe0fd.png">

### 原因
どうしてもヘッダー（グッズ紹介）からメニューへカーソルを移動させると「この〜切れてしまう」の部分（以降：hover外範囲）があるためにメニューが消えてしまう

## どうしたらいいのか
矢印がhover外範囲に移動するときでもメニューが表示された状態を保っていれば、メニューに矢印が入ればメニューの状態は維持される
### 結果
タイマーを使ってhoverから矢印が離れてから何秒までメニューを維持するコードを書く
※ヘッダー hover 離れる　とかで検索したら方法が載っていたため、ほほコピペしました。参考サイトに掲載します。

```js
$(function () {
            moveTimer = 0;
            hideTimer = 0;
            // ホバーしている時
            $('#nav_goods').hover(function () {
                menu = $('#nav_goods_ul');
                // 指定の要素内でマウスが動いている時
                $(this).on('mousemove', function () {
                    // タイマーの解除
                    clearTimeout(moveTimer);
                    clearTimeout(hideTimer);
                    // タイマーのセット(マウスが外れて○秒後にnav_menuを削除)
                    moveTimer = setTimeout(function () {
                        menu.removeClass('nav_menu_goods')
           
                    }, 10);
                });
                // ホバーが外れている時
            }, function () {
                // タイマーの解除
                clearTimeout(moveTimer);
                // タイマーのセット(マウスが外れて○秒後にnav_menuを追加)
                hideTimer = setTimeout(function () {
                    $('#nav_goods_ul').addClass('nav_menu_goods')
                }, 100);
            });
        });
```

### つまづいたこと②
できたと思ったら、今度はナビゲーション内で横にカーソルを移動させると挙動がおかしい。
お問い合わせに移動してもメニューが消えない
<img width="1014" alt="スクリーンショット 2022-01-20 20 41 06" src="https://user-images.githubusercontent.com/61651779/150332267-ed5409ee-75a9-449a-8425-a16d88f8fd60.png">

### 原因
display:noneが入っているclass[nav_menu_goods]が付与されていない
<img width="1440" alt="スクリーンショット 2022-01-20 20 50" src="https://user-images.githubusercontent.com/61651779/150336518-2c725807-d760-49cf-ac08-346a750a047d.png">

## 結果
class[nav_menu_show]を削除すると同時にclass[nav_menu_goods]を追加することにした。

```css

/* hoverすると表示される */
.nav_menu_show {
    width: 960px;
    height: 200px;
    margin: 0 auto;
    z-index: 2;

    display: flex;
    justify-content: center;

    list-style: none;
    background-color: forestgreen;

    position: fixed;
    top: 140px;
    left: 50%;
    transform: translateX(-50%);
    -webkit-transform: translateX(-50%);
    -ms-transform: translateX(-50%);
}


/* hover外れると追加される */
.nav_menu_goods,
.nav_menu_chara {
    display: none;
}


```

### 参考サイト
[【Js】遅延式のドロップダウンメニュー](https://twotone.me/web/3589/)
Guideline 2.1 - Information Needed / ATTダイアログがiOS15で出ない

##rejectされた理由##
admobの広告を追加したところ、トラッキングの許可ダイアログ（AppTrackingTransparency）を出す必要性があるとのこと。

##注意点、ハマったこと##
・ios15だとアプリがアクティブなとき（UIApplicationStateActive）にのみAppTrackingTransparencyの許可ダイアログが出る。
・applicationDidBecomeActiveが呼び出されない…と思ったら、SceneDelegateファイルがあるのでsceneDidBecomeActiveに書かないといけない

##コード##
（最終的に審査に通ったコードは一番最後です）

最初はAppDelegateのdidFinishLaunchingWithOptionsに全部書いた。自分の実機のios14までは動いたが（xcodeアップデートしてなかった）iOS15だと動かないよとrejectされた…😞
　そこで以下のようにしてみた。(SceneDelegate使ってないならOKかも)



```swift:AppDelegate
class AppDelegate: UIResponder, UIApplicationDelegate {
~省略~
   func applicationDidBecomeActive(_ application: UIApplication) {
         if #available(iOS 14, *) {
              if ATTrackingManager.trackingAuthorizationStatus == .notDetermined {
                 ATTrackingManager.requestTrackingAuthorization(completionHandler:{
                    status in
                    GADMobileAds.sharedInstance().start(completionHandler: nil)
                 })
              }
         } else {
              // Fallback on earlier versions
              GADMobileAds.sharedInstance().start(completionHandler: nil)
         }
   }
}
```

それでも出ない…🙃
調べたらSceneDelegate使ってたらapplicationDidBecomeActiveとか使えないよって公式ドキュメントに書いてあった、、
https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622956-applicationdidbecomeactive
importantのとこ。
わからなくなったら英語だけど公式ドキュメント読めということですね、、

それでsceneDidBecomeActiveに書いてみた
しかし表示されない！！！！👼

調べた結果、、、0.5秒遅らせたら普通に出た😇


```swift:SceneDelegate
func sceneDidBecomeActive(_ scene: UIScene) {
        // Initialize the Google Mobile Ads SDK.
        DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
            if #available(iOS 14, *) {
                if ATTrackingManager.trackingAuthorizationStatus == .notDetermined {
                    ATTrackingManager.requestTrackingAuthorization(completionHandler: {
                    status in
                    GADMobileAds.sharedInstance().start(completionHandler: nil)
                    })
                }
            } else {
                // Fallback on earlier versions
                GADMobileAds.sharedInstance().start(completionHandler: nil)
                
            }
        }
    }
```
stripメソッドとそれに関連するメソッドのまとめ

rubysilverを勉強するためのサイトのRexを勉強してわからなかったメソッドがあったので備忘録として残しておきます
https://rex.libertyfish.co.jp/

##Stripメソッド
stripという英語の意味は、「剥ぎ取る」という意味です
結論からいうと、文字列先頭と末尾の空白文字を全て取り除いた文字列を生成して返すメソッドなんです。
[ruby 公式ドキュメントより](https://docs.ruby-lang.org/ja/latest/method/String/i/strip.html)


このリファレンスに書いてあるのですが、「空白文字の定義は " \t\r\n\f\v"」と書いてあるんです。
そこで思ったのが、「\\t\r\n\f\v」ってなに？って思ったんですよね。
(この文字列の中にスペースも入ってるのでご注意を)

ここで大事になるのが、正規表現についての知識が必要になるんですよね。
よく調べたら、これがrubyの[公式ドキュメント](https://docs.ruby-lang.org/ja/latest/doc/spec=2fregexp.html)に載っていたんです。さすが公式ドキュメントですね！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2485775/a64fa34b-56d9-64c2-ce9c-2c86706eb91f.png)

こんなふうにまとまっているんですね！めちゃわかりやすい！

1つ1つ順に説明していきますね！
\tは水平タブを表しています。水平タブって言われるとピンと来ないかもしれないですが、僕らにパソコンについてるtabキーのことです。

\vは調べたのですが、ぶっちゃけよく分からなかったです。ただ、[wikipedia](https://ja.wikipedia.org/wiki/%E3%82%BF%E3%83%96%E3%82%AD%E3%83%BC)を調べると、今はもうほぼ使われていないそうです。(わかる方いらっしゃいましたら、ご教示いただけると嬉しいです)

\r,\n,\r\nは改行という意味です。意味はすべて同じです。では何が違うのかというと、動くOSが違うというところが挙げられます。
\rはmac,\nはUNIX全般, \r\nはwindows系全般です。
[こちらの記事](https://qiita.com/uhooi/items/dc74ff3434aecb17faa2)が参考になるとおもいますので、ぜひ参考にしてみてください！

\fは文字通り、ページを改めるということです。新しいページに移るということです。wordで作業したことがある方ならピンとくるかもしれないですね！

このように、stripメソッドは、これらの空白文字が文字列の先頭や末尾にあったら、取り除いてくれるというものです。

```
p "  abc  \r\n".strip    #=> "abc"
p "abc\n".strip          #=> "abc"
p "  abc".strip          #=> "abc"
p "abc".strip            #=> "abc"


str = "\tabc\n"
p str.strip              #=> "abc"
p str                    #=> "\tabc\n" (元の文字列は変化しない)
```

なんとなく見ればわかるかとおもいます。スペースは\tのことですね。

##lstripメソッド
stripメソッドに関連するメソッドとして、lstripメソッドがあります。
このメソッドは、文字列の先頭にある空白文字を全て取り除いた新しい文字列を返します。空白の定義は、同じく「\t\r\n\f\v」です。
stripメソッドとの違いは、末尾の空白は取り除かないということです。
lstripの「l」はleadのlだとおもわれます。leadは先頭っていう意味なので、覚えやすいですね。


```
p "  abc\n".lstrip     #=> "abc\n"
p "\t abc\n".lstrip    #=> "abc\n"
p "abc\n".lstrip       #=> "abc\n"
```

##rstripメソッド
rstripメソッドの特徴は、文字列の末尾にある空白文字をすべて取り除いた新しい文字列を返すというものです。空白文字の定義は、
「 \t\r\n\f\v\0」
**0があることが他のメソッドと違うところですね!**

今後の課題としては、\0が何を表しているかを調べていくことです！
(わかる方いらっしゃいましたら、ご教示いただけますと幸いです。)

以上です！
Visual Studio で DX ライブラリを面倒なプロジェクト設定をせずに はじめる

## まえがき

本家 DXライブラリサイトには、

* DXライブラリをダウンロード
* 空の Visual Studio C++ プロジェクトを作成
* そのプロジェクトの構成

の手順で DX ライブラリを使ったアプリケーション開発を始める説明があります。

<https://dxlib.xsrv.jp/dxuse.html>

この記事では、Visual Studio のプロジェクトテンプレートに、DX ライブラリを使った C++ プロジェクトまたは C# プロジェクトを追加し、それを使用して DX ライブラリを使ったアプリケーション開発をするための手順を説明します。

## 必要要件

Visual Studio 2017, 2019, 2022 のどれかがインストールされている環境

## プロジェクトテンプレートのインストール方法

[Visual Studio Market Place に移動します。

**Visual C++ をお使いの場合**

<https://marketplace.visualstudio.com/items?itemName=KamenokoSoft.dxlib-template-for-win32>

**Visual C# をお使いの場合**

<https://marketplace.visualstudio.com/items?itemName=KamenokoSoft.dxlib-template-for-win32-csharp>

![downloadext1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158514/88513743-7433-4b34-424d-d17275e54afe.png)

遷移先のページ上の緑色の "Download" ボタンをクリックして、拡張機能をダウンロードします。

![downloadext2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158514/1a1a9553-a12c-ab8e-2a25-bace7ed20d70.png)

ダウンロードが終わったら、ダウンロードした拡張機能をダブルクリックして、実行します。

![installext1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158514/fa8a17f1-f381-8125-e506-c5ada106413a.png)

変更内容を確認するダイアログが出てくるので、"Install" をクリックします。

![installext2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158514/3c5adddf-d59c-af4b-8399-52b2edf35980.png)

拡張機能のインストールが終わったら、"Close" ボタンをクリックして、ウィンドウを閉じます。

## プロジェクトの作成

お使いの Visual Studio を起動して、スタートウィンドウを表示します。

![launchvs1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158514/d52c53ed-a448-ec09-9953-b2942f03c187.png)

スタートウィンドウが表示されたら、新しいプロジェクトの作成をクリックします。

検索欄に "DxLib" と入力し、出てきた "DxLib" プロジェクトテンプレートを選択して、右下の "OK" をクリックします。

![launchvs2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158514/3e5632a0-e00f-cee2-9986-372de31033e1.png)

プロジェクト名の入力する画面では、好きな名前を入力して、右下の "OK" をクリックします。

![launchvs3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158514/0f399e58-b5df-687a-6e2b-7acf64ee2774.png)

## プロジェクトのビルドと実行

ツールセットの更新画面が出てきたら、そのまま "OK" をクリックします。

![retarget.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158514/7070cd96-34b1-bba3-6a82-02e054a1c08f.png)

ソースファイルに赤波線が出ていても、そのまま Visual Studio 上部の "ローカル Windows デバッガ" をクリックして、ビルドを開始します。

![build1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158514/e9a16432-13f7-44cc-0174-a1f6e45bcf95.png)

最初のビルドでは、依存関係にあるパッケージのダウンロードを行うため、5分以上時間がかかることがあります。気長に待ちましょう。

ビルドが終わり、DX ライブラリの黒い画面が出てきたら、成功です。

![build2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158514/dc4af7bb-8e96-81dd-add0-8bf27fa67a41.png)
ElementUIのel-tableのel-columnをv-forで回して配列のデータをセットする

# 概要
vue.jsのライブラリ「[ElementUI](https://element.eleme.io/#/en-US)」において、[el-table](https://element.eleme.io/#/en-US/component/table)を使うときに配列のデータを使いたいときの方法

# 結論
```vue
  <template>
    <el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="name"
        label="名前"
        width="180">
      </el-table-column>
      <el-table-column
        v-for="(value, index) in indexes"　　←v-forで繰り返す
        :key="index"
        :prop="`list[${index}]`"　　　　　　　←:propでv-bind:propの意。バッククウォートで文字列結合
        :label="`データ ${index}`"
        width="180">
      </el-table-column>
    </el-table>
  </template>

  <script>
    export default {
      data() {
        return {
          tableData: [{
            name: 'Tom',
            list: [1,2,3,4,5]
          }, {
            name: 'Mike',
            list: [12,13,14,15,16]
          }, {
            name: 'Bob',
            list: [2,3,4,5,6]
          }]
        }
      }
    }
  </script>
```

# 出力例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192137/c6ebe9cc-c7f5-1dc4-388f-8b69e5940e6b.png)

v-bindと「`」が肝です。↓こちらが参考になました。ありがとうございます。
https://uyamazak.hatenablog.com/entry/2018/11/08/160714
Dynamics 365 や Power Platform の資格について

以前に紹介した [D365 FO の調査・学習](https://qiita.com/TaichiKayama/items/f2b46629abe2c574f192)の中で、Microsoft Certified（MCP）資格をご案内しましたが、私も積極的に取得しているので、少し感想をまとめてみます。
資格不要論とかありますけど、体系的な知識の獲得・整理、モチベーション向上、外部へのアピール、など色々メリットはあるとは思います。

# 資格の体系について
・Fundamentals（レベル1）
・Functional Consultant, Developer Associate（レベル2）
・Solution Architect Expert（レベル3）

以前のMCPと違い、今はロールベースな資格となっています。
そのため、レベル1より2が難しいというわけではなく、その人との相性次第です。
開発をメインでやってきた人はレベル2は難しいと感じるかもしれませんし、コンサルをメインでやってきた人はレベル3が難しいと感じるかもしれません。
※Solution Architect Expertの資格を得るには、Functional Consultantの資格が前提で必要だったりするので、便宜的にレベルと表現しています。

コチラも参考にしてください（トレーニングジャーニー）

https://partner.microsoft.com/ja-jp/training/mstep-dynamics

# コツ
・英語で受けろ
・Learn見るだけじゃなくて、実機も触れ
・回答は素直＆ベーシックな選択を（知識がありすぎると逆に迷うことがある）
・Yes/No、迷ったらNo（保証はしない）
・選択問題、迷ったらその言葉そのものから連想して選択しろ（結構当たってるぽい）

# Fundamentals（レベル1）
・PL-900（Power Platform）
・MB-910（D365 CE）
・MB-920（D365 FO）

基礎的な用語の話や、管理ポータルの使い方（Power Platform Admin Center, LCS など）がメインになるイメージです。
常識を問うような問題も多いので、もしかするとノー勉でもいけるかもわかりません。

# Functional Consultant Associate（レベル2）
・PL-100、PL-200（Power Platform）
・MB-210、MB-220、MB-230、MB-240（D365 CE）
※それぞれにPL-200が必要です。
・MB-300、MB-310、MB-320、MB-330（D365 FO）
※それぞれにMB-300が必要です。

各SKUやモジュールの機能について、ユースケースを元に最適な設定や機能の一連の使い方・流れを問われることが多かったかなと思います。
実機で使ったことがないと全く歯が立たない気がします。

# Developer Associate（レベル2）
・PL-400（Power Platform）
・MB-500（D365 FO）

フレームワーク・開発コンポーネントの使い方、コネクタ・データ連携、バッチ処理、ビルド・デプロイ（Azure DevOps連携）、とかそんな感じになるかと思います。

# Solution Architect Expert（レベル3）
・PL-600（Power Platform）
※PL-200かPL-400が必要です。
・MB-700（D365 FO）
※MB-310かMB-320かMB-330かMB-500が必要です。

構想→開発→運用までの時間軸とプロジェクト全体での視野の広さを求められるような、設計や管理・ガバナンスの問題が中心かと思います。
また、技術的な観点でだけでなく、Success By Design の中に記載されているように、リスクマネジメントや運用設計など、戦略的な考えそのものも問われたと記憶しています。

# 資格の有効期限
日進月歩で進化するクラウドにおいては、数年もしたら知識が使い物になりません。レベル2以上はおそらく1~2年で有効期限が設定されています。
有効期限が近づくと、更新の案内メールが来ます。無料ですので、自動車免許と同じように、頑張って更新しましょう。

例.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375815/4ebfd64b-85ed-2252-6a8d-f0f49e5cdb45.png)

合格するとこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375815/c5ff2f44-06f3-e2a4-517a-11a6cfd6fcd0.png)
AOJトライに関する知識知見の記録共有：Volume0-0064

# タスク概要

Secret Number

https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0064

 
# コード実装例
TIPS

1. 例外処理含む評価パターンを追加

```Python
import pprint, sys, time, re

def core(arg, adv=True):
    if adv:
        s = ""
        for ch in arg:
            if ch.isdigit():
                s = s + ch
            else:
                s = s + " "
    else:
        s = re.sub(r'[^0-9]', ' ', arg)

    l = [int(v) for v in s.split(" ") if v != ""]
    return [sum(l), l]

def app(*args):
    ret = []
    for arg in args:
        s = []
        for adv in [False, True]:
            st = time.time()
            try:
                r = core(arg, adv=adv)
            except Exception as e:
                r = e
            s.append([adv, round(time.time() - st, 6), r])
        ret.append([arg, s])
    return ret

print(sys.version)
pprint.pprint(app(
    # basic examples
    """Thereare100yenonthetable.Iam17yearsold.
Ishouldgohomeat6pm.""",
    # additional examples
    """hog e-1.2ほげ0""",
    # exceptional examples
))
```

# 実行結果
各種補足情報出力（入力値FB、デバッグログ等）含む

```Python
3.8.10 (default, Sep 28 2021, 16:10:42) 
[GCC 9.3.0]
[['Thereare100yenonthetable.Iam17yearsold.\nIshouldgohomeat6pm.',
  [[False, 0.000151, [123, [100, 17, 6]]],
   [True, 1.8e-05, [123, [100, 17, 6]]]]],
 ['hog e-1.2ほげ0',
  [[False, 1e-05, [3, [1, 2, 0]]], [True, 5e-06, [3, [1, 2, 0]]]]]]
```

# 補遺
残課題（Pull Request絶賛募集中！）

1. 実行速度の改善（枝刈り、データ構造の見直し等）
1. コア関数の汎用化
dplyr::mutate(across())と自作関数を使ってスマートな前処理をしよう！

#前提
前処理の際に、同じようなコードを書繰り返し書くことがないでしょうか。
私はアンケート調査・研究調査で回答項目の値変換するときに、同じようなコードを書いて前処理していましたが、across()を使うことでコードを書く量が大幅に減少しました。
今回は、満足度調査を例に、across()を使った値変換をご紹介します。

A・B・C・Dの製品について満足度調査をして下記の結果が得られました。
この回答結果を`とても満足=5`・`満足=4`・`普通=3`・`非常に不満足=2`・`非常に不満足=1`という感じに点数化したいと思います。


| ID| A |B | C |D | 
|:--:|:--:|:-:|:-:|:-:|
|  1 |非常に満足   | 非常に満足  |  とても満足 | 満足  |
|  2|　 満足 | 満足  |  普通 | 非常に満足|  
|  3|  非常に不満足 | 非常に不満足 |不満足 | 不満足|
|  4|  非常に不満足 | 普通  |  非常に満足 | 非常に満足  | 



#across()を使わない場合
```r
library(tidyverse)
ID <- c(1, 2, 3, 4)
A <- c("非常に満足", "非常に満足", "非常に満足", "満足")
B <- c("満足", "満足", "普通", "非常に満足")
C <- c("非常に不満足", "非常に不満足", "不満足", "不満足")
D <- c("非常に不満足", "普通", "非常に満足", "非常に満足")
df_example <- data_frame(A = A, B = B, C = C, D = D)

df_example_notacross <- df_example %>%
  mutate(
    A = case_when(
      A == "非常に満足" ~ 5,
      A == "満足" ~ 4,
      A == "普通" ~ 3,
      A == "不満足" ~ 2,
      A == "非常に不満足" ~ 1,
    ),
    B = case_when(
      B == "非常に満足" ~ 5,
      B == "満足" ~ 4,
      B == "普通" ~ 3,
      B == "不満足" ~ 2,
      B == "非常に不満足" ~ 1,
    ),
    C = case_when(
      C == "非常に満足" ~ 5,
      C == "満足" ~ 4,
      C == "普通" ~ 3,
      C == "不満足" ~ 2,
      C == "非常に不満足" ~ 1,
    ),
    D = case_when(
      D == "非常に満足" ~ 5,
      D == "満足" ~ 4,
      D == "普通" ~ 3,
      D == "不満足" ~ 2,
      D == "非常に不満足" ~ 1,
    )
  )
```
同じような処理を何回も書くことになり、コード量非常に多くなってしまいます。
では、across()を使ってみましょう！

#across()を使う場合

```r
#値変換をする自作関数　
Func<-function(colum)(colum = case_when(
  colum== "非常に満足" ~ 5,
  colum == "満足" ~ 4,
  colum == "普通" ~ 3,
  colum == "不満足" ~ 2,
  colum == "非常に不満足" ~ 1,
))

df_example_across <- df_example %>%
  mutate(across(A:D,Func))
```
自作関数とacross()を使うことでコード量が減少しました！
across()は繰り返し処理をしてくれるので、いろんな場面で使えそうです。

#参考
* [dplyr](https://cran.r-project.org/web/packages/dplyr/dplyr.pdf)
* [Rのデータフレームの列操作についてのメモ](https://qiita.com/swathci/items/9bf403dca7c428fc3e7d)
【Laravel】 ルートグループで controller メソッドを使ってスッキリ表示！【ver.8.80 新機能】

Laravel 8.80 からの機能でルートグループに `controller メソッド` が追加されました。ネスト内にコントローラ名を書くことなしにルーティングすることができるので、今まで以上にスッキリした書き方が可能になります。

通常、グループのネスト内にコントローラ名を記述していました。

```php:[before]　web.php
use App\Http\Controllers\BlogController;
use Illuminate\Support\Facades\Route;

Route::prefix('blog')
    ->as('blog.')
    ->group(function () {
        Route::get('/', [BlogController::class, 'index'])->name('index');
        Route::get('/create', [BlogController::class, 'create'])->name('create');
        Route::post('/', [BlogController::class, 'store'])->name('store');
        Route::get('/{blog}', [BlogController::class, 'show'])->name('show');
    });
```

Laravel 8.80 以降では `controller メソッド` を使用してネスト内のコントローラ名の記述を省略可能になりました

```diff:[after]　web.php
use App\Http\Controllers\BlogController;
use Illuminate\Support\Facades\Route;

Route::prefix('blog')
    ->as('blog.')
+   ->controller(BlogController::class) // controllerメソッドを追加
    ->group(function () {
+       // ネスト内のコントローラ名を省略できます
+       Route::get('/', 'index')->name('index');
+       Route::get('/create', 'create')->name('create');
+       Route::post('/', 'store')->name('store');
+       Route::get('/{blog}', 'show')->name('show');
    });
```

ネスト内に同名のコントローラが多ければ、今回新しく追加された`controller メソッド` を使用してみると良いかもしれません。
プロパティ 'data' は型 'GraphQLResult<object> | Observable<object>' に存在しません。ts(2339)の対処メモ

## TypeScript & Amplifyで起きるエラーの対処メモ

Amplifyで作成した開発環境でGraphQLのスキーマを読み込もうとしたらこんなエラーが

```js
 async function fetchNotes() {
    const apiData = await API.graphql({ query: listNotes });
    setNotes(apiData.data.listNotes.items);
  }
```
```
プロパティ 'data' は型 'GraphQLResult<object> | Observable<object>' に存在しません。
プロパティ 'data' は型 'Observable<object>' に存在しません。ts(2339)
```

TypeScriptの型定義がされてないため、エラーが起きています。

## 解決策

```
// @ts-ignore
```

を加えると、エラーが回避されます。

例：

```js
const apiData = await API.graphql({ query: listNotes });
// @ts-ignore
setNotes(apiData.data.listNotes.items);
```

これでエラーが回避されました。
## 他の解決策

```
// @ts-ignore
```
を使うと一括で型エラーを回避してくれますが、型無効化というのは抵抗あるので他の解決策も探してみます。

参考:
[https://higelog.brassworks.jp/2824]()
[https://github.com/aws-amplify/amplify-js/issues/4257]()
ec-cube4/vagrant/docker 環境構築

# EC-CUBE 4.1 vagrant docker セットアップ手順

EC-CUBEを使う機会がありそうなので、セットアップ手順を残しておこう。

## セットアップ環境

- Apache 2.4.52
- PHP 7.4.27
- MySQL 5.7.37

##  セットアップ

**windows環境の場合改行コードがCR+LFに変換されないようにするためにgitの設定を変更しておく**  
**改行コードがCR+LFの場合、docker起動時失敗する**

```
git config --global core.autocrlf input
```

> 任意のディレクトリにリポジトリをクローンする

```
git clone https://github.com/second-fiddle/eccube4-vagrant.git
cd eccube4-vagrant
```

> ec-cube4.1 をクローンする

```
git clone https://github.com/EC-CUBE/ec-cube.git
```

> docker/docker-compose.yml の ECCUBE_AUTH_MAGIC を任意の値に書き換える

> docker-compose.yml を置き換える

- Windows
```
copy /Y docker/docker-compose.yml ec-cube
```
- Mac
```
cp -f docker/docker-compose.yml ec-cube
```

> vagrant 起動

```
vagrant up
```

> 初期設定

```
vagrant ssh
cd /vagrant/ec-cube
docker-compose exec -u www-data ec-cube bin/console eccube:install -n
docker-compose exec ec-cube composer run-script compile
質問はすべてyにした
```

> 動作確認

[フロント(http://192.168.2.100:8080/)](http://http://192.168.2.100:8080/)

[管理(http://192.168.2.100:8080/admin)](http://http://192.168.2.100:8080//admin)

## その他

- IPアドレスを変更する場合、vagrantfileの26行目のIPアドレスを変更する
- Postgresの環境にする場合、ec-cube/docker-compose.pgsql.yml の必要な部分をec-cube/docker-compse.ymlに反映する
qlmarkdownのインストール

# qlmarkdownってなに？
Finderに表示されているファイルを選択してスペースを押した時、プレビューしてくれる機能（Macのデフォルト機能クイックルック）用のプラグイン。
拡張子md（Markdownのファイル）は対応していない。なのでプラグインで機能追加する。

# 条件
コマンドのオプションが変わったりなどで、それほど古くないやり方でも失敗した。条件が大きく違ったら失敗する可能性が高い。
* MacBook Air (M1, 2020)
* MacOS 12
* Homebrew 3.3.11
* 2022年1月に実施

色々打ち込んで失敗を繰り返したが、これだけでOKだったようだ。

```
brew install qlmarkdown --cask
```

# 動作しないけど？？
コマンドの度重なる失敗のせいか、そういうものなのか、OSを再起動したら正常動作するようになった。


# 試したコマンド
古過ぎて使えなかった

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

caskをよく知らないがbrewに入っているからいらなくなったとか

```
brew install caskroom/cask/brew-cask
```

caskはオプションになったので使い方がおかしいとのこと

```
brew cask install qlmarkdown
```
モダン開発環境構築

# モダン開発環境構築
アプリケーション・組み込み・画像処理をWin/Mac/Linuxのマルチ＆クロスプラットフォームで開発することが多いので、その開発環境構築手法をまとめてみようと思います
現時点(2022/01/20)ではCMakeのみ記載してますが、今後IDE、パッケージ、クロスコンパイルについても記載していこうと思います
それぞれの技術がネストし合っているので、全て揃って完璧になる感じはあるので少々お時間、お付き合いください

1. CMake編  
    1.1 [インストール](https://qiita.com/openfields/items/78ee99ce6e7100b7b3d6)  
    1.2 [Hello, world](https://qiita.com/openfields/items/0ea6e19304a427e6c616)  
    1.3 [include, 複数ソース](https://qiita.com/openfields/items/5a7b24b0ac7416887a48)  
    1.4 [変数・環境変数・分岐・ループ](https://qiita.com/openfields/items/e8ce0e64ef4f4ee32ccd)  
    1.5 [ダイナミック/スタティックリンク](https://qiita.com/openfields/items/e2e4e1b8b900b2463f2f)  
 

# 書く理由
画像処理エンジニア・組み込みエンジニアと仕事をすることが多いのですが、「自分の環境ではビルドできる」環境を作る人が非常に多いので、少しでも正しくキャッチアップできるように情報発信できればと思います

組み込み業界は未だにサクラエディタや秀丸を使う人も多々います
15インチのモニタで作業することを苦と思わない人も多いです
私の経験上、夜遅くまで仕事して休日出勤も多く外の世界を知る時間もないので、そんな環境に慣れてしまっているのだと思います

私の環境構築を参考にしてもらえれば、開発速度・他人との共有・整理など段違いでレベル上がります
Laravel8で一気にModelとControllerとマイグレーションファイルを作成する

# 概要
Laravel8から、Modelの作成と同時に下記のファイルを作成することができるようになりました。

* CRUD特性を備えたControllerファイル
    * CRUD : データ操作に必要とされる基本的な4つの機能（Create、Read、Update、Delete）の頭文字
* マイグレーションファイル

そのことに関して、備忘のためにまとめておきます。

# Laravelのバージョンの確認
まずは、Laravelのバージョンが8以上になっていることを確認します。

```console:Laravelのバージョンを確認
$ php artisan -V
Laravel Framework 8.x.x
```

# 3つのファイルを一括で作成
バージョンが8以上となっていることを確認したら、下記コマンドを実行して3つのファイルを一括で作成します。

```console:ModelとControllerとマイグレーションファイルを作成
$ php artisan make:model Flight -mcr
Model created successfully.
Created Migration: 20xx_xx_xx_xxxxxx_create_flights_table
Controller created successfully.
```

* `php artisan make:model Flight` : `Flight` モデルを作成
* `m` オプション : モデルの作成と同時にマイグレーションファイルを作成
* `c` オプション : モデルの作成と同時にControllerファイルを作成
* `r` オプション : 作成するControllerファイルにデフォルトでCRUDのためのアクションを追加

`r`オプションがあれば、`c`オプションがなくてもControllerファイルは作成されるので、下記コマンドでも同じことができます。

```console:ModelとControllerとマイグレーションファイルを作成
$ php artisan make:model Flight -mr
```

# 作成されたファイルの確認
上記コマンドの実行が正常に行われると、下記ファイルが作成されます。

* Model ファイル : `app/Models/Flight.php`
* マイグレーションファイル : `database/migrations/20xx_xx_xx_xxxxxx_create_flights_table.php`
* Controllerファイル : `app/Http/Controllers/FlightController.php`

# 参考
- https://readouble.com/laravel/8.x/ja/eloquent.html
- https://readouble.com/laravel/8.x/ja/controllers.html
AWSコンテナ設計・構築[本格]入門 の感想とハンズオンではまったポイント

## 概要

AWSコンテナ設計・構築[本格]入門を年末にハンズオンをやってみたのでその感想とはまったポイントのメモを残しておこうかと思います。(4章までしかできていませんが・・・)


## 書籍の感想

* Amazonの評価やほかの方もブログ等で高評価がついている通り、なかなかためになる内容でした。([こちら](https://dev.classmethod.jp/articles/bookreview-introduction-guide-aws-container-design-and-construction/)の記事が本の内容について良くまとまっているかと)
* なぜコンテナを使うか？というところの説明などもあり概念としては知っていても実際はどうなのか？を理解する助けにもなりました。
* 具体的な構成についての例も載っておりそちらも理解の助けになりました
* 説明部分の1～3章に続きハンズオンの4,5章があり、4章のみ実施しましたが、ECSの実際の動かし方などを確認できました。5章はまだ実施できていません・・・


## ハンズオンのはまったポイント
以下はハンズオンではまったポイントです。4-6,4-7でコンテナの切り替え部分ではまりました。ハンズオンを実施してうまくいかなかったら参考になれば
1. ECSのコンテナの切り替え時に切り替えが終わらない
    * バックエンド側のコンテナの切り替えでデプロイが20分経っても終わらず設定をいろいろ確認しても問題はなさそうに見えました。
        * 原因はSecretsManagerからDBの情報を取得する部分で指定するSecretsManagerのARNが別のものを間違って指定していたためデプロイに失敗していたようです。
1. フロント側の切り替え時に切り替えが終わらない
    * フロントエンド側のコンテナの切り替えでも同様にコンテナの切り替えに失敗しました。
        * こちらの原因はECSの切り替え時にセキュリティグループの指定を誤っていたために失敗していました。
1. 料金がかかりすぎた
    * こちらはハンズオンのはまりポイントというわけではないですが問題点として
    * 1日でハンズオンが終わらなかったのでAuroraを止めていました。ほかのECSやネットワークエンドポイントなどを起動したままにしてしまい、上記の問題ではまって１～２週間ほどそのままにしておいたら料金が60$ほどになっていました・・・
        * 今までのAWSのイベントなどで割引のクレジットをいただいていたのでお金は直接かかっていないですがなかなか痛手です・・・
            * 料金を見るときに見た目上は0$となっていたので無料化と勘違いしたのが甘かった・・・

## 最後に
* 感想に記載したとおりコンテナに関する知識を得ることができまたハンズオンで実際の操作を学ぶことができて良かったです。
* ハンズオンの後片付けはこちらにあるので実施する際には片付けを忘れずにまたできれば１日で終わるように時間を確保してやった方がよさそうです。(コマンドを自分で打たないといけないので3～4時間は見た方がいいかと)
    * 事前にコマンド類をテキストに起こしておくのもいいかもしれません。
* [出版社のページ](https://www.sbcr.jp/product/4815607654/)から後始末の部分とCloudFormationのテンプレートなどを取得しておくとスムーズに進められます。
単体テストをするためにコードの抽象度を高くしようと思います。

# 背景

リファクタリングをしたいけど、既存コードのテストコードは書きたくない(心が折れた)ので、リファクタリングする時に一緒にテストコードを書いていくことにします。
ですが、適切かつ妥当なテストが行えているかの判断が難しいと考えています。
だからといって、テストコードの設計書を書きたくないのです。
なので、テスト対象を多くしてもテスト範囲を小さくすることで、単体テストの妥当性の判断をできる様にします。

# 諦めること

- プレゼンテーション層の単体テスト
    - 他テストで担保する
- リフレクションを使わないこと
    - 一連の処理はある程度妥協する
- private関数だらけになってしまうこと
    - クラス設計が適切であればそこまで気にならないはず。

# 方針
#### コード
1. 関数は小さな処理のみとする 
1. 条件は全て関数にする
1. 計算処理は全て関数にする
1. public関数は判定処理 および 別関数呼び出し とする

```java
class Hoge {
    public String exec(String value) {
        if (isHoge(value)) {
            getHoge();
        }
        return null;
    }

    private Boolean isHoge(String value) {
        return value === "hoge";
    }

    private String getHoge() {
        // ...何らかの処理
    }
}
```

#### テストコード
1. 関数ごとにクラスを作成する
1. ファイル内にテスト設計を書く

```java
/*
※READMEに書いても良いかも
# テスト観点
- 引数の型、値による結果を確認

# テストケース
## 正常系
### ①空文字
- テストデータ
    - 空文字
- 期待値
    - false

## 準正常系
なし

## 異常系
### ①引数が不正な型
- テストデータ
    - 1(int)
- 期待値
    - IllegalArgumentException 
 */

class Hoge_isHogeTest{
    public test_正常系_空文字() {
        // ...何らかの処理
    }
    public test_異常系_引数が不正な型() {
        // ...何らかの処理
    }
}
```
CMakeチュートリアル４【ダイナミック/スタティックリンク】

[前回](https://qiita.com/openfields/items/e8ce0e64ef4f4ee32ccd)は変数・環境変数・分岐・ループでした
ずっと単一アプリケーションで開発するわけにもいかないので、今回はライブラリと複数のプロジェクトについて解説します

# チュートリアル４
CMakeでのライブラリの作り方、複数プロジェクトの作成について解説していきます

## ルートプロジェクト
`${CMAKE_SOURCE_DIR}`は予約語でルートのCMakeLists.txtがあるディレクトリを指します
ライブラリ・アプリケーションの両者で必要になるディレクトリのため、変数\${MYLIB_INCLUDE_DIRS}にtutorial4/mylib/includeを代入しています

`add_subdeirectory(ディレクトリ名)`でサブディレクトリのCMakeLists.txtを解析します
指定したサブディレクトリには必ずCMakeLists.txtが必要です

```CMake
cmake_minimum_required(VERSION 3.13)

project(cmake_tutorial_4)

set(MYLIB_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/mylib/include")

add_subdirectory(mylib)
add_subdirectory(tutorial_4)
```

## ライブラリ
ライブラリのプロジェクトを作成するには`add_library`を使用します
ダイナミック/スタティックライブラリのどちらかを作成することができます
指定方法は後述します

```CMake
add_library(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/src/mylib.cc)
```

## 実行ファイル
`add_dependencies`で依存関係を定義します
cmake_tutorial_4はmylibに依存する、つまりcmake_tutorial_4よりmylibが先にビルドされます

`target_link_libraries`でライブラリをリンクします
今回は同じCMakeプロジェクトなので`mylib`というプロジェクト名で自動的にライブラリへのパスが解決されます
外部ライブラリを使用する場合はパスが必要になります(これについては別のセクションで記述します)

```CMake
add_dependencies(${PROJECT_NAME} mylib)

target_include_directories(${PROJECT_NAME} PRIVATE ${MYLIB_INCLUDE_DIRS})

target_link_libraries(${PROJECT_NAME} mylib)
```

## ビルド

```
cd cmake_tutorials
cmake -S tutorial_4 -B build/tutorial_4 -D BUILD_SHARED_LIBS=ON
cmake --build build/tutorial_4
```

今回は`-D BUILD_SHARED_LIBS=ON`が追加されていることに注意してください
`-D 変数名=値・文字列`でCMakeLists.txt内部の変数の初期値を代入する事ができます
`BUILD_SHARED_LIBS=ON`にする事でダイナミックリンクを作成するように指定しています
スタティックリンクを作成する場合は`BUILD_SHARED_LIBS=OFF`、もしくは何も設定しないでください(デフォルト値はOFF)

---
これでアプリケーション・ライブラリを作るための一通りは説明し終えました
次回はコンフィグレーションについて解説していこうと思います
ディスプレイの解像度によってEmacsのフォントを切り替える

ディスプレイの解像度によってフォントとフレームサイズを切り替えるコード。

高さが2160以上の場合とそれ未満の場合の2つに場合分けして、それぞれ設定してみます。

```
(if (boundp 'window-system)
    (if (>= (x-display-pixel-height) 2160)
        (setq initial-frame-alist
              (append (list
                       '(font . "PlemolJP regular 13")
                       '(width . 120)
                       '(height . 80))
                      initial-frame-alist))
        (setq initial-frame-alist
              (append (list
                       '(font . "PlemolJP light 11")
                       '(width . 80)
                       '(height . 60))
                      initial-frame-alist))))

(setq default-frame-alist initial-frame-alist)
```

もっと洗練した書き方があると思いますが、このようにベタに書くほうが、別の環境に持って行ったときにすぐにちょこちょこっと書き換えて対応できるので、こうしています。

余談になりますが、上記で使用しているフォントは [yuru7/PlemolJP: IBM Plex Mono と IBM Plex Sans JP を合成したプログラミングフォント PlemolJP (プレモル ジェイピー)](https://github.com/yuru7/PlemolJP) です。数字のゼロとアルファベットのオーなどの紛らわしい文字が区別できるようになっているし、よく問題の原因となる全角スペースも可視化されるし、コーディングにはお勧めです。ウェイトも豊富に用意されています。
プロトコルでジェネリクスを使うためのメモ

# はじめに
protocolでassociatedtypeを使い、extensionで抽象的な関数を追加する方法をまとめた。

## associatedtype入りのprotocol

```swift
public protocol Pr {
    associatedtype AT
    func fn(arg: AT) -> AT
}
```

## protocolのextension
ここでは、演算子のようなパターンを想定。
パラメータ、戻り値のSelfはATでも良い。

```swift
extension Pr where Self == AT {
    public static func exfunc (_ a: Self, _ b: Self) -> Self {
        a.fn(arg: b)
    }
}
```

## enum版
処理は、比較。一致した場合にmatchを返す。

```swift
public enum En: Pr {
    public typealias AT = En
    case case1
    case case2
    case match
    public func fn(arg: En) -> En {
        if self == arg {
            return .match
        } else {
            return self
        }
    }
}
```

## struct版
処理はIntの足し算。

```swift
public struct St: Pr, CustomStringConvertible {
    public typealias AT = St
    public var description: String { String(format: "%05d", val) }
    var val: Int
    public func fn(arg: St) -> St {
        St(val: val + arg.val)
    }
}
```

## class版
処理はFloatの掛け算。

```swift
public class Cl: Pr, CustomStringConvertible {
    public typealias AT = Cl
    public var description: String { String(format: "%.3f", val) }
    var val: Float
    init(val: Float) { self.val = val }
    public func fn(arg: Cl) -> Cl { Cl(val: self.val * arg.val) }
}
```

## 実行結果

```swift
print(En.exfunc(En.case1, En.case1))
// --> match
print(En.exfunc(En.case1, En.case2))
// --> case1
print(St.exfunc(St(val: 1), St(val: 2)))
// --> 00003
print(Cl.exfunc(Cl(val: 2), Cl(val: 3)))
// --> 6.000
```

# まとめ
protocolのassociatedtypeと、extensionのwhere句の使い方を確認した。
【強化学習】Sarsa、Q学習の弱点について

本記事は書籍のコードを参考にしているため、全てのコードは公開致しません。
また、AI初心者が投稿している記事です。
理解不足・不正確な情報があることはご容赦ください。

##目次
[1.概要](#1概要)
[2.参考書籍](#2参考書籍)
[3.環境構築](#3環境構築)
[4.弱点と思われる箇所](#4弱点と思われる箇所)
[5.方向の選択方法](#5方向の選択方法)
[6.一筆書き迷路](#6一筆書き迷路)
[7.行動価値関数Q](#7行動価値関数Q)
[8.提案](#8提案)

##1.概要
下記の書籍を参考に、オリジナルの一筆書き迷路をAIに強化学習させてみた。
その時に、Sarsa、Q学習の弱点と思われる箇所を発見した。

##2.参考書籍
・書籍名：AlphaZero 深層学習・強化学習・探索 人工知能プログラミング実践入門
・著　者：布留川 英一
・初版

https://www.borndigital.co.jp/book/14383.html#:~:text=%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-,AlphaZero%20%E6%B7%B1%E5%B1%A4%E5%AD%A6%E7%BF%92%E3%83%BB%E5%BC%B7%E5%8C%96%E5%AD%A6%E7%BF%92%E3%83%BB%E6%8E%A2%E7%B4%A2%20%E4%BA%BA%E5%B7%A5%E7%9F%A5%E8%83%BD%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80,-%E8%91%97%E8%80%85%EF%BC%9A%E5%B8%83%E7%95%99%E5%B7%9D

##3.環境構築
・Google Colaboratory(2022/01/17)

##4.弱点と思われる箇所
AIの解説に「最初は答えがわからないため、模索方向をランダムにする」と良く目にする。
参考書籍にも、行動価値関数の初期値をランダムにするコードが記載されている。(p.149)
参考書籍では、学習が進むにつれ、その状態の中で最も高い行動価値関数の値(方向)を選択するようになっている。(p.149)
しかし、行動価値関数の初期値をランダムにすると不正解ルートの行動価値が高く設定されるケースが見られた。
この場合、学習が進むにつれ、不正解ルートしか辿らなくなり無限ループに陥ってしまう。(何時まで経ってもゴールできない)

##5.方向の選択方法
IF=Trueの場合、ランダムで方向を選択する。
elseの場合、行動価値関数で最も高い値の方向を選択する。
変数epsilonは初期値0.5で、1エピソード完了ごとに1/2に減らしていく。
そのため、最初の方のエピソードはIF=Trueとなることもあるが、徐々に高確率でelseになる。

```Python
def get_a(s, Q, epsilon, pi_0):
    if np.random.rand() < epsilon:
        return np.random.choicekl([0, 1, 2, 3], p=pi_0[s])
    else:
        return np.nanargmax(Q[s])
```

0は上、1は右、2は下、3は左を意味する。
変数pi_0は、初期状態で移動できる方向を示唆している。
数値は確率である。(状態0の場合は、左0% 右50% 下50% 上0%)

変数pi_0
![スクリーンショット 2022-01-20 224304.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497747/551382ff-7a21-dbb7-2642-0523b0006dc2.png)


##6.一筆書き迷路
・今回は、正解が1通りしかない。
・状態「0」が、スタート地点。
・ポイントは、状態「0」の時に下方向(状態「3」)、状態「4」では上方向(状態「1」)に行動すること。
・エピソードは、全10回とする。
![スクリーンショット 2022-01-17 212119.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497747/275e6166-b31f-ac6b-d716-7ad7550d63bb.png)

##7.行動価値関数Q
問題となった、ランダムによる行動価値関数Q
![スクリーンショット 2022-01-17 214801.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497747/dd9fe0ba-079a-bdae-2617-9855b7ede8c2.png)

###状態0について
＜初期値＞
右が「0.701」、下が「0.004」と、不正解ルート(右)が圧倒的に行動価値が高くなっている。
![スクリーンショット 2022-01-19 001919.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497747/573ca0f5-97be-8bb6-b302-92bba1fb5e53.png)

＜エピソード7回目終了時点＞
右が「0.701」、下が「0.396」と、初期値に比べ正解ルート(下)の行動価値が高くなっている。(不正解ルート右は、変化なし)
しかし、エピソード8回目からはepsilonが非常に小さなりelse(行動価値が最も高い方向=右、不正解ルート)ばかりが選択され、無限ループに陥った。
![スクリーンショット 2022-01-19 002355.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497747/c159064f-4541-05ef-5191-127f1b0155fd.png)

###状態4について
状態0と同じ現象のため、割愛

##8.提案
＜提案１＞
エピソード回数をもっと増やし、epsilonの減り具合ももっと緩やかにする。
例：エピソードを全100回にし、epsilonの減り方を0.9倍ずつにする。

＜提案2＞
行動価値関数の初期値を、ランダムにしない。
初期値は、全て同じ配分にする。
例：初期値は全て0.1、進めない方向はnanにする。
![スクリーンショット 2022-01-19 004948.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497747/0fb971f7-de2e-b640-edf0-ea44a0d72580.png)
CloudFormation での IAM Policy (管理ポリシー)作成

最近CloudFormationをいじっているのだけど、いろいろと詰まることが多い。今日はIAMのPolicy作成でつまった。

以下のAWS::IAM::Policy を利用してポリシー作成したらインラインポリシーになってしまった。思いっきり最初の文章にかいてあるのだけど、読まずにさわっていた。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html#cfn-iam-policy-roles

どうやら管理ポリシーとして作成する場合はAWS::IAM::ManagedPolicyを利用するらしい。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-iam-managedpolicy.html#cfn-iam-managedpolicy-policydocument

インラインポリシーの場合はロール側にVersionがあれば正常とみなされたが、ManagedPolicyはそれ自体にVersionが必須となるので注意。あと、名前もPolicyNameでなくManagedPolicyNameを指定する必要がある。

開発途中で気が付いたのだけど、手元でcfn-lintを利用していて、マネジメントコンソールのエラー表示よりも前者の方が親切なエラーを吐いてくれる。
下のエラーはManagedPolicy のバージョン指定において間違えた文字列を指定した場合のエラーだがcfn-lintの方が間違いが特定しやすい。

cfn-lint
E2507 IAM Policy Version needs to be one of (2012-10-17, 2008-10-17).

マネジメントコンソール
AmazonIdentityManagement; Status Code: 400; Error Code: MalformedPolicyDocument;


明日は今日作成したロールをEC2のインスタンスプロファイルに付与できるように実装を進めたい。
AWS CodeDeployエージェントのサポートRubyバージョン

## CodeDeployエージェントとRuby
[AWS CodeDeployエージェントをインストール](https://docs.aws.amazon.com/codedeploy/latest/userguide/codedeploy-agent-operations-install-linux.html)する上では前提条件としてRubyをインストールしろと記載されているが、そのバージョンは記載されていない。
Rubyのバージョンを3系などにアップデートして大丈夫なのか知りたかったけれど、ドキュメントには記載がなかった。
CodeDeployエージェント自体は[OSSとして公開されている](https://github.com/aws/aws-codedeploy-agent)が、READMEにもリリースノートにもRubyバージョンは記載がなかった。

## 実装の確認
最新のバージョン1.3.2における[エージェント起動スクリプト](https://github.com/aws/aws-codedeploy-agent/blob/1.3.2/bin/codedeploy-agent)および[インストールスクリプト](https://github.com/aws/aws-codedeploy-agent/blob/1.3.2/bin/install)を確認すると
Ruby2.0から2.7までをサポートしていることがわかる。
Ruby3.0では動かないようで[issueが起票されている](https://github.com/aws/aws-codedeploy-agent/issues/301)。

ただし、[テスト](https://github.com/aws/aws-codedeploy-agent/blob/master/.github/workflows/ruby.yml)を見るとRuby2.6と2.7でしか確認していない。
基本的にはRuby2.6 or 2.7を利用するのがよさそう。
「if errorlevel」と「if %errorlevel%」は意味が違う。

【書き方1】
if %errorlevel% equ 1 ; 1に等しい場合

【書き方2】
if errorlevel 1 ; 1以上の場合。
if not errorlevel 1 ; 1未満の場合

比較演算子が入る書き方1は「errorlevel」をユーザ変数と同じように扱います。

書き方2はいっそのこと「if errorlevel」構文だと思った方が分かりやすいですかね。


書き方2の何が便利かというと、
errorlevel判定のネストが必要な場合でも
setlocal enabledelayedexpansion指定しなくてもよいということでしょう。
（遅延展開は値に「!」が含まれてると誤動作するので避けたい）

【書き方1の場合】

```
{処理1（成功なら0、失敗は1以上の数値を返すとする）}
if %errorlevel% equ 0 (
  {処理2（成功なら0、失敗は1以上の数値を返すとする）}
  if !errorlevel! equ 0 (
    {処理3}
  )
)
```

【書き方2の場合】

```
{処理1（成功なら0、失敗は1以上の数値を返すとする）}
if not errorlevel 1 (
  {処理2（成功なら0、失敗は1以上の数値を返すとする）}
  if not errorlevel 1 (
    {処理3}
  )
)
```
DataBindingでハマった事

#DataBindingでハマった事
###前置き
他の人のプログラムを参考にDataBinding使ってボタンのenableを管理しようとしていたが上手く行かずハマっていた。
その対処をメモ代わりに投稿します。
あくまでも個人の解釈によるメモなので、これを見て間違った認識をしていても当方では何の責任も負えません。
その辺りを注意してください。

###やろうとしていた事
ButtonとEditTextが二つあるlayoutを作り,
DataBinding(ViewModel)を利用して二つあるEditTextの両方が空かどうか
でButtonのEnableを動的に変更しようとしてた。
###原因
DataBindingを見様見真似で使っていた為、一方向DataBindingを利用していたため
EditTextの入力をViewModelで受け取れていなかった。
###対処
一方向ではなく双方向DataBindingを使うように変更した事で
上手く想定通りの挙動になるようになった。

```layout.xml
   <EditText
       ・
       ・
　　　　　　　　　　　　　　android:text="@{viewmodel.hoge}"
   />
       ↓
   //変更点はtext="@{を　text="@={　に
   <EditText
       ・
       ・
　　　　　　　　　　　　　　android:text="@={viewmodel.hoge}"
   />

```

###一方向DataBindingとは
ざっくり言うと
一方向DataBindingを利用すると
xml側でバインディングを利用し属性値を設定することでJava/Kotlin側の変更した値を一々Setterを使わずとも表示の更新ができる。
また値だけでなくListenerもセットすることができる。
＊詳しくは[公式][google]を見てください

###双方向DataBindingとは
ざっくり言うと一方向DataBindingで属性値とリスナーを別々にセットする必要があったのを
一つにまとめxml(View)の変更とJava/Kotlin側での変更を一つの変数で共有できるようになる。

＊詳しくは[公式][google]を見てください

----
###参考
[公式ドキュメント][Google]
[Google]:https://developer.android.com/topic/libraries/data-binding/two-way?hl=ja）
【メモ】不要なコメントがおりました

エラーを握りつぶしている所を発見。
理由を知りたかったけど有識者に聞くしかなかったのでメモしておく。
(ついでに近辺で気になったコメントのこともメモ)

##### 無意味なコメント
`〇〇をする。` や `〇〇である。` みたいなコメントは、コードを見ればわかります。
コメントは　**What** ではなく **Why/Why not** を書く様にしてください。

**Bad**

```javascript
try {
    // ...何らかの処理
} catch(Exception e) {
    // 何もしない
}
```

**Better**

```javascript
try {
    // ...何らかの処理
} catch(Exception e) {
    // ○○なのでエラーにさせない
}
```

##### 説明のためのコメント
複雑なものはコメントで説明するのではなく、名称(変数や関数など)でわかる様にしてください。(そもそも複雑怪奇な処理は避けてください)
単純なものは見ればわかるので不要です。
コメントは負債であると考えてください。
コードを修正する時に合わせて修正(の判断)をしなければならないものです。
修正が漏れて、不適切な内容となってしまった場合、他のコメントの信用も低下してしまいます。

**Bad**

```javascript
if (hoge === null && hoge === "") {
    // 空の場合
} else if (/* 条件いっぱい */) {
    // 〇〇の時
}

// 結果を返す
return result;
```

**Better**

```javascript
/* ex) 関数化しておく */

private function isEmpty(value) {
    return value === null || value === "";
}

private function isHoge() {
    // ...何らかの判定処理
}
```

```javascript
if (this.isEmpty(hoge)) {
    // ...何らかの処理
} else if (this.isHoge()) {
    // ...何らかの処理
}

return result;
```
【Swift】CollectionViewでタップ時に一瞬だけセルを透過させる

CollectionViewでタップ時に一瞬だけセルを透過させるコード。

## 実装コード

```swift
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    if let cell = collectionView.cellForItem(at: indexPath) {
        cell.contentView.alpha = 0.3
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.08) {
            cell.contentView.alpha = 1.0
            
            //タップ後の処理
            print("tapped!!")
        }
    }
}
```

タップした直後にCollectionViewのセルを透過させて、その0.08秒後に透過を戻して、任意の処理を実行させるプログラム。

個人的には0.08秒が最も違和感なく透過が変化する長さでしたが、人によって感じ方は様々ですのでお好みで変更したほうが良いかもしれません。

## 参考

https://developer.apple.com/documentation/uikit/uicollectionview

https://developer.apple.com/documentation/uikit/uiview/1622417-alpha

https://developer.apple.com/documentation/uikit/uitableviewcell/1623229-contentview

## Swiftのお役立ち情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
React チュートリアル　パート12　（npm install axios ）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/271d9696-e87e-4ba5-216f-89b4d6c29155.png)

#目標:military_medal:
今回は、axiosを使って外部のファイルを取得して、ブラウザに表示させてみます:bangbang:

内容はこちらの動画を参考にしています:arrow_down:

https://youtu.be/cgG2_tBDWjE

#”npm install axios”をインストール
まず、Vscodeのターミナルを開いて”npm install axios”をインストールしてください。

#アプリケーションとサーバーを起動する
ターミナルに npm start を入力

#App.jsに記述

![code.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/d1e7b995-a9e3-609a-4e2b-8a062108d30d.png)

>【11行目】axios.get()で外部からファイルを取得します。

>【18行目】filter()で検索機能を実装しています。

>【34行目】coinを”＜Coin/＞”コンポーネントに渡します。

#Coin.jsに記述

こちらが、”＜Coin/＞”コンポーネント”の中身になります。

![code.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/db3b6e37-3874-607c-20c3-705856118509.png)

#ブラウザで確認:fire::fire:

![2022-01-20_22h00_10.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/f53c7b6c-ed05-7165-3efd-48aaa9b3aac5.gif)

#次回:bell:
npm の便利なパッケージを紹介します！

#参考:ledger:

https://youtu.be/cgG2_tBDWjE
Power BI: カスタムコネクター作成を楽に。by Auto Deploy

# 背景

カスタムコネクターの作成時、特殊なプロジェクトになってる為にコネクターの Copy が面倒なんですが
以下に乗ってて、素晴らしい！って思ったので記録用に

<iframe height=600 width=800 src="https://www.youtube.com/embed/ecfRTEoYadI" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>



# 概要
以下使うだけ

https://github.com/lennyomg/VsAutoDeploy/

:::note warn
VS の仕様変更で、単に追加しても動かせないです。
:::

https://devblogs.microsoft.com/visualstudio/updates-to-synchronous-autoload-of-extensions-in-visual-studio-2019/

ビルドの前後イベントもないので、Auto Deploy 無いと超面倒ですよね。

# 環境

- Visual Sutdio 2019: 16.11.7
- Power BI バージョン: 2.99.862.0 64-bit (2021年11月)
- Power Query SDK Update (1.0.0.25)

https://marketplace.visualstudio.com/items?itemName=Dakahn.PowerQuerySDK

# 事前準備

## カスタムコネクターの保存先を作成

> 認定されていないカスタム コネクタを使用する場合、コネクタの .pq、.pqx、.m、または .mez ファイルを、[ドキュメント]\Power BI Desktop\Custom Connectors フォルダーに入れます。 フォルダーが存在しない場合は作成します。

```bat:保存先
%userprofile%\Documents\Power BI Desktop\Custom Connectors
```
環境変数は、ここら辺

https://docs.microsoft.com/ja-jp/windows/deployment/usmt/usmt-recognized-environment-variables


https://docs.microsoft.com/ja-jp/power-bi/connect-data/desktop-connector-extensibility

# 設定
## 設定はここから
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/7c47fde7-b0e8-e4dd-d945-1a4e5c7068ef.png)

## カスタムコネクターの Deploy 先を設定して対象ファイルを選ぶだけ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/f83e839c-afbe-78e1-c2cf-9a69693dc09f.png)
自動で日付を変更する R markdown tips 

Rmarkdownでは、ヘッダーでタイトルや作成者、日付などをYAML形式で指定できます。その際に、手作業でknitするたびに日付を変更する方がいらっしゃるかもしれませんが、手作業は必ずミスのリスクを伴います。
研究結果をまとめた資料の日付が間違っていると、どちらのファイルが最新なのか分からず、誤った研究結果を公表してしまう可能性があります。
そこで、ヘッダーのdateの箇所の日付を、knitした日に自動で変更する方法があります。

参考記事：[私たちのR: ベストプラクティスの探究](https://www.jaysong.net/RBook/rmarkdown.html#rmarkdown-chunk)

最初は以下のようになっていると思います。

```
title: "Untitled"
author: "Masato Terai"
date: "2022/1/20" #R markdownファイルを作成した日
output: html_document
```
このままでもよいですが、knitするたびに日付を手動で変えなければなりません。

しかし、ここのdateに**Sys.Date()関数**をつければ、knitした際に、その日付を自動で表示してくれます（例 2022-01-20）。関数の前にrをつけてください。

```
title: "Untitled"
author: "Masato Terai"
date: "`r Sys.Date()`"   # ``と""で囲うのを忘れない！
output: html_document
```

これで毎回日付を手動で変更する必要はありません。

ちなみに**時間**まで記録したい方は、**Sys.time()関数**で指定すれば、秒単位までの時間を記録してくれます（例 2022-01-20 21:36:36）。timeは小文字なので注意！

```
title: "Untitled"
author: "Masato Terai"
date: "`r Sys.time()`"   # ``と""で囲うのを忘れない！
output: html_document
```

これで、日付の変更し忘れの心配はないですね。
C言語でBM法

# 早速実装
アルゴリズムの説明は他で十分だからとにかく実装例が見てみたい！という人のためにc言語での実装の一例を置いておく。

```boyerMoore.c
#include <limits.h>
#include <stdio.h>
#include <string.h>

int next_step(int table[], char target, int remain);
int boyerMooreSearch(const char str[], const char pat[]);
#define MAX_LEN 100

int main() {
	char str[ MAX_LEN ];
	char pat[ MAX_LEN ];

	printf("Enter the string: ");
	fgets(str, MAX_LEN, stdin);
	printf("Enter the pattern: ");
	fgets(pat, MAX_LEN, stdin);

	printf("The result is: %d\n", boyerMooreSearch(str, pat));

	return 0;
}

int next_step(int table[], char target, int remain) {
	/* ループ防止のために確認する */
	if (table[ target ] > remain) {
		/* ずらし表から値を取得する */
		return (table[ target ]);
	} else {
		/* 照合を開始した地点の次の文字に進める */
		return (remain);
	}
}

/*
 * [機能]: "txt[]"から、"pat[]"を探索する
 * [引数]: char txt[] : 探索する元の配列
 * 		 : char pat[] : 探索する対象の配列
 * [戻り値]:int pt: 探索した配列が配列元の配列の何文字目に発見されたか
 * 			int -1: 探索した結果、一つも見つからなかった時
 */
int boyerMooreSearch(const char str[], const char pat[]) {

	if (strstr(str, pat) == NULL) {
		return (-1);
	}
	int pt;                    /* txtをなぞるカーソル */
	int pp;                    /* patをなぞるカーソル */
	int txt_len = strlen(str); /* txtの文字数 */
	int pat_len = strlen(pat); /* patの文字数 */
	int skip[ UCHAR_MAX + 1 ];
	/* スキップテーブル */
	for (pt = 0; pt < UCHAR_MAX; pt++) {
		/* スキップテーブルの作成 */
		skip[ pt ] = pat_len;
	}
	for (pt = 0; pt < pat_len - 1; pt++) {
		skip[ pat[ pt ] ] = pat_len - pt - 1;
	}

	pt = pp = pat_len - 1; /* 比較位置をパターン末尾にする */
	while ((pt < txt_len) && (pp >= 0)) {

		if (str[ pt ] != pat[ pp ]) {
			/* ずらし表を参照して、次の比較位置を設定する */
			pt += next_step(skip, str[ pt ], (pat_len - pp));
			pp = pat_len - 1; /* 比較位置をパターン末尾にする */
		} else {
			/* 文字が一致したので、前の文字を照合していく */
			pp--;
			pt--;
		}
	}

	if (pp < 0) {
		return pt + 1;
	} else {
		return 0;
	}
	return (-1);
}

```
[javscript]ローカルストレージにjson形式でデータを保存し、取得する

# やりたいこと
ローカルストレージに値を入れたいのだが、文字列しか入れられない。
trueやfalse、数値などのbooleanやnumber型は登録できないので、管理しやすいように
json形式でデータを保存し、データを取得しそれを使えるようにする。

## ローカルストレージの基本
まずローカルストレージとはブラウザなどにデータを保持させておく仕組みです。
ローカルストレージは永続化するので、場合によっては削除する処理を入れないといけません。

### ローカルストレージの確認方法(chrome)
開発者ツールを開き、開発者ツール上部の矢印からApplicationを選択します。

![スクリーンショット 2022-01-20 18.48.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163415/b3198836-d8a3-86fe-9c08-1af523e7b7a8.png)


Storageという項目の中にLocal Storageという項目があるのでそちらの項目を開き、該当のサイトをクリックすると
そのサイトで登録されているローカルストレージの情報が確認できます。

![スクリーンショット 2022-01-20 18.50.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163415/72c84432-13c7-94ec-e225-fdcd7fcf819e.png)

※ データの登録、削除は開発者ツール上でもできるので試してみてください。
右クリックなどで登録・削除ができます。

### ローカルストレージにデータをセット
ローカルストレージに値をセットする場合は、以下の形でセットします。
こちらを実行するとローカルストレージに保存されます。
setItemの第一引数には任意のkey名、第二引数には設定したい任意の文字列を追加してください。

```.js
localStorage.setItem('任意のkey名', '任意の文字列');
```

### ローカルストレージにデータを取得
ローカルストレージの値を取得したい場合は以下の形で取得します。
こちらを実行するとローカルストレージに登録されている該当のデータ(value)を取り出すことができます。
getItemの引数には取り出したいデータのkey名を設定してください。

```.js
localStorage.getItem('取得したいkey名');
```

### ローカルストレージのデータを削除
ローカルストレージの値を削除したい場合は以下の形で削除します。
こちらを実行するとローカルストレージに登録されている該当のデータを削除できます。
removeItemの引数には削除したいデータのkey名を設定してください。

```.js
localStorage.removeItem('削除したいkey名');
```

または、以下のコードでストレージに保存されている全てのデータを削除できます。

```.js
localStorage.clear();
```

## JSON
上記だけだと文字列型しかストレージに保存できません。
booleanなどを設定したり、オブジェクトをセットしたい場合はjson形式でやればできます。

### JSONをストレージに保存
まずはJSONを用意して、ストレージに保存していきます。
ストレージに保存する場合は、文字列でないといけないので
JSON.stringifyで文字列に変換してあげます。

```.js
const sample = {
  name: "taro",
  flag: true,
}

const jsonString = JSON.stringify(sample);
localStorage.setItem('sample', jsonString);
```

これでローカルストレージの部分を確認すると保存されていると思います。

### ストレージから値を取得してJSONの形に戻す
保存ができたので今度は取り出して値を使えるようにします。
次はparseを使って文字列からjsonに直します。

```.js
const sampleJson = JSON.parse(localStorage.getItem('sample'));

console.log(sampleJson.flag); // true
```

## まとめ
ローカルストレージとJSONを使えばある程度やりたいことができそうな気がしました。
ですが、個人情報などをセットしたり、重要なデータをセットしたりするのは避けた方がいいかもしれないです。
どうしてもというときは削除することを忘れないようにしたいです。
駿台予備校広告のあの答え合わせをJuliaで一行でやってみた

https://qiita.com/sano192/items/a27a481395ce8827bbf6
https://qiita.com/TSeri/items/6958d0ad98d4beb7571d

要するに，6文字の順列を作り，重複を省いて，ソートして，100 番目の要素を出力する。
Julia なら，順列を生成する Combinatorics.nthperm を使う。

```Julia
using Combinatorics
sort(unique(join(nthperm(split("GAKKOU", ""), i)) for i in 1:factorial(6)))[100]
```