OmniAICreator/Qiita-1.07M huggingface dataset:
【Dev Container】Dockerコンテナをあたかもホスト環境かのようにVSCodeを開く

VSCodeの拡張機能「Dev Container」を使うことで、Dockerコンテナにアタッチした状態でVSCodeを開くことができる。
つまり、あたかもホスト環境かのように作業することが可能。
当記事で使用方法を簡単に紹介。

# 事前準備
#### Dev Container拡張機能インストール
https://marketplace.visualstudio.com/items/?itemName=ms-vscode-remote.remote-containers

#### Docker環境用意(Docker-Compose使用)
次のような構成のDocker-Compose環境を用意しておく (ただのnode.js環境…)
```yaml:docker-compose.yml
version: "3.8"

services:
  app:
    build:
      context: ./app
      dockerfile: Dockerfile
    tty: true
    stdin_open: true
    volumes:
      - .:/workspace
      - app_store:/workspace/app/node_modules
    command: >
      sh -c 
        "tail -f /dev/null"

volumes:
  app_store:
```
```Dockerfile:app/Dockerfile
FROM node:20-alpine
WORKDIR "/workspace/app"
RUN apk update && apk upgrade
```
# 実際にやってみる
#### devcontainer.jsonの作成
コンテナにアタッチする作業用ディレクトリ(今回の場合だとapp/)に、.devcontainerディレクトリを作成。その中にdevcontainer.json(設定ファイル)を作成する
```json:app/.devcontainer/devcontainer.json
{
  "dockerComposeFile": "../../docker-compose.yml", //docker-compose.ymlの相対パス
  "service": "app", //docker-compose.ymlに指定したサービス名
  "workspaceFolder": "/workspace/app", //コンテナ内の作業ディレクトリ
  "shutdownAction": "none" //未指定だとVSCodeを閉じた際コンテナが停止してしまう。自分は、noneを指定して停止しないようにしている。
}
```
#### 実行してみる
1. Docker-Composeを立ち上げる
    ````
    $ docker-compose up
    ````
1. コンテナにアタッチする作業用ディレクトリに移動し、VSCodeを開く。そうすると、右下にポップアップが出てくるため「コンテナーで再度開く」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551098/83c6bd25-89b1-4b3e-8837-1824d86636b4.png)
1. すると、コンテナにアタッチした状態のVSCodeが開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551098/cdf2843d-4a02-4ea9-87e3-45c830b2ad57.png)
    - 当然、ターミナルはコンテナ内のものを開くことができる
    ![Screenshot from 2025-05-11 22-09-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551098/b22dc97a-8c90-4079-8a39-b69b59da218c.png)
    - また、拡張機能をコンテナ内にのみ設定することも可能 (ホスト側の拡張機能を汚さず済む)
        ````json:app/.devcontainer/devcontainer.json
        {
          ︙
          "customizations": {
            "vscode": {
              "extensions": ["Prisma.prisma"]
            }
          }
        }
        ````
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551098/bd4a7816-f48d-41b4-a988-dfef38d57a89.png)
# 参照
公式ドキュメント
https://code.visualstudio.com/docs/devcontainers/containers
特定のBPMのn分音符の長さを求める方法

# 前提
- BPM とは **B**eats **P**er  **M**inute の略で、1 分間にどれだけの単位音符が鳴るかでテンポを示す指標
    - ４分音符を基準とすることが多い。また、この記事では４分音符を基準とする

- 音符の分割数 $n$ について、この記事では次のとおり定義する
    - $n$ は整数で、範囲は $1 \leq n \leq 192$
    - 全音符は 「１分音符」と読み替え、$n$ 分音符はこれを $n$ 分割したものとする
    - $n$ 連符も同様に 「$n$分音符」と読み替える。 e.g. $16$ 分音符の３連符→ $24$ 分音符

# 計算方法
まず、変数を以下の通り定義する。
- $T$ ... **T**empo より。BPMの値を指す
- $n$ ... **n** 分音符より。 音符の分割数を指す
- $L_n$ ... **L**ength より。音符の長さを指す。下付き文字が定数 $a$ の場合、$a$ 分音符を指す

$4$ 分音符の長さは、BPM の定義より次のように表される。ここで、$4$ 分音符の長さ(秒)を $L_4$ と表すこととする。

$$L_4[s] = \frac{60}{T} $$

$2$ 分音符の場合は $L_2[s] = \frac{120}{T} $、全音符($1$ 分音符)の場合は $L_1[s] = \frac{240}{T} $ と表される。$64$ などといった大きな分割数でも扱いやすいように単位を $ms$ にし、以下のように一般化ができる。

$$L_n[ms] = \frac{240000 \div n}{T}$$

# C++ における実装例

```c++
#include <iostream>
usnig namespace std;

int main() {
    int t = 0, n = 0;
    
    cout << "Please input BPM -> ";
    do {
        cin >> t;
        if(t > 0) break;
        cout << "Please input BPM correctly! ->"
    } while(t <= 0);

    cout << "Please input the note division -> ";
    do {
        cin >> n;
        if(n > 0) break;
        cout << "Please input the note division correctly! ->"
    } while(n <= 0);

    cout << "Note length: " << (240000 / n) / t << endl;

    return 0;
}
```
Databricks AI/BIダッシュボードの予測の生成を使ってみた

## 前提
・利用環境：Databricks

https://www.databricks.com/jp/try-databricks?scid=7018Y000001Fi15QAC&utm_medium=paid+search&utm_source=google&utm_campaign=17377047998&utm_adgroup=138148229998&utm_content=trial&utm_offer=try-databricks&utm_ad=732035937815&utm_term=databricks%20%E3%83%88%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%AB&gad_source=1&gclid=CjwKCAiA8Lu9BhA8EiwAag16b8b3zbkIb3V7gp-8VUwKukXnhtVZRQ-1RY8SbETmGVgNT4bQramYmRoCX5wQAvD_BwE#account

## 参考ドキュメント

https://docs.databricks.com/aws/ja/dashboards/#ai-forecast

## 参考ブログ
https://qiita.com/taka_yayoi/items/fcfe1b24e768793e4a00

## 操作手順（動画）

<iframe width="100%" height="315" src="https://www.youtube.com/embed/lWvgXPQoby4?si=PGDIbxGUO_QkPMlm" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
【PostgreSQL】Windowsで5433ポートの別インスタンスを追加する手順（既存5432あり）

### はじめに
Windows環境で既に5432ポートでPostgreSQLが動作している場合に、別のインスタンスを5433ポートで追加・起動する方法をまとめます。
- OS：Windows 10/11
- PostgreSQL：バージョン共通（13〜16想定）
- 目的：既存インスタンスに影響を与えず、別ポートのPostgreSQLを動かす

### 🎯 ゴール
PostgreSQLを 5432と5433の2インスタンス 並行で動作させる

サービスとしてそれぞれ起動・停止ができるようにする

# 手順
### 1. 📁 新しいデータディレクトリを作成
任意の場所に新しいデータディレクトリを作成します。
例：
```plaintext
C:\PostgreSQL\data_5433
```

### 2. ⚙️ initdbで初期化
- 管理者権限でコマンドプロンプトを開きます。
- PostgreSQLの bin ディレクトリへ移動：
```cmd
cd "C:\Program Files\PostgreSQL\16\bin"
```
- 以下のコマンドで新しいデータディレクトリを初期化：

```c
initdb -D "C:\PostgreSQL\data_5433"
```
※ パスは環境に合わせて変更してください。

### 3. 🔧 ポート番号を5433に変更
`C:\PostgreSQL\data_5433\postgresql.conf` をテキストエディタで開きます。
```c
# 修正前
#port = 5432

# 修正後
port = 5433
```

### 4. 🛡️ pg_hba.conf の接続設定（必要に応じて）
`data_5433` 内の `pg_hba.conf` を開いて、必要なら接続ルールを追加します（ローカルからの接続など）。

### 5. 📦 サービス登録（5433ポート用）
以下のコマンドで新しいPostgreSQLサービスを登録します。
```cmd
pg_ctl register -N "PostgreSQL5433" -D "C:\PostgreSQL\data_5433" -S auto -o "-p 5433"
```
- `-N`：サービス名（自由に変更可）
- `-D`：新しいデータディレクトリ
- `-S auto`：自動起動
- `-o "-p 5433"`：ポート指定

### 6. ▶️ サービスを起動
サービスマネージャーまたはコマンドで起動できます。
```cmd
net start PostgreSQL5433
```

### 7. ✅ 動作確認
ターミナルまたはpgAdminから5433に接続して確認：
```cmd
psql -h localhost -p 5433 -U postgres
```

# 🎉 おわりに
この手順で、5432ポートとは別に5433ポートでPostgreSQLインスタンスを起動できます。
- テスト用の環境を分けたいとき
- マルチバージョン運用をしたいとき
- 同一マシン上で複数プロジェクトを分けて管理したいとき
に役立ちます！
Proxmox VEで仮想マシンを別マシンに移動した話(非クラスタ)

# この記事を読む対象者
- 二台のPromxmoxが互いにSSHできる環境を構築している人
- NAS/NFSなどの共有ストレージが存在しない構成の人
- じょうき2点の状況において仮想マシンを丸ごと移動したい人
※二台あればクラスタ構成＋共有ストレージ構成の方が多いと思いますが私は面倒で構築していなかったためこのような記事を書いています。

 # 構成図(概要)
 ![スクリーンショット 2025-05-11 012002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545289/2364351f-bcf4-4a60-bb3f-1cffe7442e16.png)

