OmniAICreator/Qiita-1.07M huggingface dataset:
【勉強ノート #2】学振とJST次世代の手取り

# 概要

博士学生に対する経済的支援に関する次の2つの代表的事業に着目し，その税金の仕組みや手取り (実質的に手元に残る金額)，節税対策についてまとめました．
- 日本学術振興会「特別研究員DC」
- 科学技術振興機構 「次世代研究者挑戦的研究プログラム」

ノートは [本記事の最後](#勉強ノート) に置いてあります．

### 収録内容
- 事業概要と支援内容
- 納める税金
- 手取り計算
- 節税対策とシミュレーション

::: note warn
本ノートはあくまで個人的な見解に基づくものです．
税理士法により，非税理士が以下を行うことは禁止されています．
1. 税務手続きを代行すること (税理代理)
1. 税務書類を作成すること (税務書類の作成)
1. 税務に関する相談を受けること (税務相談) 

そのため，税務関係の個別の相談は一切お受けできませんのでご了承ください．
:::

# ノートのまとめ
以降，特別研究員DCを「学振」，次世代研究者挑戦的研究プログラムを「JST次世代」と略記します．
- 学振は国から直接選出され，JST次世代は各大学から選出されます
- 学振は20万円/月，JST次世代は約20万円/月の生活費相当額が支給されます (生活費相当額とは別に研究費が支給されます)
- 一方，採択されると"扶養"から外れて"世帯主"となるので，納税義務が生じます
- これを踏まえて手取りを計算すると，両者で**11万円**程度となります
    - 学振の場合は学費免除となることが多いので，この場合手取りは16万円程度となります
- どちらも研究に係る支出を「経費」とすることが可能です
    - 経費に計上できれば納めるべき税金が少なく済みます
    - しかし，学振は制約が厳しいです (例えば，授業料は計上できないとか...)
    - 一方，JST次世代は基本的に制約がないので，授業料，交通費，パソコン購入費などを経費として計上できます
    - ただし，家事按分 (事業分と私用分の比率) を考慮する必要あります
    - 経費に計上して良いかどうかは最終的に税務署が決めます

::: note warn
JST次世代の研究奨励費は基本的に白色申告なため，青色申告できるかどうかは，予め各所属機関あるいは各税務署に問い合わせてください．
:::

# 勉強ノート
勉強ノート (pdf) は以下に置きました．
内容に誤りを含む可能性がありますので，取り扱いにはご注意ください．

https://drive.google.com/file/d/1MCRBEAPR1cc4b53DKs7LOsnB2IZxpfSD/view?usp=drive_link
paizaBランク問題「名刺バインダー管理」を解く

paiza×Qiitaコラボキャンペーン、もう少しで終わりますね。

最後に一つ面白そうな問題を見つけたので解いてみます。
paiza問題ランクB Final問題の「名刺バインダー管理」になります。

※問題文はリンクより参照してください。

https://paiza.jp/works/mondai/b_rank_skillcheck_archive/name_card

## 解き方
以下の流れに沿って解いていきます。

1. 面裏のバインダー番号配列作成
2. 再帰関数で検索数値が含まれているバインダー番号配列があるまで繰り返す
3. 検索数値が含まれていれば現在のバインダー番号配列を返却
4. バインダー番号配列から検索番号の位置を特定
5. 配列最後から検索番号の裏側の値を取得 <- これが目的

あとはこれをコードに書き写せばいいですね。

## 完成コード
別段難しいことはしていませんが、再帰関数の使い方がコツでしょうか。次々とバインダー番号配列を作成し、検索番号があるまで繰り返すようにしています。

目的は**配列最後から検索番号の裏側の値を取得**することなので、`binder[(binder.length - 1) - index]`としています。配列最後のインデックスから検索番号のインデックスを引き、裏側の値を取得しています。

```javascript
const [n, m] = lines[0].split(' ').map(v => +v);

function binderExamination (start, end) {
    const binder = [];
    // 面裏のバインダー番号配列作成
    for (let i = start; i <= end; i++) {
        binder.push(i);
    }
    // 検索数値が含まれていれば現在のバインダー番号配列を返却
    if (binder.includes(m)) {
        return binder;
    }
    const maxBinderValue = binder[binder.length - 1];
    // 再帰関数で検索数値が含まれているバインダー番号配列があるまで繰り返す
    return binderExamination(maxBinderValue + 1, maxBinderValue + (n * 2));
}

const binder = binderExamination(1, n * 2);
// バインダー番号配列から検索番号の位置を特定
const index = binder.indexOf(m);
// 配列最後から検索番号の裏側の値を取得 
console.log(binder[(binder.length - 1) - index]);
```

## さいごに
問題が面白いと解きがいがありますね。

これはあくまで自分の解き方です。もっといいアルゴリズムがあるなどありましたら教えていただきたいです。
raspberrypiでopenframeworksを自動起動させるときのsystemdの設定

/etc/systemd/system/myApp.service
```
[Unit]
Description=My App Service
After=multi-user.target
Wants=multi-user.target

[Service]
ExecStartPre=/bin/sleep 30
Environment="DISPLAY=:0"
ExecStart=/home/pi/startupApp.sh
WorkingDirectory=/home/pi/of_v0.12.0_linuxarmv6l_release/apps/Project/Appname/
Restart=always
User=pi

[Install]
WantedBy=multi-user.target
```

startupApp.sh
```
#!/bin/bash
export DISPLAY=:0
cd /home/pi/of_v0.12.0_linuxarmv6l_release/apps/Project/Appname
make run
```
辞書のリスト内の特定のキーに対応する値を合計【Python】

## 説明

1. `sum()`関数を使用して、`data`リスト内のすべての辞書から`time`キーに対応する値を合計しています。
2. `item["time"] for item in data`はリスト内包表記で、`data`リスト内の各辞書から`time`の値を取り出します。
```python
data = [
  {"time": 60},
  {"time": 180}
]

total_time = sum(item["time"] for item in data)

print(total_time)  # 出力: 240
```

## キーが一致していない場合でも、すべての値を集計

1. `item.values()`を使用して、各辞書内のすべての値を取得します。
2. 内側の`for`ループで`item.values()`からすべての値を取り出し、外側の`for`ループで`data`リスト内の各辞書を処理します。
3. `sum()`関数を使用して、これらすべての値を合計します。

```python
data = [
  {"morning": 60},
  {"evening": 180}
]

total_time = sum(value for item in data for value in item.values())

print(total_time)  # 出力: 240
```
VOICEVOXの音声合成速度の計測と比較

webアプリにvoicevox_coreによる音声合成を組み込んでサービスを開発したかったため、現実的な速度で合成できるか、速度を計測した。


## 実行時間の測定
以下のような `main.py` を実行し、速度を計測した。
```python:main.py
from pathlib import Path
from voicevox_core import VoicevoxCore
import time


core = VoicevoxCore(open_jtalk_dict_dir=Path("open_jtalk_dic_utf_8-1.11"))

speaker_id = 1 #ずんだもん
text = "こんにちは、これはテストなのだ。"

core.load_model(speaker_id)  # 指定したidのモデルを読み込む
start = time.time()
for i in range(100): # 実行回数をここで調整
    wave_bytes = core.tts(text, speaker_id)  # 音声合成を行う
end = time.time()

print("time:", end - start) # 実行時間を出力
with open("test_zundamon.wav", "wb") as f:
    f.write(wave_bytes)  # ファイルに書き出す
```

### 環境ごとの実行時間の比較
各環境で以下の結果を得た。
* m1 mac book air でCPU推論：
  100回の合成で76秒程度 => 1.3 回/秒 程度の推論速度
* racknerdの格安VPSでCPU推論：
  10回の合成で100秒程度 => 0.1 回/秒 程度の推論速度
* runpodで借りたA4000インスタンスでGPU推論：
  100回の合成で3秒程度 => 33 回/秒 程度の推論速度

## voicevoxを用いたアプリのホスティング手段の検討
voicevoxによる音声合成を機能として組み込んだwebアプリの実現可能性について検討する。
* 格安サーバーレベルの貧弱なcpuでは1回の生成に10秒程度かかり、実用的な推論速度を得ることができているとは言い難い。
* m1 mac book air レベルの高性能CPUを用いた場合、アクセス数の規模が非常に小さい場合（同接20人程度でそれぞれが20秒に1回リクエストする程度）、低速とはいえ現実的な実行速度を出すことができそうだった。高性能CPUを複数台組み合わせるなどで現実的なアプリケーション開発ができる可能性がある。
* 高性能GPUを用いた場合、飛躍的に推論速度が上昇した。gpuインスタンス1台でも、アクセス数の規模が小さければ（例えば同接500人程度でそれぞれが20秒に1回リクエストする程度）十分な実用性でアプリ開発ができそうである。複数台組み合わせることでよりスケールを上げることも考えられる

### GPUサーバーのコストについて
runpodでの最安で借りられるA4000のspotインスタンスでの料金が`$0.16/hour` = `$115/month` である。
つまり1年借りると20万円程度の出費となる。
A4000の購入価格は12万円であり、他の諸々のパーツを含めても20万円くらいでサーバーPCが組める。これを考えると1年以上運用するつもりならA4000なりもっとコストの低いGPUを購入し、自宅サーバーで運用した方が圧倒的にコストカットが計れる可能性がある。

## まとめ、今後の展望
### まとめ
* voicevox_coreを用いた音声推論をubuntuサーバーで行なった
* 推論速度は格安サーバーでは遅く、現実的なものではなかった
* GPUサーバーでは高速な推論が可能であったがコストがボトルネックになっている

### 今後の展望
* コスト、推論速度の按配を見て、格安、低品質なGPUサーバー、あるいは高品質なCPUサーバーの調査を行いたい
* 場合によってはサーバーPCを作成し自宅で管理することも考慮する

## 追記: GPUごとのVOICEVOXの音声合成速度リスト
すでにGPUごとに速度を計測、比較してらっしゃる方がいた。

https://zenn.dev/kuronekoserver/articles/d63fc8c71c44e3
英語翻訳はローカルLLMで動かせる時代。その時必要なスキルは？

DeepLの衝撃から6年ほど。
自然な英語翻訳はローカルLLMで実現する時代が来た。色々なものが生成AIで淘汰される時代でもある。
大事なことはそのときに必要なスキルはどんなものか考えてみた。

<blockquote class="twitter-tweet" data-media-max-width="560"><p lang="ja" dir="ltr">gpt-4o-miniとLlama3.1(8B on Mac mini M2Pro)での翻訳速度と内容の比較<br>前半がLlama、後半がgpt-4o-mini<br>普段の翻訳ならセキュリティ諸々を考えるとオンプレミスで十分<br>DeepLも進化しているけど、ネット接続が不要な時代がくる<br>僕ら自身でもモデルをホストとしていろんなことが提供できそう <a href="https://t.co/DeYvoiK1f8">pic.twitter.com/DeYvoiK1f8</a></p>&mdash; 有馬三郎 CTO@セゾンテクノロジー iPaaS開発しています (@SaburoA) <a href="https://twitter.com/SaburoA/status/1827646837408632945?ref_src=twsrc%5Etfw">August 25, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 上記の実行に必要なスタック
- 実行環境 Mac mini M2Pro 16GB
- OpenAIとのAPI利用契約
- 利用可能なクレジットカード
- Cursorのダウンロード（未契約でOK）
- [ソースコード](https://github.com/simpleapples/chatgpt-translator)
- LM Studio
- Llama3.1 8B
- 知識
    - プログラミング知識（普通レベル）
    - Typescript（初学者の一歩上レベル）
    - Electron（初学者レベル）
    - 設計能力（普通レベル）
    - Cursorに質問する言語構成力（普通レベル）
    - Cursorの回答を読み解く言語理解力（普通レベル）
    - Node関連のビルド、デバッグ知識（初学者レベル）
    - IDE（VSS）の知識（初学者レベル）
    - Github,Gitの操作（初学者レベル）
    - OpenAIのAPI・サブスク利用（普通レベル）
    - オンプレでの生成AIモデル実行知識（普通レベル）
    - オンプレ生成AIモデルとの通信知識（普通レベル）
- 好奇心

## 大事なこと１
アーキテクチャとして、生成AIがDBのようなレベルでシステム開発の範囲に入ってくること。仕組みを知らないとミスる。パフォーマンス、代替ルート、冪等性など。

## 大事なこと2
AIを活用したプログラミングはこれまでの知識を代替するものではなく、ものすごくパワーアップさせるものであること。そして、これまでの要件定義、外部・内部設計、コーディング、テストの境界を上方に曖昧にしていく。設計とコーダーの分離は害しかなさなくなってくる。

## 大事なこと3
AIとの対話に必要なものはしっかりとした文章力であり、考える力が必要になる。これはすぐに身につきにくいので一番絶望的かもしれない。本や新聞を定期的に読んでる人が報われる時代かもしれない。IT知識もすぐには身につかない。なので必ずベースとして技術の勉強をやめないこと。

## 今から始めること
[新版　考える技術・書く技術　問題解決力を伸ばすピラミッド原則](https://amzn.to/3YXjUke)を読んで文章力をつけよう。この本は30年以上前の出版であるが、有名コンサルは1年目の必須書籍らしい。私も3冊買って15年ぐらい読んでいる。

そして、オープンソースを落として、Cursorを使って概要の把握や小改修を毎日１個やってみよう。
個人的には以下がおすすめ。私の関連する分野でもあるし、新しい技術が入ってきている。
https://www.embulk.org/
https://github.com/apache/airflow

新時代のプログラミングを楽しもう。
そして、自分の作りたいものを作ってみよう。

セゾンテクノロジーはエンジニアを募集しております。
【豆知識+Error】コードがあっていても少し位置が違うだけでエラーになってしまうrenderのお話

# はじめに
今日は短めですが、自分でコードを入力していく中で位置が違っただけでうまく表示されない、ローカルにアクセスしたときエラーの画面になってしまったので、同じようなミスをしない為にも記事にすることでアウトプット＆記憶にとどめやすいようにしたいと思います。

## 環境
- Windows, WSL
- Docker
- Ruby 3.2.3
- Rails 7.1.3


## どんな状況だったのか
```ruby
<div class="w-5/6 mx-auto max-w-screen-xl">
  <div class="my-10">
    <h1 class="text-4xl md:text-5xl font-bold mb-10 pb-4 border-b-4 border-dashed border-stone-400 text-center">
      パスワード再設定
    </h1>

    <div class="w-full md:w-2/3 lg:w-1/2 mx-auto">
      <%# バリデーションエラーメッセージ表示 %>
      <%= render 'shared/error_messages', object: f.object %>
    </div>

    <%= form_with model: @user, url: password_reset_path(@token) do |f| %>
```
さぁ、皆さんはこんなコードを書いたときどんなエラーが起こると思いますか？

シンキングタイム

と書きつつ答えはすぐ出す

## Error内容はこんなでした
```ruby
NameError in PasswordResets#edit Showing /myapp/app/views/password_resets/edit.html.erb where line #9 raised:

undefined local variable or method `f' for #ActionView::Base:0x000000000237d0

<%= render 'shared/error_messages', object: f.object %>
```
### エラー内容の意味と原因
- fが定義されていないためにエラーが発生している
- fはform_withブロック内で定義されるローカル変数だから、form_withのブロックの中で使わないといけない

### 修正
```ruby
<div class="w-5/6 mx-auto max-w-screen-xl">
  <div class="my-10">
    <h1 class="text-4xl md:text-5xl font-bold mb-10 pb-4 border-b-4 border-dashed border-stone-400 text-center">
      パスワード再設定
    </h1>

    <div class="w-full md:w-2/3 lg:w-1/2 mx-auto">
      <%= form_with model: @user, url: password_reset_path(@token) do |f| %>
        <%# バリデーションエラーメッセージ表示 %>
        <%= render 'shared/error_messages', object: f.object %>
```
このようにちょっと位置を変えただけ、ちゃんとform_withのブロックの中で使ってあげることでエラーが消えました！！

# さいごに
通常のフラッシュmessageはコントローラーの中で定義することで、ファイルを見た時にすぐに「このエラーはこういうアクションをとった時にこんな内容でフラッシュmessageを表示することができるのか」とわかりやすいのですが、バリデーションmessageはちゃんとした場所に置かないと表示するされない以前にエラーでサイト自体表示されない！！という事がよくわかりました。GPTへの質問の仕方も考えさせられました💦
今回の記事が何か参考になれば幸いです
ubuntuサーバー x python で voicevox_core を動かす

## なにこれ
ubuntuサーバーでvoicevox_coreを動かそうとしたらいくつか穴にはまったので個人的に最適な方法をメモ。

## 1. ダウンロードスクリプトを取得
[githubのリリース上](https://github.com/VOICEVOX/voicevox_core/releases) からdownload.shファイルのダウンロードurlをコピーする。（macなら右クリック→「リンクのアドレスをコピー」）
![スクリーンショット 2024-08-25 19.04.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117442/331472b4-a4e3-0223-b9bd-5b88e7276ed1.png)

ubuntu上でwgetしてダウンロードスクリプトをダウンロード。
```bash:bash
wget https://github.com/VOICEVOX/voicevox_core/releases/download/0.15.4/download.sh
```
### はまった穴
リリースのリンクに `download-linux-x64` のスクリプトもあり、公式ではこちらを推薦しているが、自分の環境ではダウンロードが途中で止まってしまうことが多く、`download.sh` の方が安定していた。

## 2. ダウンロードスクリプトを実行
実行できるようパーミッションを変更
```bash:bash
chmod +x download.sh
```
ダウンロードスクリプトを実行する。（cudaが使えるかどうかによりオプションを調整）
```bash:bash
./download.sh --device cuda  # cuda GPUが使える場合
./download.sh  # CPU上で実行する場合
```

### はまった穴
公式チュートリアルだと `--devices cuda` と書いてあるけど多分間違い。

## 3. pythonライブラリのインストール
[githubのリリース上](https://github.com/VOICEVOX/voicevox_core/releases) からwhl
ファイルのダウンロードurlを同様にコピーする。
cpuで実行するかcudaで実行するか、osのアーキテクチャによって適切なwhlを選ぶ。
![スクリーンショット 2024-08-25 19.12.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117442/beea78e9-8b9a-3510-e748-289e886f529c.png)

pipを用いてコピーしたアドレスからパッケージをインストール
```bash:bash
pip install https://github.com/VOICEVOX/voicevox_core/releases/download/0.15.4/voicevox_core-0.15.4+cpu-cp38-abi3-linux_aarch64.whl
```
ryeを使う場合以下のようにインストールする
```bash:bash
# ライブラリをダウンロード
wget https://github.com/VOICEVOX/voicevox_core/releases/download/0.15.4/voicevox_core-0.15.4+cpu-cp38-abi3-linux_aarch64.whl
# ライブラリをローカルパッケージからインストール
rye add voicevox_core --path voicevox_core-0.15.4+cpu-cp38-abi3-linux_aarch64.whl
```

## 4. voicevox_coreを用いた音声合成を実行
先のdownload.shスクリプト実行後voicevox_coreディレクトリが作成されているはずなのでそこに移動する。
```bash:bash
cd voicevox_core
```
音声合成をするスクリプトを作成する。
```bash:bash
vi main.py
```
中身は以下のようにする。
```python:main.py
from pathlib import Path
from voicevox_core import VoicevoxCore


core = VoicevoxCore(open_jtalk_dict_dir=Path("open_jtalk_dic_utf_8-1.11"))

speaker_id = 1 #ずんだもん
text = "こんにちは、これはテストなのだ。"

core.load_model(speaker_id)  # 指定したidのモデルを読み込む
wave_bytes = core.tts(text, speaker_id)  # 音声合成を行う
with open("test_zundamon.wav", "wb") as f:
    f.write(wave_bytes)  # ファイルに書き出す
```


スクリプトを実行
```bash:bash
python main.py
```

問題なければ test_zundamon.wav が作成される。

### はまった穴
公式ではvoicevox_core.blockingを用いたpythonスクリプトが挙げられているが、それは動作しなかった。（多分voicevox_coreの修正がチュートリアルコードに反映されてない。）
C言語で書いたプログラムをgoogletestでテストできるようにした

# はじめに
こんにちは。

先日、データ構造について再度勉強する機会があり、C言語を用いて線形リストに関するプログラムを書いていました。

作成した線形リストのプログラムが正しいかどうかを確認するために、`main.c`に毎回シナリオを書き込んで実行し、その結果を確認していましたが、とても手間に感じました。

そこで
**C言語で書いたプログラムのテストをコマンド1つで実行できる**ような、C言語の環境を整えました。


:::note warn
私自身、あまりC言語やその背景知識に詳しくありません。
上記のような問題にぶつかり、調べながら以下の環境を作成したので、間違っている部分が多々あると思います。間違いや改善点を見つけたらコメントしていただけると嬉しいです。
:::

ぜひ、ご参考にしてください！


# 作った開発環境

下のURLが今回開発した環境です。

https://github.com/kaitokimuraofficial/article-strage/blob/main/Qiita/created-dev-env-of-Clang-that-can-test-easily-with-gooletest


こちらのレポジトリにアクセスしてフォルダごとコピーしてください。`README.md`にもあるとおり、
```txt
make test
```

の**1コマンド**で実際にテストを実行できます！
([`Docker`](https://www.docker.com/ja-jp/)の環境構築が必要です。)


## 使い方

README.mdを見ていただければ、大体わかると思いますが、

1. `src`ディレクトリに適切にソースコードを書く
2. `tests`ディレクトリに対応するテストコードを作成する
3. `tests/CMakeLists.txt`に設定を追加する

をします。
その後、`make test`を実行すればテストが開始します。

全てのテストがパスすればテスト用に作成したdockerのビルドイメージが削除され終了し、
何かのテストに失敗すればエラーがログに表示されます。

## 簡単な説明

### 使用したテストフレームワーク
今回は[`googletest`](https://github.com/google/googletest)を使用しました。

調べたところC言語の単体テストのフレームワークには[`CUnit`](https://sourceforge.net/projects/cunit/)というものもあるそうですが、`googletest`の方が更新が頻繁に行われているのと、[ドキュメント](https://google.github.io/googletest/)が豊富であると考え、`googletest`を採用しました。

### ビルドツール
ビルドツールとして[`CMake`](https://cmake.org/)を利用しました。正直よくわかっていません。他にいいやつがあったら教えてください。(ビルドがなんなのかきちんと説明できるかも怪しい。)


### Docker
誰でも簡単に環境を再現できる方が良いと思い、Docker上で環境が構築されるようにしました。


# 最後に
C言語は大学の授業で軽く触った程度なので、よくわからないことが多かったですが、ひとまず形になるものを作れてよかったです。間違いや修正点が多くあるダメダメだと思いますが、ある程度のプログラムの単体テストだったらこれで十分な気がします。

ここまで読んでいただきありがとうございました。


**P.S.**

冒頭にも述べましたが、私は作成したプログラムが正しいかを確認するために、`main.c`に毎回シナリオを書き込んで実行し、その結果を確認していました。

一回の修正に数分しかかからないので、そこまで大変な作業ではないのですが、何回も繰り返すとストレスが溜まる作業です。

周辺技術について詳しくない状態からのスタートだったので、開発環境を整えるのに数時間がかかりましたが、結果的にはテストを数秒で終わらせられるようになりました。これこそまさに

**[エンジニアあるある]**
**3分でできる作業を3時間かけて3秒でできるようにする奴**

なのかもしれません。
RaspberryPi4にUSBマイクを認識させる

## はじめに
以前、以下の記事でUSBマイクを認識させて使っていたのですが、今回はRaspberryPi4にデバイスが変わったので改めて試してみました。

https://qiita.com/cnysntry/items/f5b0654f91f8e39b0897

## マイク接続
まずは前回と同じようにマイクをRaspberryPi4に接続して、
```cat /proc/asound/modules ```を確認します。
![0824_asoundmodules.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750854/1f972b60-62e0-82e4-18c9-4a63f7df8df4.png)

index=2にUSBが見えていますね。このUSBマイクの優先度を上げるため、```/etc/modprobe.d/alsa-base.conf```を以下のように編集します。
```
options snd-usb-audio index=0
options snd_bcm2835 index=1
options snd_bcm2835 index=2
```
このようにsnd_bcm2835も明示的にindex指定してあげる必要がありそうです。
RaspberryPi4を再起動して、```cat /proc/asound/modules ```を確認すると、
以下の通り、USBマイクが最優先に格上げされています。
![0824_asoundmodules_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750854/c160808a-1be1-0a33-13be-38b9b00c918d.png)

あとは以下のようなコマンドを使って実際にUSBマイクからキャプチャできるかを確認します。
```
$ arecord -f S16_LE -r 44100 -w hw:0,0 sample.wav
```
44.1kHz/16ビット幅でWAV形式で録音しています。
これによりUSBマイクからの音をWAVファイル出力することができました。
資料作成に活用できる生成AIツール：Napkinを紹介します

最近、パワポ資料に載せる図表を自動生成できるAIツール（Napkin）を見つけました。使ってみたところ非常に便利だったので、皆さんにも紹介したいと思います。

使用方法は非常にシンプルで、テキストを入力して生成ボタンをクリックするだけで、入力した内容に基づいて様々な形式の図表が自動的に作成されます。⇩（ちなみに、このツールは現時点では英語のみ対応しています）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/3297762e-d2b6-5ced-ac4c-24f380df3a17.png)

例えば、RAGの説明資料を作成する場合には、以下のような流れで使えます。
まず、RAGに関する説明文を用意します。（今回はGoogle公式サイト上にあるRAGを説明する文章を引用します）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/bee92d4e-6c46-0765-6f30-b9e96c040a2a.png)

https://cloud.google.com/use-cases/retrieval-augmented-generation?hl=en

この文章をNapkinの入力欄にコピペし、左側にある青色のアイコン（生成ボタン）をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/94695910-2eba-9575-2c05-fd02d74d182a.png)

すると、様々な種類の図表が生成されます。例えば、以下の図表はRAGと従来の検索技術を比較したものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/6323b1b1-c78d-2bca-02ac-740a0a249163.png)

また、RAGの仕組みを説明する段落から生成すると、⇩のような図が作成されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/7b67d539-4c1b-c092-a252-238af697a8d9.png)

これらの生成された画像は、PDFやJPG形式で簡単にダウンロードすることもできます。
さらに、WordやPowerPointファイルを直接ドラッグ＆ドロップして図表を生成することも可能です。⇩試してみたところ、こちらもかなり良いアウトプットが生成できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/20301dd5-649f-68f0-4c03-6586ddff0f36.png)

Napkinは基本的に無料で使えますので、興味ある方試してみてください：

https://www.napkin.ai/
DP法(動的計画法)について

こんにちは、jjj0331です。今回は、Atcoderというプログラミング競技を通じて学んでいるアルゴリズムの中から、特に DP法（動的計画法） についてお話ししたいと思います。

## DP法(動的計画法)とは？
DP法（Dynamic Programming）は、問題をいくつかの小さな部分に分けて、それぞれを解き、その結果を組み合わせて最終的な解を導き出す手法です。この方法は、特に次のような問題にとても役立ちます。

部分和問題: 集合の中から、特定の和を持つ部分集合を見つける問題。
ナップザック問題: 価値と重量が決まっている複数のアイテムの中から、できるだけ価値の高い組み合わせを選ぶ問題。
DP法の基本的な考え方
DP法の基本は、「大きな問題を小さく分けて解決する」ことにあります。まず大きな問題を、より小さな部分問題に分解します。そして、それらの解を再利用することで、効率よく最終的な答えを導き出します。

例えば、ナップザック問題では、各アイテムを「選ぶか、選ばないか」を順に決めていきます。こうすることで、最適な解を見つけ出せます。また、すでに計算した部分問題の結果をうまく活用することで、無駄な計算を省くことができます。

## 具体例：DP法の実際の適用例: ナップザック問題
DP法が効果を発揮する代表的な問題として、ナップザック問題があります。


例: ５kgまで入るカバンにアイテムを入れていきます。次のようなアイテムがあります：

パソコン: 重量 1kg, 価値 100
水: 重量 5kg, 価値 50
本: 重量 3kg, 価値 40
これらのアイテムを、合計10kgまで入るカバンに詰め込み、価値が最大になるようにします。

DP法を使った解法
この問題をDP法で解くために、重さの制限と各アイテムの価値を考慮しながら部分問題に分割して解いていきます。

DPテーブルの定義
dp[i][w] を、i 番目までのアイテムから重さ w までのカバンに詰めたときの最大価値とします。

漸化式
アイテム i を選ばない場合: dp[i][w] = dp[i-1][w]
アイテム i を選ぶ場合: dp[i][w] = dp[i-1][w - weight[i]] + value[i]

これにより、次のようにDPテーブルを更新していきます。


``` 
# アイテムのリスト: (重量, 価値)
items = [(1, 100), (5, 50), (3, 40)]
max_weight = 5
n = len(items)

# DPテーブルの初期化
dp = [[0] * (max_weight + 1) for _ in range(n + 1)]

# DPテーブルの更新
for i in range(1, n + 1):
    weight, value = items[i - 1]
    for w in range(max_weight + 1):
        if w >= weight:
            dp[i][w] = max(dp[i-1][w], dp[i-1][w-weight] + value)
        else:
            dp[i][w] = dp[i-1][w]

# 最終結果の出力
for row in dp:
    print(row)
print(f"最大の価値: {dp[n][max_weight]}") 
```

**DPテーブルの視覚的表示**
|アイテム\重量  |0kg |1kg|2kg|3kg|4kg|5kg|
|---|--- |---|---|---|---|---|
|-	|0	 |0	 |0	 |0	 |0	 |0|
|パソコン (1kg)|0|100|100|100|100|100|
|水 (5kg)|0|100|100|100|100|100|
|本 (3kg)|0|100|100|100|140|140|


## 結果の解釈

このプログラムを実行すると、最大の価値は140となります。これは、パソコン (1kg, 価値100) と 本 (3kg, 価値40) をカバンに入れることで達成されます。

DPテーブルの各行での動作 
- dp[0][w] (初期状態):
まだ何も選んでいない状態で、全ての重さに対して価値は 0 です。

- dp[1][w] (アイテム: パソコン):
パソコンを選ぶか選ばないかを検討します。
w = 1kg 以上の重量では、パソコンを選ぶことができ、価値は 100 になります。

- dp[2][w] (アイテム: 水):
水を選ぶか選ばないかを検討します。
w = 5kg の場合、パソコンを選んだ場合の価値 100 と、水だけを選んだ場合の価値 50 を比較します。100 の方が大きいため、DPテーブルは更新されません。

- dp[3][w] (アイテム: 本):
本を選ぶか選ばないかを検討します。
w = 3kg 以上の場合、本を選ぶと、残りの容量にパソコンが入れられるので、パソコンと本を両方選んだ場合の価値は 100 + 40 = 140 になります。

最終的に、5kgの重さでは、同様に本とパソコンを選んだ場合が最適で、価値 140 が最大です。

## まとめ
このように、DP法を用いることで、各ステップでどのアイテムを選ぶべきかを効率的に判断し、カバンに入れる最適な組み合わせを見つけることができます。最終的に、パソコンと本を選ぶことで、価値の合計を最大の 140 にすることができました。

A,B,C問題を解くのであればDP法を使用することはないのですが、
学習したので記事にしました。
プログラミング言語の様々な分類

プログラミング言語の分類です。

プログラミング言語とは
機械語に翻訳しやすく、かつ人間にもわかりやすい中間の言語

自己学習用として忘れないためにもQiitaに残しています
# 目次
[1.手続き型言語](#1-手続き型言語)
[2.関数型言語](#2-関数型言語)
[3.論理型言語](#3-論理型言語)
[4.スクリプト型言語](#4-スクリプト型言語)


# 1.手続き型言語
処理手順を１行１行順を追って記述する言語
COBOL,FORTRAN,C,C++,Javaなどが従来のプログラム言語では該当する。

# 2. 関数型言語
関数の定義とその呼び出しでプログラムを記述する言語
数学的なものを指し、引数の値が定まれば結果も定まるという参照透過性を持つものである
再帰処理向き、[Lips](https://ja.wikipedia.org/wiki/LIPS)が代表例として挙げられる。
※参照透過性：同じ値を返す式を与えたら必ず同じ値を返すような性質

# 3. 論理型言語
術後論理を基礎とした論理式でプログラムを記述する言語
形式論理の論理式をソースコードの書式に投影することが基本とされ、人工知能の研究開発で使用される[Prolog](https://ja.wikipedia.org/wiki/Prolog)が代表例として挙げられる。

# 4. スクリプト型言語
機械語にコンパイルするのではなく、スクリプトのように記述して１行１行処理する簡易的な言語
シェルスクリプトやExelのマクロ言語などがある。

Webブラウザ上で動く言語としてJavascriptがある。
javaのスクリプト言語としてJSP(Java Server Pages)などもある。
そのほかにもRuby,PHP,Pythonなどもスクリプト言語として挙げられる。


### 参考文献
-[徹底攻略　応用情報技術者教科書　令和6年度](https://book.impress.co.jp/books/1123101067)
TypeScript初学者の振り返り

## はじめに
TypeScriptを勉強していく中で、印象的だったものを書き出していく。

## null
型宣言をしたプロパティに対してnullの代入を行うとエラーになる。
後述するユニオンをしようするとnullも許容することができる。
tsconfig.jsonのstrictNullChecksを無効にすると、すべての型にnullやundefinedが許可される。

```typescript:
let test1: string = "aaa";
test1 = null;

let test2: number = 1;
test2 = null;

let test3: null = null;

let test4: string | null = "bbb";
test4 = null;

```

## ユニオン型
関数の引数やオブジェクトのプロパティに対して型を指定する際、複数の型を指定することができる記法。

```typescript:
const test = (age: number | string) => console.log(`im ${age}  years old`);

test(20);    // im 20  years old
test("20");  // im 20  years old

test(false); // 型エラー
```

リテラルを指定することで、特定の値のみに制限することもできる。

```typescript:
const test = (value: "world" | "country" | 10) => console.log(`hello ${value}`);

test("world");   // hello world
test("country"); // hello country
test(10);        // hello 10

test("people");  // 型エラー
```

## オプショナルパラメータ
関数の引数やオブジェクトのプロパティに対して指定することができ、値を設定しなくても良いパラメータを作り出すことができる。
値の設定有無が自由なのはメリットに思える反面、外側から見るとプロパティの有無が担保されない側面もある。

未設定のオプショナルプロパティはundefinedになる。
```typescript:
const test = (value?: string) => `hello ${value}`;

console.log(test("world")); //hello world
console.log(test());        //hello undefined
```

```typescript:
interface Test {
  name: string;
  age?: number;
}

const test1: Test = { name: "TARO" };
const test2: Test = { name: "ZIRO", age: 20 };

console.log(test1); // { name: 'TARO' }
console.log(test2); // { name: 'ZIRO', age: 20 }
```

## コンストラクタ引数でのインスタンス変数宣言
通常、インスタンス変数を宣言する際はコンストラクタの外側に記述する必要がある。

```typescript:
class Test {
  public name: string;
  private age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

const test = new Test("Alice", 30);
```

コンストラクタ引数内でアクセス修飾子を付与することで、インスタンス変数の宣言と設定を省くことができる。
```typescript:
class Test {
  constructor(public name: string, private age: number, isMan: boolean) {}
}

const test = new Test("aaa", 20, true);
console.log(test.name);  // aaa
console.log(test.isMan); // インスタンス変数は存在しないのでエラー
```
forEachの使用例

# forEcachの使用例
forEachの使い方を備忘録として残しておく。
## 使用例 その1
### やりたいこと
配列に格納されている値に対して繰り返し処理したい

### 構文

配列.forEach( value, index, arry ){ 各配列の値ごとに行う処理 }
    // 第一引数　value: 配列の値が一つずつ渡される
    // 第二引数　index: 配列の添え字が一つずつ渡される
    // 第三引数　arry: 配列自体が渡される


### サンプルコード
```js
// 配列を作成    
const arry1 = ["りんご","メロン","オレンジ"];


// forEachを実行
arry1.forEach( function( value, index, arry ) {
    console.log( "大もとの配列は " + arry )
    console.log( "添え字が" + index + "番目の値は" + value )    
})

arry1.forEach( function( value ) {
    console.log( "好きな果物は" + value )    
})
```

#### 出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858406/acdb37fc-32a6-ce73-cf19-aa0ff300eccb.png)


## 使用例 その2
### やりたいこと
配列の各値に対して、関数を適用させたい

### 構文
配列.forEach( 関数 ) { 各配列の値ごとに行う処理 }

### サンプルコード
```js
// 配列を作成    
const arry1 = ["りんご","メロン","オレンジ"];

// 関数を定義
function sampleFunc( arg ){
    console.log( "好きな果物は" + arg ) 
}

// forEachの引数に関数を渡す
arry1.forEach( sampleFunc )
```

#### 出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858406/c7c2614b-f9d9-45cd-321b-e025bcd3f042.png)


## 使用例 その3
### やりたいこと
配列（値がオブジェクト）を繰り返し処理したい

### 構文
配列.forEach(配列) { 繰り返し処理 }

```js
// 配列を作成    
const arryProductData = [
    {id:1, pdname:"iPhone15", price:2000},
    {id:2, pdname:"iPhone14", price:1500},
    {id:3, pdname:"iPhone13", price:1000},
]


// forEachを実行
arryProductData.forEach( function( arry ) {
    console.log( 
        "製品 " + arry.id ,
        "製品名 " + arry.pdname ,
        "価格 " + arry.price
    )    
})
```

#### 出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858406/72bb46f8-b8a6-63b8-7d9b-b0c87c6c4ad8.png)




## 使用例 その4
### やりたいこと
* 配列の各値を編集する
* 編集した値を配列に追加する

### 構文
配列.push(配列に格納する値)

```js
// 配列を作成    
const arryProductData2 = [
    {id:1, pdname:"iPhone15", price:2000},
    {id:2, pdname:"iPhone14", price:1500},
    {id:3, pdname:"iPhone13", price:1000},
]


// 配列の値の個数を取得&#xff08;この場合は3&#xff09;
addId = arryProductData2.length


// forEachを実行
arryProductData2.forEach( function( arry ) {
    // 3をベースにして1ずつ加算する
    addId += 1
    // 編集した値を配列に追加する
    arryProductData2.push(
        // 配列の各値を編集する
        { 
            id: addId,
            pdname: arry.pdname + "半額;", 
            price: arry.price/2 
        }
    )
})

console.log(arryProductData2)
```

#### 出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858406/88e807cf-96b0-1fc3-3714-caf50ac22047.png)
Python仮想環境関連コマンド備忘

# はじめに
Pythonをたまにしか使用していないので、毎回忘れてしまうvenvやpython関係コマンドの備忘内容を記載します。実行環境はWSL2のUbuntu 22.04.2 LTSです。

# pyenv

## pyenvインストール
### githubからgit clone
```
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
```
### .bashrcに追記
```
export PYENV_ROOT="$HOME/.pyenv"
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
```
### シェルに反映
```
source ~/.bash_aliases
```

## pyenv使用方法

### 利用できるpythonバージョン確認
```
pyenv install -l
```

### バージョン指定でインストール
```
pyenv install 3.10.14
```

### バージョン指定でアンインストール
```
pyenv uninstall 3.10.14
```

### インストール済みのバージョン確認
```
pyenv versions
```

### バージョン切り替え

#### global指定
```
pyenv global 3.10.14
```

#### shell指定
```
pyenv shell 3.10.14
```

#### local指定
```
pyenv local 3.10.14
```



# 仮想環境(venv)

## 仮想環境作成
pyenvで作成したいpythonバージョンに切り替えて実行
```
python -m venv [仮想環境名]
```

## 仮想環境有効化
```
. [仮想環境名]/bin/activate
```

## 仮想環境無効化
```
(仮想環境名) deactivate
```

## pythonバージョン確認
```
(仮想環境名) python --version
```
WAVファイルをALAC(apple lossless) に変換する方法

## 環境
- Windowsを使っている
- iPhoneを使っている
- iTuensで音楽ファイルを管理している
- Apple Oneに含まれるApple Musicを使用している
 
## 問題
Windows版iTunesで、WAV形式のファイルをApple Lossless形式に変換できない

## 対応方法
### qaac64.exeのインストール
- [qaacの配布元](https://github.com/nu774/qaac/releases)から使いたいバージョンのファイルをダウンロードする
- iTunes64Setup.exeを[Apple公式](https://www.apple.com/jp/itunes/)からダウンロードする
- [qaacの配布元](https://github.com/nu774/makeportable)からスクリプトをダウンロードして、拡張子を*.cmdにして保存する
- iTunes64Setup.exeをcmdファイルに投げ込んで展開する
- 展開後、QTfiles64配下のdllをqaac64.exeと同階層に配置する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3522343/ef16597c-9fb3-2f33-4c7f-0656f8a8c3a8.png)
- qaac64.exeが存在するフォルダでDOS窓を開き`qaac64.exe --formats`を実行して、圧縮可能な形式が複数表示されればインストール成功
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3522343/8acc35ee-123b-9c7c-c595-fa003e27d8df.png)

### エンコード方法
- ショートカットを作成してリンク先の末尾に引数を設定![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3522343/bc0dce28-3333-2979-e45a-0ea0f93a0bcd.png)

:::note info
今回はALACにしたいので-Aを指定する
:::
- 作成したショートカットにWAVファイルを投げ込むとエンコードされる

## 補足
- 過去バージョンのiTunesだと、いったんライブラリに登録したWAVファイルをGUIからALACに変換可能だったが、Apple Musicアプリが分離した際にエンコード機能が削除された
- FLAC形式で販売・配布されているファイルについても、ALACに変換してからライブラリに追加すればApple Musicで聴ける
- 手間はかかるが対応策があることに感謝

## リンク
[qaacの開発・配布元](https://github.com/nu774/qaac/releases)
[インストール方法の説明](https://github.com/nu774/qaac/wiki/Installation)
[引数の説明](https://github.com/nu774/qaac/wiki/Command-Line-Options)
[iTuensの分割に関する記事](https://k-tai.watch.impress.co.jp/docs/news/1567542.html)
【学習記録_Vue.jsの前に】Windows GitHub cloneで早速つまずいた話

## はじめに
フロントエンドエンジニアのhara-showです。
 Webコーダーとして活動しています。

この度、Vue.jsを使用した
チーム開発プロジェクトに参加することになりました。

Vue.jsでの開発は初めてなので、
学習内容やプロジェクトでの気付きを、記録として投稿していきます。

## 早速つまずいた内容
開発環境構築のため、まずはリポジトリをクローンしようとしましたが、
エラーが発生してしまいました。

## 発生した問題

git clone コマンド実行時に
以下エラーが発生しました。

`remote: Repository not found.`

HTTPS, SSH 両方試しましたが、同じエラーが発生。

私の環境はWindowsですが、
チームのみなさんはMacだったためか、
やり方が異なるようでした。

## 解決手順
2回にわたって私の画面を共有しつつ
チームメンバーにサポートいただき、以下の手順で解決しました。


1.ローカルでssh key発行
2.Githubに公開鍵登録
3.接続確認
　`ssh -T git@github.com`
4.初期化
　`git init`
5.gitリモート登録
　`git remote add origin git@github.com:◯◯◯◯/◆◆◆◆.git`
6.clone ※1
　`git clone git@github.com:◯◯◯◯/◆◆◆◆.git`

 ※1 リモートに接続のたびにパスワードを求められる。
 　　このパスワードを忘れるとアウト汗
 

## 今後の課題
上記手順でクローンは完了したものの、
GitHubにリモート接続するたびパスワード入力を求められます。

Macユーザーであるチームメンバーはパスワード不要で接続できているようなので、この違いについては引き続き調査が必要です。

## 最後に
ここまでご覧いただきありがとうございました。

Windows環境でのGitHub操作やVue.js開発に関して、
同様の課題に直面している方々の参考になれば幸いです。
パッケージ管理「uv」を使ってみた

# パッケージ管理「uv」を使ってみた
Xで、最近何かと目にするパッケージ管理「uv」について、個人的な勉強がてらブログにまとめていきます。
※技術ブログを書くことに慣れていないので、お手柔らかにお願いします。

# 基本コマンド
各コマンドについてまとめます。
## インストール手順

### pipの場合
```pip install uv```
※今回私は、こちらの方法でインストールしました。

### curlの場合
```curl -LsSf https://astral.sh/uv/install.sh | sh```

## 仮想環境関連
### 仮想環境作成
```uv venv```
### 仮想環境起動
```source .venv/Scripts/activate```
### 仮想環境終了
```deactivate```
※この辺は仮想環境のコマンドと同じ

## 依存関係の管理
### requirements.txtの生成
```uv pip compile pyproject.toml > requirements.txt```

出力内容の例
``` bash
$ uv pip compile pyproject.toml
Resolved 4 packages in 7ms
# This file was autogenerated by uv via the following command:       
#    uv pip compile pyproject.toml
asgiref==3.8.1
    # via django
django==5.1
    # via my-project (pyproject.toml)
sqlparse==0.5.1
    # via django
tzdata==2024.1
    # via django
```

### requirements.txtを基にインストール
```uv pip sync requirements.txt```コマンドで依存関係を仮想環境にインストール

# 感想
今回は基本的なコマンドだけまとめました。
自分もこれまでしかまだ使えていないので...
とりあえずdjangoでアプリでも作ってみようかと思います！！！
これからもボチボチ記事を書いて個人的に整理していきたいと思います。
誤った情報がございましたら、ご指摘いただければと幸いです。
現在絶賛転職活動中なので、ご連絡はXのDMまでご連絡ください。
またシステムエンジニア志望の未経験の方々もお気軽にご連絡ください。
答えられる範囲でご回答したいと思います。
勉強を習慣化させるために行なったこと3選

# はじめに
現在、私は「100daysOfCode」という、100日間毎日コーディングを続けるチャレンジを行っています。毎日勉強する習慣をつけるために、このチャレンジを始めました。（執筆時点で60日以上、毎日勉強を続けています。）

しかし、そもそも習慣化できないという方に向けて、私が実践している3つの方法を紹介したいと思います。

↓100daysOfCodeについては、こちらの記事で紹介していますので、ぜひご覧ください。
https://qiita.com/masafumi1073/items/97ef3d12f96a4aef01e0

:::note warn
警告
今回こちらで紹介する内容は***全く習慣化することが出来ない方***に向けた最低限のことになります。効率などを考えればもっとよい方法などはたくさんあると思います。
:::

# 何をすればいいの？
私が勉強を習慣化するために行った具体的な方法は以下の3つです。
***<font color="Red">改めてですが、ここでは習慣化することを目標にしています</font>***。

+ ***勉強時間を決めない***
+ ***やることを決めない***
+ ***自分を褒める***

## 勉強時間を決めない
多くの人は習慣化しようとするとき、「1日2時間は勉強しよう」といったように勉強時間を決めがちです。では、もしその2時間ができなかったらどうなるでしょうか？モチベーションが高い初期のうちは続けられるかもしれませんが、やがてやらなくなります。

***習慣化するためには、あえて時間を決めないでください***。習慣化において、1日の勉強時間は重要ではありません。たとえ5分でも勉強したことになります。

実際のところ、以下のようなデータがあります。 日本人の多くは、仕事後に勉強していません。ですから、5分でも勉強している時点で、すでに多くの社会人よりも十分に勉強していることになります。

https://news.yahoo.co.jp/expert/articles/fa5e772fdf159d49fcccf348dc8a9a6a2125c3ae

## やることを決めない
基本的な考え方は、勉強時間と同じです。今日は具体的に何をやるかを決めることは良いことです。しかし、習慣化する上では必須ではないと考えます。多くの人が、決めたことをできずに挫折してしまうからです。

***決めたことができずにやめてしまうのであれば、最初から決めないでください***。その日、やりたいと思ったことをやってみてください。

## 自分を褒める
***続ける上で最も重要なのはモチベーションです***。ここでは、モチベーションを維持するために自分を褒めるという方法を紹介します。

『勉強時間を決めない』でも触れましたが、世の中の多くの人は仕事が終わった後に勉強などしていません。ですから、1日5分でも勉強しているあなたは、十分にすごいのです。なので、5分でも勉強したら自分を褒めてください。決して***5分しか勉強していない***などとは思わないでください。

自分を褒めることで、「少しでもやれば良いんだ」と思えるようになり、きっと習慣化が進むでしょう。

# 守って欲しいこと
習慣化する上で守って欲しいことがあります。

+ 連続してできなくても気にしない

## 連続してできなくても気にしない
例えば、「1週間続いたけど、1日休んでしまったからもうやめよう」ということがあるかもしれません。仮に1日休んでしまっても、続けてください。習慣化とは、どれだけ連続して行えるかではありません。ですから、休んでも必ず戻ってきてください。

最初は再開するのに気持ちが乗らないかもしれませんが、習慣化してしまえば、1日休んだくらいでは何とも思わなくなります。

# 最後に
今回は、私が毎日勉強する習慣をつけるために行った3つの方法を紹介しました。繰り返しになりますが、<font color="Red">***紹介した内容はあくまでも私の体験であり、最低限のことです***</font>。

おそらく、習慣化に関して調べると、全く逆の内容が出てくることもあるでしょう。しかし、それらがどちらが正しいというわけではなく、あくまでも私がうまくいった方法であることを最後にお伝えします。



# 参考
　『衝撃】日本の「ゼロ勉強社会人」は52.6％ なんと1日の勉強時間は平均13分だけ』

https://news.yahoo.co.jp/expert/articles/fa5e772fdf159d49fcccf348dc8a9a6a2125c3ae
jetpack compose navigationでViewModelから遷移データを取得する

# はじめに
こんかいはJetpack composeNavigationを使った遷移時にデータを渡すとき、ViewModel側で取得する方法を紹介していきます
### 本文
まず、遷移ロジックです
```kotlin
composable(
    "${HogeDestionation.Hoge.route}/{hoge}",]
    arguments = listOf(
        navArgument("hoge") { type = NavType.StringType },
    )
) {
    HogeScreen()
}

internal fun NavController.navigateToHoge(hoge: String) {
    navigate("${HogeDestination.Hoge.route}/$hoge")
}
```
次に受け取り側の処理です
ViewModel内に下記を記述します
```kotlin
val hoge = checkNotNull(savedStateHandle["hoge"])
```
こうすることでViewModel内でも遷移データを使うことができます
### さいごに
備忘録としての役割が強いですが、どなたかのお役に立てれば幸いです
TypeError: firebaseApp.firestore is not a functionのエラー対処

# はじめに
Firebase Authの初期化でエラーが出たので解決策を書いていきます。

# 問題
そもそもfirebaseの初期化周りでエラーが出て画面が真っ白になる。
```
TypeError: firebaseApp.firestore is not a function
```
以下のコードでエラーになる
```js
/*---firebase.js---*/
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';

const firebaseApp = firebase.initializeApp = ({
// 省略
});


const db = firebaseApp.firestore();
const auth = firebase.auth();

export { db, auth };
```

# 解決策
initializeAppの呼び出し方が間違っていたみたいです。以下のようにすると正常に初期化ができました。
```js
/*---firebase.js---*/
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';

const firebaseConfig = {
// 省略
};

const firebaseApp = firebase.initializeApp(firebaseConfig);

const db = firebaseApp.firestore();
const auth = firebase.auth();

export { db, auth };
```

# おわりに
Firebase Authを始めて使ったのですが、手軽に認証処理が実装できて便利ですね👀
【React✖️Typescript】デジタル名刺アプリを作って学んだこと

# はじめに
前回まではReactとその周辺技術を用いて学習記録アプリを作りました。今回は新しくデジタル名刺アプリというものを作ったので作りながら苦労した点や気づきなどを共有していきます。前回の記事です↓

https://qiita.com/bisketoriba/items/95d04d88e09dd478ebb2

# 作ったもの
名刺の登録、参照ができるアプリです。必須項目を入力しなかった場合はバリデーションのエラーメッセージが出るようになっています。


<div style="display: flex; justify-content: space-around;">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3279945/4d857559-c716-8e9b-50f3-378e12d783b9.gif" width="49%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3279945/e877b73c-d39c-92ff-63fd-b9927a32da00.gif" width="49%">
</div>



今回の反省点として名刺を登録した際に何もアクションなく最初のページに遷移してしまっており正常に登録できているかどうかわかりずらいので、登録ボタンを押下した際に何かしらのポップアップを表示させるなどした方が良いと思いました。


# 苦労したこと
今回は前回の学習記録アプリとほとんど同じ技術しか使っていないので機能実装自体は割とスムーズにできました。苦労した点があるとすれば学習記録アプリの時と違い、テーブルを3つ使う必要があった点です。初めはユーザーとスキルのデータをつなぐ中間テーブルの概念がよく分からず苦労しましたが、調べながら落ち着いて考えればそこまで難しいものではありませんでした。supabaseはRDBなので少しデータベース設計やSQLの知識があったらより使いこなせそうな気がします。

# 学べたこと
### 基本的なアプリ開発の流れを把握できた
ここまで学習記録アプリとデジタル名刺アプリを作りながら、基本的なアプリ開発の流れは共通していることを知ることができました。以下基本的な開発のステップになります。
```
1. VITEでReact(Typescript)の環境構築
2. Firebaseにデプロイ
3. Jestの環境構築
4. CICD構築
5. Supabaseの初期設定
6. 機能実装
7. テスト
8. 随時機能追加やリファクタリング 
```
今回は題材が決まっていたのですぐに開発に取り掛かれましたが、実際の個人開発では自分でアイディアを決めたり最低限何を機能実装するかなどを決めていく必要があるので、今後はそのあたりにもチャレンジしていきたいです。

# おわりに
学習記録アプリとデジタル名刺アプリの開発を通してかなり開発に慣れてきたので、次回からは自分で考えたアプリを開発していきます！また色々躓きそうですが頑張って乗り越えようと思います。ここまで見てくださりありがとうございました🤲

# JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？

気になる方はぜひHPからライン登録お願いします:point_down:

https://projisou.jp
AndroidStudioで特定の行を常に表示してスクロールできる設定

# やり方
・Android Studioの設定　→ Editor → **Sticky Lines**　まで移動し、一番上の『**Show Sticky lines while scrolling**』にチェックを入れます。

・『**Maximum number of lines:** 』で最大５行まで固定する行を指定できます。

・『**Languages:**』で固定したいコードで使用している言語を指定できます。


また、　
Android Studioの設定　→ Editor → Color Scheme　→ Generalまで移動し、
Sticky Lines → backGround　から　固定したい行の背景色を帰ることができるので、これを用いれば視認性が上がりそうです。



# 参考
https://pleiades.io/help/idea/sticky-lines.html

https://www.youtube.com/watch?v=EOzyI9joGzM
Flutter Test のカバレッジをマージする

# 課題
Flutter で Unit Test と Integration Test を作成し、カバレッジを計測できるようにしました。
しかし、それぞれの結果をマージする方法がわからず、全体としてテストのカバレッジを計測することができていませんでした。。。

# 前提
テストを行いカバレッジを計測できる環境であるとします。
- /test ディレクトリに Unit Test コードがあること
- /integration_test ディレクトリに Integration Test コードがあること
- 必要なパッケージが導入されていること（テストが実行できる状態）
- lcov がインストールされていること

# やりたいこと
- Unit Test をカバレッジ計測ありで実行する
- Integration Test をカバレッジ計測ありで実行する
- それぞれのカバレッジ結果をマージする
- マージされた結果を html に変換して表示する

# スクリプト

```sh
#!/bin/bash

# Coverage の出力先ディレクトリを作成
mkdir -p coverage

# build_runner を実行してテストファイル自動生成を行う
flutter pub run build_runner build --delete-conflicting-outputs

# ユニットテストを実行して、カバレッジを取得する
flutter test --coverage --coverage-path ./coverage/lcov_test.info

# 統合テストを実行して、カバレッジを取得する
flutter test --coverage --coverage-path ./coverage/lcov_integration_test.info integration_test

# ユニットテストと統合テストのカバレッジをマージ
lcov -a coverage/lcov_integration_test.info -a coverage/lcov_test.info -o coverage/lcov_merged.info

# 自動生成されたコードを対象から外す
lcov --remove coverage/lcov_merged.info 'lib/**.g.dart' -o coverage/lcov_result.info --ignore-errors unused

# 統合テストとユニットテストのカバレッジをマージしたものを HTML に変換
genhtml coverage/lcov_result.info --output=coverage/html

# 結果（HTML)をブラウザで開く
open coverage/html/index.html
```

# 最後に
今回は全てのテストを実施して結果をマージする方法を知ることができました。
しかし、テストが増えると毎回全てのテストを実施するのは辛いので、テストの単位を小さくできて全てをマージできるようにしたいですね。
AWSでの環境構築

こんにちは、jjj0331です。

今回は、AWSを利用した環境構築についてご紹介します。この記事では、VPCの作成から始め、EC2インスタンスのセットアップ、「Git」「Ruby（Rails）」「Next.js」「Nginx」のインストール方法をステップバイステップで解説します。

事前の準備として、AWSにログインできる状態にしておいてください。

## 1:VPCの作成
VPCとは、AWS内に自分専用の仮想ネットワークを作成できるサービスです。

AWSの検索バーで「VPC」と入力し、「VPCを作成」をクリックして作成画面に進みます。

「作成するリソース」では「VPCのみ」を選択し、VPCの名前を入力します。「IPv4 CIDR ブロック」は「手動入力」を選択し、CIDR範囲を10.0.0.0/24として指定します。「IPv6 CIDR ブロック」は「なし」を選択し、最後に「VPCを作成」をクリックしてVPCを作成します。

## 2:サブネットの作成
次に、VPC内にサブネットを作成します。「VPC」→「サブネット」→「サブネットの作成」を選択し、作成画面に進みます。

作成したVPCに対して、合計4つのサブネットを作成します。これらは、private-subnetとpublic-subnetを2つずつ作成します。

各サブネットには「サブネット名」と「アベイラビリティーゾーン」（例: ap-northeast-1a, ap-northeast-1c）を設定します。IPv4 CIDR ブロックは以下の範囲で設定します。

サブネット1: 10.0.0.0/26
サブネット2: 10.0.0.64/26
サブネット3: 10.0.0.128/26
サブネット4: 10.0.0.192/26
※サブネット1とサブネット2は「パブリックIPアドレスの自動割り当て」を有効にすることを忘れないでください。
※VPC内に4つのサブネットを構築したのは、後々構築するRDSやロードバランサーで使用します。

## 3:インターネットゲートウェイの作成
次に、インターネットゲートウェイ（IG）を作成します。「VPC」→「インターネットゲートウェイ」→「インターネットゲートウェイの作成」を選択します。

インターネットゲートウェイを作成したら、先ほど作成したVPCにアタッチします。これにより、VPCがインターネットと接続できるようになります。

## 4:ルーティングの設定
VPCに対してルーティングを設定します。「VPC」→「ルートテーブル」→「作成したVPC」→「ルートの編集」を選択し、「0.0.0.0/0」からの通信を「インターネットゲートウェイ（IG）」にルーティングする設定を追加します。

その後、「ルートテーブル」内の「サブネットの関連付け」メニューから、作成したサブネットのうち2つを選択して関連付けを行います。

## 5:セキュリティーグループの作成
次に、セキュリティグループを作成します。以下の設定を行います：

- SSH: TCPポート22、アクセス元を自分のPCのIPに限定
- HTTPS: TCPポート443、すべてのIPアドレスからのアクセスを許可（0.0.0.0/0）
- HTTP: TCPポート80、すべてのIPアドレスからのアクセスを許可（0.0.0.0/0）

## 6:EC2の作成
「EC2」→「インスタンスの起動」から、EC2インスタンスを作成します。

アプリケーションおよびOSイメージ (Amazon マシンイメージ)

[Amazon Linux 2023 AMI]
インスタンスタイプ

[t2.small]
ストレージの設定

[25GiB以上に設定してください]
ネットワーク設定でVPCを選択し、作成したセキュリティグループを適用してください。

※EC2の詳細な設定については、別途学習してください。

## 7:EC2にログインおよび初期設定

セキュリティーグループで「SSH:TCP(22)→自分のPCのIPからのみアクセス可能に設定」に設定しているので
SSHでログイン可能してください。


```システムの更新.
sudo yum update -y
```

```Gitをインストール.
sudo yum install git -y　
```

**次にRubyをインストールする準備を始めます。**

```Rubyをインストールするための必要なパッケージをインストールする.
sudo yum install -y gcc openssl-devel libyaml-devel libffi-devel readline-devel zlib-devel gdbm-devel ncurses-devel
```

```Node.jsとnpmをインストール.
sudo yum install -y nodejs
```

## 8:アプリの起動に向けて
```Next.jsの起動に向けて.
--Next.jsのルートディレクトリに移動して
npm init -y
npm install
```
```Next.js(ポート80で受け付ける).
sudo npm run dev -- -H 0.0.0.0 -p 80
```
```Railsの起動に向けて.
--Railsのルートディレクトリに移動して
bundle install
```
ちなみに、私のGitのアプリのRubyのVersionは「3.2.3」で
EC2にインストールしたVersionが「3.3.3」なので
```appで使用するRubyのVersionを変更.
--Railsのルートディレクトリに移動して
echo "3.3.3" > .ruby-version
```
を実行しました。

次にRDSで作成したデータベースに接続するようにRailsの設定を変更する手順を以下に示します。
※RDSの説明は省略します。


```config/database.yml ファイルを編集します。production 環境用の設定を、RDSの接続情報に書き換えます。.
production:
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: your_rds_username
  password: your_rds_password
  host: your_rds_endpoint
  database: your_database_name
  port: 3306

```

```必要なGemのインストール.
gem 'mysql2', '>= 0.4.4'
```

再度に
```
bundle install
```

## まとめ
今回はここまでにしておきます。

記事を作成時に私の頭の中で整理できていることを書きましたが、
Railsのシークレットキーの扱いや今回のアプリではAPIサービスと利用しており
そのAPIキーを設定する方法があるのですが、内容を文章にできるほど理解できておりませんので、
しばらくお待ちください。

以上で、AWSにEC2を構築しそのサーバーに「Git」「Next.js」「Rails」をインストールする方法を解説しました。
(「Rails」の起動はまだできませんが。。。)

次回は
- 各種のシークレットキーの設定方法
- HTTPS通信のためのロードバランサー
- Nginxnの設定方法など

を記事にしていきます。
性能効率性テストについて

## 書いたきっかけ
非機能テストについて、各項目の意図がはっきりしていなかったので学び直した。
特に自分の中で紛らわしかった性能効率性テストの観点をはっきりさせる。

## そもそも性能効率性とは
ISO/IEC 25010で定義された品質特性の1つである。
ソフトウェアがリソースをどの程度効率的に使用しているかを評価するもの。
以下の3点を要素として持つ。
	•	時間効率性: 応答時間やスループットなど、時間に関連する性能。
	•	資源効率性: CPU、メモリ、ディスクなどのリソースの使用量。
	•	容量満足性: 最大容量や処理可能な最大負荷。

## 性能効率性のテスト
性能効率性テストでは以下の4つのテストを実施する
- 性能テスト
    - 処理結果が設定の時間内に返ってくるかどうかをテストする
    - 時間効率性のテスト
- 負荷テスト
    - 同時多重実行などの負荷状態で、システムが正常に動作するかどうかをテストする
    - （排他時間を考慮した）時間効率性のテスト
- ストレステスト
    - メモリ、ディスクなどのリソースが限界に近づいた状態でシステムが正常に動くことをテストする
    - 資源効率性のテスト
- 容量テスト
    - データ容量の増加に伴って、システムの挙動がどう変化するかをテストする
    - 容量満足性のテスト

# 注意したいこと
テスト観点が異なるので単に性能効率性と言っても性能効率性の3つの要素、および４つのテストを網羅して行っていく。

## 参考
[システム構築の上流工程強化（非機能要求グレード）](https://www.ipa.go.jp/archive/digital/iot-en-ci/jyouryuu/hikinou/ent03-b.html)
[2時間で学ぶ！非機能テスト入門講座～性能やユーザビリティなどシステムの非機能を考える～](https://www.udemy.com/course/shift-nonfunctionaltest/?couponCode=SKILLS4SALEJP)
【備忘録】Sqlcmdのオプション

# 概要
sqlserverでサーバーやユーザー名、パスワードを指定して、任意の環境のDBを操作する際に使用していたコマンドというかステートメント。
## よく使うオプション
単体で使うことはほぼない。組み合わせて使う。
| オプション| 説明 |
|:-:|:-:|
|-U|ユーザーIDを指定|`Sqlcmd -U <user_id>`
|-P|パスワードを指定|   
|-d|データベースを指定|   
|-I|識別子を引用符で区切る|   
|-s|区切り文字を指定|   
|-W|余分な空白文字を削除|   
|-Q|“コマンドライン クエリ” と終了（goを省略できる）|   
|-o|アウトプットファイルを指定|   
|-i|インプットファイルを指定|   
|-S|インスタンス(サーバー名)を指定|

## 具体例
- サーバー名`Example_Server`にユーザー名`user_001`でログインし、目的のデータベース`sqldb-example001`にログインしてsqlを実行し、結果を`/data/app/output.dat`に出力したい。パスワード:`Password001`where句は適当。

```bash
sqlcmd -S Example_Server -U user_001 -P 'Password001' 
       -d sqldb-example001 -Q 'select top 5 * from Example_db where Example_id > 10' 
       -o /data/app/output.dat 
```
加えて出力するデータを`|`で区切るなどする場合は`-s \|`などする。

### 参考
https://learn.microsoft.com/ja-jp/sql/tools/sqlcmd/sqlcmd-utility?view=sql-server-ver16&tabs=go%2Cwindows&pivots=cs1-bash
docker postgresql のhealth checkの備忘録

### TL;DR

1. dockerのpostresql containerにhealthcheck blockを追加
1. test block内に　pg_isready commandを利用したhealth check コマンドを追加する
1. application container 側のdepends_on blockに　db:　condition: service_healthyを追加

## 0. 参考

[docker blog](https://www.docker.com/blog/how-to-use-the-postgres-docker-official-image/)
[postgre docker image](https://hub.docker.com/_/postgres)
[docker compose reference](https://docs.docker.com/reference/compose-file/services/#healthcheck)
[peter-evans/docker-compose-healthcheck #17](https://github.com/peter-evans/docker-compose-healthcheck/pull/17)

# 1. postgresql imageの準備をする

```terminal
tree ${PROJECT_PATH} -L 2
${PROJECT_PATH}
├── README.md
├── compose.yaml
├── database
│   └── dockerfile
```

```${PROJECT_PATH}/compose.yaml
services:
  database_container:
    container_name: database_container
    build:
      context: ./database
      dockerfile: dockerfile
    tty: true
    restart: always
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: example
      POSTGRES_USER: example

volumes:
  pgdata: {}
```


```${PROJECT_PATH}/database/dockerfile
FROM postgres:16
```

## 2. healthcheck blockを追加する

[docker blog](https://www.docker.com/blog/how-to-use-the-postgres-docker-official-image/)を参考に、health check blockの追加を実施。

```${PROJECT_PATH}/compose.yaml
services:
  database_container:
      container_name: database_container
      # ...
      # 追記
      healthcheck:
      test: ["CMD-SHELL", "pg_isready"]
      interval: 1s
      timeout: 5s
      retries: 10
```

```terminal
% docker compose up --build
database_container  | 2024-08-25 08:17:56.724 UTC [40] FATAL:  role "root" does not exist
```

role "root" does not existとなってしまい、まぁ起動しているから追加すれば良いのですが、毎回でるの辛いので、pg_isreadyから確認する。

## 3. health check blockを修正する

> -U username
--username=username
Connect to the database as the user username instead of the default.
[https://www.postgresql.org/docs/current/app-pg-isready.html](https://www.postgresql.org/docs/current/app-pg-isready.html)

> peter-evans/docker-compose-healthcheck issues 17
[peter-evans/docker-compose-healthcheck issues 17](https://github.com/peter-evans/docker-compose-healthcheck/issues/16)

上記から、container > healthcheck > testコマンドないでuserを設定して渡らせる。

```${PROJECT_PATH}/compose.yaml
services:
  database_container:
    container_name: database_container
    build:
      context: ./database
      dockerfile: dockerfile
    tty: true
    restart: always
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: example
      POSTGRES_USER: example
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
      interval: 1s
      timeout: 5s
      retries: 10
```

```terminal
docker compose up --build
database_container  | 2024-08-25 08:19:17.311 UTC [1] LOG:  database system is ready to accept connections
database_container  | 2024-08-25 08:24:17.340 UTC [27] LOG:  checkpoint starting: time
```
Excel LAMBDA関数で「ハノイの塔」を解く

[paiza×Qiita記事投稿キャンペーン「プログラミング問題をやってみて書いたコードを投稿しよう！」](https://qiita.com/official-events/9ab96aa95d62fe3cbdd7)に参加してみた。

問題は[ハノイの塔](https://paiza.jp/works/mondai/real_event/hanoi)

残念ながら、問題通りのアウトプットが作れませんでした。配列の状態を書き換えるのができないので、書き換えずに常に3本の杭の状態を返す関数を作ればよいのだと思うのですが、難しい。。。
=>何とか解くことができましたので、完成版はこちら。

https://qiita.com/madilloar/items/a8cc29307d8ae4493d81

使い方はこんな感じ。
円盤3枚を初期値として、4回まで動かすとしたら、``=HANOI(3,4)``とするイメージ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76786/15641901-7103-75ed-1c8c-3d7939bb2200.png)

# Excel LAMBDA関数版「ハノイの塔」のコード
```javascript:コード
HANOI = LAMBDA(_n, _t,
    LET(
        // Zコンビネータ。無名関数で再帰を実現するヘルパー関数
        Z, LAMBDA(_functionTemplate,
            LET(
                _applyFunction, LAMBDA(_recursiveFunction,
                    _functionTemplate(LAMBDA(_a1,_a2,_a3,_a4,_a5, _recursiveFunction(_recursiveFunction)(_a1,_a2,_a3,_a4,_a5)))
                ),
                _applyFunction(_applyFunction)
            )
        ),
        // ハノイの塔を解く関数。再帰呼び出しで実現
        _fncHanoi,Z(LAMBDA(_fnc, LAMBDA(_moves, _n, _from, _to, _work,
            IF(_n = 0,
                // voidをreturnできないので、空を表すレコードをスタックに積む
                VSTACK(_moves, HSTACK(_n, 0, 0)),
                LET(
                    _moveFromToOther, _fnc(_moves, _n-1,_from, _work, _to),
                    _pusedhMoveLog, VSTACK(_moveFromToOther, HSTACK("円盤:"&_n&"を", _from & "から", _to & "へ。")),
                    _return, _fnc(_pusedhMoveLog, _n-1, _work, _to, _from),
                    _return
                )
            )))),
        //　ハノイの塔を解く
        _solvedHanoi, _fncHanoi(VSTACK(0),_n,"杭A","杭C","杭B"),
        // 空のレコードを取り除く
        _removedEmptyDisc, LAMBDA(_table, FILTER(_table, INDEX(_table, 0, 1) <> 0))(_solvedHanoi),
        _toSeq, IF(ROWS(_removedEmptyDisc)<_t, SEQUENCE(ROWS(_removedEmptyDisc)), SEQUENCE(_t)),
        _return, MAP(_toSeq, LAMBDA(_i, TEXTJOIN("",TRUE, INDEX(_removedEmptyDisc,_i)))),
        _return
    )
);
```

# JavaScript版「ハノイの塔」のコード
こんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76786/018d2ff9-82bc-815b-6540-43efc7ad7d59.png)

```JavaScript:コード
const  hanoi=(n, t)=>{
    // 初期状態の杭
    let pegs = [
        Array.from({ length: n }, (_, i) => n - i),
        [],
        []
    ];

    // 移動の記録
    let moves = [];

    // ハノイの塔の再帰関数
    const _hanoi=(n, from, to, work)=>{
        if (n === 0) return;
        _hanoi(n - 1, from, work, to);
        moves.push([from, to]);
        _hanoi(n - 1, work, to, from);
    };

    // ハノイの塔を解く
    _hanoi(n, 0, 2, 1);

    // 指定された回数 t まで移動を実行
    for (let i = 0; i < t; i++) {
        let [from, to] = moves[i];
        pegs[to].push(pegs[from].pop());
    }

    // 各杭の状態を出力
    pegs.forEach(peg => {
        if (peg.length === 0) {
            console.log("-");
        } else {
            console.log(peg.join(" "));
        }
    });
};

```
jupyter notebookのinstall〜起動

# Jupyter Notebookのインストールと起動手順

## 1. Pythonのインストール
まず、Pythonをインストールします。公式サイトから最新のPythonをダウンロードし、インストールします。

- [Python公式サイト](https://www.python.org/downloads/)

インストール時に「Add Python to PATH」にチェックを入れることを忘れないでください。

## 2. pipの確認
Pythonには標準でpipが含まれています。ターミナルまたはコマンドプロンプトを開き、以下のコマンドを入力してpipが正しくインストールされているか確認します。

```bash
pip --version
```

## 3. Jupyter Notebookのインストール
pipを使用してJupyter Notebookをインストールします。ターミナルまたはコマンドプロンプトで以下のコマンドを実行します。

```bash
pip install notebook
```

## 4. Jupyter Notebookの起動
インストールが完了したら、Jupyter Notebookを起動します。ターミナルまたはコマンドプロンプトで以下のコマンドを実行します。

```bash
jupyter notebook
```

これにより、デフォルトのWebブラウザが開き、Jupyter Notebookのダッシュボードが表示されます。

## 5. ノートブックの作成
ダッシュボード上で「New」ボタンをクリックし、Python 3を選択して新しいノートブックを作成します。

## 6. ノートブックの使用
セルにコードを入力し、Shift + Enterで実行することができます。必要に応じてセルを追加したり、Markdown形式で文書を作成したりできます。

## 7. Jupyter Notebookの終了
作業が終わったら、Jupyter Notebookのターミナルまたはコマンドプロンプトで`Ctrl + C`を押して終了します。プロンプトが表示されたら、`y`を入力して停止します。

以上がJupyter Notebookのインストールと起動手順です。