OmniAICreator/Qiita-1.07M huggingface dataset:
あえてVirtualBox、Hyper-V、VMwareなどの仮想環境を使用して仮想環境でUbuntu踏み台サーバーを構築する手順解説



## はじめに

仕事でUbuntuの踏み台サーバーを構築することになり、最初は不安でしたが、実際にやってみると意外と理解しやすかったです。
この記事では、私が実際に躓いたポイントも含めて、だれでも分かりやすいように解説していきます。

### この記事で分かること
- 踏み台サーバーとは何か、なぜ必要なのか
- 実際の構築手順と各手順の意図
- よくあるトラブルとその解決方法

### 必要な準備
- PC（メモリ8GB以上推奨）
- 仮想化ソフト（VirtualBox推奨）
- Ubuntu Server 22.04 LTS（長期サポート版）

## 1. 踏み台サーバーって何？

踏み台サーバーは、社内の重要なシステムを外部からの攻撃から守るための「関所」のような役割を果たします。

例えば：
1. 社外から直接データベースサーバーにアクセスできると危険
2. 踏み台サーバーを経由することで、アクセスを管理・監視できる
3. セキュリティが向上し、万が一の際の追跡も容易になる

## 2. 仮想マシンの準備

### 基本設定（15分）
VirtualBoxで新規仮想マシンを作成します：

```
名前: Ubuntu-Bastion
メモリ: 2GB
ストレージ: 20GB（動的割り当て）
```

なぜこの設定なのか：
- メモリ2GBは最小構成として十分
- 動的割り当てでストレージを効率的に使用
- 検証環境なので必要最小限のスペック

### ネットワーク設定（5分）
踏み台サーバーには2つのネットワークが必要です：

1. **外部接続用**：
   - 設定：NAT
   - 目的：インターネットへのアクセス用
   - 用途：システムアップデートなど

2. **内部接続用**：
   - 設定：ホストオンリーアダプター
   - 目的：内部システムとの通信用
   - 用途：社内サーバーへのアクセスなど

## 3. Ubuntu Server のインストール（10分）

### 重要なポイント
1. インストール時の選択：
```
言語: 日本語
キーボード: 日本語
ネットワーク: デフォルトのまま
```

2. **必ず確認！**
   - OpenSSH Serverのインストール
   - ユーザー名とパスワードのメモ

これらを忘れると後で大変です。私も最初は忘れて、インストールからやり直しました...。

## 4. セキュリティ設定

セキュリティ設定は踏み台サーバーの要です。各設定には明確な理由があります：

### システムアップデート
```bash
# まずは最新に更新
sudo apt update
sudo apt upgrade -y
```
⇒ セキュリティホールをふさぐため

### SSHの設定
```bash
# 設定ファイルの編集
sudo nano /etc/ssh/sshd_config
```

重要な設定と理由：
```bash
# rootログイン禁止
PermitRootLogin no
# 理由：システム管理者権限での直接ログインを防ぐ

# パスワード認証禁止
PasswordAuthentication no
# 理由：ブルートフォース攻撃を防ぐ

# 公開鍵認証を有効化
PubkeyAuthentication yes
# 理由：より安全な認証方式を使用
```

### ファイアウォール設定
```bash
# UFWの設定
sudo apt install ufw -y
sudo ufw allow ssh
sudo ufw enable
```
⇒ 必要最小限の通信だけを許可

## 5. 動作確認

### 接続テスト
```bash
# ホストマシンからSSH接続
ssh ユーザー名@サーバーIP
```

### うまくいかない場合のチェックリスト
1. SSHサービスは起動していますか？
```bash
sudo systemctl status ssh
```

2. ファイアウォールはSSHを許可していますか？
```bash
sudo ufw status
```

3. ネットワーク設定は正しいですか？
```bash
ip addr show
```

## まとめ：これだけは覚えておこう！

### 重要ポイント3箇条
1. 二つのネットワーク（外部用・内部用）の役割を理解する
2. SSHの基本的なセキュリティ設定を必ず行う
3. 定期的なアップデートを忘れない

### 次のステップ
- ログ監視の設定
- バックアップの設定
- 監視システムの導入

## あとがき

実際に手を動かして構築することで、踏み台サーバーの役割や重要性が理解できると思います。