# 気を付けるべきこと
本手順で作成する仮想マシンのバックアップはProxmoxのOSが存在する領域に作成されます。デフォルトで構築している場合、この領域が小さい場合はバックアップNGになります十分な領域を確保してください。

## 手順1.仮想マシンのバックアップ
コマンド：
```
vzdump <<VM-ID>> --mode stop --compress zstd --storage <<バックアップ先ストレージ>>
```
コマンド例：VM-ID 511のマシンをlocalストレージにバックアップする
```
vzdump 511 --mode stop --compress zstd --storage local
```

## 手順2.SCPで当該ファイルを転送
コマンド：
```bash
scp /var/lib/vz/dump/<<転送されたファイル名>>.zst root@192.168.1.201:/var/lib/vz/dump/
```
コマンド例：作成したファイルをSCPで転送
```
scp /var/lib/vz/dump/vzdump-qemu-511-YYYY_MM_DD.tar.zst root@192.168.1.201:/var/lib/vz/dump/
```

## 3.転送先で仮想マシンを展開する
コマンド:
```
qmrestore /var/lib/vz/dump/<<転送されたファイル名>>.zst <<展開時のVM-ID>> -storage <<展開するストレージ名>>
```
コマンド例：展開時のVM-IDを600、展開するストレージをlocal-lvmとした場合
```bash
qmrestore /var/lib/vz/dump/vzdump-qemu-511-2025_05_10-18_43_24.vma.zst 511 -storage local-lvm
```

# 参考サイト
公式ドキュメント-qmrestoreコマンド
https://pve.proxmox.com/pve-docs/qmrestore.1.html
公式ドキュメント：Backup and Restore
https://pve.proxmox.com/pve-docs/chapter-vzdump.html
【OCI】Oracle Cloud Database Services 2024 Certified Professional の勉強法と問題集

## はじめに
Oracle Cloud Database Services certified professional（1Z0-1093-24） は、Oracle Cloud Infrastructure上で動作する各種のデータベースサービスに関する知識を問う資格です。
以下のようなスキルが求められます
　1.Exadata Database Service（Dedicated / Cloud@Customer）の構築・ライフサイクル管理
　2.Bare Metal / VM DB Systems の構築・ライフサイクル管理
　3.NoSql databaseの概要
　4.Database Managementサービスの有効化・管理
　5.MySQL HeatWave概要

**上記がオフィシャルの出題範囲ですが、本番試験ではCLIユーティリティの実務操作やOCIの基本構造(IAM、ネットワーキング、モニタリングなど）に関する内容も出題されています。**
## おすすめの勉強法
**1.Oracle University の公式ランニングパスを活用**

https://mylearn.oracle.com/ou/learning-path/japanese-become-an-oracle-cloud-database-services-professional-2024-/142600


Oracle公式のトレーニングパスでは、試験概要からチュートリアルまで全部整っています。
各トピックに短めの動画と、2～3問の小テストがセットになっていて、基礎を固めるのに最適です。また、英語動画ですが、字幕が使えます！

(**P.S.** 上記の公式パスは2024年版の日本語学習パスですが、パス中のコア・コースのリンク先は既に2025年版の動画に更新されました。出題範囲や各トピックの重みは変更されていないため、どちらのバージョンでも問題なく学習に活用できます。)

**2.試験対策問題集を活用**
公式の学習パスで提供されている小テストだけでは、本番試験の形式への慣れが足りなかったと感じる方には、対策模擬試験問題集をお勧めします。

下記のクーポンリンクを使えば、40%値下げで利用できます

https://www.udemy.com/course/oracle-cloud-database-service-professional-2024/?couponCode=3F4E8A5F9590DBE5A4BB

**この問題集は、以下のような方に最適です：**
　1.実際の試験に近い問題を解きながら対策したい
　2.選択肢ごとに丁寧な日本語解説を読みたい
　3.間違えた部分を繰り返し復習したい

 ## 最後に
Oracleの学習パスや対策問題集など、学習を進めやすい環境が整っています。
ご興味のある方は、この機会にぜひ挑戦してみてはいかがでしょうか。
LaTeXのtabular環境内で[ ]を使ったらエラーを吐かれた話

## tl;dr

- `tabular`環境内である行最初のセルが`[ ～ ]`から始まるとエラーを吐くことがある
- 対処法としては以下などがある
    - `\lbrack ～ \rbrack`を用いる[^1]
    - 直前の強制改行`\\`を`\\ \relax`に変更する[^2]
    - 数式環境にしてしまう（`$[ ～ ]$`）

## どういう状況だったか

```LaTeX
\documentclass{ltjsarticle}

\usepackage{unitsix}
\usepackage{mhchem}

% 中略

\begin{table}[h]
  \begin{tabular}{c|r}
    \hline 化合物・イオン&\thead{モル濃度} \\ \hline\hline
    [\ce{H2SO4}] & \qty{5.74}{mol.L^{-1}} \\
    [\ce{HSO4-}] & \qty{4.34}{mol.L^{-1}} \\ \hline
  \end{tabular}
\end{table}
```

というようにしてpdfを作成するコマンドを実行すると，以下のようなエラーメッセージが返ってきた．

```
(ファイルの保存場所)100: Missing number, treated as zero.
<to be read again>
\tex_let:D l.100     [\ce{HSO4-}] & \qty{4.34}{mol.L^{-1}}
```

このエラーは以下のように説明されている[^3]

> 数値あるいは寸法・グルーが必要な箇所に然るべき値が与えられなかった場合に現れるエラーメッセージ （のうちのひとつ）です．

［ボク］.◦゜（つまりどういうこと？？）

## 結局どういうエラーだったのか

- 行頭や行末の半角スペース，タブ文字，改行コードは無視される
- 強制改行の`\\`と`[ ～ ]`が起こした事件

それぞれ説明していこう

### 行頭や行末の半角スペース，タブ文字，改行コードは無視される

例えば，今回実行したファイルの`tabular`環境内のコードは，$\LaTeX$ファイルを作る際に以下のように認識される（はず）．

```
\begin{table}[h]\begin{tabular}{c|r}\hline 化合物・イオン&\thead{モル濃度} \\ \hline\hline[\ce{H2SO4}] & \qty{5.74}{mol.L^{-1}} \\[\ce{HSO4-}] & \qty{4.34}{mol.L^{-1}} \\ \hline\end{tabular}\end{table}
```

### 強制改行の`\\`と`[ ～ ]`が起こした事件

勘のいいひとは気づいたかもしれないが，先ほど示したものの中に`\\[\ce{HSO4-}]`という部分が含まれている．

実は，強制改行には`\\[10pt]`のような角かっこ(bracket)を使ったマクロが存在する[^4]．
ということは......

- `\\[\ce{HSO4-}]`が強制改行のマクロとして認識されてしまった
    - `\ce{HSO4-}`の部分が改行幅指定するべき数値として解釈された
        - これは数値ではないから，`Missing number, treated as zero.`とエラーを吐いた

というような順序をたどったものと推測する．

## それで解決法は？

冒頭に示した通り，簡単な解決法としては以下がある．

- `\lbrack ～ \rbrack`を用いる[^1]
- 直前の強制改行`\\`を`\\ \relax`に変更する[^2]
- 数式環境にしてしまう（`$[ ～ ]$`など）

このどれもが，半角スペース，タブ文字，改行コードを除いたときに`\\[ ～ ]`の並びを作らないための方法だ．

　

問題解決の参考になれば幸いです．

[^1]: http://www.yamamo10.jp/yamamoto/comp/latex/make_doc/table/table.php#TECH （2025年5月11日閲覧）
tabular環境内で角かっこの使用できない場合がある旨と，コマンドによる角かっこの呼び出しを書いている

[^2]: https://muscle-keisuke.hatenablog.com/entry/2016/07/13/004942 （2025年5月11日閲覧）
本質的にはこれと同じ問題だったのだなと執筆中に気づいた

[^3]: https://texwiki.texjp.org/?TeX%20%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8 （2025年5月11日閲覧）

[^4]: https://medemanabu.net/latex/line-and-page-breaking/ （2025年5月11日閲覧）
初心者でもできる、パフォーマンスを意識したコーディング

# 概要
コーディングに慣れていないと、つい書くことで精一杯になってしまうもの。
しかしながら、パフォーマンス（今回の場合はメモリの利用効率）を意識できると、
低燃費なサービス運用に貢献できます。

この記事では、JavaScript を学習している人向けに、リソース効率の良いコーディングを行うための方法を 1つ紹介します。

# 使わなくなった値は、再参照できないようにしよう
今回お伝えしたいことは、「使わなくなった値は、再参照できないようにしよう」ということです。

JavaScript は、ガベージコレクションという仕組みを持っています。
これは、参照がなくなったデータを自動でメモリから解放する機能です。

たとえば、以下のようなコードがあります。
```javascript:
let obj = { name: "Test" };
console.log(obj.name); // => Test
```
上記のログ出力後、もう変数 `obj` を使用しない場合、
以下のように処理を追記して、メモリを解放してあげるべきです。
```javascript:
let obj = { name: "Test" };
console.log(obj.name); // => Test

// もう使わないので参照を切る
obj = null;

// この時点で { name: "Test" } は参照されなくなり、ガベージコレクタの対象になる(メモリが解放される)
```
また、これを `null` ではなく、値を再代入しても、`Test` を保持していた分のメモリは解放されます。
```javascript:
let obj = { name: "Test" };
console.log(obj.name); // => Test

// 別の値を代入する
obj = { name: "Production" };

// この時点で { name: "Test" } は参照されなくなり、ガベージコレクタの対象になる(メモリが解放される)
```

## 特に、グローバル変数の扱いには気をつける
大抵の場合は変数を `let` で宣言するときは、値を再代入して使い回すでしょうから、あまり気にすることはないかもしれません。

ただし、グローバル変数の扱いには注意すべきです。
具体的には、グローバル変数は必要な数に絞って宣言した方がよいです。

たとえば、以下のようなコードがあります。
```javascript: Sample1
// objをグローバル変数として定義
let obj = { name: "Test" };

function test() {
  console.log(obj.name);
}

test();

// 関数のあともobjはまだ参照できる
console.log(obj.name); // "Test"
```
グローバル変数は、プログラムが終了するまで、`obj` に値を持ち続けます。
つまり、ずっと一定量のメモリを占領し続けることになります。

次に、以下のように、`obj` を関数内に宣言します。
```javascript: Sample2
function test() {
  let obj = { name: "Test" };
  console.log(obj.name);
}

test();
// ここで関数が終わったので、objの参照が消え、メモリも解放される(メモリが解放される)
```
すると今度は、関数が終了した時点で `obj`はガベージコレクションの対象になり、その分のメモリが解放されます。

Sample1 のように、グローバルに宣言した変数をいつでも使い続けられるのは便利です。
その一方、一度や二度しか使わないのにグローバル変数にしてしまうと、その分メモリを占領し続けることになり、リソース効率が悪くなります（他にメモリが必要な処理にたいして使える容量が少なくなる）。

<br>
<br>

---
今回は、分かりやすいグローバル変数に触れながら説明しました。
しかし、開発していると不必要にメモリを使ってしまっていることって他にもあると思います。
「あれ、これもう使わないんじゃね？」って思ったら、こまめに参照を切りながらコーディングできると、高コスパエンジニアへ一歩近づけそうですね。
Pythonで学ぶ統計入門2

復習用に確率論の一部を記載

## ▶️ 確率論ってなに？

確率論は、未来の「どうなるか分からないこと」を数字で整理する技術です。
ビジネスや機械学習でも、意思決定のベースになるスキルです！

---

## ▶️ Pythonで実践する確率論

### 1. 基本の確率計算

#### コイン投げの確率をシミュレーションしてみる

式：

$$
P(\text{heads}) = \frac{\text{表が出た回数}}{\text{総回数}}
$$

* \$P(\text{heads})\$：表が出る確率
* 表が出た回数を総回数で割るだけ！

```python
import random

# コインを1000回投げたときに表が出る割合を確認
results = [random.choice(['heads', 'tails']) for _ in range(1000)]
prob_heads = results.count('heads') / len(results)
print("表が出る推定確率:", prob_heads)
```

✅ **実践ポイント**: 理論上0.5だけど、実験では少しブレる！

---

### 2. 条件付き確率を使うシナリオ

式：

$$
P(A|B) = \frac{P(A \cap B)}{P(B)}
$$

* \$P(A|B)\$：Bが起きたときにAも起きる確率
* \$P(A \cap B)\$：AかつBが同時に起きる確率
* \$P(B)\$：Bが起きる確率

#### 例: 商品購入者のうち、メルマガ登録している人の割合

```python
# データ仮定
p_purchase_and_register = 0.1
p_register = 0.3

# 購入した人がメルマガ登録している確率
p_purchase_given_register = p_purchase_and_register / p_register
print("メルマガ登録者が購入する確率:", p_purchase_given_register)
```

✅ **実践ポイント**: 何か起きた「後」の確率を考えるときに使う！

---

### 3. 全体確率を使ったシナリオ

式：

$$
P(B) = \sum_{i} P(B|A_i) \times P(A_i)
$$

* \$P(B)\$：最終的にBが起きる確率
* \$P(A\_i)\$：それぞれのパターン（\$A\_i\$）が起きる確率
* \$P(B|A\_i)\$：パターン\$A\_i\$のもとでBが起きる確率

#### 例: 誰でもいいから陽性になる確率を計算する

```python
# 仮定：
p_disease = 0.01  # 病気である確率
p_healthy = 0.99  # 健康である確率
p_positive_given_disease = 0.99  # 病気の人が陽性になる確率
p_positive_given_healthy = 0.05  # 健康な人が陽性になる確率

# 全体確率の計算
p_positive = (p_positive_given_disease * p_disease) + (p_positive_given_healthy * p_healthy)
print("陽性になる全体確率:", p_positive)
```

✅ **実践ポイント**: 複数の原因があるときは、それぞれの寄与を合計する！

---

### 4. ベイズの定理を使った予測アップデート

式：

$$
P(A|B) = \frac{P(B|A) \times P(A)}{P(B)}
$$

* \$P(A|B)\$：Bが起きたときにAが真である確率（事後確率）
* \$P(B|A)\$：Aが真であるときにBが起きる確率（尤度）
* \$P(A)\$：Aが起きる確率（事前確率）
* \$P(B)\$：Bが起きる確率（正規化項）

#### 例: 病気検査の結果から本当に病気か推定する

```python
# 仮定：
p_disease = 0.01
p_positive_given_disease = 0.99
p_positive_given_healthy = 0.05
p_healthy = 1 - p_disease

# 陽性の全体確率（全体確率を使う）
p_positive = (p_positive_given_disease * p_disease) + (p_positive_given_healthy * p_healthy)

# ベイズの定理による事後確率
p_disease_given_positive = (p_positive_given_disease * p_disease) / p_positive
print("陽性反応の人が実際に病気である確率:", p_disease_given_positive)
```

✅ **実践ポイント**: 背景にある確率（全体確率）をちゃんと考慮するのが重要！

---
ピアリングを試してみる

## はじめに
Azure仮想ネットワークを複数作成することでネットワークを分離できますが、異なる仮想ネットワーク間での通信が必要な場合があります。
そこで仮想ネットワーク間のピアリングを設定することで、異なる仮想ネットワーク間での通信が可能となります。

この記事では実際にピアリングを設定し、仮想マシン間での通信ができることを確認してみます。

## やること
3つの仮想マシンを作成しプライベートIPでの通信が可能かどうか検証します。

仮想マシンA,B,Cを作成し、AとB, BとCでピアリング設定を行います。

ピアリングの特徴として推移することはありません。具体的にはAとCにはピアリング設定を作成しないため、AとC間では通信することはできません。この点も確認してみます。

## 構成
以下の構成で疎通を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1518953/70ebeba9-e77e-470e-bde4-c73e4489c91e.png)

## ピアリング設定前のネットワークを確認する
ピアリング設定する前にまずは各VM間で通信できていないことを確認しておきます。
VMのネットワークインターフェースの有効なルートを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1518953/01e0b5b1-4c56-49a4-8a73-79b50a62a63a.png)
上記はVM1のネットワークインターフェースとなります。インターネットと自身がおかれているVnet1（10.0.0.0/24）のみの経路が存在することがわかります。


実際にVM1で確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1518953/b0f11661-8b98-40fe-9f92-cf67f5d7d0f8.png)
この通りVM2（10.1.0.4）、VM3（10.2.0.4）へは通信できていないことが確認できました。


## ピアリングを設定する
ではピアリングを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1518953/b78283f5-9d00-4d2f-80b7-561c498fcf89.png)

仮想ネットワークのピアリングから設定を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1518953/ee6b7e94-ad02-45d4-909e-af64cc619b1b.png)
Vnet1とVnet2間のピアリングを追加しました。

VM1のネットワークインターフェースの有効なルートを確認すると10.1.0.0/24が追加されていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1518953/f8cd933d-24f7-4afd-88b7-cf1d174e6472.png)

同様にVnet2とVnet3間のピアリングも追加します。

## 最後に通信を確認してみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1518953/66d13b90-551e-4a98-81f5-3ae64f33941b.png)

VM1からVM2への通信は成功しますが、VM3は通信できないことが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1518953/d061f62e-9d87-4334-b135-4474aee07427.png)
VM2からはVM1とVM3のどちらも通信可能なことが確認できました。

## まとめ
Azureの仮想ネットワーク間でピアリングを設定し、異なるネットワークに属する仮想マシン同士がプライベートIPアドレスで通信できるかを検証しました。設定手順を詳しく紹介し、ピアリングが正しく構成されていれば、VNet間でシームレスな接続が可能であることを確認しました。
【Android】Proxy 環境下でビルドできるようにする

# はじめに
Proxy 環境下でビルドするために必要なことをまとめます。
内容自体は他の記事にもありますが、最近個人的に色々調べてたこともあり、成果のメモ書きな感じです。

# 先に書く結論

* Proxy 環境下の PC のアプリは別途 Proxy 設定を指定する必要がある
* Android は gradle.properties に Proxy 設定をする
* ライブラリーが外部のライブラリーのダウンロードしようとする場合、そのライブラリーの宣言に Proxy 設定をする必要がある
* terminal、cmd のため環境変数にも Proxy 設定を行う

# Proxy 環境
セキュリティ向上、匿名性などの理由に、社内のネットワークが Proxy 環境に置かれているケースがあります。
PC に Proxy 設定をしていれば、ブラウザアプリは自動的にその設定を読み込んでいるので普通にページに接近できたりしますが、 Android の開発環境は別途 Proxy 設定をする必要があります。

# gradle.properties の設定

gradle.properties はグローバルな設定、プロジェクト内の設定として 2つがあります。

* グローバル設定
    * rootディレクトリにある .gradle フォルダーの中
* プロジェクト内の設定
    * プロジェクトフォルダーの中の　.gradle フォルダーの中