### 参考資料
- [Ubuntu Server ドキュメント](https://ubuntu.com/server/docs)
- [OpenSSH セキュリティガイド](https://www.openssh.com/security.html)

---
Instanaワンライナーインストーラーの中身を読んでみる

昨日に続き、Advent Calendarにエントリさせていただきます、カワノです！よろしくお願いします。

そんなわけで、この記事はInstana Observability Advent Calendar 2024 5日目のエントリになります。

# はじめに
皆さん、エージェントのインストールってどう実施しました？やっぱりかんたんなのは linuxへのワンライナーインストールですよね。え？あのワンライナーなにやってくれるのかよくわからないから触るの怖い…？
そんな構えないでも大丈夫！本当に簡単にインストールできるんですよ。一度お試しあれ。

しかし、あのワンライナーは内部で何やってるんでしょうね？わざわざコードを読み込む方は少ないと思いますので、ここでざっと解析してみようと思います。

ちなみに、今回使うワンライナーコードは 2024年11月26日にダウンロードしたものです。最新では更新されている可能性があります。ご了承ください。

最近は ChatGPTでソースコード解析できちゃうんですよね。便利な世の中です。
ちなみにIBMにもWatsonx Code Assistantというソースコード解析や各種支援ができるツールがあるのですが、シェルスクリプトはまだサポートされていないようです。
Javaなどは強力に支援してくれますので、ぜひお試しください。詳細は下記をご覧ください。

https://qiita.com/yanagih/items/63fd0ff497bb22fc50bd

## ワンライナースクリプト(ソースコード)のダウンロード
スクリプト自体はインターネット上で公開されていますので、ダウンロードして名前をつけて保存します。
``` sh
curl -o setup_agent.sh https://setup.instana.io/agent
```
ワンライナースクリプトをsetup_agent.shというファイルとして保存しました。
これを解析します。

## スクリプトの説明
では早速スクリプトを説明します。
このスクリプトは、環境の検出と適切な構成を自動的に行い、ユーザーが複雑な環境を考慮した上で 手順に沿ったインストール作業を**行わなくても良い** 作りになっています。

### 1. 指定可能な引数
スクリプトで指定可能な引数は以下の通りです。
- `-a`：エージェントキー
- `-d`：ダウンロードキー
- `-e`：エージェントのエンドポイント
- `-l`：リージョン（非推奨）
- `-m`：モード（`apm`, `infra`, `aws`）
- その他、Gitリポジトリの設定や動作に関する引数

モードについては以下のドキュメントを参照してください。

https://www.ibm.com/docs/ja/instana-observability/current?topic=planning-instana-agent-types#host-agent-modes
   

### 2. システム環境の確認
引数チェック後、以下の確認を行います。
- スクリプトが**rootユーザー**で実行されているかチェック
- 対応するOSとアーキテクチャかどうか確認
  - 非対応の場合（macOS, AIX, Solarisなど）は終了

### 3. システムの環境検出
続けて、環境チェックを行います。
- システムのアーキテクチャを検出（`x86_64`, `aarch64`, `ppc64le`）
- パッケージ管理システムを検出（`apt`, `yum`, `dnf`, `zypper`）
- `systemd`、`upstart`を検出

### 4. 事前条件の確認
インストールに必要なソフトウェアが導入済みか確認します。
- `curl`または`wget`が利用可能か確認
- `gpg`がインストールされていない場合、ユーザーに継続確認を求める(InstanaリポジトリからAgentをダウンロードするために GPG keyを利用するため)

### 5. エージェントのセットアップ
エージェントリポジトリを設定しダウンロード・インストールします。
- システムに応じたパッケージリポジトリを設定
   - `apt`（Debian/Ubuntu）
   - `yum`（CentOS/Red Hat）
   - `dnf`（Fedora）
   - `zypper`（SUSE）
- エージェントのダウンロードキーや認証情報を設定
- 必要に応じて内部パッケージリポジトリを有効化
- エージェントのダウンロードとインストール

### 6. モードの設定
エージェントの動作モードを以下のいずれかに設定します。
  - `apm`：アプリケーションパフォーマンスモニタリング
  - `infra`：インフラモード
  - `aws`：AWS統合用モード

### 7. サービスの開始
Instana Agentをサービスとして登録し有効化します。
- 環境変数を構成
- `systemd`や`upstart`を使用してエージェントを起動、サービスの有効化

## 最後に
ざっと記載しましたが、linuxの多くのDistroに対応していることがお分かりいただけたかな、と思います。
ワンライナーを利用の際、導入環境に対応してるかどうか確認する際はぜひこちらご参考にされてください。
Twitterデータのスクレイピングにおけるベストプラクティス：効率的なデータ収集方法の比較と解決策

はじめに
ビジネスアナリストやマーケターとして、Twitterのデータ収集は重要なタスクの一つです。しかし、効率的にデータを収集することは、思った以上に複雑で課題が多いものです。この記事では、様々なTwitterデータ収集方法を比較し、それぞれの長所・短所を詳しく解説します。
現状の課題
1. Twitter公式APIの問題点
高額な利用料金
Basic: $100/月
Pro: $5,000/月
Enterprise: $42,000/月
このような高額な料金設定は、個人開発者や小規模企業にとって大きな負担となっています。
制限の厳しさ
リクエスト制限が厳しい
データ取得の遅延
複雑なAPI仕様
2. Tweepyなどのライブラリを使用する場合の問題
アカウント凍結のリスク
大量のリクエストによるアカウント停止
IP制限の可能性
アカウント復旧の困難さ
開発・運用コスト
エラーハンドリングの実装
プロキシ管理
継続的なメンテナンス
解決策：効率的なデータ収集方法
最適な方法の提案
私たちが開発したAPIソリューションは、これらの課題を解決するために以下の特徴を備えています：
1. コスト効率
1000ツイートあたり$0.25という合理的な価格設定
使用量に応じた柔軟な課金システム
2. 高い安定性
独自のインフラストラクチャ
自動エラー回復機能
99.9%の稼働率
3. 簡単な実装
```
import requests
import json

# you can find your API token in the Apify dashboard ：https://console.apify.com/settings/integrations
API_TOKEN = "apify_api_XXXXXXXXX"
twitterContent = "make from:elonmusk"
maxItems = 18
queryType = "Latest"

headers = {
    "Content-Type": "application/json"
}

data = {
  "maxItems": 200,
  "startUrls": [
    "https://twitter.com/search?q=apify%20&src=typed_query"
  ]
}

#response = requests.post(f"https://api.apify.com/v2/acts/kaitoeasyapi~twitter-x-data-tweet-scraper-pay-per-result-cheapest/run-sync-get-dataset-items?token={API_TOKEN}", headers=headers, data=json.dumps(data))

response = requests.post(f"https://api.apify.com/v2/acts/apidojo~tweet-scraper/run-sync-get-dataset-items?token={API_TOKEN}", headers=headers, data=json.dumps(data))

print(response.text)
```

実際の使用例
1. マーケティング分析
[ここに分析結果のスクリーンショットを挿入]
2. 競合分析
[ここに競合分析のダッシュボードを挿入]
3. トレンド予測
[ここにトレンド予測グラフを挿入]
パフォーマンス比較
従来の方法 vs 新しいAPI
| 項目 | 従来の方法 | 新しいAPI |
|------|------------|-----------|
| コスト | 高額 | 低コスト |
| 安定性 | 低い | 高い |
| 実装の容易さ | 複雑 | 簡単 |
| メンテナンス | 必要 | 不要 |
具体的な活用方法
1. ツイート取得
より詳細なコード例を記載
2. フォロワー分析
フォロワー分析のコード例
まとめ
Twitterデータの収集は、ビジネスにおいて重要な要素です。しかし、従来の方法では多くの課題がありました。新しいAPIソリューションを使用することで、これらの課題を効率的に解決することができます。
主なメリット
コスト削減
開発時間の短縮
安定したデータ収集
メンテナンスフリー
参考資料
https://apify.com/kaitoeasyapi/twitter-x-data-tweet-scraper-pay-per-result-cheapest
https://developer.x.com/en

API利用統計データ
実際のユースケース事例
遠回りが近道になるとき ～アプリ開発者がネットワーク技術を学ぶ理由～


## G's ACADEMYから始まったアプリ開発と課題
G's ACADEMYを卒業して既に4年。その時登壇させていただいたGGAの直前に生まれた長男も4歳になり、ついこの前次男も生まれました。

G'sでプログラミングを学び、現在は社内向けのWebアプリを3本リリースし、現在も1本展開中です。
あの頃はPHPで書いていたのですが、今やC#がメイン。

もっとコードで実装できる機能や、表現力の幅を広げるために書籍やUdemyを買い漁り実践しては首を捻ったりしていました。

ですが、IT系企業でもない製造業の中で働くプログラマーは、ただコードを書いているだけでは業務の完結はしないのです。

##  クラウドを積極活用したい理由

アプリ開発は「作って終わり」ではありません。
これは1本目のデプロイから苦心している点ですが、作ったアプリが問題なく継続して稼働する場所を確保し、監視でき、トラブル対応をしていかなければなりません。
1本目の時は未知との遭遇的な難しさがあり、稼働するアプリが増えるごとに、発生するトラブル対応や、機能追加後やバグ修正後のデプロイ対応でじわじわと時間が削られていくようになりました。

少数の人員で運用を続けるには自動化技術（IaCやCI/CD）の取入れが急務と感じ、それ以外にも動機はあるのですが、クラウドの適切な活用による運用保守コストの削減を目指すようになります。


##  Ciscoでネットワークを学ぶという選択

私は普段愛用している言語がC#ということもあり、その延長戦でAzureにも興味がありました。
そこでAzureを色々と触り始めるのですが、なんともはっきりとはしないのですがモヤモヤを抱え続けることになります。

その原因がこれです。

```
192.168.0.1
172.16.0.1
10.0.0.1
```

そうです。
IPアドレスです。
それ以外にもFirewallなどのキーワードが出てくると、思考停止してしまっていることに気づいたのです。
ネットワーク関連の知識は必須という認識はもともとあったのですが、書籍を読んでOSI参照モデルの図を見ても、TCP/IPモデルの図を見ても、それ以上のイメージが発展せず、C++でネットワークプログラミングを実践しても、ただパケットをプロトコルに従って処理する以上のイメージが掴めませんでした。

そんな私がクラウド上で表現される構成図を見ても、
「なんだろう、見えない壁があってこれ以上先に進めない！」
という気持ちが解消されることはありませんでした。

そんな私がたどり着いた解決策がCiscoでした。  

実はこのアドベントカレンダーを投稿する前にこんな記事を書いています。

https://qiita.com/_ddDaisuke/items/35d5e855761c120f6f22

この記事は、あるきっかけで知った研修に参加した際の体験談的なものです。
簡単に説明すると、Ciscoの機器が実機でおいてある教室で、実機にコマンドを打ちまくって色んなパターンのネットワーク環境を構築するものになっています。

研修参加者も情シス部門の方や、ネットワーク構築ベンダーの方がいたりと、アプリ開発者は珍しいパターンのようでした。
といっても最大8名の研修なので、特に気にならなかったです。


##  遠回りの価値

私の取り組みは一見「遠回り」に見えるかもしれません。
しかし、この経験から得たネットワーク技術の影響は大きかったです。

事実として、「抵抗感」がなくなりました。
クラウド上で登場するネットワークにはパブリックとプライベート、それに合わせてVPNで接続するか否かなどの選択肢があり、特にこの領域は社内向けアプリを提供する私にとっては避けては通れない領域になります。

AzureやAWSなどには資格試験があり、そこをきっかけに始める方法が主流だとは思います。

ですが中には私のような物好きな方もいらっしゃると思います。
特にG'sの現役生、卒業生は、こういった学び方が好きな方もきっといるはず！  


私自身、業務で実践していく中で、アプリ開発はプログラミングを行うだけでなく、クラウド、ネットワーク、セキュリティといった分野を総合的に扱う「総合格闘技」のように感じるようになりました。


アプリの要件に見合ったちょうど良い設計を選べる力を身に着けたい。
単なる開発者ではなく、プロジェクト全体を俯瞰して最適解を導き出せるエンジニアになりたいという方には、こんな遠回りもたまにはいかがでしょうか？
24/12/03 読書記録 ~ソフトウェアテストの教科書~

# 書籍
[【この1冊でよくわかる】 ソフトウェアテストの教科書](https://amzn.asia/d/6jSYRVM)

# 書籍を読む目的

 - [ ] 「品質」を理解する
 - [ ] 品質を担保できるテストを理解する

## Chap08. テスト技法適用チャート

### 学び 📝

#### 悩みを解決するテスト技法
品質面は悩んでいない。
しかし、テストが膨大で「もっと効率的にテストを行えるのでは？」が日頃疑問である。
以上の悩みで適用できるのは「組合せテスト技法」かな。

また、機能の全体像が確認できず、コードリーディングに苦労することも多い。
本著では「状態遷移図」が勧められているが、個人的にシーケンス図でも良いのでは？となっている。


### Chap8 感想 :writing_hand_tone5:

悩みは環境により変わっていくものなので、課題意識を持ち、本章を見て解決策を考えて行きたい。
WindowsのBATファイルからHPテンプレートをBATで作成するサンプルソース

WindowsのBATファイルでまとめてファイルを作成する方法を説明します。以下に3つの主な方法を紹介します。

## 単純なファイル作成スクリプト
```bat
@echo off
echo ファイル1の内容 > file1.txt
echo ファイル2の内容 > file2.txt
echo ファイル3の内容 > file3.txt
```
## forを使用した繰り返しファイル作成
```bat
@echo off
for %%i in (A B C D E) do (
    echo %%iファイルの内容 > %%i.txt
)
```
## 外部テキストからファイル作成
```bat
@echo off
for /f "tokens=*" %%a in (filenames.txt) do (
    echo %%aのファイル内容 > %%a.txt
)
```
### 各方法のポイント
- 最初のスクリプトは直接的で単純
- 2番目は変数を使用して柔軟に対応
- 3番目は外部リストからファイルを生成可能

### 注意点
- スクリプトは同じフォルダに保存
- 既存ファイルは上書きされるため注意
- 必要に応じて権限設定に注意

## BATファイルからHPテンプレートをBATで作成するサンプルソース

このBATスクリプトは以下を自動生成します。

### プロジェクトディレクトリ構造
- index.html
- CSS (style.css)
- JavaScript (script.js)
- README.md

実行すると、最小限の構造を持つウェブプロジェクトテンプレートが作成されます。
### サンプルソース
```bat
@echo off
setlocal enabledelayedexpansion

:: Create project directory structure
mkdir project
cd project
mkdir css
mkdir js
mkdir img

:: Create index.html
(
echo ^<!DOCTYPE html^>
echo ^<html lang="ja"^>
echo ^<head^>
echo     ^<meta charset="UTF-8"^>
echo     ^<meta name="viewport" content="width=device-width, initial-scale=1.0"^>
echo     ^<title^>My Website^</title^>
echo     ^<link rel="stylesheet" href="css/style.css"^>
echo ^</head^>
echo ^<body^>
echo     ^<header^>
echo         ^<h1^>Welcome to My Website^</h1^>
echo     ^</header^>
echo     ^<main^>
echo         ^<p^>コンテンツはここに追加^</p^>
echo     ^</main^>
echo     ^<footer^>
echo         ^<p^>&copy; 2024 My Website^</p^>
echo     ^</footer^>
echo     ^<script src="js/script.js"^>^</script^>
echo ^</body^>
echo ^</html^>
) > index.html

:: Create CSS file
(
echo body {
echo     font-family: Arial, sans-serif;
echo     line-height: 1.6;
echo     margin: 0;
echo     padding: 0;
echo }
echo header {
echo     background-color: #333;
echo     color: white;
echo     text-align: center;
echo     padding: 1rem;
echo }
) > css/style.css

:: Create JavaScript file
(
echo document.addEventListener('DOMContentLoaded', function() {
echo     console.log('ページが読み込まれました');
echo });
) > js/script.js

:: Create README
(
echo # My Web Project
echo ## プロジェクト概要
echo このウェブサイトは自動生成されたテンプレートです。
) > README.md

echo HTMLプロジェクトテンプレートが作成されました。
```
4日目: Weighted UnionFindを実装する

[競プロ用ライブラリを作る Advent Calendar 2024](https://qiita.com/advent-calendar/2024/yukkku-ribitol)の4日目です.

https://qiita.com/advent-calendar/2024/yukkku-ribitol

# Weighted UnionFindって?

「値の差」みたいな情報を速く計算出来るデータ構造です.
$N$個の数値$x_1, x_2, ..., x_N$について
- 「$x_i - x_j = X$だ」というような情報を追加する
- $x_i - x_j$ の値を調べ
  - 情報が不足している
  - 情報が矛盾している
  - 答えは$X$だ

  のどれかの返答をする

という操作が$O(\alpha(n))$みたいな計算量でできます. ($\alpha$は前日にも出てきたアッカーマン関数の逆関数です)

:::note info
このデータ構造ができることを考えると「重み付きUnionFind」ではなく「ポテンシャル付きUnionFind」が正しいという話があったりします.
ですが, 私の場合PotentialよりもWeightedの方が速くタイピングできて競プロに有利なので, ここではWeighted UnionFindという呼び方をすることにします.
:::

# 仕組み

UnionFindに追加の情報を乗せます.
UnionFindで木の親を指す情報を持っていましたが, そこに親との値の差も持つようにします.
そして根の要素はグループのサイズに加えて「そのグループ内で矛盾した情報が無いか」という情報も管理します.

# 抽象化

抽象化すると群が乗ります.
更に抽象化するとGroupoid (全ての射が同型射な圏) にもできますが, Rustの表現能力だと実装にほとんど差が無いので気にしないで良いです.

一般の群は交換法則が成り立たないので順番には気をつけて実装しましょう.

# 実装

- [`weightedunionfind.rs`](https://github.com/Yukkku/ribitol/blob/main/src/weightedunionfind.rs)

パフォーマンスを良くするために非再帰で`find`を書きたいですが, 昨日のUnionFindと同じ方法だと辛いので経路圧縮の方法を変えます.
Path Halvingという名前で,
```mermaid
flowchart RL
  1((1))
  2((2)) --"+1"--> 1
  3((3)) --"&minus;3"--> 2
  4((4)) --"&minus;7"--> 3
  5((5)) --"+5"--> 4
  6((6)) --"±0"--> 5
  7((7)) --"+3"--> 6
```
こういうのを
```mermaid
flowchart RL
  1((1))
  2((2)) --"+1"--> 1
  3((3)) --"&minus;2"--> 1
  4((4)) --"&minus;7"--> 3
  5((5)) --"&minus;2"--> 3
  6((6)) --"±0"--> 5
  7((7)) --"+3"--> 5
```
こういう風に1つ飛ばしで繋ぎなおす経路圧縮です. これでも$O(\alpha(N))$が保証されるらしいです.

# まとめ

いかがでしたか?

明日は前日のUnionFindを使った最小全域木のアルゴリズムを実装します.
プログラミングへの意識が芽生えるまで

私はプログラミングが好きですが、それは最初からではなく、さまざまな経験を通じて徐々に惹かれていった結果だと思います。ここでは、その過程を3つの段階に分けて振り返ります。

## おもしろフラッシュにハマった
子どもの頃、「おもしろフラッシュ倉庫」というサイトに夢中になっていました。Flashで作られたゲームやムービーの数々を楽しみ、中でも「ウォーリーを探さないで」といった作品は、純真無垢な少年時代の私に強烈な印象を残しました。この時期、ゲームやコンテンツを通じて「何かを作る」という面白さに触れるきっかけを得たのだと思います。やがて、PSPや3DSといったデバイスに夢中になる時期に移行していきましたが、この体験が私の創作への興味の原点だったと言えるでしょう。

## 中学校の文化祭で友人がボンバーマンを作っていた
中学生の頃、3DSでボンバーマンを遊ぶのにハマっていました。そんなある日、学校の文化祭で友人がプログラミング部の展示として自作のボンバーマンを披露しているのを目にしました。その瞬間、「ゲームって作れるんだ」「作っていいんだ」と気づき、衝撃を受けました。ゲームの世界に入り込むプレイヤーから、ゲームを作り上げるクリエイターへの憧れが芽生えた瞬間でした。しかし当時は他の活動で手一杯で、プログラミングを始めるには至りませんでした。

## レディ・プレイヤー1を観た
2018年に公開された映画『レディ・プレイヤー1』は、VRゲームをテーマにしたSF作品で、過去のゲーム文化へのリスペクトが色濃く描かれています。この映画では、ゲームそのものだけでなく、その背後にいる「作者」の人生にもスポットが当てられていました。その描写に触れたとき、ゲームを単なるコンテンツ以上のものとして捉える視点が芽生えました。「ゲームの魂を吹き込む存在」としての作者に憧れ、私もゲームを作りたいという気持ちが強くなりました。

## まとめ
振り返ると、私がプログラミングに興味を持つまでのプロセスは、次の3つの段階に整理できます。

1. ゲームに没頭する体験を通じて、コンテンツの魅力に触れる
2. 文化祭で友人の作品に触れ、ゲームの「作り手」という存在を知る
3. 映画を通じて、ゲーム制作に対する憧れが生まれる

これらを通じて、ゲームを作る手段としてのプログラミングと出会い、さらにそれが仕事に繋がる可能性に気づきました。今ではプログラミングが楽しいと思えるようになったのは、過去の自分が積み重ねてきたこれらの経験のおかげです。今の私を支えているその原点に、感謝しています。
npm ciって何？

コードをクローンしたり、リポジトリをプルした際、`package.json`に記載された依存パッケージを `node_modules`にインストールするため、`$ npm i`を実行すると思います。

この`$ npm i`と似たコマンドに`$ npm ci`があります。今回は、この2つのコマンドの違いについてご紹介します。また、昨日「`package.json`と`package-lock.json`の違い」についての記事も書きましたので、興味があればそちらも併せてご覧ください。

https://qiita.com/y_ta/items/bc899958f131fb84871b

# npm i
`$ npm i`を実行すると、`package-lock.json`に記載されている正確なバージョンのパッケージが `node_modules`にインストールされます。ただし、`package-lock.json`が存在しない場合は、`package.json`に記載されているバージョン範囲内で最新のバージョンのパッケージがインストールされます。このとき、新たに`package-lock.json`が生成され、インストールされたパッケージの正確なバージョンが記録されます。

# npm ci
`$ npm ci`は`package-lock.json`に記載されている正確なバージョンのパッケージをインストールする点では`$npm i`と似ていますが、動作にはいくつか違いがあります。`$ npm ci`は`package-lock.json`が存在しない場合にエラーを吐き、コマンドが実行できません。また、`package.json`と `package-lock.json`に矛盾がある場合もエラーとなります。さらに、`$ npm i`が不足分を補完して再利用するのに対し、`$ npm ci`は既存の`node_modules`を完全に削除した上でパッケージを再インストールします。


# どちらを使えばいいのか
これらの違いから、`$ npm i`は**開発中**の柔軟な依存関係管理に向いており、`$ npm ci`は**本番環境や CI/CD**のように再現性が求められる場面で使用するのが適しています。

# まとめ
この記事では、`$ npm i`と`$ npm ci`の違いについて解説しました。2日連続でパッケージ管理に関する記事を書いたことで、少し詳しくなった気がします。今後も、Web開発に役立つ小ネタを発信していきますので、ぜひお楽しみにしてください！
【HTML】複数のinput要素を無効にする方法

`fieldset`要素を使用して以下のように記述すると複数のinput要素を無効にできます。

```html
<fieldset disabled>
	<div>
	  <input type="email" name="name" />
	</div>

	<div>
	  <input type="password" name="password" />
	</div>

	<div>
	  <input type="submit" value="submit" name="button" />
	</div>
</fieldset>
```
【TIPS】マップリストにScikit-learnのimputerっぽい欠損値処理をする

この記事は、[Elixir Advent Calendar 2024 シリーズ9](https://qiita.com/advent-calendar/2024/elixir) の9日目です

---

【本コラムは、5分で読め、2分で試せます】

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

Scikit-learnのimputerは、AI・LLMの前処理における「欠損値置換処理」を、[fillna](https://qiita.com/piacerex/items/d4066d262bc791cab2f5) のような固定値では無く、データの統計値を計算し、実現します

統計アルゴリズムを指定しない場合、各列ごとの平均値（`mean`）が適用されます

```diff_elixir
maplist = [
  %{"c1" => "v1", "c2" => 2, "c3" => 3}, 
  %{"c1" => "v2", "c2" => nil, "c3" => 6}, 
  %{"c1" => "v3", "c2" => 5, "c3" => nil}
]

結果：[
  %{"c1" => "v1", "c2" => 2, "c3" => 3}, 
  %{"c1" => "v2", "c2" => 3.5, "c3" => 6}, 
  %{"c1" => "v3", "c2" => 5, "c3" => 4.5}
]
```

これを実装すると、[fillna](https://qiita.com/piacerex/items/d4066d262bc791cab2f5) に近いコードになります

なお、Scikit-learnでは、`SimpleImputer` 等のImputerインスタンスにより、データを事前に学習させ、統計値を出しますが、ここでは、`Statistics` ライブラリで即値統計計算で代用します

```diff_elixir
Mix.install([{:statistics, "~> 0.6"}])

maplist = [
  %{"c1" => "v1", "c2" => 2, "c3" => 3}, 
  %{"c1" => "v2", "c2" => nil, "c3" => 8}, 
  %{"c1" => "v3", "c2" => 1, "c3" => nil}
]
keys = ["c2", "c3"]

keys
|> Enum.reduce(maplist, fn key, acc -> 
    fill = acc 
      |> Enum.map(& &1[key]) 
      |> Enum.reject(& &1 == nil)
      |> Statistics.mean
    acc
    |> Enum.map(& Map.update!(&1, key, fn v -> 
        if v == nil do fill else v end 
      end))
  end)

結果：[
  %{"c1" => "v1", "c2" => 2, "c3" => 3}, 
  %{"c1" => "v2", "c2" => 1.5, "c3" => 8}, 
  %{"c1" => "v3", "c2" => 1, "c3" => 5.5}
]
```

平均値では無く、最大値（`Statistics.max`）や最小値（`Statistics.min`）、最頻値（`Statistics.mode`）、標準偏差（`Statistics.stde`）、中央値（`Statistics.median`）などに変更も可能です

```diff_elixir
Mix.install([{:statistics, "~> 0.6"}])

maplist = [
  %{"c1" => "v1", "c2" => 2, "c3" => 3}, 
  %{"c1" => "v2", "c2" => nil, "c3" => 8}, 
  %{"c1" => "v3", "c2" => 1, "c3" => nil}
]
keys = ["c2", "c3"]
stat = &Statistics.max/1

keys
|> Enum.reduce(maplist, fn key, acc -> 
    fill = acc 
      |> Enum.map(& &1[key]) 
      |> Enum.reject(& &1 == nil)
      |> stat.()
    acc
    |> Enum.map(& Map.update!(&1, key, fn v -> 
        if v == nil do fill else v end 
      end))
  end)

結果：[
  %{"c1" => "v1", "c2" => 2, "c3" => 3}, 
  %{"c1" => "v2", "c2" => 2, "c3" => 8}, 
  %{"c1" => "v3", "c2" => 1, "c3" => 8}
]
```

# p.s.このコラムが、面白かったり、役に立ったら…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/907a8695-4d83-1b5c-8052-d0ce52de5f66.png) にて、どうぞ応援よろしくお願いします :bow:
【G検定】文系新卒1年目のエンジニアがG検定にチャレンジした話

はじめまして、Adacchiといいます。
現在3年目で、Azureを中心にクラウドやAI、VBでアプリ開発などをしています。

アウトプットの練習も兼ねて記事を執筆したいと思います。

今回は文系からプログラム経験なしで入社した私が、入社1年目(2023年3月)にG検定を受験したときの話になります。

# G検定とは
検定を主催するJDLAの公式サイトに説明がありますので、ご覧ください。

https://www.jdla.org/certificate/general/

# 勉強方法
①テキストを読んでインプット
「ディープラーニングG検定公式テキスト」を最初に1周読み、問題集を一通り解いた後でもう1周読み直しました。

https://www.amazon.co.jp/dp/4297129264?ref=cm_sw_r_ffobk_mwn_dp_Y7P9TPWX8C54CTEMASCP_1&ref_=cm_sw_r_ffobk_mwn_dp_Y7P9TPWX8C54CTEMASCP_1&social_share=cm_sw_r_ffobk_mwn_dp_Y7P9TPWX8C54CTEMASCP_1&language=en_US&bestFormat=true&dplnkId=f89446e0-6a1a-4409-a8af-868ad6492af1&nodl=1

②問題集でアウトプット
テキストを1周した後に「最短突破 ディープラーニングG検定(ジェネラリスト) 問題集 第2版」の問題を一通り解いて現状を把握し、2周目はテキスト1章ごとに該当分野の問題を解きました。

https://www.amazon.co.jp/dp/4297129264?ref=cm_sw_r_ffobk_mwn_dp_Y7P9TPWX8C54CTEMASCP_1&ref_=cm_sw_r_ffobk_mwn_dp_Y7P9TPWX8C54CTEMASCP_1&social_share=cm_sw_r_ffobk_mwn_dp_Y7P9TPWX8C54CTEMASCP_1&language=en_US&bestFormat=true&dplnkId=f89446e0-6a1a-4409-a8af-868ad6492af1&nodl=1

③Webの模擬試験で学習
問題集を解き終えた後は、Study AIの模擬試験で学習していました。
出先や移動中にも手軽にできるので、6〜7周してほぼ満点が取れるまで学習していました。

https://study-ai.com/generalist/

# 試験までの勉強期間
勉強着手が12月でしたので、コツコツと勉強することにしました。
平日を中心に1日1時間ほど勉強していました。休日は移動中くらいしか出来ていませんでしたが、試験が近づくと3時間は勉強するようにしていました。

# 試験当日の流れ
自宅受験でしたので、試験開始の30分前にはインターネットケーブルをPCに接続し、準備していました。

試験開始後は、問題数がかなり多いため、約90分でまず一通り問題を解きました。
その上で、残り30分で見直すようにしていました。
見直しでは全く分からない問題よりも、記憶が曖昧なものや2択で迷うものに時間を割き、より得点しやすいように考えていました。

# 結果
試験日(2023/03/03)から約2.5週間後の3/20に結果通知がありました。

分野別の得点率は以下の通りでした。
①人工知能:88%
②機械学習:78%
③ディープラーニング概要:96%
④ディープラーニングの手法:82%
⑤ディープラーニングの社会実装:100%
⑥数理:50%
⑦法律:89%

数理系が低いですが、他分野で得点して何とか合格できました。

# 終わりに
基礎的な知識を身に付けられたことで、周りのエンジニアの話が分かるようになり、勉強して良かったと感じています。

拙い文章で恐縮ですが、お読みいただきありがとうございました！
Playwrightに軽く入門してみる

ローカルでスクレイピングをしたい場面が出てきたので、Playwrightに入門しつつローカル上でWebサイトへアクセスする処理を試してみます。

https://playwright.dev/docs/intro


## インストールしテストを試す

新しくディレクトリを作り、そこでnpm initでインストールします。

```sh
mkdir scrap
cd scrap
npm init playwright@latest
```

下記のようなディレクトリ構成が作成されます。

```
playwright.config.ts
package.json
package-lock.json
tests/
  example.spec.ts
tests-examples/
  demo-todo-app.spec.ts
```


表示通り、下記を実行するとテストがヘッドレスで実行されます。

```sh
npx playwright test 
```

show-reportコマンドを叩くことで、結果をブラウザ上にUIで表示できます。

```sh
npx playwright show-report
```

リスト | 詳細画面
--- | --- 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3589058/30a2ff9e-409b-2965-24fa-ce31b735adc0.png) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3589058/08ab996f-f8df-edc1-b8c5-11a00c0de48e.png)



## スクレイピングしてみる

今回はスクレイピングしたいので、playwrightを別途インストールします。

```sh
npm i playwright
```

下記のようなjavascriptファイルを作成します。
ページを開き、タイトルの取得、スクリーンショットの保存までを行っています。

```js
import { chromium } from 'playwright'; 

(async () => {
  let browser = null;
  let page = null;

  try {
    // ヘッドレスモードをオフにしてブラウザを起動
    browser = await chromium.launch({
      headless: false, // ヘッドレスモードをオフ
    });

    const context = await browser.newContext(); 
    page = await context.newPage();

    // 指定したURLを開く
    await page.goto('https://example.com');
    console.log('ページが開かれました！');

    // サンプル操作: ページタイトルを取得して表示
    const title = await page.title();
    console.log(`ページタイトル: ${title}`);

    // サンプル操作: スクリーンショットを撮る
    await page.screenshot({ path: 'example.png' });
    console.log('スクリーンショットが保存されました！');

    // 必要に応じて、ページ内の要素を操作する
    // 例: 特定のボタンをクリック
    // await page.click('text="More information..."');

  } catch (error) {
    console.error('エラーが発生しました:', error);
  } finally {
    // ブラウザを閉じる
    if (browser) {
      await browser.close();
    }
  }
})();
```

launchでヘッドレスモードをオフにすることで、実際にブラウザが起動し、スクリーンショットを取得する処理を行っています。
処理が一瞬なので、ブラウザの表示は一瞬です。
3秒待つなどの処理を入れるとわかりやすいです。

```javascript 
browser = await chromium.launch({
  headless: false, // ヘッドレスモードをオフ
});
```


## 普段使っているChromeのProfileを使ってみる


chromium.launchをlaunchPersistentContextにし、プロファイルとChromeのパスを渡します。

パスの場所は、chrome://version/へブラウザからアクセスすることで取得できます。

注意点として、useDataDirは親ディレクトリを選ぶ必要があります。

```js

    // プロファイルと実行可能ファイルのパスを指定
    const userDataDir = '/Users/name/Library/Application Support/Google/Chrome/';
    const executablePath = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';

    // ヘッドレスモードをオフにしてブラウザを起動
    context = await chromium.launchPersistentContext(userDataDir, {
      headless: false,
      executablePath: executablePath,
    });

```

https://playwright.dev/docs/api/class-browsertype#browser-type-launch-persistent-context-option-user-data-dir

この状態で node index.jsを叩くことで、普段使っているユーザープロフィールでブラウザ操作ができるはずです。
React勉強メモ

React条件分岐 Trueだったら ? の後のコードを実行 Falseだったら : の後のコードを実行
例: {expression.length > 0 ? expression.join("") : count}　みたいな

join(" ")は配列の要素を空白で区切って結合する関数

==========================================================
型のエラーが出たら、とにかく明示!!

============================================================
この書き方は丸暗記でもいいかも
const lastElement = expression[expression.length - 1];

if (!["+", "-", "*", "/"].includes(String(lastElement))) {
  setExpression([...expression, operator]);
} else {
  console.log("すでに演算子が入力されています");
}

要はexpressionのラストに記号が含まれて"いない"なら、expressionに operatorを追加して
setExpressionに反映って流れ。　

結論　→→ ! は　「〇〇じゃなかったら」　
!true 「trueじゃなかったら」
!false 「falseじゃなかったら」

要勉強
ABC262 Dの解法メモ【Ruby】

入水目指して過去挑戦して解けてないAtCoder Problems上でDifficultyが水色の問題を解いていく。

# [ABC262 D: I Hate Non-integer Number](https://atcoder.jp/contests/abc262/tasks/abc262_d)概要

長さNの整数列の部分列のうち、要素の平均が整数になる部分列の数を求める問題。

# 解法イメージ

$ 2^{100} = 2^{10 \times 10} = 1024^{10} \fallingdotseq 10^{3 \times 10} $なので全パターンを数え上げるのは制限時間内には間に合わない。
$ i $個の整数の平均が整数になるということは和を$ i $で割った時の余りが0になるので、各$ i $に対して各整数の剰余を管理すればよさそう。
$ 1 \le N \le 100 $であり部分列の和を計算するのでDPが使えそうなので検討してみる。

各$ i $に対して部分和のDPを考えるので、$ j $番目までの整数から$ k $個の整数を選択した場合として考える。
今回は$ i $で割った時の余りが0になる個数を計算したいので、$ k $個の和の剰余($ mod\ i $)が$ l $となる部分列の個数を管理してあげると、$ l^{'} \equiv l - A_j \  (mod\ i)$とすると
```math
dp[j][k][l] = \left\{
\begin{array}{ll}
dp[j-1][k][l] & (k = 0) \\
dp[j-1][k][l] + dp[j-1][k-1][l^{'}] & (k \gt 0) \\
dp[j-1][k-1][l^{'}] & (k = j)
\end{array}
\right. 
```
で計算できる。

求めたいのは$ dp[N][i][0] $なので、これらを各$ i $について求めた合計値を出力すればよい。

# 実装例

```ruby
n = gets.to_i
arr = gets.split.map(&:to_i)
mod = 998244353

c = 0
# dp[0]は固定で以降は毎回再計算されるのでiのループで初期化をする必要はない
dp = Array.new(n + 1) { Array.new(n + 1) { Array.new(n) { 0 }}}
dp[0][0][0] = 1
(1..n).each do |i| # i個の平均が整数になるケース
  (1..n).each do |j| # j番目の要素までで
    a = arr[j - 1]
    ([i, j].min+1).times do |k|| # k個の要素を足したときに
      i.times do |l|   # iで割った時の余りがlになるもの
        # dp[j-1][-1]は常に0の配列になるので問題ない
        dp[j][k][l] = (dp[j-1][k][l] + dp[j-1][k-1][(l-a)%i]) % mod
      end
    end
  end
  c = (c + dp[n][i][0]) % mod
end
puts c
```
便利なスクロールバーを紹介

# コード
https://gist.github.com/comefrombottom/3a4696983ae6fb73e265011ebdde5be1
📃

# 動作
https://x.com/camefrombottom/status/1863894548042448988

# 変数の意味
![スクリーンショット 2024-12-03 195122.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620250/85d315e4-eeed-f497-cc8a-856caa612793.png)

コンストラクタ引数はそれぞれこの図のような意味があります。

# 中身のちょっと非自明なところを解説

`.scroll✕✕✕To()`や`.scrollBy()`、`.scrollAdd()`によって好きな座標分移動させることができますが、中身はただスクロールバーの速度を変えているだけです。

:::note
`.scrollBy()`は速度を指定し、`.scrollAdd()`速度を加算します。
素早く二回連続で呼んだときにちゃんと二回分進んでほしい場合は`.scrollAdd()`を使います。
:::

つまり、`.scrollBy(100)`は描画場所を丁度100進めたところでピッタリ止まってくれるような速度を算出して速度に代入しているわけです。

スクロールバーはどのような挙動をしているかというと、

座標の更新：
`viewTop += viewVelocity * stepTime;`

速度の更新：
`viewVelocity += -viewVelocity * stepTime * resistance;`

に従って減速しながら`viewTop`をずらしていきます。

$T$ : `viewTop` , $V$ : `viewVelocity` , $S$ : `stepTime` , $R$ : `resistance`
と表します。

$$\alpha = 1 - RS$$

とすると、速度は$V→V\alpha→V\alpha^2→V\alpha^3→…$と減速していきます。

よって位置は、
$$ΔT=VS+V\alpha S+V\alpha^2 S +V\alpha^3 S +…$$

で計算でき、無限等比級数の和であることが分かります。

$$ΔT=VS+VS\alpha+VS\alpha^2 +VS\alpha^3 +…$$

$$\alpha ΔT=VS\alpha+VS\alpha^2 +VS\alpha^3 +…$$

$$(1-\alpha)ΔT=VS$$

$\alpha = 1 - RS$を代入し、

$$RSΔT=VS$$

$$V=RΔT$$

$ΔT$動かすための$V$を求めることができました。なんと$S$が消えてとてもシンプルな式になりました！

コードを見てみましょう。
```cpp
void scrollBy(double h) {
	viewVelocity = resistance * h;
}
 ```

 なんとこれだけで`h`だけスクロールさせる処理になっています。驚きですね。

 正直何か目標座標的なメンバ変数を持たせて追従モードみたいなものを実装した方が色々自由に制御できそうですが、こんなに簡潔に表現できるならこの方式を採用せざるを得ませんね。

 以上
【Rustのまほう2】#4 おすすめ参考資料とBevyテンプレート

# おすすめ参考資料

開発やこのシリーズの記事を書くにあたって私が参考にした資料をいくつか挙げておきます。Bevyは公式チュートリアルは本当に薄いぺらっぺらで、これだけではウォーミングアップにもなりません。

https://bevyengine.org/learn/quick-start/getting-started/

どちらかというと、サンプルコードを読んで学べ！というストロングスタイルだと思われます。

https://bevyengine.org/examples/

まとまった量の参考資料が欲しいなら、非公式ながらこちらの Unofficial Bevy Cheat Book がとても参考になります。

https://bevy-cheatbook.github.io/

こちらのTainted Codersというサイトにもかなりの量の文献があります。特に物理エンジンについても触れているのが非常にありがたいです。

https://taintedcoders.com/




# Bevyのサードパーティプラグイン

Bevyのコアは小さめなので、実際の開発ではサードパーティーのプラグイン(ライブラリ)に頼ることが多いと思います。プラグインは以下のページで探すのが早いです。

https://bevyengine.org/assets/

こちらのページに載っていないものもたくさんあるはずなので、もちろん [GitHub](https://github.com/topics/bevy) や [crates.io](https://crates.io/keywords/bevy) で探すのもいいと思います。私が使っているプラグインは、このシリーズの記事で随時紹介していきたいと思います。





# Bevyのプロジェクトテンプレート

サクッとBevyの開発環境を用意するには、こちらのテンプレートプロジェクトを複製するのが手っ取り早いと思います。

https://github.com/NiklasEi/bevy_game_template

私は最初このプロジェクトテンプレートの存在を知らなかったので自力で設定して始めましたが、けっこう大変でした。このあたりは好みによるとは思うのですが、いきなり大きなコードベースをポイっと渡されるとどこから見たらいいか迷子になりやすいですし、私は自力で開発環境を設定して始めるほうが知識が身に付きやすいので好きかもです。
いいかげんちゃんと理解したいGradle(第一章)

# はじめに
いつも開発する際に、お世話になっているGradleさん。
buildや実行やUnitテスト実行など必要な操作はわかっているが、手順としてなんとなくわかっているだけで、ちゃんと理解せずに使ってしまっている。
エラーが起きた時、調査に時間がかかったり、やりたいことはできたけど、ここに書いていいのかなとか、もっといいやり方があるのではといつも思ってはいるが、ちゃんと知らないのでいつもまーいっかとなって逃げてしまっている。
**いいかげんちゃんと理解したい**なと思ったので、アウトプットして理解を深めGradleで幸せなエンジニアライフを送りたいと思いました。

# とりあえず公式のチュートリアル
今回のバージョンは8.4でやります。  
[チュートリアル](https://docs.gradle.org/8.4/userguide/part1_gradle_init.html)

## Initialize the project
まずはプロジェクトを初期化します。
```
.
├── app // プロジェクトディレクト
│   ├── build.gradle.kts // プロジェクトのビルドスクリプト
│   └── src // ソースディレクトリ
├── gradle
│   ├── libs.versions.toml // バージョンカタログ
│   └── wrapper // Gradleのwrapper jarが入っているディレクトリ
├── gradlew // Gradleのwrapper(mac,linux実行用)
├── gradlew.bat // Gradleのwrapper(windows用)
└── settings.gradle.kts // サブプロジェクトの設定ファイル
```
### gradle wrapper
Gradleラッパーは、プロジェクトごとに特定のGradleバージョンを指定し、そのバージョンでビルドを実行できるようにするツールです。  
これにより、チーム内でのバージョン不一致を防ぎ、安定したビルド環境を維持できます。

### settings.gradle.kts
`settings.gradle.kts`はプロジェクトのメタ情報や構造を設定します。
```
rootProject.name = "tutorial"
```
対象のプロジェクトの名前を設定します。

#### マルチプロジェクト構成の定義
```
include("app")
```
これによって、gradleは`app`ディレクトリをサブプロジェクトとして認識します。
#### プラグイン管理
Gradleプラグインを設定します。
```kotlin
plugins {
    // Apply the foojay-resolver plugin to allow automatic download of JDKs
    id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
```
#### ビルドスクリプトのリポジトリ設定
使用する依存関係やプラグインを検索するリポジトリを指定します。
```kotlin
dependencyResolutionManagement {
  versionCatalogs {
    create("libs") {
      from(files("../gradle/libs.versions.toml"))
    }
  }
}
```

### build.gradle.kts
Gradleのビルドスクリプトは、プロジェクトのビルド手順や依存関係を定義する重要なファイルです。
このスクリプトを通じて、タスクの定義やプラグインの適用、依存ライブラリの指定などを行います。  

ルートに`build.gradle.kts`はないのが推奨みたいです。
良くspringbootのプロジェクトを作るときに`build.gradle.kts`がルートにあるので、これはへーって感じですね。
```
Some builds may contain a build.gradle.kts file in the root project but this is NOT recommended.
```
理由はおそらく、プロジェクトが大きくなると、ルートに`build.gradle.kts`があると、ルートのビルドスクリプトが肥大化してしまうからとか、
プロジェクトの構成が明確になりエンジニアがパッと見でわかりやすいとか、そういう理由があるのかなと思いました。
チュートリアルにはただ非推奨とだけ書いてあったので、従いうようにします。

### buildの概念
以下のような一緒に処理できる関連するソフトウェア全体のことを指します。
- ビルド（ソースコードを実行可能な形式に変換する作業）
  - jarファイルにする
- テスト（ソフトウェアが正しく動作するか確認する作業）
  - JUnitなど
- リリース（最終的にソフトウェアを配布する作業）
  - Maven Centralにデプロイする
- ライブラリ: ソフトウェアの一部として再利用可能なコード
  - JDBCなど
- プラグイン: 機能を拡張するモジュール
  - flywayなど
- ビルドツール: ビルドプロセスをサポートするソフトウェア
  - Gradle, Mavenなど

ビルドっていうとソースコードを実行可能な形式にする作業だけをイメージしていましたが、
他のものも含めてビルドという場合もあるんですね。

### プロジェクトの概念
**project（プロジェクト） は、アーキテクチャ全体を構成する1つの部品**
- ライブラリ: 再利用可能なコードの集合
- アプリケーション: 完成したソフトウェア（モバイルアプリやWebアプリなど）
- Gradleプラグイン: Gradleの機能を拡張するモジュール

必要に応じて、他のプロジェクトを含むことができます。
- マルチプロジェクト: 複数のプロジェクトを含むプロジェクト

# まとめ
ビルドとは、実行可能な形式にするところから〜公開するところまでの一連の流れまでの話で、
プロジェクトは、アーキテクチャのパーツの一部
という概念がわかりました。
gradlewarpperを使えばバージョンをみんなで揃えることができて便利
settings.gradle.ktsがプロジェクト全体のメタ情報を設定する重要なファイル。
こんなのが第一章のまとめになりますかね。
動画編集には番号ふってリネームのが鍵🔑

# ちょこっと業務を簡略化したい
　この記事では、ちょこっと効率化させたいことをプログラミングやツールをつかって解決していきます
ちょこっと削減した時間を、もっと人生楽しくなることに使いましょう！

# 本日のお題
## 指定したフォルダ内のすべてのファイルをリネーム

Youtube動画編集中、プロジェクトパネルに同じような動画や画像を載せる時、リネームしていた方がとってもやりやすいです。
意外とこういうちょっとした技術が大切🚨
これだと何かわからないし、共有もできない、でも手作業はめんどくさい

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636287/8efe1ea7-6a15-4558-ba2d-bc767851a90f.png" width=80%>


## pythonで解決してみた
<環境>
🖥 Mac
🐍 python 3.12.5
🏆 VSCode

このバラバラな名前とファイルの種類を「編集＋数字」にしたい。
イメージ↓


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636287/627a9923-1f45-ef8f-d7b2-efc1fe25a1a0.png" width=80%>



↓
0.01秒で完成

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636287/d2e51c98-5f2b-723d-330a-3a38b22d76db.png" width=80%>




## 共有コード


 ```python:python
import os

def rename_files_in_folder(folder_path):
    files = os.listdir(folder_path)
    
    # ファイルを番号付きでリネーム
    for index, file_name in enumerate(files, start=1):
        old_file_path = os.path.join(folder_path, file_name)
        if os.path.isdir(old_file_path):
            continue
        
        # 「編集」は、任意
        file_extension = os.path.splitext(file_name)[1]  # .jpg, .png など
        new_file_name = f"編集{index}{file_extension}"
        new_file_path = os.path.join(folder_path, new_file_name)
        os.rename(old_file_path, new_file_path)
        print(f"Renamed: {old_file_path} -> {new_file_path}")

# ファイル名変更
folder_path = r'あなたのファイルパス'
rename_files_in_folder(folder_path)

 ```

 

# 最後に
このコードをベースに修正し、業務をちょこっと楽にしてみてください〜

今後、このようにちょっとした効率化のための情報を載せます。あなたの業務でも役立つこと願っています💓
MZmine4によるmzwizardを用いた質量分析データ解析

弊研究室では、質量分析データの解析のためのソフトウェア[MS-DIAL](https://systemsomicslab.github.io/compms/msdial/main.html)を開発しています（後日いろいろな記事が上がるはずです）が、ここでは質量分析データ解析ソフトウェア[MZmine](https://mzio.io/mzmine-news/)を用いた質量分析データの解析方法について紹介します。

※MS-DIALのチュートリアルは[こちら](https://systemsomicslab.github.io/mtbinfo.github.io/MS-DIAL/tutorial.html)。
※MZmineの公式ドキュメントは[こちら](https://mzmine.github.io/mzmine_documentation/index.html)。

# 前提
この記事は、ノンターゲットリピドミクスデータでアライメント処理したかった人（私）のための備忘録です。ついでに、自作ライブラリでのアノテーションをつけているので、そのような需要がある人には参考になるかもしれません。

# MZmine4のダウンロード
ここでは、[MZmineのホームページ](https://mzio.io/mzmine-news/)上で、mzmine communityをクリックして、[MZmine4.4.0](https://github.com/mzmine/mzmine/releases/tag/v4.4.0)を入手した。解凍し、起動する。
起動したら、とりあえずアカウントを作成し、ログインしてみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929126/d677fbad-6d3f-6eca-ef01-eca39a8d2500.png)
そしたらきっとこんな感じになるはず。

# 解析全般
まず、上記画面内のmzwizardをクリックする。
※[mzwizard](https://mzmine.github.io/mzmine_documentation/wizard.html)は、複雑なワークフローの設定を簡素化するための機能。

そしたら、以下のような画面が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929126/861a3bb0-4618-548c-f531-a0c795ed4e2c.png)
　　
右上部分の分析条件をタブで選択し、右下の設定項目を左から順に設定する。

　　
・**Data**に使用するデータを置く。今回は、"D:\data\pos_data1.wiff"、"D:\data\pos_data2.wiff"を使用。
・**HPLC**、**QTOF**、**Filter**など、必要であればパラメーターを設定する。
・**Annotation**にアノテーションをつけるライブラリを置く。今回は"D:\data\library_pos.msp"を使用する。mspの中身は以下の体裁。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929126/7c6781b4-7168-299a-08bb-f96dac5804c9.png)
・**DDA**や**DIA**で、Export pathを設定する。

ここまでできたらCreate batchを押すと、以下のような画面が出る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929126/f0e783c8-b926-d371-df2b-b9246e52e077.png)

使用したいモジュールを選択し、各項目をダブルクリックして詳細設定をする。
各パラメーターはいい感じにしていただくとして、たとえば、今回であればImport MS dataの中身は以下のよう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929126/c6edd288-593f-a6ec-61e3-4541873d4f06.png)

諸々設定ができたら、OKを押すと解析が走る。

解析が終わるといろいろ見れるようになる。例えば、Raw data overview。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929126/baeaf6cf-518b-46bb-45d6-8b74e9374de4.png)
AlignmenのFeature listはこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929126/12517bc4-a47e-7826-406e-fe939e579702.png)

BatchのところでCSV出力とかを選択していれば、上記のようなAlignmentの結果は既に指定したPathに出力されている。

# さいごに
これからも研究がんばります！(^_-)-☆
【TIPS】マップリストにpandasのfillnaっぽい欠損値置換処理をする

この記事は、[Elixir Advent Calendar 2024 シリーズ4](https://qiita.com/advent-calendar/2024/elixir) の8日目です

---

【本コラムは、5分で読め、2分で試せます】

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

pandasのfillnaは、AI・LLMの前処理における「欠損値置換処理」を実現します

これにより、数値しか行列処理では扱えないAI・LLMに対し、数値では無いNaN（Elixirだとnilに相当）を数値化することで、行列処理を可能とし、傾向分析を可能とします

```diff_elixir
maplist = [
  %{"c1" => "v1", "c2" => 2, "c3" => 3}, 
  %{"c1" => "v2", "c2" => nil, "c3" => 6}, 
  %{"c1" => "v3", "c2" => 5, "c3" => nil}
]
fill = 0

結果：[
  %{"c1" => "v1", "c2" => 2, "c3" => 3}, 
  %{"c1" => "v2", "c2" => 0, "c3" => 6}, 
  %{"c1" => "v3", "c2" => 5, "c3" => 0}
]
```

これを実装すると、こんなコードになります

```diff_elixir
maplist = [
  %{"c1" => "v1", "c2" => 2, "c3" => 3}, 
  %{"c1" => "v2", "c2" => nil, "c3" => 6}, 
  %{"c1" => "v3", "c2" => 5, "c3" => nil}
]
keys = maplist |> List.first |> Map.keys
fill = 0

keys
|> Enum.reduce(maplist, fn key, acc -> 
    acc
    |> Enum.map(& Map.update!(&1, key, fn v -> 
        if v == nil do fill else v end 
      end))
  end)

結果：[
  %{"c1" => "v1", "c2" => 2, "c3" => 3}, 
  %{"c1" => "v2", "c2" => 0, "c3" => 6}, 
  %{"c1" => "v3", "c2" => 5, "c3" => 0}
]
```

任意の列指定もできます

```diff_elixir
maplist = [
  %{"c1" => "v1", "c2" => 2, "c3" => 3}, 
  %{"c1" => "v2", "c2" => nil, "c3" => 6}, 
  %{"c1" => "v3", "c2" => 5, "c3" => nil}
]
keys = ["c1", "c3"]
fill = 0

keys
|> Enum.reduce(maplist, fn key, acc -> 
    acc
    |> Enum.map(& Map.update!(&1, key, fn v -> 
        if v == nil do fill else v end 
      end))
  end)

結果：[
  %{"c1" => "v1", "c2" => 2, "c3" => 3}, 
  %{"c1" => "v2", "c2" => nil, "c3" => 6}, 
  %{"c1" => "v3", "c2" => 5, "c3" => 0}
]
```

# p.s.このコラムが、面白かったり、役に立ったら…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/907a8695-4d83-1b5c-8052-d0ce52de5f66.png) にて、どうぞ応援よろしくお願いします :bow:
VFXGraphsがWebビルドに対応したので、早速ビルドをしてみた!

https://qiita.com/advent-calendar/2024/unity


この記事は[Unity Advent Calendar 2024](https://qiita.com/advent-calendar/2024/unity) 12/3の記事です

### この記事について

この記事では最近公開されたUnity6のVFXGraphがWebビルド対応をしたとのことで、VFXGraphのサンプルエフェクトをWebビルドすることを目的としています

先に伝えると、ProjectSettingの「webGLEnableWebGPU」の設定でほとんどの方が躓くと思うので、もしVFXGraphsをWebビルドで出力する予定がある方は確認をおすすめします

### VFXGraphとは

https://learning.unity3d.jp/3276/

> Visual Effect Graph（VFX Graph）はノードベースのビジュアルエフェクトエディターです。 旧来のパーティクルエディタである Particle System と使用すべき用途は似ていますが、大きな違いはシミュレーションにGPUを使っており、大量のパーティクルの複雑な処理を高速で行うことができます。

### 手順

#### 1)プロジェクト作成

今回はUnity6000.0.28f1で作成します
![UnityHub_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393006/759e0644-bd1e-5710-e0f8-fdc061ee7c6f.png)

プロジェクト作成後の画面はこのような形

![Unity_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393006/9e6b90ca-4249-42ac-961e-7096ca1d3dd6.png)

#### 2)VFXGraphのインストール

VFXGraphをPackageManagerから取得します

![PM_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393006/415644f9-e292-826a-1d24-beb7a605a9c0.png)

PackageManagerからUnityRegistryを選んで「Visual Effect Graph」をインストール
![PM_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393006/c87ada56-a767-f573-b951-245623c54307.png)

#### 3)VFXGraphのサンプルの配置

VFXGraphをAssetsウィンドウ上で右クリックから作成
![VFX_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393006/901d3a31-47a2-fe5c-f651-9383824b0ea9.png)

テンプレから、今回は「FireWork」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393006/2f13adfa-ae42-e643-dc9e-fae3bf746cb3.png)

Hierarchyに作成したVFXGraphを配置して実行確認
![File_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393006/5242a95b-c841-b166-3abe-03818d6eb749.png)

少し背景のカメラ設定を触っていますが、こちらのようなエフェクトが表示されるはずです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393006/8d4ccefb-31ea-2854-bf52-48ff2bf6a3cc.png)


#### 4)webビルド

WebGPUProjectSettingsフォルダ以下にあるProjectSetting.Assetファイルをエディタで開いて、「webGLEnableWebGPU」の項目を「１」に設定し、Experimentalの設定を使えるようにします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393006/ef679354-8022-ce05-0050-ed41128f16e3.png)

Experimentalについてはこちらをご確認ください

https://docs.unity3d.com/ja/2021.1/Manual/pack-exp.html

ProjectSettingからGraphicsAPIをWebGPUに設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393006/c8d7743d-22e5-f96a-6b54-7894fe092127.png)

BuildProfilesからwebビルドを実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393006/df4c87e2-7029-e30f-546b-1d0868bc2bff.png)

#### 6)webビルド結果

無事VFXGraphのエフェクトが表示されました

![Movie_001.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393006/7d9a6385-2248-1a0f-e439-2abd227ece95.gif)


### まとめ

Unity6のVFXGraphをWebで表示させることが出来ました
「webGLEnableWebGPU」の項目以外では特に躓くことはないと思います

今月もUnity1Weekがあるので、ぜひVFXGraphを用いてイケイケなエフェクトで自分のゲームを装飾していってください！

https://unityroom.com/unity1weeks
【Rustのまほう2】#3 デバッグ用プラグイン

開発をはじめるにあたって、まずは実行時に内部で何が起こっているかを把握する手段が必要になります。いきなりですが、Bevyで使えるデバッグ用の手段を紹介しておきます。

# ロギング用マクロ

いわゆるprintfデバッグをしたいとき、Rust標準の`println!`だとブラウザ上で出力を表示できません。そこで、Bevyは`debug!`などの独自のロギング用マクロを数種類提供しています。

```rust
trace!("very noisy");
debug!("helpful for debugging");
info!("helpful information that is worth printing by default");
warn!("something bad happened that isn't a failure, but thats worth calling out");
error!("something failed");
```


https://bevyengine.org/examples/application/logs/

これだとブラウザで実行したときもちゃんと出力できますし、ログの時刻やログレベル、ソースコード上の位置なども出力してくれるので、デバッグ時にとても便利です。




# bevy-inspector-egui

ゲームが起動すると内部では大量のエンティティが作成されてツリー構造が形成されますが、BevyはGUIエディタを持たないので、実行中に内部で何が起こっているのかを把握しづらいです。bevy-inspector-eguiというプラグインを使うと、現在のワールドの中に含まれるエンティティの構造をGUIで表示できます。

https://github.com/jakobhellermann/bevy-inspector-egui



また、エンティティの内部のパラメータを手動でいじることもできます。例えば、ゲーム内のライトの明るさというのは実際に実行してみないとどう見えるのかわかりませんが、明るさの定数を変えながら何度も再実行するのは面倒です。そういうときにこのプラグインを使うと、即興でデータを修正して見栄えを確認することができます。

以下は実際に使ってみたときのスクリーンショットですが、左上のウィンドウにエンティティがツリー上に表示されていて、そのなかに含まれるコンポーネントの一覧も表示されています。`Transform`コンポーネントの`translation`は`60.268`、`-671.202`などという数が表示されていますが、これはプレイヤーキャラクターのX座標とY座標です。GUI上でこの数値を手動でいじることもできて、テキストボックス上をマウスでドラッグして数値を変えると、即座に反映されて本当に画面上のプレイヤーキャラクターの位置が変わります。便利！

![スクリーンショット 2024-12-03 231736.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64695/1a650800-41a0-9967-a8f7-29c1cdab9cb3.png)

エンティティに`Name`というコンポーネントを追加すると、このGUI上で表示されるときの名前を設定することができます。私のゲームの場合、プレイヤーキャラクターには`Name::new("witch")`というコンポーネントを追加してあるので、この画面上でも`witch`という名前で表示されます。コンポーネントの名前でフィルタリングできるので、大量にエンティティがあっても名前で絞り込んでたどり着くことができます。便利！






# lldb

Rustではlldbでデバッグできるわけで、もちろんBevyでも使えます。私が試したら動くことは動くのですが激重で、そのまままったく動かなくなることもしばしばでした。そのため常用はせず、どうしても必要な時に補助的に使うに留まっています。Rust初心者すぎてlldbのデバッグに良い方法があるのかわかりませんでした。たすけてください。


# 参考文献

- Rustプログラムのデバッグ辛すぎ問題 https://qiita.com/k0kubun/items/766dc15773ec73925163
python_リスト、タプル、辞書の違い

# python勉強始めて最初の壁
pythonの勉強をスタートして最初に頭こんがらがった概念でした。
自分の備忘用且つアウトプット用として記事に残します。
同じ悩みを持つ方の手助けになれば嬉しいです。

::: note warn
本記事は誤りが多い可能性が高いです。
初心者だったあの頃を思い出しながら笑ってネタに昇華してください。。
:::

# 【結論】データを格納/操作する為のオブジェクト
名前が異なるという事はそれぞれ宣言の方法も異なると考えて良いです。
かなりざっくりそれぞれの宣言方法を下にまとめてみました。

### リスト
```python:create_list.py
list = [1,2,3] #list型オブジェクトの宣言とデータ格納
print(list) # 出力結果 [1,2,3]
```

### タプル
```python:create_tuple.py
tuple = (1,2,3) #タプル型オブジェクトの宣言とデータ格納
print(tuple) # 出力結果 (1,2,3)
```

### 辞書
この方だけ宣言方法がちょっと複雑です。
値に紐づくキーが必要と覚えちゃいます。
```python:create_dict.py
dict = {1:"a",2:"b",3:"c"} # 辞書型オブジェクトの宣言とデータ格納
print(dict) # 出力結果 {1:"a",2:"b",3:"c"}
```

ただ、実際に↑にまとめた方法での使い方はほとんど無いはずです。
単にprintするだけではそれぞれのデータ操作が全然できていない為です。

# 実際の使い方
オブジェクトの宣言方法については前段の違いを見ていただければと思います。
ではどういった違いが出てくるのかもう少し詳しくオブジェクト別にまとめます。
(オブジェクト別のファイル名は前段と同じです)
## リストとタプル
### リスト
```python:list.py
#list = [1,2,3] #list型オブジェクトの宣言とデータ格納
    print(list[2]) # 出力結果 3
```
### タプル
```python:create_tuple.py
#tuple = (1,2,3) #タプル型オブジェクトの宣言とデータ格納
print(tuple[2]) # 出力結果 3
```
...一緒、、、(ちなみに[ ]内の数値が負の数だと要素の後ろから取り出します)

もちろん違いはあります。
**ミュータブル：変更可能**か**イミュータブル：変更不可能**かによる違いです。
ここでいう変更可能/不可能というのは要素の値を更新できるか否かと考えて良さそうです。
<dl>
    <ul>
        <li>リスト：ミュータブル（変更可能）
        <li>タプル：イミュータブル（変更不可能）
    </ul>
</dl>
タプル型オブジェクトの要素を更新しようとするとエラーが表示されます。

```python:tuple.py
#tuple = (1,2,3) #タプル型オブジェクトの宣言とデータ格納
tuple[2] = 0
print(tuple[2]) # エラー出力「TypeError: 'tuple' object does not support item assignment」
```

、、、リストだけで良くない？
と思いましたがオブジェクトが区別されている以上タプルにも良さあります。
<dl>
    <ul>
        <li><dt>不変だからこそ良い</dt>名前など一度入力された後に変更されてほしくないデータを格納するとき<br>また、辞書型のキーとして使えるという点もあります。<br>
        　例えば緯度経度と建物を紐づけて辞書型に格納する場合、緯度経度はそうそう変わらない、というか変わっちゃいけないのでタプル型で一度宣言してキーとして使うといった使い方も良いです
        <li><dt>処理速度が速い</dt>このメリットを享受することはめっちゃでかいデータを格納しない限り少ないかと思いますがリストよりは処理速度が速いそうです
    </ul>
</dl>

以上を踏まえてここぞというタイミングでそれぞれ使い勝手の良い方を使っちゃいましょう。

## 辞書
```python:create_dict.py
#dict = {1:"a",2:"b",3:"c"} # 辞書型オブジェクトの宣言とデータ格納
print(dict[2]) # 出力結果 b
```
リストやタプルと違って引数で指定したキーに紐づく値を引っ張ってきてくれます。
0相対とかそういった事も考えなくて良さそうです。
辞書型はミュータブル(変更可能)なオブジェクトです。
更により深く辞書型の辞書や、専用のメソッドを使って要素の追加(.append)や要素の削除(.pop)なんかもできたりします。

# 一旦ここまで
色々思い出しながら記事を書いていたので途中途中更にこんがらがってしまいましたが各オブジェクトの簡単な紹介と説明をさせていただきました。

今後も覚えていったことをどんどんアウトプットしようと思いますので目に留まったら見ていただけると嬉しいです。
ABC275Eを解いた【動的計画法,mod998244353】


筆者はレート800前後の茶～緑コーダ

ABC275のE問題を解いていく

https://atcoder.jp/contests/abc275/tasks/abc275_e

# 実装コード

この問題のポイントはmod998244353におけるMの逆数?(以下iM)を求めることらしい。
Python3.8以降の`pow`関数は剰余の計算に対応しているので、-1乗すればOK

```python:Mの逆元を求める例
mod = 998244353
inv = lambda x: pow(x, -1, mod)
iM = inv(M)
```

逆元を求めたあとは素直に動的計画法をすればいいようだ。
- dp[i][j]: i回コマを動かしたあとjマスにいる確率
- dp[0][0] = 1 : 初期値
- dp[i+1][j+m] = dp[i][j]*iM: jマスにいて、i回目のルーレットでmが出たときの遷移

```python:main.py
import sys
def rI(): return int(sys.stdin.readline().rstrip())
def rLI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def rI1(): return (int(sys.stdin.readline().rstrip())-1)
def rLI1(): return list(map(lambda a:int(a)-1,sys.stdin.readline().rstrip().split()))
def rS(): return sys.stdin.readline().rstrip()
def rLS(): return list(sys.stdin.readline().rstrip().split())
def err(*args): print(*args, file=sys.stderr)

class ModInt:
    def __init__(self, x, mod = 998244353):
        self.mod = mod
        self.x = x.x if isinstance(x, ModInt) else x % self.mod
    __str__ = lambda self:str(self.x)
    __repr__ = __str__
    __int__ = lambda self: self.x
    __index__ = __int__
    __add__ = lambda self, other: ModInt(self.x + ModInt(other).x)
    __sub__ = lambda self, other: ModInt(self.x - ModInt(other).x)
    __mul__ = lambda self, other: ModInt(self.x * ModInt(other).x)
    __pow__ = lambda self, other: ModInt(pow(self.x, ModInt(other).x, self.mod))
    __truediv__ = lambda self, other: ModInt(self.x * pow(ModInt(other).x, self.mod - 2, self.mod))
    __floordiv__ = lambda self, other: ModInt(self.x // ModInt(other).x)
    __lt__ = lambda self, other: self.x < ModInt(other).x
    __gt__ = lambda self, other: self.x > ModInt(other).x
    __le__ = lambda self, other: self.x <= ModInt(other).x
    __ge__ = lambda self, other: self.x >= ModInt(other).x
    __eq__ = lambda self, other: self.x == ModInt(other).x
    __ne__ = lambda self, other: self.x!= ModInt(other).x

class mint(ModInt):
    pass

mod = 998244353
inv = lambda x: pow(x, -1, mod)

def main():
    N, M, K = rLI()
    
    iM = inv(M)
    
    dp = [[mint(0)]*-~N for _ in range(K+1)]
    
    dp[0][0] = 1
    
    for i in range(K):
        for j0 in range(N):
            for m in range(M):
                j=j0+m+1
                if j > N:
                    j = 2*N-j
                dp[i+1][j]+=dp[i][j0]*iM
        dp[i+1][N]+=dp[i][N]
    ans = dp[K][N]
    print(ans)
    
if __name__ == '__main__':
    main()

```

# まとめ

ABC275Eを解くにあたり、動的計画法を使用した。

期待値をmod998244353で出力するという方式は最初よくわからなかったが、一旦イメージを掴めた気がするので今後似たような問題が出ても萎縮せずに解きたい。
AWS Backupの概要とメリットデメリット

## はじめに
クラウド環境におけるデータ保護は安定した運用に必ず必要になってきます。
AWS Backupはさまざまなサービスのバックアップを一元管理できるサービスです。
## AWS Backupとは
### 概要
- 自動化：バックアッププランを作成して、スケジュールを設定することで定期的にバックアップの実行が可能
- 一元管理：AWSリソースごとに異なる管理手法を統一
- クロスリージョン対応：別のAWSリージョンに複製することで災害復旧対策を強化

### バックアップできるリソース
| サービス | バックアップ内容 |
|:-:|:-:|
| Amazon EC2 | EBSボリュームのスナップショットをバックアップ |
| Amazon EBS | Elastic Block Storeのボリュームデータをバックアップ |
| Amazon EFS | Elastic File System（ファイルストレージ）のバックアップ |
| Amazon RDS | リレーショナルデータベース（MySQL、PostgreSQL、MariaDB、Oracle、SQL Server）の完全なバックアップ |
| Amazon Aurora | Auroraクラスターのバックアップ（MySQLおよびPostgreSQL互換） |
| Amazon DynamoDB | テーブルデータのバックアップ |
| Amazon FSx | FSx for Windows File Server、Lustre、OpenZFS、NetApp ONTAP |
| AWS Storage Gateway | Tape Gatewayを含むストレージゲートウェイボリューム |

### メリットとデメリット
#### メリット
- 管理の簡素化：複数のAWSリソースを単一のサービスでバックアップ・復元が可能
- 自動化：スケジュールポリシーで自動バックアップが可能
- 高いセキュリティ：AWS KMSによるバックアップデータの暗号化、データを保護
- 災害復旧の対応：クロスリージョンでのバックアップ機能で災害時の復旧が迅速に行える
- コスト効率：使用したストレージ量の応じたコストが発生。オンプレミスと比べるとコスト効率がいい。
#### デメリット
- 対応リソース制限：対応していないAWSサービスがある
- 学習コスト：初期設定での用語や設定方法の理解に時間がかかる
- データ転送コスト：クロスリージョンバックアップで、データ転送料金が発生して、運用コストが膨らむ場合がある

## まとめ
AWS Backupは、クラウド上でのデータ保護を効率化し、複数のAWSリソースを一元管理できるサービスです。セキュリティ、柔軟性、コスト効率などの多くのメリットがありますが、一方で学習コストや一部のリソース制限といったデメリットも存在します。

AWS Backupの利用により、災害復旧（DR）や運用効率の向上を図ることができます。