設定したいスコープに合うフォルダーの中の gradle.properties に Proxy の設定を以下のように書き込めば設定は完了です。（あらかじめ、PC の Proxy 情報は把握しておきましょう）

アカウント認証周りは不要であれば書かなくて OK です。

```text
systemProp.http.proxyHost=hogeproxy.co.jp
systemProp.http.proxyPort=8080
systemProp.http.proxyUser=****
systemProp.http.proxyPassword=****
systemProp.https.proxyHost=hogeproxy.co.jp
systemProp.https.proxyPort=8080
systemProp.https.proxyUser=****
systemProp.https.proxyPassword=****
```

設定が完了されたら、 Gradle ビルドでライブラリなどがダウンロードされます。

# ライブラリの宣言に Proxy 設定が必要なケースがある

上記の設定をすれば大体は完了ですが、一部のライブラリはプロジェクトビルド時に従属の追加のライブラリをダウンロードします。
このケースは gradle.properties の設定では Proxy が通らずエラーになります。

例として [Robolectric](https://robolectric.org/) はビルド時に [android-all-instrumented](https://mvnrepository.com/artifact/org.robolectric/android-all-instrumented) のライブラリをダウンロードしますが、Proxy 環境下では Maven に接近できず失敗します。
自分がハマったところがこれだったのですが、Robolectric の公式ページを見ると Proxy の設定方法を案内していました。
https://robolectric.org/configuring/#system-properties

このように、ビルド時にどこで失敗しているかを確認し、該当するライブラリ側で設定を提供しているか確認しましょう。

# 自動化のため、コマンドの環境変数にも設定する

プロジェクト内の Proxy 設定が環境したらビルドはできる状態だと思います。
ただ、この PC を自動化のマシンとして使いとか、コマンドでの通信を行う場合は環境変数に Proxy 設定をする必要があるので設定しおくといいです。

# おわりに

最近自分がハマったところをメモ書きとして残しました。
もし内容に指摘がありましたらコメントお願いします。

# 参考リンク

https://qiita.com/hishida/items/9479fb64a016032c0938
Pythonで学ぶ統計入門1

統計学の復習用に記載
## ▶️ 記述統計ってなに？

記述統計は「データをぱっと見ただけで分かるように整理する技術」です。
データをまとめたり、戦略を立てる基盤になります！

---

## ▶️ Pythonでサクッと計算

### 【例題データ】

```python
import numpy as np
import pandas as pd

# サンプルデータ
data = [10, 20, 30, 40, 50]
```

### 1. 平均 (Mean)

```python
mean = np.mean(data)
print("平均:", mean)
```

* 全体のまとまり。
* 値が大きければ、全体的に高い値と言えます。

### 2. 中央値 (Median)

```python
median = np.median(data)
print("中央値:", median)
```

* 中間の値。
* 特に偏ったデータに対して、平均よりも実態を表しやすいです。

### 3. 最頻値 (Mode)

```python
mode = pd.Series(data).mode().values[0]
print("最頻値:", mode)
```

* 最もよく出る値。
* みんなが好きなものやよく選ばれる値のイメージ！

### 4. 分散 (Variance)

```python
variance = np.var(data, ddof=1)
print("分散:", variance)
```

* どれだけばらついているかの指標。
* 値が大きいと、データにばらつきが大きいと言えます。

### 5. 標準偏差 (Standard Deviation)

```python
std_dev = np.std(data, ddof=1)
print("標準偏差:", std_dev)
```

* 分散をもっと直感的にわかりやすくしたもの！
* 値が大きければ、平均に対して大きく変動していることがわかります。

### 6. 相関係数 (Correlation Coefficient)

```python
# 別のデータを作成
data2 = [15, 25, 35, 45, 55]
correlation = np.corrcoef(data, data2)[0, 1]
print("相関係数:", correlation)
```

* お互いの関連度。
* +1に近いほど、両者が同じ方向に変化する。-1だと逆方向に変化！

---
異世界MMORPGゲームを作りたい 

私私は異世界MMORPGをテーマにしたゲームを作りたいと思っており、プレイヤーと観客が異世界ジャンルに惹かれることを理解しているので、この理解を組み合わせることで 素晴らしいゲームであり、プレイ中にプレイヤーが退屈することは絶対にありません。
データベースの正規化について(第1正規化～第3正規化)

# 正規化について

---
## 第1正規化 (1NF)

> **ポイント**
- 繰り返しの属性を排除する
- テーブルは同じカラムを複数持てない
---

#### 🔹 第1正規化前のテーブル

| 学生ID | 氏名     | 電話番号       | 電話番号       |
|--------|----------|------------------|------------------|
| 1      | 佐藤太郎 | 090-1234-5678    | 080-1111-2222    |
| 2      | 鈴木花子 | 070-3333-4444    |              |


または

| 学生ID | 氏名     | 電話番号                          |
|--------|----------|-----------------------------------|
| 1      | 佐藤太郎 | 090-1234-5678<br>080-1111-2222    |
| 2      | 鈴木花子 | 070-3333-4444                     |

のようなテーブル

### 例1) 繰り返しの列を分割して行にする方法

#### 🔸 第1正規化後のテーブル

| 学生ID | 氏名     | 電話番号        |
|--------|----------|------------------|
| 1      | 佐藤太郎 | 090-1234-5678   |
| 1      | 佐藤太郎 | 080-1111-2222   |
| 2      | 鈴木花子 | 070-3333-4444   |

---

### 例2) 別のテーブルに分ける方法
---

#### 🔸 第1正規化後のテーブル

**学生テーブル**

| 学生ID | 氏名     |
|--------|----------|
| 1      | 佐藤太郎 |
| 2      | 鈴木花子 |

**電話番号テーブル**

| 電話番号ID | 学生ID | 電話番号        |
|------------|--------|------------------|
| 1          | 1      | 090-1234-5678   |
| 2          | 1      | 080-1111-2222   |
| 3          | 2      | 070-3333-4444   |

> 💡 学生IDを外部キーにする

---

## 第2正規化 (2NF)

> **ポイント**
- 部分的な主キーへの従属を無くす

---

### 例

#### 🔹 第2正規化前のテーブル

| 学生ID | 講座ID | 学生名   | 講座名           | 成績 |
|--------|--------|----------|------------------|------|
| 1      | A01    | 佐藤太郎 | 数学基礎         | 80   |
| 1      | B02    | 佐藤太郎 | 英語リーディング | 90   |
| 2      | A01    | 鈴木花子 | 数学基礎         | 85   |

- 主キーは **学生ID + 講座ID** の複合キー
- 「学生名」は学生IDにのみ依存、「講座名」は講座IDにのみ依存
- 👉 これは部分関数従属であり、第2正規化で排除する

---

#### 🔸 第2正規化後のテーブル

**学生テーブル**

| 学生ID | 学生名   |
|--------|----------|
| 1      | 佐藤太郎 |
| 2      | 鈴木花子 |

**講座テーブル**

| 講座ID | 講座名           |
|--------|------------------|
| A01    | 数学基礎         |
| B02    | 英語リーディング |

**成績テーブル**

| 学生ID | 講座ID | 成績 |
|--------|--------|------|
| 1      | A01    | 80   |
| 1      | B02    | 90   |
| 2      | A01    | 85   |

---

## 第3正規化 (3NF)

> **ポイント**
- 非キー → 非キーの従属を解消する（推移的関数従属の排除）

---

### 例

#### 🔹 第3正規化前のテーブル

| 社員ID | 社員名   | 部署ID | 部署名 |
|--------|----------|--------|--------|
| 1      | 佐藤太郎 | D01    | 営業部 |
| 2      | 鈴木花子 | D02    | 開発部 |
| 3      | 高橋一郎 | D01    | 営業部 |

- 主キーは社員ID
- 「部署名」は「部署ID」に依存（非キー → 非キーの従属）

---

#### 🔸 第3正規化後のテーブル

**社員テーブル**

| 社員ID | 社員名   | 部署ID |
|--------|----------|--------|
| 1      | 佐藤太郎 | D01    |
| 2      | 鈴木花子 | D02    |
| 3      | 高橋一郎 | D01    |

**部署テーブル**

| 部署ID | 部署名 |
|--------|--------|
| D01    | 営業部 |
| D02    | 開発部 |

---
【CLI】時間指定をして動画をGIFに変換する方法

動画をGIFに変換するには `ffmpeg` コマンドを使用します。

https://ffmpeg.org

## インストール

以下のコマンドを実行してインストールします。

```terminal
brew install ffmpeg
```

https://formulae.brew.sh/formula/ffmpeg

## 使用方法

以下のようにコマンドを実行するとMP4をGIFに変換できます。

```terminal
ffmpeg -i input.mp4 output.gif
```

### 開始時間・終了時間を指定する

開始時間や終了時間を指定するには `-ss` および `-t` を使用します。

```terminal
ffmpeg -ss 00:00:00.000 -i input.mp4 -t 00:00:15.000 output.gif
```

上記の場合、開始時間は 0 秒、終了時間は 15 秒となります。
【WPF】TextBoxの自動改行時の行数を取得する方法

***いいね、悪いね、コメントでの Ass fuckなどが励みになります***



WPFのテキストボックスが自動改行（"Wrap"）のとき、そのテキストの行数(LineCount)を取得できるのか実験してみました。

自動改行でも実際は.netのメソッドで簡単にできるっぽいですね

以前の.netじゃ不可だったとか？知らんけど

# Microsoft Learn
https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.controls.textbox?view=windowsdesktop-8.0

>指定された文字インデックスが含まれている行に対応する、0 から始まる行インデックスを返します。　

とある


https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.textbox.getlineindexfromcharacterindex?view=windowsdesktop-9.0

対応
| Product         | Versions          |
|-----------------|--------------------|
| .NET Framework  | 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1 |
| Windows Desktop | 3.0, 3.1, 5, 6, 7, 8, 9, 10   |


# XAML
```xml:外観
<Window x:Class="WpfTextBox_BrakeLineCounter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfTextBox_BrakeLineCounter"
        mc:Ignorable="d"
        Title="MainWindow" Height="160" Width="200">
    <Grid >
        <!--自動改行を設定-->
        <TextBox x:Name="MyTextBox" 
                 TextWrapping="Wrap"
                 AcceptsReturn="True"
                 Width="200" 
                 Height="100" 
                 TextChanged="MyTextBox_TextChanged"
                 />
        <TextBlock x:Name="LineCountTextBlock" 
                   Margin="0,0,0,0" 
                   Text="Line Count: 0"
                   VerticalAlignment="Top"/>        
    </Grid>
</Window>

```

# メソッド定義

```cs
  
        public static int GetWrappedLineCount(TextBox textBox)
        {
            if (!textBox.IsLoaded)
            {
                // TextBoxがまだ描画されていない場合、正しいLineCountが得られない
                return -1;
            }
            int lastCharIndex = textBox.Text.Length;

         
            ///文字列のインデックスを取得
            int lineIndex = textBox.GetLineIndexFromCharacterIndex(lastCharIndex);
            return lineIndex + 1; // 0-based indexなので+1
        }
```

```cs
 
        private void MyTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
          ///非同期実行にしておく  
           MyTextBox.Dispatcher.InvokeAsync(() =>
            {
                int lineCount = TextBoxHelper.GetWrappedLineCount(MyTextBox);

                LineCountTextBlock.Text = $"Line Count: {lineCount}";

            });

        }
```


# 実行（自動改行``"wrap"``でも実は関係ない）
布教活動も兼ねて

https://x.com/sheephuman/status/1921216921753842021


# あとがき
生成AIによると不可能みたいな事言ってたんだけど、FormatTextを生成するやり方だったんで。
***生成AIに頼りすぎると却って正解が遠のきます***。


Stack OverFlowも出鱈目が多くてそんなにあてにならない:sweat_smile:

↓笑えるほど役に立たなかった記事
```Detect the number of line breaks in TextBlock with wrap?```
https://stackoverflow.com/questions/15950210/detect-the-number-of-line-breaks-in-textblock-with-wrap


....ぶっちゃけ真面目に勉強しようかなと思うこともたまにあります。
Excel VBA ファイルを開く

### はじめに
ファイルを開きます。

### プロシジャーの説明
ByVal（値渡し）とByRef（参照渡し）を利用し、ファイルAとファイルBを開き各々の最終行を取得します。

### サンプル１ 
``` VB
Option Explicit
    Dim wbMy As Workbook
    Dim wbA As Workbook
    Dim wbB As Workbook
    Dim wsMy As Worksheet
    Dim wsA As Worksheet
    Dim wsB As Worksheet
    Dim wsAlastRow As Long
    Dim wsBlastRow As Long
    Dim fp1 As String
    Dim fp2 As String
    Dim fp1Sheetname As String
    Dim fp2Sheetname As String
    Dim fp1lastRetu As Byte
    Dim fp2lastRetu As Byte


Sub maindesu()
    '値渡し用。WorkbookOpenで渡すだけ
    fp1 = "C:\ALLlib\エクセルマクロ\練習0510A.xlsx"
    fp2 = "C:\ALLlib\エクセルマクロ\練習0510B.xlsx"
    fp1Sheetname = "データA"
    fp2Sheetname = "データB"
    fp1lastRetu = 2
    fp2lastRetu = 1
    
    '参照渡し用。WorkbookOpenで渡し結果値をもらう
    wsAlastRow = 0
    wsBlastRow = 0
    Set wsA = Nothing
    Set wsB = Nothing
    Set wbA = Nothing
    Set wbB = Nothing
    
    ' マクロが書かれているブック（このブック）を設定
    Set wbMy = ThisWorkbook
    
    Call WorkbookOpen(fp1, fp1Sheetname, fp1lastRetu, wsAlastRow, wbA, wsA)
    Call WorkbookOpen(fp2, fp2Sheetname, fp2lastRetu, wsBlastRow, wbB, wsB)
    
    ' A1セルの値を取得し、A2セルへペースト
    wsB.Range("A2").Value = wsA.Range("A1").Value
    ' ブックAをアクティブにする
    wbA.Activate
    ' シートAをアクティブにする
    wsA.Activate
    MsgBox wsAlastRow
    MsgBox wsBlastRow
End Sub


Function WorkbookOpen(ByVal filePas As String, ByVal sheeto As String, ByVal retu As Byte, _
                      ByRef RetwslastRow As Long, ByRef Retwb As Workbook, ByRef Retws As Worksheet)
'********************************************************************
'6ケの値は３ケがByValで３ケがByRef。ByRefは元のプロシジャーで使用
'　ByVal（値渡し）呼び出し元の変数には影響を与えない
'　ByRef（参照渡し）呼び出し元の変数が変更される
'********************************************************************

    ' ブックを設定（開いているブック名を指定）
    Set Retwb = Workbooks.Open(filePas) ' フルパスを指定
    
    ' シートを設定
    Set Retws = Retwb.Sheets(sheeto) ' シートAの名前を指定

    'wsの?列の最終行を取得
    RetwslastRow = Retws.Cells(Retws.Rows.Count, retu).End(xlUp).Row

End Function


``` 

### おわり
ByVal（値渡し）とByRef（参照渡し）を利用するとスッキリしたソースが書けます
Databricksチュートリアル(Day5): Apache Sparkを使用してETLパイプラインを構築してみた

## 前提
・利用環境：Databricks

https://www.databricks.com/jp/try-databricks?scid=7018Y000001Fi15QAC&utm_medium=paid+search&utm_source=google&utm_campaign=17377047998&utm_adgroup=138148229998&utm_content=trial&utm_offer=try-databricks&utm_ad=732035937815&utm_term=databricks%20%E3%83%88%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%AB&gad_source=1&gclid=CjwKCAiA8Lu9BhA8EiwAag16b8b3zbkIb3V7gp-8VUwKukXnhtVZRQ-1RY8SbETmGVgNT4bQramYmRoCX5wQAvD_BwE#account

## 参考ドキュメント

https://docs.databricks.com/gcp/ja/getting-started/etl-quick-start

## 操作手順（動画）
<iframe width="100%" height="315" src="https://www.youtube.com/embed/pr0YE8ExnR4?si=7WvXzBos7Eaf9pbG" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
fmlでGmailの「ループ防止」機能（自己宛て抑制）を回避する方法

/home/(USER_NAME)/fml/spool/ml/(ML_NAME)/
にあるconfig.phに以下の記述を追加。


```
# YOU CAN EDIT MANUALLY AFTER HERE.

$USE_ORIGINAL_MESSAGE_ID = 0;

$SKIP_FIELDS = "Received|Return-Receipt-To|DKIM-Signature|X-Google-DKIM-Signature|X-Gm-Message-State
|X-Google-Smtp-Source|X-Received";

$SMTP_OPEN_HOOK = q#
     $Envelope{'fh:reply-to:'} = $MAIL_LIST;
     $header_from = $Envelope{"h:From:"};
     $header_from =~ s/\/\)/g;
     $header_from =~ s/\"//g;
     $header_from =~ s/^\s+//;
     $header_from =~ s/\s+$//;
     $Envelope{'fh:from:'} = "\"" . $header_from . "\"<" . $MAIL_LIST . ">";
#;

@DenyProcedure =
```

その後、

```
perl -c config.ph
```
を実行して
```
config.ph syntax OK
```
となればOK。
ABC405をPythonで（A～E）

AtCoder Beginner Contest 405（Promotion of AtCoder Career Design DAY）の解答等の速報的まとめ

https://atcoder.jp/contests/abc405



# A問題
https://atcoder.jp/contests/abc405/tasks/abc405_a

問題文のまま
```python:A
r, x = map(int, input().split())
print("Yes" if (x == 1 and 1600 <= r < 3000) or (x == 2 and 1200 <= r < 2400) else "No")
```

# B問題
https://atcoder.jp/contests/abc405/tasks/abc405_b

先頭から見て最初に全部揃う個所まで消すのが答え。揃う個所がないときは0が答え
```python:B
n, m = map(int, input().split())
a = list(map(int, input().split()))

s = set()
target = {i for i in range(1, m + 1)}
border = n
for i, a_i in enumerate(a):
    s.add(a_i)
    if s == target:
        border = i
        break

print(n - border)
```

# C問題
https://atcoder.jp/contests/abc405/tasks/abc405_c

問題文の式を変形すると
$a_1 \times (a_2 + a_3 + ...+ a_n) + a_2\times(a_3+a_4+...+a_n)+...$
となるので、後ろから計算していく
```python:C
n = int(input())
a = list(map(int, input().split()))

ans = 0
sums = 0
for a_i in a[::-1]:
    ans += a_i * sums
    sums += a_i

print(ans)
```

# D問題
https://atcoder.jp/contests/abc405/tasks/abc405_d

すべての非常口から始まるダイクストラの要領で来た方向に矢印を書いていく
```python:D
from collections import deque

h, w = map(int, input().split())
a = [input() for _ in range(h)]

ans = [[""] * w for _ in range(h)]
q = deque()
for i in range(h):
    for j in range(w):
        if a[i][j] != ".":
            ans[i][j] = a[i][j]
        if a[i][j] == "E":
            q.append([i, j])

arrays = [[1, 0, "^"], [-1, 0, "v"], [0, 1, "<"], [0, -1, ">"]]
while q:
    x, y = q.popleft()
    for a_i, a_j, arrow in arrays:
        x_i, y_i = x + a_i, y + a_j
        if 0 <= x_i < h and 0 <= y_i < w and ans[x_i][y_i] == "":
            ans[x_i][y_i] = arrow
            q.append([x_i, y_i])

for ans_i in ans:
    print(*ans_i, sep="")
```

# E問題
https://atcoder.jp/contests/abc405/tasks/abc405_e

まず$a$の左端を固定して調べていく。その$a$の左端までには$b$しか混ざらないので組み合わせは$a$の左端-1までに$a$を置くパターン数になる

残りのスペースには$b,c,d$を置くが、$b$と$d$は混ざらないため$c$の場所を確定させたら1通りに定まる

```python:E
class combination:
    # nが小さく(10**7未満)ないと厳しい
    def __init__(self, N, mod):
        self.fact = [1, 1]
        self.factinv = [1, 1]
        self.inv = [0, 1]

        for i in range(2, N + 1):
            self.fact.append((self.fact[-1] * i) % mod)
            self.inv.append((-self.inv[mod % i] * (mod // i)) % mod)
            self.factinv.append((self.factinv[-1] * self.inv[-1]) % mod)

    def cmb(self, n, r):
        if (r < 0) or (n < r):
            return 0
        r = min(r, n - r)
        return self.fact[n] * self.factinv[r] * self.factinv[n - r] % mod

a, b, c, d = map(int, input().split())
n = a + b + c + d
mod = 998244353

C = combination(a + b + c + d, mod)

ans = 0
for i in range(a, a + b + 1):
    # aの一番右がiにある
    c_i = C.cmb(i - 1, a - 1)
    # cの場所が決まれば、bとdの置き方は１通りに固定
    ans += c_i * C.cmb(n - i, c) % mod
    ans %= mod

print(ans)
```
openFrameworksのアドオンを開発してみた

# はじめに
この記事はopenFrameworksのアドオン開発で躓いたことを中心に開発を説明していきます。
自分の使っているバージョンのせいかそもそもopenFrameworksがVisual Studio 2019でした。


# 目標
独自のアドオンを作り、ビルドが通ること。

# 前提環境
Visual Studio 2022
openFrameworks 0.12.0

# openFrameworksをDLする
次のリンクからzipファイルをDLしてください。
https://openframeworks.cc/ja/download/

Visual Studioを使って開発をするので、以下の「Visual Studio」をクリックしてDLすれば大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561872/0056c36e-7085-4e83-a98c-b2c88993d4ef.png)


# プロジェクトを作る
まずはprojectGeneratorでVisual Studioプロジェクトを作ります。

以下にあるファイルを実行します。
```
<root>/projectGenerator/projectGenerator.exe
```
※<root>はopenFrameworksのルートフォルダです。INSTALL.mdファイルがあるフォルダです。

次のようなウィンドウが表示されます。Addonsはひとまず空のままでGenerateを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561872/21e538d2-7862-431c-ae54-17a68ff96e1b.png)

注意：
もう一度このソフトを使う機会があるためウィンドウは閉じないことを推奨します。
閉じてしまった場合には上記のGenerateの際に指定したパラメータを再度入力すれば問題ないです。

# 自作のaddonを作ってみる
以下のフォルダにアドオン名でフォルダを作ります。
一般的に「ofx」を先頭につけるルールがあります。

```
<root>/addons/
```

今回はofxBaseという名前にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561872/50350ab2-3d9a-4cdd-9565-c673134d59bf.png)

# アドオンの設定ファイルをつくる
以下のファイルを作ります。
```
<addon_root>/addon_config.mk
```
※<addon_root>は上記で作ったアドオンフォルダです。

次のように記載します。「ADDON_NAME」にはフォルダ名を指定します。
別の名前を付けられますが、混乱を避けるためにも同じにすることを推奨します。
```yml
meta:
	ADDON_NAME = ofxBase
common:
    # ADDON_DEPENDENCIES = ○○
```

「ADDON_DEPENDENCIES」は他のアドオンを指定することでそのアドオンの機能を使えるようになります。

# ソースコードを配置する
openFrameworksでは一般的にsrcフォルダにコードを置く習慣があります。
またサードパーティのコードやライブラリはlibsフォルダに置くのが一般的なようです。

今回はサンプルコードを以下のように配置しました。
```
<addon_root>/src/sample.h
```

# プロジェクトにアドオンを追加する
以下のようにAddonsに今回作ったアドオンを指定します。
設定がうまくいっていれば予測変換に出てくるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561872/d6fbd665-0823-4310-8489-4f5d6a7b659c.png)

Updateボタンを押して再生成します。

# Visual Studioのプロジェクト設定を修正する
このままだとVisual Studio 2019向けの設定になっており、ビルド時にパスの問題などでエラーが出る場合があります。

おそらく更新したプロジェクトを開くと（Visual Studio 2019）がプロジェクト名についていると思います。
（開発中のプロジェクトなためプロジェクト名が違います）

このままプロジェクトをビルドすると次のようなエラーが出ます。

```
2>C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Msbuild\Microsoft\VC\v160\Microsoft.CppBuild.targets(992,5): error MSB3191: ディレクトリ "E:\NodeEditor\obj\x64\Debug\Build\E:\of_v0.12.0_vs_release\addons\ofxGui\src\Debug" を作成できません。指定されたパスのフォーマットはサポートされていません。
```

そこでプロジェクトをVisual Studio 2022ように設定を修正します。
画像のように「構成プロパティ」→「全般」にある「プラットフォームツールセット」を「Visual Studio 2022 (v143)」に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3561872/a212a32f-787c-4492-aad1-aeb2a70f089a.png)

これでビルドが成功するはずです。

以降の開発は先ほど作ったソースコードのフォルダにファイルを追加していけば問題ありません。

**注意**：
ファイルを追加・削除した場合、必ずprojectGeneratorでプロジェクトを再生成してください！

# 最後に
かなり簡略化した説明でしたが参考になれば幸いです。
プログラム動作の掲載に便利　動画をgifへ変換出来るサイト(備忘録)

## サイト
https://ezgif.com/video-to-gif

## 注意点
10MB以上だとQIITAの制限で貼れないため、
sizeを調節して容量を調整する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/12a68937-c32b-418e-92f0-8412510d791c.png)

## 効果
![ezgif-44e0763867eb84.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/ec745f52-a3d2-488b-aff7-827df907e637.gif)
Lambda Web Adaptorを使ってLaravelをサーバーレスで動かす

AWSでLaravelのようなWEBフレームワークを使ってアプリをホストする場合、ECSやApp Ruunerを使うことが多いと思うが、これらはアクセスしていない時でもある程度のコストがかかる。
たまにしか使われない社内ツールやPoCの初期段階などではそのコストを避けたいこともあるため、Lambdaでホストすればアクセス時のみのコストで済むし、大半は無料枠に収まる。

LaravelをLambdaで動かす方法を調べるとBref + Serverless Frameworkがよくヒットするが、Serverless Frameworkが有償化されたりしているのでちょっとな・・・ってなっていたところ、AWS公式が出しているLambda Web Adaptorがあったので、これを使ってみる。

# Lambda Web Adaptor

https://aws.amazon.com/jp/builders-flash/202301/lambda-web-adapter/

詳細は上記を参考にするが、どうやらLambda内でリクエストをWEBフレームワーク用に変換して渡すことで、WEBフレームワーク側に大きな変更を加えずに、そのまま使えるようになるらしい。

# 使ってみた
使い方は簡単でDockerFileに一行足すだけ。こうすることで、Lambda内でイベントを変換してよしなにやってくれるみたい。

```Dockerfile
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter 
```

注意点としては、Lambdaは単一コンテナで動作するため、ベースイメージにはphp-apacheなど単一コンテナで動作するものを選ぶ必要がある。今回は動作確認だけしたいのでphpのビルトインサーバーを使った。
また、Lambdaは書き込み領域が/tmp配下のみなので、書き込みが必要な場合は別途考慮が必要。

Dockerイメージを作成後、ECRにプッシュして、Lambdaにデプロイする。Lambdaにデプロイ後の動作確認は、簡単のため関数URLを有効化してアクセスする。
URLにアクセスすると、Laravelのウェルカムページが表示され動いていることが分かる。

![スクリーンショット 2025-05-10 22.27.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469482/7fdd63a1-eafb-418c-8439-365859915274.png)


詳細な手順などは以下のリポジトリのREADMEに記載したので試してみたい方は参照してみてください。

https://github.com/KaiFujiwara/lambda_web_adaptor_sample_laravel

実際に動かすならセッション管理やDB接続の設定も必要だし、Lambdaのスペックの設定なども必要になると思います。

# 終わり
AWSでごく小規模なコンテナアプリをホストしようとするとどうしても起動しない時間分の金額面が気になるので選択肢としてはかなりアリだと思った。
（GCPのCloud Runだったらわざわざこういうことをしなくても起動しない時間分は0円らしいので、GCPが使えるならそっちでもいいかも。単純な比較はできないけど。）

ただちゃんとしたアプリを動かすなら色々気になる部分はあると思うので、あくまで顧客に直接公開する用途以外で使うものな気はする（Lambda Web AdaptorがというよりはLambdaで動かすというアプローチ自体が）。
AtCoderをPythonで取り組んだ振り返り(ABC405 A~C,Dも追加)

どうもこんにちは！

今週のコンテストはA～Cを完答。Cの完答はひさびさ。

# 問題

問題は以下のリンクから。完答できたCまでを振り返ります。

https://atcoder.jp/contests/abc405/tasks

https://atcoder.jp/contests/abc405/editorial

## A - Is it rated? -
レーティングとDivの値が与えられるので、ABCのRated対象かを判定する問題。Divが1ならレーティングが1600以上2399以下のとき、2なら1200以上2399以下のときにそれぞれRated対象となります。
シンプルに、与えられたレーティングとDivの値を比較しました。
~~~Python
r,x = map(int,input().split())
if (1600 <= r < 3000 and x == 1) or (1200 <= r < 2400 and x == 2):
  print("Yes")
else:
  print("No")
~~~

## B - Not All -
与えられる整数列Aと正整数Mが与えられ、Aの末尾を0回以上削除していきます。Aの中に1以上M以下の整数のうち含まれない整数が出てくるには何回削除が必要かを出力する問題。例えばAが1 2 3 2でMが3だったとき、Aの末尾の削除が1回だとまだ1,2,3すべて含まれますが、2回削除したら3がAから無くなるので答えは2回となります。なお、Aに含まれる整数は1からMまでで、M+1以上の値が含まれることはないです。また、最初から1以上M以下の整数のいずれかがAに含まれていない場合もあります。
さて、Aの中に1以上M以下の整数がすべて含まれている場合、Aの集合はM個です。なので、Aの末尾から1個ずつ削除して、Aの集合の数がM-1個となるときの削除回数が答えとなります。
~~~Python
n,m = map(int,input().split())
s = [int(x) for x in input().split()]

ans = 0
while len(set(s)) == m:
    s.pop()
    ans += 1

print(ans)
~~~

## C -Sum of Product -
与えられた長さNの整数列Aの$\\sum_{1<=i<j<=N} A_i × A_j$の値を出力するという問題。例えばAが1 2 3 だとすると、1×2+1×3+2×3で答えは11となります。数列の最大項数は$3 × 10^5$個で、計算量を考えないといけないC問題の定番ですね。
計算量を考えなければ2重ループで足しこんでいけばよいですが、おそらくTLEになります。計算を整理すると$A_1 × (A_2+A_3+…+A_n)+ A_2×(A_3+A_4+…+A_n)+…+A_{n-1}×A_n$となるので、累積和を使って、例えば$A_1×(A_1+A_2+A_3+…+A_n-A_1)$という感じで計算して足し合わせればよいとなります。
~~~Python
n = int(input())
s = [int(x) for x in input().split()]

# 累積和の配列を作る
psum = [0]
for i in range(len(s)):
    tmp = psum[i] + s[i]
    psum.append(tmp)

# 累積和を使って求める値を計算する
# 累積和の配列の末尾が数列すべての合計、そこからAiまでの合計を引いてAiを掛け算
ans = 0
for i in range(len(s)-1):
    ans += s[i] * (psum[len(psum)-1]-psum[i+1])
print(ans)
~~~


--以下 2025/5/11追加--
## D -Escape Route -
H×Wマスのグリッドがあり、各マスに通路・壁・非常口のいずれかが設定されています。各通路マスから最短距離で非常口に向かう方向をマスに上書きするという問題。通路がある場合は必ず非常口にいけるとされています。(なお、すべてのマスが壁の場合や非常口が複数個ということもある)
あるマスから非常口までの最短距離は幅優先探索で求められるとまでは考えたんですが、そのときの方向指定の方法が考えつかず断念していました。解説によると、非常口のマスを起点として幅優先探索をして、そのマスに来る直前にいたマスの方向を通路マスに上書きすればよいとのこと。
解説はC++で書いていたので、勉強がてらPythonにしたのが以下です。このとき、キューを配列で実装したらTLEとなり、dequeでの実装が必要でした。調べてみると、リストの先頭のpopの計算量はO(N)、dequeで実装するとO(1)ですむとのこと。
~~~Python
from collections import deque

h,w = map(int,input().split())
s= []
for _ in range(h):
    s.append(list(input()))

dx = [1,0,-1,0]
dy = [0,1,0,-1]
a = '^<v>'
q = deque()

# 非常口の特定
for i in range(h):
    for j in range(w):
        if s[i][j] == 'E':
            q.append([i,j])

# 非常口からの幅優先探索
while len(q) > 0:
    i,j = q.popleft()
    for k in range(0,4):
        ni = i + dx[k]
        nj = j + dy[k]
        if ni < 0 or ni >= h or nj < 0 or nj >= w or s[ni][nj] != '.':
            continue
        s[ni][nj] = a[k]
        q.append([ni,nj])


# 出力
for i in s:
    print("".join(i))
~~~
-- 追加ここまで --


# おわりに
ひとまずCを解けたのはよかったです。Dは幅優先探索の応用かなとは思いましたが、アルゴリズムがまとめられず断念。
ところで、順位表に各問題の最速回答者が出ていますが、A~Cはそれぞれ30秒程度で解いているみたいですね。過去に解いた同様の問題のソースコードを引っ張り出してくる時間という感じなんでしょうか。

ではでは。
スターレンタルサーバでVS-codeからsshして、venvでpipするところまで

windows環境でvs-codeを利用している。スターレンタルサーバの無料枠はsshができるので試してみる。

登録した後、ssh接続を有効化する。
sshは公開鍵・秘密鍵方式で、パスワード認証は使えない。
https://note.com/htrkwn/n/n47fa18499635
https://www.star.ne.jp/support/manual/man_server_ssh.php

pip参考
https://colour-field.jp/2024-12-22/

レンタルサーバでユーザーの権限が制限されており、pipがetcにアクセスする際にエラーがでる。

## 仮想環境の構築
まず pip を仮想環境内にインストールせずに venv を作成し、その後手動で pip を導入します。pythonのバージョンが古い（３．６）なので、それに合わせる必要もある。
```bash
python3 -m venv test_venv --without-pip

source test_venv/bin/activate

curl https://bootstrap.pypa.io/pip/3.6/get-pip.py -o get-pip36.py
python get-pip36.py

# 以下の出力を得た。
(test_venv) [ssxxx@svxxxxx ~]$ pip list
Package    Version
---------- -------
pip        21.3.1
setuptools 59.6.0
wheel      0.37.1
(test_venv) [ssxxx@svxxxxx ~]$


```
1日30分二ヶ月で受かった基本情報技術者試験の勉強法と感想

## はじめに

 基本情報技術者試験はIPAの情報処理技術者試験のうちレベル2にあたるもので、技術的な内容かからマネジメント的な内容まで、幅広く問われる試験。
 
 今年に入ってから受けて、1日30分という舐めた勉強スケジュールではありましたが、二ヶ月の勉強で一発合格できたので実践した勉強法や感想について書きたいと思います。

 ※キャッチーなタイトルになってしまいましたが、私は情報系の大学生なのでかなり学校の講義分ブーストがあります。1日30分をただ二ヶ月続けただけじゃ流石に受からないと思われる。

 ## なぜ基本情報を選んだか？

  理由はシンプルで、ITパスポートだとレベルが低すぎるが応用情報にいきなり行くと範囲が広すぎるから。
  
 応用情報は基本情報よりもさらに範囲が広く、しかし基本情報と被ってる部分がそこそこあるため、基本情報をスキップして応用情報に行くと勉強時間がかなりかかります。

 それから基本情報はいつでもCBTで受けることができますが、応用情報は春季と秋季しかない、と言うのも大きいです。
 
 CBTならば自分の学習状況に応じて柔軟に試験予定を作ることができます。しかし、応用情報はそうもいかない。合格発表時期なども加味すると合格者を名乗れるまでに相当なラグがあります（スパンがさらに長い資格なんてザラにあるが、少なくとも基本情報よりは）。

## 勉強法

まず、色々Pythonでコード書いたり、大学の授業で関係知識を得たりしていた関係上、わりかし前提知識はありました。科目Bの仮想コードはほぼ勉強なしで解けたし、科目Aもテクノロジ系の基礎は余裕。

しかし、それだけで受かる試験ではありません。

立ちはだかるのは学生にとって微塵も馴染みのないマネジメント系、ストラテジ系。さらに、テクノロジ系の中でも深いところは特定のフレームワークやプログラミング言語の内容に触れていたりもしていました。科目Bのセキュリティ問題も日本語を読めれば解けるとはいえ、慣れが必要。

勉強のためにまず最初にやったのは、もちろん参考書。書店で目についたものを一冊買って読破しました。（ネットでおすすめされてるものではなかったので、名前は挙げないでおく）

そのあとどうするべきかネットで色々みたところ、参考書は三冊ほど読んでおくのが良い、あとはひたすら過去問道場という意見が主流のようでした。

しかし、私は情報系学部生。授業で基礎知識が身についている分、参考書一冊を読めば、そうでない人の三冊分になるのではないか。そう考え、過去問道場をやってみました。すると、最初から7割弱の正答率。合格ラインは6割、このまま受けるのは流石に危険ですが、かなり良いスタートと言えます。

これによって、情報系の学部の授業と、基本情報の関係性がなんとなく掴めると思います。私の大学の授業のカリキュラムがどれだけ一般的なものなのかはわかりませんが、比較的基本情報に大学の講義内容は役立つと考えていいでしょう。

ただし、どんな人であっても参考書を一冊も読まないのはお勧めしません。参考書には知識だけでなく、試験のフォーマットや出題の方向性などの情報もわかりやすく載っていますから、その辺りの情報は知っておくべきです。

そして、科目Aの勉強はそのまま脳筋戦法で過去問道場を解き続けたわけですが、そこに一点の工夫を取り入れました。それは「わからんもんは即座にググる」です。

というのも基本情報の科目Aは四択問題で、計算はともかく知識問題は選択肢や答えを変えた、似ている問題が出ることも多い。そのため、一度出た問題は消去法で答えが分かればいいのではなく、選択肢や問題文に現れた全ての語句の意味を理解しておくべきなのです。

しかし、細かい基本情報の知識はぶっちゃけ範囲が広すぎて参考書でも網羅はできてない（ネットおすすめじゃない参考書買ったので、おすすめのやつならワンチャン網羅してる可能性もある）。

とにかく、知らん語句はググって都度覚えるののが最短だと、私は思います。

これが普通の勉強ならググって覚えるのきついかもしれませんが、これはエンジニアの試験です。エンジニアはAPIとかググりまくりますよね。なんで、そのテンションで勉強してました。

で、科目Bの話です。仮想コードについては正直Python書いてるので、経験値でゴリ押しました。多少過去問にも目を通しましたが、制度が変わってあまり時間が経っていないのもあり、問題のサンプル数は少ないです。過去問に目を通して仮想コードに慣れるのは必要ですが、どちらかといえば素のコーディングスキルの方が重要だと思われます。

一方、セキュリティ問題。これは現代文の問題に情報系の要素をたんまり詰め込んだようなものです。つまり、ある程度の情報系の知識というか、視点があるならあとは読解力の問題。やはり、慣れですね。

科目Bは過去問道場よりも、IPAから過去問や制度切り替え時のサンプルを引っ張ってきて解くのがお勧めです。というか、過去問道場は制度切り替え前の午後試験の問題ばかりなので役に立たないです。

## 試験中、試験後

配布されるメモ用紙、筆記用具を使いながらPCで回答します。CBTじゃないのもありますが、CBTを受けられない確固たる理由がない限りは絶対こっちのがいいです。パソコンを前に一人でうんうん唸る方が紙の試験より気が楽。試験会場が自宅近くになりやすいですし。

全ての回答が終わったらその場で点数が出て、AB両方で6割超えてたら合格ということにはなりますが、厳密にはその場では合格しません。

点数が基準を超えていても、合格を決定するのは（確か）経済産業大臣で、合格確定は翌月の、IPA webサイトに記載の日時です。それまでは合格者を名乗れません。ちょっと嫌な期間ですね。点数はわかってるのでいいですけど。

## 感想

他の試験勉強はあまり自分の興味関心と一致しないことが多いですが、基本情報はかなり一致度の高い試験だったので今までの様々な試験勉強の中では結構楽しかったです。
次は応用情報を取るつもりではありますが、CBTではないのでスケジュールの都合上、相当先にはなりそうです。
前橋ロボコン2025に向けて

こんにちは　ロボットテクノ部です。
今年も、まえばしロボコン2025が近づいてきました。　
去年、準優勝を果たすこと、悔いなく大会を終えられました。前回の大会によって、人とのつながりが、年齢関係なくモノづくりでは、大切だと実感しました。
今年も悔いなく、去年以上に頑張りたいと思います。
![1000000519.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3914799/3fced451-81e9-4a27-8c4e-5cd4f20cffc3.jpeg)
Ruby学習メモ（初学者向け）②

# Ruby学習メモ（初学者向け）

どうも、nus4です。

Ruby学習メモの第二弾です。
前回に引き続き、こんなのあったな〜っと思っていただければ嬉しいです。

## 学習方法
- Progate Rubyコース
　（１ヶ月有料利用する予定なので、期間中に積極的活用してます！）

## 📝 目次  
- [メソッドの書き方](#メソッドの書き方)  
- [キーワード引数を使用したメソッドの書き方](#キーワード引数を使用したメソッドの書き方)  
- [クラスの書き方](#クラスの書き方)  
- [インスタンスの書き方](#インスタンスの書き方)  
- [initializeメソッドの書き方](#initializeメソッドの書き方)  
- [クラスの読み込み](#クラスの読み込み)  
- [コンソールの入力を取得する](#コンソールの入力を取得する)  
- [クラスの継承](#クラスの継承)  
- [日付を取得する方法](#日付を取得する方法)  

## メソッドの書き方
```ruby
# メソッドの宣言
def メソッド名(引数名)
    処理
    return 戻り値
end

# メソッドの呼び出し
メソッド名(引数名)
```
戻り値には前の"return"を省略する方がRubyっぽいみたいです

# キーワード引数を使用したメソッドの書き方
```ruby
# メソッドの宣言
def メソッド名(引数名1:, 引数名2:, 引数名3:)
    処理
    return 戻り値
end

# メソッドの呼び出し
メソッド名(引数名1: 値1, 引数名2: 値2, 引数名3: 値3,)
```
引数が複数あるメソッドは、ハッシュの応用で、キーワード引数にしてあげると、
呼び出し側の引数の対応がわかりやすいです。

# クラスの書き方
```ruby
# クラスの宣言
class クラス名
    # インスタンス変数の宣言
    attr_accessor :変数名

    # メソッドを持たせることも可能（インスタンスメソッド）
    def メソッド名(引数名)
        処理
        return 戻り値
    end

    # メソッドを持たせることも可能（クラスメソッド）
    def クラス名.メソッド名(引数名)
        処理
        return 戻り値
    end
end
```
attr_accessorを使用して宣言することで、
setter,getterの定義を省略してインスタンス側で読み書きが可能になります。

クラス内のみで完結するメソッドはクラスメソッド、
インスタンスで使いたいメソッドはインスタンスメソッドを使いましょう。

# インスタンスの書き方
```ruby
# インスタンスの作成
インスタンス名 = クラス名.new

# インスタンス変数の書き込み
インスタンス名.変数名 = 値

# インスタンスメソッドの使用
インスタンス名.メソッド名
```

# initializeメソッドの書き方
```ruby
# 引数が2つある場合の記載例
def initialize(引数名1:, 引数名2:)
    処理

    # 変数の書き込みを実装したいとき（事前にインスタンス変数を宣言）
    self.変数名 = 値
end
```
initializeメソッドとは、インスタンス生成直後に自動生成されるメソッドです。
上記の引数が2つある例の場合、インスタンス作成側も引数を2つ用意する必要があります。
ex）インスタンス名 = クラス名.new(引数名1: 値1, 引数名2: 値2)

# クラスの読み込み
```ruby
require "./相対パス.rb"
```
インスタンスの作成など、他クラスの呼び出しを行う際は
呼び出し元のクラスを用いてrequireする必要がある。

# コンソールの入力を取得する
```ruby
# 入力値を変数に代入する（入力値が文字列）
変数名 = gets.chomp

# 入力値を変数に代入する（入力値が数値）
変数名 = gets.chomp.to_i
```
上記コードが実行されるとその瞬間にコンソールは入力待機状態になり、
エンターキーを押されるまでに入力された値を取得することができます。

# クラスの継承
```ruby
# クラス宣言時に追記するだけ
class クラス名 < 親クラス名
```
継承することで、親クラスで定義されたメソッドを使えたり、
子クラス側で親クラスのメソッドを書き変えることができます。
（いわゆるオーバーライド。変えない部分は書く必要ない）

逆に、親クラス側の同名メソッドを使いたい場合は、
superメソッドを使うことで子クラス側で呼び出すことができます。

# 日付を取得する方法
```ruby
# Dateクラスを読み込む
require "date"

# 今日の日付のDateインスタンスを作成する
インスタンス名 = Date.today

# 指定した日付のDateインスタンスを作成する
インスタンス名 = Date.new(YYYY, MM, DD)

# 日曜日か判定するメソッド
インスタンス名.sunday?
```
DateクラスはすでにRubyで準備されているため、
呼び出すだけで色々な便利メソッドが使えます。

---

ProgateのRuby講座はこれで完了しました。
次回はRails講座に挑戦したいと思います！
ランダムな数値、日付

# はじめに
サンプルデータを作る為、ランダムな数値、日付が大量に必要になりました。
データはExcelで作成しDBに投入しましたが、C#でも作成してみました。

# Excel
```text:Excel数式
>a以上b未満の整数
=ROUNDDOWN(RAND()*(b-a)+a,0)

>0.0以上1.0未満の浮動点小数
=RAND()

>2000-01-01～2025-12-31
=DATE(2000,1,1)+ROUNDDOWN(RAND()*(DAYS(DATE(2025,12,31),DATE(2000,1,1))+1),0)
```

# C#
C#では「Random」を使う方法と「RNGCryptoServiceProvider」を使う方法があるようですが、厳密さは求められていないので、「Random」を使いました。

```c#:C#
var r = new Random();

// 整数
int intRandom1 = r.Next(); // 0～111（0以上）
int intRandom2 = r.Next(10); // 0～9（0以上10未満）
int intRandom3 = r.Next(-5, 10); // -5～9（-5以上10未満）

// 小数
double valRandom = r.NextDouble(); // 0.0以上1.0未満の浮動点小数

//　日付
var ds = new DateTime(2000, 1, 1);
var de = new DateTime(2025, 12, 31);
DateTime d = ds.AddDays(r.Next((de - ds).Days) + 1); // 2000-01-01～2025-12-31
```