OmniAICreator/Qiita-1.07M huggingface dataset:
scriptタグを使いまわしたい

#どういうことか
いろんなHTMLに同じscriptタグ(js,css)を使いたい...!
ググっても出てこない...そんなあなたにお勧めです！
初投稿です。
#沼ってたとき
Document.write 非推奨
innerHTML 使えない
insertAdjacentHTML 使えない
#なぜ
セキュリティの関係で無効化されてるようです。
#解決策
createElementを使いましょう！
コードを書いてみました。

```js:head.js
var script;
var link;
const js = url => {
    script = document.createElement('script');
    script.src = url;
    document.head.appendChild(script);
}
const css = url => {
    link = document.createElement('link');
    script.href = url;
    script.rel = "stylesheet";
    document.head.appendChild(script);
}
//使用例
js("hoge.js");
js("https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.js")
css("hoge.css");
css("https://fonts.googleapis.com/css?family=M+PLUS+Rounded+1c");
```

```html:index.html
<head>
  <script src="head.js"></script>
</head>
```
相対パスも使えて便利です！
使えなかったらごめんなさい😥
UnityプロジェクトにFirebaseSDK導入後Android Gradleビルドエラー対策

# 環境
Windows 10
Unityバージョン：2020.3.15f2
Android/iOS関係モジュールはUnity Hub経由で導入。

# やったこと
【ゲーム作成】
- 2D Modileテンプレートでプロジェクト新規作成
- Unityプログラミング、実行（動作確認OK）
- player設定＞iOS/Androidビルド時の.NETバージョンを4.xに変更
- apkビルド、実行（動作確認OK）
【Firebase導入】
- 公式サイトからfirebase_unity_sdk_8.1.0.zipをダウンロード、解凍。
- 一個ずつインポート…
❌ FirebaseFunctions.unitypackage
こいつをインポートしたら、コンパイル時エラー出まくる。

# ビルドエラー対応
## `Configure project :launcher WARNING: The option setting 'android.enableR8=false' is deprecated`
trueでもfalseでもだめです。その行をコメントアウトしないといけない。
【解決】Project Settings＞Player＞Android＞Publish Settings＞Build＞Custom Gradle Properties Templateをチェック。表示されるファイルのR8該当行の先頭に#を追加▼
`#android.enableR8=**MINIFY_WITH_R_EIGHT**`

## `D8: Cannot fit requested classes in a single dex file (# methods: xxxxx > 65536) com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: The number of method references in a .dex file cannot exceed 64K.`
【解決】Project Settings＞Player＞Android＞Publish Settings＞Build＞Custom Launcher Gradle Templateをチェック。表示されるファイルに

```txt:build.gradle
android {
    defaultConfig {
        ...
        minSdkVersion 15
        targetSdkVersion 28
        multiDexEnabled true
    }
    ...
}

dependencies {
    implementation "androidx.multidex:multidex:2.0.1"
}
```

`multiDexEnabled true`と`implementation "androidx.multidex:multidex:2.0.1"`を追加。

#`launcher:checkReleaseDuplicateClasses`
```
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':launcher:checkReleaseDuplicateClasses'.
> 1 exception was raised by workers:
Duplicate class com.google.android.gms.internal.firebase_messaging.zza
found in modules jetified-com.google.firebase.firebase-iid-20.0.1-runtime.jar
(:com.google.firebase.firebase-iid-20.0.1:)
and jetified-com.google.firebase.firebase-messaging-22.0.0-runtime.jar
(:com.google.firebase.firebase-messaging-22.0.0:)
......
```
【解決】firebase-iid最新バージョンを[別途インストールする](https://developers.google.com/unity/archive#firebase_instance_id)


#終わり
[自分用忘備録]git push解決

# この記事は
先日いきなり`git push`ができなくなったのでその対処法。


##起きたエラー

```
  ! [remote rejected]       ローカルブランチ名 -> リモートブランチ名 (failure)
error: failed to push some refs to 'github.com:hogehoge/hogehoge.git'
```

オプションに-fを付けても同じエラーでプッシュできませんでした。
`git push -f origin ブランチ名`

## まずやってみたこと
リモートを確認
`git remote -v `

ローカルをきれいにする(ファイルの差分を全部消す)
`git checkout -- . && git clean -df`

リモートから最新を取得
`git pull origin ブランチ名`

または、
`git fetch`
`git merge origin/ブランチ名`

これだけやってもダメでした。

## 解決法
```
git push -u origin ブランチ名
```

リモートとの紐付けがダメになったらしい？
-uを付けてプッシュしてみたらできました。

##参考
https://qiita.com/shumpeism/items/1b8027c8905ca826416d
https://qiita.com/ironsand/items/6c301fef730d53f35bc3
結局dwave-ocean-sdkが入らなかった

諦めの記録
##環境

```bash
$ sw_vers
ProductName:	macOS
ProductVersion:	11.4
BuildVersion:	20F71

$ uname -a
Darwin MBA.local 20.5.0 Darwin Kernel Version 20.5.0: Sat May  8 05:10:31 PDT 2021; root:xnu-7195.121.3~9/RELEASE_ARM64_T8101 arm64

$ python3 --version
Python 3.9.6
```

M1 MacBook Airです

##エラー１
###内容

```
dimod/binary/cybqm/cybqm_float32.cpp:648:10: fatal error: 'numpy/arrayobject.h' file not found
  #include "numpy/arrayobject.h"
           ^~~~~~~~~~~~~~~~~~~~~
  1 error generated.
error: command '/usr/bin/clang' failed with exit code 1
  ----------------------------------------
  ERROR: Failed building wheel for dimod
Failed to build dimod
ERROR: Could not build wheels for dimod which use PEP 517 and cannot be installed directly

```

###解決法
```
$ python3
Python 3.9.6 (default, Jun 28 2021, 19:24:41) 
[Clang 12.0.5 (clang-1205.0.22.9)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy
>>> numpy.get_include()
'/opt/homebrew/lib/python3.9/site-packages/numpy/core/include'
```
パスをコピペ

```
$ export CFLAGS="-I $(コピペしたpath) $CFLAGS"
```

##エラー2
###内容
```
#include <boost/graph/graph_traits.hpp>
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      1 error generated.
      error: command '/usr/bin/clang' failed with exit code 1
```

###解決法

```
$ brew install boost
```

##エラー3
###内容
```
  dimod/binary/cybqm/cybqm_float32.cpp:673:10: fatal error: 'dimod/quadratic_model.h' file not found
  #include "dimod/quadratic_model.h"
           ^~~~~~~~~~~~~~~~~~~~~~~~~
  1 warning and 1 error generated.
  error: command '/usr/bin/clang' failed with exit code 1
  ----------------------------------------
  ERROR: Failed building wheel for dimod
```

###解決法

```
$ git clone https://github.com/dwavesystems/dimod.git
$ cd dimod
$ export CFLAGS="-I ./dimod/include $CFLAGS"
```

###エラー４
##内容
```
    Complete output (8 lines):
    running install
    running build
    running build_py
    running build_ext
    building 'tabu._tabu_search' extension
    swigging tabu/tabu_search.i to tabu/tabu_search_wrap.cpp
    swig -python -c++ -threads -o tabu/tabu_search_wrap.cpp tabu/tabu_search.i
    error: command 'swig' failed: No such file or directory
    ----------------------------------------
```

###解決法
```
$ brew install swig
```

##エラー4以降
###内容
```
  ERROR: Failed building wheel for numpy
Failed to build dwave-greedy dwave-preprocessing dwave-tabu pyqubo numpy
ERROR: Could not build wheels for dwave-preprocessing, numpy which use PEP 517 and cannot be installed directly
```

###解決法
心が折れた
諦めた

##あとがき
ARMとx64の切り替え，homebrewとPythonのごちゃごちゃ，M1の銅のこうのが原因のような
Dockerでどうにかしたほうがいい気がしてきた

**更新**
続き→[M1でdwave-ocean-sdkを使いたい~Docker編~](https://qiita.com/hiro2do/items/8593043a9f2350d64285)
WordVBAで表の操作

##アクティブなページのテーブルを選択

```
'アクティブなページのテーブルを選択する。
    With ActiveDocument.Bookmarks("\Page").Range.Tables
     If .Count = 0 Then Exit Sub
        .Item(1).Select
    End With
```

##表内の文字サイズ,デザイン,行間の指定

```
'例はサイズ7p , デザインは"ＭＳ Ｐゴシック"
    With Selection.Range.Font
        .Size = 7
        .Name = "ＭＳ Ｐゴシック"
    End With
    
'例は行間8p固定
    With Selection.ParagraphFormat
        .LineSpacingRule = wdLineSpaceExactly
        .LineSpacing = 8
    End With
```

##表内の全セルを垂直方向中央揃え

```
 Dim rowMax As Long, i As Long
 rowMax = ActiveDocument.Bookmarks("\Page").Range.Tables.Item(1).Rows.Count
 For i = 1 To rowMax
    With ActiveDocument.Bookmarks("\Page").Range.Tables.Item(1).Rows(i)
        .Cells.VerticalAlignment = wdCellAlignVerticalCenter 
    End With
Next
```

##行の高さを変更

```
'1行目を7.5mmに変更
Call ActiveDocument.Bookmarks("\Page").Range.Tables.Item(1).Rows(1).SetHeight(MillimetersToPoints(7.5), wdRowHeightExactly)
```

##列の幅を変更
```
'１列目を8mmに変更
Call ActiveDocument.Bookmarks("\Page").Range.Tables.Item(1).Columns(1).SetWidth(MillimetersToPoints(8), wdAdjustNone)
```
Anaconda環境で最新のRを使う（Windows）

# 要約
* Anaconda公式の方法では，R 3.6.1しかインストールできない模様．
* 理由としては，ダウンロード元の更新が2020年4月で停止（※2021年8月時点）していたから．
* 最新のR（記事作成時は4.1.0）をconda環境で使う場合は，[r channel](https://anaconda.org/r/r)ではなく[conda-forge channel](https://anaconda.org/conda-forge/r-base)からインストールすることで解決．

# 環境
* Windows 10 Home 21H1
* python 3.7.9 (condaの`base`環境でのversion)
* conda 4.9.2

# 背景
* 普段はPythonでのデータ解析やモデル作成を行っているが，Rを使用せざるを得ない状況に（[PypeRというPythonとRを連携するlibraryもある](https://qiita.com/m__k/items/df83a03bc7aa1ad0a59e)が、更新が長らくされていないので不安だったのもある）．
* [Rstudio](https://www.rstudio.com/)を使うのもよいが，できれば私が普段使っているツール（Jupyter notebook）で解析を行いたい&環境を汚したくなかったのでAnacondaにRをインストールすることに．
* [Anacondaの公式ドキュメント](https://docs.anaconda.com/anaconda/user-guide/tasks/using-r-language/)に従ってRの仮想環境を立てたが，私が使いたいlibraryが対応していない様子だった．

# 公式の方法を実行した場合
Anaconda公式で案内されているのは下記の通り．
> Creating an environment with R
> 1. Download and install Anaconda.
> 2. Create a new conda environment with all the r-essentials conda packages built from CRAN:
> `conda create -n r_env r-essentials r-base`
> 3. Activate the environment:
> `conda activate r_env`
> 4. List the packages in the environment:
> `conda list`

上記1-4.をAnaconda promptで実行すると、下記のパッケージがインストールされた`r_env`というcondaの仮想環境が作成される。なお、全てのパッケージは[r channel](https://anaconda.org/r/r)からダウンロードされている模様．

```
    package                    |            build
    ---------------------------|-----------------
    _r-mutex-1.0.0             |      anacondar_1           3 KB
                            （中略）
    r-base-3.6.1               |       hf18239d_1        55.3 MB
                            （中略）
    zipp-3.5.0                 |     pyhd3eb1b0_0          13 KB
    ------------------------------------------------------------
                                           Total:       190.8 MB
```
上記の通り，Rのバージョンを規定すると思われる`r-base`が`3.6.1`だった．
（自分が必要だったのは`3.6.2`以上という皮肉...）
もちろん`conda update`なども試したものの，元々そのchannelの最新のパッケージをインストールしているのでうまくいかなかった．

# 解決策
[r channel](https://anaconda.org/r/r)以外にRを置いていないか確認してみると，[conda-forge channel](https://anaconda.org/conda-forge/r-base)に比較的新しい`r-base`（conda-forgeにあったのは`4.1.0`，[最新は`4.1.1`だった](https://www.r-project.org/)）の存在を見つけた．

従って，下記の手順で自作のR環境をcondaで作成した．  

1. Anaconda promptで`conda create -n renv`を実行して仮想環境（以下記事中では`renv`で記載，環境名は各自自由に）を作成
1. **`base`環境で**`conda install r-base -n renv -c conda-forge`を実行し作成した`renv`に`r-base 4.1.0`をインストール

基本はここまででOK．
私はJupyter notebookでRを使いたかったので，[こちらの記事](https://nxdataka.netlify.app/rjup/)を参考にして、

1. `conda install jupyter -n renv -c conda-forge`
1. `conda install r-irkernel -n renv -c conda-forge`

を実行して、Jupyter notebookでRを使えるようにした．
（`jupyter`をインストールする際，Python自体や周辺の最低限Pythonを動かすのに必要なlibraryもインストールされるが，同じ環境でデータ分析や学習モデルを作成したい場合は`numpy`, `pandas`, `sklearn`などがインストールされないので注意されたし）

# 参考
* [Using R language with Anaconda](https://docs.anaconda.com/anaconda/user-guide/tasks/using-r-language/)
* [PypeRを使ってみた](https://qiita.com/m__k/items/df83a03bc7aa1ad0a59e)
* [jupyter notebookでRを使う](https://nxdataka.netlify.app/rjup/)
Rails と SQL Server の組み合わせで DB ユーザーのパスワードを '#' からはじまるものを使うと Rails アプリから接続できない

# 要約

記事タイトルのままですが、 DB ユーザーのパスワードを '#' からはじまるものにしていると Rails アプリから DB に接続できません。


# 利用しているバージョン

- [CentOS](https://www.centos.org/): [7.6.1810](https://hub.docker.com/_/centos?tab=tags&page=1&ordering=last_updated&name=7.6.1810)
- [freetds](https://www.freetds.org/), freetds-devel: [1.1.20-1.el7.x86_64](https://centos.pkgs.org/7/epel-x86_64/freetds-1.1.20-1.el7.x86_64.rpm.html)
- [Microsoft SQL Server](https://www.microsoft.com/ja-jp/sql-server/sql-server-2019): [2019-latest](https://hub.docker.com/_/microsoft-mssql-server)
- [Ruby](https://www.ruby-lang.org/ja/): 3.0.2
- [Rails](https://github.com/rails/rails): 6.1.4
- [rails-sqlserver/activerecord-sqlserver-adapter](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter): 6.1.0.0
- [rails-sqlserver/tiny_tds](https://github.com/rails-sqlserver/tiny_tds): 2.1.5


# パスワードを '#' からはじまるものにしているとき

`sqlcmd` を利用すると接続できます。

```
[user@machine app]$ sqlcmd -H db -U user -P "#hogehoge"
1> use my_database
2> go
Changed database context to 'my_database'.
1> select count(id) from samples
2> go

-----------
          0

(1 rows affected)
1> quit
[user@machine app]$
```

しかし、 Rails アプリからは接続できません。

```
[user@machine app]$ cat .env
DATABASE_HOST=db
DATABASE_USERNAME=user
DATABASE_PASSWORD="#hogehoge"
[user@machine app]$ bin/rails r 'Sample.find 1'
/app/vendor/bundle/ruby/3.0.0/gems/tiny_tds-2.1.5/lib/tiny_tds/client.rb:60:in `connect': Login failed for user 'user'. (TinyTds::Error)
	from /app/vendor/bundle/ruby/3.0.0/gems/tiny_tds-2.1.5/lib/tiny_tds/client.rb:60:in `initialize'
    ...
	from bin/rails:4:in `<main>'
[user@machine app]$
```

# パスワードを '#' からはじまらないものにしているとき

```
[user@machine app]$ cat .env
DATABASE_HOST=db
DATABASE_USERNAME=another_user
DATABASE_PASSWORD="not-starts-with-hash"
[user@machine app]$ bin/rails r 'Sample.find 1'
/app/vendor/bundle/ruby/3.0.0/gems/activerecord-6.1.4/lib/active_record/core.rb:338:in `find': Couldn't find Sample with 'id'=1 (ActiveRecord::RecordNotFound)
	from /app/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4/lib/rails/commands/runner/runner_command.rb:45:in `<main>'
    ...
    from bin/rails:4:in `<main>'
[user@machine app]$
```

`.find` には失敗していますが、接続はできています。
zsh: parse error near `&'

# 事象 : curlのパラメータに「*」を入れたら怒られた
- 環境
    - macOS BigSur バージョン11.3.1
    - zsh 5.8 (x86_64-apple-darwin20.0)

RedmineのRestAPIでチケット一覧を取得する時、`status_id`に「*」を指定することができる。

> status_id: get issues with the given status id only. Possible values: open, closed, * to get open and closed issues, status id
> [Rest Issues - Redmine](https://www.redmine.org/projects/redmine/wiki/Rest_Issues)

`status_id`に「*」を指定して`curl`コマンドでAPIを呼び出したら怒られた・・・

```zsh
$ curl -X GET -H 'X-Redmine-API-Key:{APIキー}' {RedmineのURL}/issues.json?limit=100&sort=asc&status_id=*
zsh: parse error near `&'
```

## 原因 : 不明
`status_id=*`があっても他に指定するパラメータによっては怒られない、なんで？

```zsh
# パラメータが「status_id」だけだとエラーにならない
$ curl -X GET -H 'X-Redmine-API-Key:{APIキー}' {RedmineのURL}/issues.json?status_id=* 
{"issues":[{"id":...

# パラメータが「limit」と「status_id」だとエラーにならない
$ curl -X GET -H 'X-Redmine-API-Key:{APIキー}' {RedmineのURL}/issues.json?limit=1&status_id=* 
{"issues":[{"id":...

# パラメータが「limit」と「issue_id」と「status_id」だとエラーになる
$ curl -X GET -H 'X-Redmine-API-Key:{APIキー}' {RedmineのURL}/issues.json?limit=1&issue_id=1&status_id=*
zsh: parse error near `&'

# 「*」を'(シングルクォーテーション)で囲ってもエラーだった・・・
$ curl -X GET -H 'X-Redmine-API-Key:{APIキー}' {RedmineのURL}/issues.json?limit=100&sort=asc&status_id='*'
zsh: parse error near `&'
```

### 対応 : URLを`で囲う
URLを「'(シングルクォーテーション)」で囲ったら怒られなかった・・・理由を知りたいがとりあえずいけた。

```zsh
$ curl -X GET -H 'X-Redmine-API-Key:{APIキー}' '{RedmineのURL}/issues.json?limit=100&sort=asc&status_id=*' 
{"issues":[{"id":...
```
こどもの自由研究にGCP AppEngineアプリ作成のススメ

#はじめに
小学校４年生の長男の自由研究でGoogle Cloud PlatformのAppEngineにアプリ（底辺と高さの値を入力すると三角形の面積を求めるアプリ）をデプロイすることに取り組んでみたという記事です。
なお、この取り組みは**Google Cloud Platform GAEソフトウェア開発入門――Google Cloud Authorized Trainerによる実践解説 (Software Design plusシリーズ)**の第６章までを参考（いや、参考というより大部分を写経）して作成しました。
アプリについては百聞は一見に如かず、https://itsk-project.an.r.appspot.com/
をご確認ください。

#GCPがすごい
まず、GCPがすごいです。なぜならCloudShellを使うとサーバー上がローカルのテスト環境となり、
**gcloud app deploy ./**
このコマンドですぐにアプリがデプロイでき、web上でアプリが動くのですから。

#やったこと
##１日目
長男に取り組ませる前に、上記した参考図書を約１日かけて予習しておきます。そこでつまずきそうなところを確認し、その予習の成果として、こんなことができるよと先に目標、動機付けを長男に対して行いました。

##２日目
ローカル環境のブラウザーにHello World!を表示させるプログラムmain.py（App Engineのpythonアプリはすべてmain.pyという名前にします）を作成しました。
Hello Worldアプリは**python**でブラウザーに表示したい文字列"Hello World!"を入力し、**Flask**の**return**コマンドで返すだけです。
入力ミスをするとエラーが返りますが、自ら写経した本と見比べてデバッグすることも学び、キーボード操作の習得にもつながります。
また英語の勉強にもなるという学習教材として非常に優れています。
文字列部分を子供に自由に書かせて、ブラウザーでそれが表示させるとそれだけで目が輝きました。
これだけでも十分に自由研究として成立していますが、子供の成長ぶりから、３日目にさらに上を目指しました。


##３日目
三角形面積を求めるアプリの作成です。
本来なら、HTMLファイルをテンプレートとして作成し、cssでデザインするという方法で作成しますが、長男にはファイルが多岐に渡るのはその仕組みを理解するのは難しいと判断し、"Hello World!"の文字列部分をHTMLファイルの中身にしてreturnだけで返すことにしました（本来はreturn render_template('result.html',val1=val1などで変数をHTMLファイルに送り、HTMLでは{{}}で受ける）。HTML部分は先に親が作成しテストしておき、これを写経させることにしました。
最初は真っ白なバックに黒い文字列（三角形の面積）が書かれるアプリでしたが、フリー素材でアプリに沿った好きな画像を選ばせて、それをHTMLにて表示させるようにしました。
以下がmain.pyです。
htmlのstyle部分（本来ならcssファイルに書き込む部分）はhttps://qiita.com/NoxGit/items/59dfcb41b204008bea9f
を参考にしています。

```main.py
from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def area_tri():
    #三角形の面積を求める入力フォーム
    return """
    <html><body style="text-align: center;background-image: url(/static/image/triangle.png);">
    <form action="/answer" methond="GET">
    <h1>三角形の面積を求めます</h1>
        <div id = "input">
            <h1>
            <dd>底辺は？<input type="number" name="btm" size="5" value=""></dd>
            <dd>高さは？<input type="number" name="hig" size="5" value=""></dd>
            <dd><input type="submit" value="面積算出"</dd></h1>
        </div>
    </form>
    </body></html>
    """

#/answerへアクセスがあったとき
@app.route('/answer', methods=['GET'])
def answer():
    btm = float(request.args.get('btm'))
    hig = float(request.args.get('hig'))
    area = btm * hig * 0.5
    return """
    <html>
    <body style="text-align: center;background-image: url(/static/image/answer.jpg);
                                    background-size: cover;
                                    min-height: 100vh;">    
    <h2 style="color: yellow; font-size: 24pt;
        text-shadow    : 2px  2px 1px black, -2px  2px 1px black, 
　　　　　　　　　　　　　2px -2px　1px black, -2px -2px 1px black, 
　　　　　　　　　　　　　2px  0px 1px black,　0px　2px 1px black,
　　　　　　　　　　　　 -2px  0px 1px black, 0px -2px 1px black;">
    <dd>底辺{0:7.2f}cm</dd>
    <dd>高さ{1:7.2f}cm</dd>
    <dd>公式：底辺*高さ÷2</dd>
    <dd>A.求める三角形の面積は{2:7.2f}cm2です</dd>
    </h2>
    """.format(btm,hig,area)

if __name__=='__main__':
    app.run(host='127.0.0.1', port=8080, debug=True)
```

#オチ
高度な（？）自由研究になってしまったせいで、子供がこれを学校で披露するのが恥ずかしいということになり、結局**写真立てを作成する**という自由研究を発表することになりました。
まぁ、とりあえず小学校４年生にして、プログラミングの第一歩、スタートが切れたということで、後は子供の興味に任せることにします。
正規表現で末尾が一致するのにif文でfalseが返ってくる。

Javaの正規表現を学習しているときに躓いたところがあるので、忘備録として残しておきます。

#やりたかったこと

あるディレクトリにあるファイルのうち、拡張子がpdfのもの(末尾がpdfで終わる文字列)をListに追加していく処理を行いたかった。

ちなみに拡張子がpdfのファイルはファイル名が8桁の整数で構成されているとする。

例：00000001.pdf

上記の処理を行うために以下のようにコードを記述した。

```Java:Java
File[] files = new File(args[0]).listFiles();

		//pdfファイルを保持するためのList
		ArrayList<File> pdfFiles = new ArrayList<>();

		//配列filesに代入したファイルをfile数の数だけ取得する
		for(int i = 0; i< files.length; i++) {

			String fileName = files[i].getName();

			if(files[i].isFile() && fileName.matches("pdf$")) {
				pdfFiles.add(files[i]);
			}
		}
```


#発生した不具合

if(files[i].isFile() && fileName.matches("pdf$"))の部分で正規表現を用いて末尾がrdcのファイルを判定しているがこの状態で実行してもfalseになり、Listに追加することができなかった。


ググって調べたが、間違っているようには思えなかったのだが、、

どうやら"pdf$"だとpdfという文字にしかマッチしないようで、pdfより前に文字が存在する値は一致せずfalseになるようだ。

例：①値が"pdf"→trueが返ってきてリストに追加可能
　
　　②値が"32412.pdf"→falseが返ってきて値はリストに追加されない


今回の場合、拡張子pdfの前には8桁の整数があったので例の②が当てはまりfalseとなったと思われる。


#対処法


正規表現をいずれかに修正することで問題なく処理が通るようになった。

```Java:パターン1
			if(files[i].isFile() && fileName.matches("^[0-9]{8}.pdf$")) {
				pdfFiles.add(files[i]);
			}
```
```Java:パターン2
			if(files[i].isFile() && fileName.matches(".*pdf$")) {
				pdfFiles.add(files[i]);
			}
```


パターン１では^[0-9]{8}で0~9の数字が8桁あること、.で任意の1文字が続くことを表している。(ここでは拡張子の「.」)

パターン2では.*で任意の1文字が0回以上繰り返すことを表している。




正規表現は勉強中であるため、間違いはあるかもしれないので、不備があればご指摘いただければ幸いです。
VisualStudio＋CppUTestのJenkinsでの設定

こちらの記事の続きです。

https://qiita.com/h1day/items/b89ead13faee1d80b736

この記事は「ビルド→テスト→メール通知」です。

このあとの記事はReSharperでコードのチェック(無料)です。

https://qiita.com/h1day/items/3f837dc807f24baba1f5


# プラグインの追加

Jenkinsの管理 > プラグインの管理

MSBuildを検索して「install without restart」します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/ef7e7a10-64d0-1c67-a37d-ec9fefffe4d0.png)

# ジョブの作成

ジョブの新規作成を押します。

レポジトリはhttps://github.com/h1day/AgileSD_Payroll を使ってみますので、名前は「payrollproject」にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/de589c7b-cbfb-54b3-101a-c31c6bcd97a2.png)

ここはデフォルトでmasterですが、最近作ったブランチだとgithubのデフォルトはmainなので注意です。
私は結構嵌りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/a6c33de2-7293-4a3f-eb47-6586bfe73127.png)

https://www.publickey1.jp/blog/20/githubmainmastermain.html

「ビルド手順の追加」を押して、「MSBuildの実行」を選びます。
コマンドライン引数でコンフィグレーションを指定しておいたほうが無難そうです。
このslnはこれでテストを実行するexeを作るようになっています。

```
AgileSD_Payroll.sln
/p:Configuration=Release /p:Platform=x64
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/e6bfd8dc-6458-c52a-3bab-f20ca76e911e.png)

https://www.it-swarm-ja.com/ja/msbuild/msbuild%E3%81%AE%E3%83%97%E3%83%A9%E3%83%83%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF%E3%81%A9%E3%81%86%E3%81%99%E3%82%8C%E3%81%B0%E3%82%88%E3%81%84%E3%81%A7%E3%81%99%E3%81%8B%EF%BC%9F/969313992/


「ビルド手順の追加」を押して、「Windowsバッチコマンドの実行」を選びます。
メモリーリークを検出したいのでテストフレームワークは[CppUTest](https://cpputest.github.io/manual.html#command_line)にしています。
JUnit形式の出力が可能ですので、テスト実行時のコマンドライン引数として「-ojunit」を指定します。

```
x64\Release\AgileSD_Payroll.exe -ojunit
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/87b83aac-edb0-8636-210c-f8de47e77631.png)

「ビルド後の処理の追加」を押して、「Junitテスト結果の集計」を選びます。
テストで生成されるxmlを指定します。

```
cpputest_PayrollTest.xml
```

「ビルド手順の追加」を押して、「拡張E-mail通知の追加を」を選びます。
Advanced Settingsを選んで、Add TriggerでSuccessも足しておきました。動作確認しやすいので。
デフォルトのDevelopersだと届かない（設定した覚えがないし）ので、Recipeint Listに変更しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/cfba9642-3e91-8f2e-d175-4c31f543ffd4.png)

ここまでで、ビルド→テスト→メールで通知 まできました。
↓続きます。

https://qiita.com/h1day/items/3f837dc807f24baba1f5
ReSharperでコードのチェック(無料)をJenkinsで実施

これらの記事の続きです。

https://qiita.com/h1day/items/b89ead13faee1d80b736

https://qiita.com/h1day/items/d7af1240d71a853c965a

# Resharper commandline の追加

Reshaperによるコードの分析です。ReSharperはコマンドラインで使う分には無料です。
明示的に書いている場所が少ないですが、C++でも動きます。
（コードの重複チェックはC#とVB.netしか動かないようです。）

エージェントのマシンで[global .NET Core tool](https://docs.microsoft.com/ja-jp/dotnet/core/tools/global-tools) としてインストールします。
powershellで以下のコマンドによりインストールするだけで、どこからでも呼べます。すごい楽です。

``` :powershellで実行
dotnet tool install -g JetBrains.ReSharper.GlobalTools
```

Jenkinsに戻ります。
ダッシュボード＞Jenkinsの管理＞プラグインの管理＞利用可能　で
Warnings Next Generation Pluginを入れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/e7dc80a8-a2c1-03d6-e4f2-d52953363ee5.png)


プロジェクトの設定画面に移動します。
Jenkinsで「ビルド手順の追加」を押して、「Windowsバッチコマンドの実行」を選びます。
inspectcode.xmlは出力用のファイル名です。なんでもいいです。

``` :コマンド欄
jb inspectcode AgileSD_Payroll.sln -o="inspectcode.xml"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/b53f081a-8640-cc29-4878-9ec42e83eea3.png)


続いて「ビルド後の処理の追加」を押して、「Record compiler warnings and static analysis results」を選びます。
「Tool」は「Resharper Inspeections」を選びます。
「Report File Pattern」 には、先ほど出力ファイル名として設定した 「inspectcode.xml」 と書きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/e2beefe7-5a38-80e2-09dc-2bd3acd7ad64.png)

ビルド結果でResharper Inspections Warningsを選べるようになり、統計情報を見れるようになりました。
見やすいです。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017728/7ce7a7af-6435-6a56-c8ee-27c736e0a206.png)

# 参考

https://www.jetbrains.com/help/resharper/ReSharper_Command_Line_Tools.html#install-and-use-resharper-command-line-tools-as-net-core-tools

https://baba-s.hatenablog.com/entry/2019/05/07/084000
Microsoft Storeが起動しない場合の再インストール方法

会社のWindowsでMicrosoft Storeが起動しない現象がたまに発生してしまうんですよね。

フォルダリダイレクト・オフラインファイル・移動プロファイル組み合わせているので、たぶん競合とか同期ミスとかでおかしくなっちゃんじゃないかなぁと勝手に予想しています。

それならばと、再インストールを試みるのの、毎度うまくいった試しがないのです。結局プロファイルリセットとかで対応していたのですが、今日はリセットせずに対処できたので記録しておきます。

まずはPC全体でMicrosoft Storeを再インストールします。

PowerShellを管理者モードで起動して下記のコマンドを実行します。

```powershell
Get-AppXPackage -AllUsers -Name microsoft.WindowsStore | Foreach {Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppXManifest.xml" -Verbose}​
```

こんなメッセージになりましたか?

```
詳細: 対象 "C:\Program Files\WindowsApps\Microsoft.WindowsStore_12105.1001.23.0_x64__8wekyb3d8bbwe\AppXManifest.xml"
に対して操作 "パッケージの登録" を実行しています。
詳細: 次の操作が完了しました: C:\Program Files\WindowsApps\Microsoft.WindowsStore_***\AppXManifest.xml
```

そうしたら、最後に表示されるXMLのパスをコピーしておきます。

(まずここで「詳細: 次の操作が完了しました」が表示されないと後続の操作もうまく行かないかなと思います。だいたいここでエラーになる場合はPCの再インストールじゃないと解決できない気がします。)

続いてPowerShellをユーザーモードで起動して下記のコマンドを実行します。

```powershell
Add-AppxPackage -DisableDevelopmentMode -Register "C:\Program Files\WindowsApps\Microsoft.WindowsStore_***\AppXManifest.xml" -Verbose
```

(XMLのパスは先程コピーしたもの)

これでMicrosoft Storeが起動するようになりました。
LeetCode "42. Trapping Rain Water" のApproach 2をPythonで書いた話

昨日、LeetCode "42. Trapping Rain Water"に挑戦したものの、Timelimit Exceededで解けませんでした。
LeetCodeは一部の問題について無料で解答例の方針とコードを見ることができます。
この問題については、解答例のコードがC++で与えられています。
その方針のうち、Approach 2が私にとって理解しやすかったです。
私はPythonしかできないので、PythonでApproach 2を実装します。

#問題

こちらから挑戦できます。
https://leetcode.com/problems/trapping-rain-water/

>
>n個の非負整数が与えられています。それらの非負整数は、標高の地図を表しています。（各非負整数が表す）バーの幅を１とします。この標高地図は、降雨の後にどれだけの水をためられるでしょうか。計算してください。
>

#昨日の失敗
LeetCode "42. Trapping Rain Water"が再帰関数で解けなかった話
https://qiita.com/Takeshi_Sue/items/ed0e58c5fc8eaba3fd46

失敗の原因は、再帰関数で挑んだためではないでしょう。失敗の原因は、与えられた一次元の配列を元に標高と水嵩を表す二次元の配列を作ったことにより計算時間を食ったためだと考えています。

#Approach 2

ここから解法を見ることができます。
https://leetcode.com/problems/trapping-rain-water/solution/

Approach 2を私なりに解釈すると、このような形です。
![酸素と水素.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1851956/768ec650-c7e4-84be-7a9c-4e37dec81b8e.png)

•壁の左側にだけ水素を撒く
•壁の右側にだけ酸素を撒く
•それらを爆発させると、水素または酸素のうち高さの低いほうに合わせて、水が出来上がる
•水を数えて、答えとする。

#提出したコード


```py
class Solution:
    
    def trap(self, height: List[int]) -> int:
        # len(height)は何回も使いそうなので、あらかじめ取得してしまいます。
        len_height = len(height)

        # 水素を充満させた結果を記録する配列、h2_heightを用意します。
        h2_height = [0 for _ in range(len_height)]
        # cur_max：　forで繰り返していくなかで、その時点での最大の壁の高さを記録します。
        cur_max = 0

        # 壁より右側に水素を充満させます
        for i in range(len_height):
            cur_max = max([height[i], cur_max])
            h2_height[i] = cur_max

        # 酸素を充満させた結果を記録する配列、o_heightを用意します。
        o_height = [0 for _ in range(len_height)]
        # cur_max：　forで繰り返していくなかで、その時点での最大の壁の高さを記録します。
        cur_max = 0

        # 壁より左側に酸素を充満させます
        for i in reversed(range(len_height)):
            cur_max = max([height[i], cur_max])
            o_height[i] = cur_max

        # res: 最終的に返す値
        res = 0

        for h2, oxigen, wall in zip(h2_height, o_height, height):
            # min([h2, oxigen]):水素と酸素があった場所、つまりは水がある場所
            # wall: 水の位置を底上げしている壁
            res += min([h2, oxigen]) - wall

        return res
```
結果：解答通りにやってるので、もちろん成功します。
![解けた.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1851956/bb88067a-5296-404f-2a26-ae30681c941a.png)

#感想
めっちゃ悩んで解いて間違ったものの解答が、実はこんなに簡単だと、なかなかに気分がわるいね！
ストゼロ飲んで寝よ！！！！！！！！！
SQLアンチパターン

※この記事は[こちら](https://yk0807.com/techblog/2021/08/10/sql%e3%82%a2%e3%83%b3%e3%83%81%e3%83%91%e3%82%bf%e3%83%bc%e3%83%b3/)のブログ記事をQiitaに移植したものです。

## はじめに
やろうと思っていた個人開発がどうにも滞ったまま何ヶ月も経ってしまい、でも久々に記事だけでも更新しなきゃなということで今回は技術書の紹介。
今回紹介するのは[SQLアンチパターン](https://www.oreilly.co.jp/books/9784873115894/)という本。業務でDB設計をやる機会が増えて、設計に関して気をつけなきゃいけないことを把握しようと思って買ってみた。
本全体の感想としては、DB設計に関わる人なら一度は読んでおくべき本だなという印象。テーブル定義や設計などで避けるべきことが網羅されている感じ。
紹介されているパターンが25もあるので、今回は特にやりがちなパターンを3つほど紹介してみる。

## 3章 : IDリクワイアド（とりあえずID）
新しいテーブルを作る時、何でもかんでもとりあえずIDカラムを入れるというのをやりがちな人は結構多いのではないかと（自分含む）。
例えば、学生ごとに受講する科目を定義するstudent_subjectというテーブルを考えてみる（studentテーブルとsubjectテーブルは別途定義されているとする）。

| id | student_id | subject_id |
|-----------:|---------:|---------:|
| 1     | 1       |   1|
| 2     | 1      |   2|
| 3     | 2      |   3|
| 4     | 3      |   2|

また、テーブルを生成する際にUNIQUE KEY (student_id, subject_id)でstudent_idとsubject_idが一意になるようにする。
そうなると、**”id”カラムって何のために使うんだ**という話になってくるので、必要でないカラムをあえて入れておく必要はないのではということになる。
とはいえ、このテーブルに成績を表すgradeというカラムを追加して、さらに別のテーブルと連結させる必要が出てきたりした場合はidカラムに相当するものが必要になるので、ケースバイケースではあるが（もっとも、この場合はテーブル名をもっと別の適切な名前にすべきだが）。
要約すると、「このidカラム、本当に必要ですか？」ということか。

## 10章: サーティーワンフレーバー（31のフレーバー）
あるカラムに入る文字列の値をいくつかに限定したい場合、MySQLではENUM型で定義することがある。他のRDBMSはあまり使ったこと長いのでわからないが、CHECK制約を入れて入る値を限定するやり方があるらしい。
例えば、従業員が所属する支社が”TOKYO”、”OSAKA”、”NAGOYA”、”SAPPORO”の4つのいずれかという場合、officeカラムをENUM(‘TOKYO’,’OSAKA’,’NAGOYA’,’SAPPORO’)という風に定義していたとする。
employeeテーブル

|employee_id |name      |  office|
|-----------:|---------:|---------:|
|1            |          Suzuki   |    TOKYO |
|2             |         Sato     |    OSAKA |
|3            |         Tanaka    |   NAGOYA |
|4             |        Yamamoto |  TOKYO |
|5             |        Yoshida  |    SAPPORO |
ところがある日、那覇支社が新たに追加された場合ENUM(‘TOKYO’, ‘OSAKA’,’NAGOYA’,’SAPPORO’,’NAHA’)に定義を変更するのは結構面倒臭い。

このような状況を避けるには、以下のようにすればいい。
officeテーブルを新たに定義し、employeeテーブルにoffice_idを持たせる。
employeeテーブル(修正版)

|employee_id |name       | office_id|
|-----------:|---------:|---------:|
|1        |   Suzuki    | 1|
|2 |Sato |2|
|3 |Tanaka |3|
|4 |Yamamoto |1|
|5 |Yoshida| 4|
officeテーブル（追加）

|office_id| office_name|
|-----------:|---------:|
|1| TOKYO|
|2| OSAKA|
|3 |NAGOYA|
|4 |SAPPORO|
|5| NAHA|

ただし、入る値が”LEFT”、”RIGHT”など絶対に追加されることが無いと断言できる場合はENUM型を使ってもいいと思う。なので、ENUM型での定義を考える場合は新たな値が追加される可能性をまず検討すべきかと。

## 18章 : インプリシットカラム（暗黙の列）
プログラム内でデータベースから検索する時、

```SQL
SELECT * from （テーブル名） where （検索条件）
```
に相当するような検索クエリを呼び出すような形で結果を取得するようなことがあると思う。
あるいは、

```SQL
INSERT INTO （テーブル名） （カラム） VALUES （値）
```
でレコードを追加するときにデフォルト値が設定されているカラムを省略したりすることもあるはず。
けど、実はこれらには落とし穴があったりする。例えば、カラム数が10あったとして、取得した値をカラムごとに配列に入れていた場合、誰かが不要なカラムを1つ削除したとすると、**配列の要素数が9しかないのに10番目の要素にアクセスしたらエラーになってしまう！**
それ以外にも不要なデータまでも持ってきていることでクエリが必要以上に重くなってしまうこともあり得る。
なので、多少面倒でも必要なカラムのみを明示的に指定した方が後々問題が発生するのを避けることができる。

## 終わりに
25のアンチパターンの中で、自分も気をつけていないとついやりがちなパターンを3つほど上げてみたけど、逆に「これは普通やらないだろ」ってのもちらほらあったなあ。
例えば、1章の「ジェイウォーク（信号無視）」は1つのカラムに無理やり複数の値をカンマ区切りで入れるのは少なくとも自分は気持ち悪く感じるし、20章の「SQLインジェクション」は最近のフレームワークだとほぼ対策がされているのではないかと（それでも、ユーザー向けのシステムの場合はテストの時にフォームにSQL文を入れて変なことにならないかの確認はやるけど）。
それでも、こういう「べからず集」は意識して開発していけば後々のトラブルの元が減らせることになるので、設計していて違和感を感じたら本を見返して問題点と対策を把握しておくのがいいだろうな。

半年近く滞っていた個人開発の方も、どこかのタイミングで再開したいなあ。
生やしたバグ集

ただの頭回ってなかったとか注意不足みたいなやつじゃなくて、知らないと沼るやつを集めた
やらかす度に追加されていきます
言語は、特に書いていなければCかC++です。


### (Python / numpy) 参照は複雑怪奇
Pythonでは代入でオブジェクトがコピーされないという罠があるのは有名である。
では以下の例はどうだろう ?
```
a = [[1, 2], [3, 4]]
b = a[0]
a[0] = a[1]
print(b)
```
これはさすがに`[1, 2]`が出力される。しかし
```
import numpy as np
a = np.array([[1, 2], [3, 4]])
b = a[0]
a[0] = a[1]
print(b)
```
では`[3 4]`が出力される。やってられない

### string に int を代入
```cpp
std::string s;
s = 3;
```
コンパイルは通る。s は "3" にはならない。
この代入、使われているのは```operator= (char c);```で、charをstringに代入してその1文字からなる文字列にする。  
つまりこの場合文字コード3の文字1文字からなる文字列になる (は～～～ ?)

整数リテラルそのまま書くとさすがに気づくかもしれないけど変数を代入しようとして```std::to_string```忘れたとかだと起こりそうでしょう ?

### グローバル変数の初期化順序

```c++:a.hpp
struct TestStruct {
  TestClass ();
};
```

```c++:a.cpp
std::vector<TestStruct *> instances;
TestStruct::TestStruct () {
  instances.push_back(this);
}
```

```c++:b.cpp
TestStruct hoge;
```
色々突っ込み所のあるコードだが、一番致命的なのはプログラムが開始しても ```instances``` が空かもしれないということだ。  
異なるファイル間でのグローバル変数の初期化順序は未規定(だよね ?) なので ```instances``` が ```hoge``` より後に初期化されると... ? 
そもそもその場合初期化されてないstd::vectorを使うのは大丈夫なのか ? というのはよく分からん。

### 符号なし整数
```cpp
int index = -3;
auto element = array[(index % array.size() + array.size()) % array.size()];
```
めっちゃ書きそう。壊れる。(細かいことは忘れたが%で型を共通にするときにサイズの大小と符号の有無によって何に合わせるかが決まって、このコードは多くの場合符号なし側に合わせちゃう)

### reverse_iterator.base()
```a.rbegin().base()``` は、```std::prev(a.end())``` ではなく ```a.end()```  (え～)
確かに「じゃあ ```a.rend().base()``` はどうなるんや」って言われたらその通りなんだけど...なんか設計もやる

### std::ifstreamのbinary指定
バイナリファイルをstd::ifstreamで開くときはstd::ios::binaryを指定する必要あり。
デフォルトのままだとテキストモードで開かれてバイナリファイルの中の\r\nが全部\nになるし0x1Aに出会おうものならそこで読み込みが打ち切られます。

### constexprな変数を参照してはいけない(?)
以下のコードをGCC 12.1.0, `-std=c++11` でコンパイルすると `undefined reference to 'TestStruct::INF'` でリンカーエラーになります。  
よく分からないが発生条件シビアなせいでサンプルコード書くのにも時間がかかった

```c++
#include <vector>

struct TestStruct {
	static constexpr int INF = 1000000000;
	std::vector<int> a;
	
	TestStruct (int n) {
		a.assign(n, INF);
	}
};

int main() {
	TestStruct tmp(100);
	return 0;
}

```

### decltypeの結果にキャストするときは参照に注意
事の発端はジェネリックラムダ式
```c++
#include <iostream>
#include <vector>
#include <cstdint>

typedef uint32_t u32;
typedef uint64_t u64;

int main() {
	auto f = [] (const auto &a, auto &b) {
		b.resize(a.size());
		for (size_t i = 0; i < a.size(); i++) b[i] = (decltype(b[0])) a[i] * a[i];
	};
	std::vector<u32> a{1, 2, 3};
	std::vector<u64> b;
	f(a, b);
	for (auto i : b) std::cerr << i << std::endl;
	return 0;
}
```
`decltype(b[0])`が`u64`になってほしいけど`u64 &`になってます。  
`a[i]`は`u32 &`なのでコンパイルが通らないと思いきや、なんと`u32 &`が`u64 &`に変換されて`-Wall -Wextra -Wpedantic`下ですら警告なしでぶっ壊れます。strict aliasing rule違反で、実際には`a[i]`と`a[i + 1]`をu64として読むようなコードが生成されてるものと思われます。  
ジェネリックラムダ式でなく普通に`(u64 &) a[0]`とか書くと警告してくれるのにどうして...
`std::remove_reference`をしましょう

### libcurlはCのライブラリです
```cpp
#include <curl/curl.h>

int main() {
  CURL *curl;
  std::string url = "https://example.com";
  // ...
  curl_easy_setopt(curl, CURLOPT_URL, url);
  // ...
  return 0;
}

```
```CURLOPT_URL``` を指定した時の ```curl_easy_setopt``` は第3引数に ```const char *``` を期待するんですって
コンパイル通るんかい💢
こんなん絶対何回でもやらかすに決まってるのでラッパー書いて二度とlibcurl生で触らなくていいようにするわ
【AWS】EC2インスタンス起動時にユーザーデータ（user data）を使おう

#はじめに
皆さんがEC2を作成にあたって、SSMエージェントや、Linux系のリポジトリなどを、あらかじめインストールしておきたいものが必ずあると思います。
EC2のユーザーデータ機能を使えば、EC2が作成されると同時に、自分がインストールしたいリソースも迅速にインストールされることとなります。
本記事は、ユーザーデータを使い方や、使う際にあたっての注意事項をまとめておきたいと思います。

#例
下記は一つの例として挙げたいと思います。
・OS情報：Amazon Linux 2
・ユーザーデータでインストールしておきたいもの：

|項番            | 内容 |
|:------------------|:------------------|
|1|EPEL リポジトリ|
|2|nginxのインストールと自動起動設定|
|3|unzip|
|4|aws cli2|
|5|mysql|

```
#!/bin/bash
amazon-linux-extras install epel -y
yum install nginx -y
systemctl start nginx
systemctl enable nginx
yum install unzip -y
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
./aws/install
yum install mysql -y
```

#注意点①：#!/bin/bashを付け加える
通常スクリプトを書く際と同じように、```#!/bin/bash```をユーザーデータ上に記載しておく必要があります。
>ユーザーデータシェルスクリプトは、#! 文字と、スクリプトの読み取り先であるインタープリタのパス (通常は /bin/bash)) で開始する必要があります。シェルスクリプティングに関する有用な紹介文は、Linux ドキュメントプロジェクト (tldp.org) の「BASHプログラミングのハウツー」で入手できます。


#注意点②：sudoコマンドを付け加えない
ユーザーデータ書くにあたって、sudoコマンドは使用してはいけません。
理由は下記公式サイト上で記載されています。
>ユーザーデータとして入力されたスクリプトは、root ユーザーとして実行されます。そのため、スクリプトでは sudo コマンドを使用しないでください。作成したファイルはすべて root ルートの所有になることを忘れないでください。ルート以外のユーザーにファイルアクセスを与える場合、スクリプトで権限を適宜変更する必要があります。また、スクリプトはインタラクティブに実行されないため、ユーザーフィードバックを必要とするコマンド (yum update フラグのない -y など) を含めることはできません。

#注意点③：ユーザーデータでは、デフォルト最初作成時にのみ実行される
ユーザーデータはデフォルトでは最初作成起動時にのみ実行されるので、EC2インスタント作成後に、再起動をかけてもユーザーでは実行されることがありません。
>デフォルトでは、ユーザーデータスクリプトと cloud-init ディレクティブは、EC2 インスタンスが起動される最初の起動サイクルでのみ実行されます。

#注意点④：インスタンスを再起動する度にユーザーデータを実行させるには
もしサーバーが再起動されるタイミングで、何かのコマンドを実行させたいであれば、公式サイトでは下記のご案内があります。
参考URL：

https://aws.amazon.com/jp/premiumsupport/knowledge-center/execute-user-data-ec2/


上記URL内容を簡単にまとめると、ユーザーデータを毎回インスタンス起動時に実行させたければ、下記のコマンドをユーザーデータ内にあらかじめ追加しておけばOKです。

```bash
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0

--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"

#cloud-config
cloud_final_modules:
- [scripts-user, always]

--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"

#!/bin/bash
あなたのスクリプト内容はここに書いてね〜！
--//--
```

#参考資料

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/user-data.html#user-data-shell-scripts

https://aws.amazon.com/jp/premiumsupport/knowledge-center/execute-user-data-ec2/
M1に対応したN予備校プログラミングで勉強継続

#M1の環境構築につまづく恐れがなくなった
M1のMacBookAirを購入した後に、M1は初学者向けではないとの記事をいくつも発見した。
環境構築でつまづくし、自力で解決できる能力がまだ無いから、情報に溢れているIntel版のほうが良い、ということだ。
自分は2020年度版のN予備校プログラミング教材を途中まで進めていて、M1が届いたので今後はこれで進めようと途中から変更したのだが、ものの見事にこの環境構築でつまづいた。

もちろん、事前にある程度の情報は集めていたのだが、ある程度は楽観視していた。
言うてもう時間結構経ってるし、対応してる（情報が発信されてる）でしょ。
こんぐらいのノリでM1をポチっていた。

実際は執筆時点（2021年8月10日）でVirtualBoxをインストールできなかった。
それっぽい方法はあったが、設定している見た目の画像がおっかなかったので触らなかった。

改めてN予備校プログラミングコースについて調べてみると、M1対応の2021年度版が出ていた。
助かりました。

おかげでDockerを用いた仮想環境構築ができました、と。
この環境構築進めているうちに、これ最近のドットインストールでもやったなぁってのがあったので、もしかしたらドットインストールの方が先に対応していたのかも・・・？
【Ruby】sliceメソッドを使った文字列取得の問題

sliceメソッドとは？
文字列や配列から第一引数に指定した値から第二引数の値の分だけ取得するというメソッドです。

```rb
str = "Hello"
result = str.slice(2,3)
puts result

# => "llo"
```
といった感じで取得できます。

引数に負の値を指定することもできます。

```rb
str = "Hello"
result = str.slice(−２,２)
puts result

# => "lo"
```

ちなみに元の文字列strに影響はありません。

```rb
puts str
# => "Hello"
```

今回はこのsliceメソッドを使った問題でした。
*対象の文字列から末尾にある2文字を取得すること
*取得した2文字を3回繰り返して出力すること

```rb
def extra_end(str)
  right2 = str.slice(- 2, 2)
  puts right2 * 3
end

extra_end('Goodbye')

# => "yeyeye"
```
2行目で第一引数に文字列の何番目から取得するかを指定、第二引数で取得する文字数を指定しています。
最後にright2 * 3で代入されている"ye"を3回繰り返す記述をすれば完成。
arduino+超音波センサーで玄関ウェルカムボイス装置

#やりたいこと

+ 誰か（大抵は家族）が玄関に入ってきたときに、ちょっとほっこりできるように声をかけてあげたい。
+ 余っているarduinoUNOと超音波センサーHC-SR04とISD1840搭載録再ボードを組み合わせて何か作りたい。

#やったこと
##準備物

+ arduino (UNO R1)　多分互換機でも動く。
+ HC-SR04　多分アマゾンで買った。
+ ISD1840を積んだボード どこから買ったか忘れた。百数十円だった。

##動作原理

超音波センサーで距離をリアルタイム測定し、決められた距離以下になったら録再ボードに再生信号を送る。

##配線の様子

P-Eに接続すると、１回の信号入力で最後まで一通り再生される。
下の画像は、arduino４番ピンからP-Eに接続されています。

![bd.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/793262/2fbfcaab-08f1-63f5-14df-a5ddc27afc7c.jpeg)

arduino側ピン。ソースにも書いてありますが、

+ 2番ピン→超音波センサーのエコー
+ 3番ピン→超音波センサーのトリガー
+ 4番ピン→録再ボードへの再生トリガー

です。画像の「再生用」の４番ピンが録再ボードのP-Eにつながってます。
Vccは、超音波センサーのVccとブレッドボード上で共有しています。
![pin.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/793262/7bfb38f2-8547-5d3a-a88f-984a24696db9.jpeg)

##全体
とりあえず動作すればいいや、なのでこんな感じに。
超音波センサーの超音波が出る部分を玄関側にセットしています。
![genkan.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/793262/044c98b4-7904-e711-846a-90e8ef211b20.jpeg)
##コード
```c:uss-isd1820.c
//********************************************************************
//*超音波センサを使って距離を表示するプログラム
//
//*ピンアサイン
// 基板を正面（超音波がでる裏側）から見たときの左から順に
// GND Echo Trig Vcc
//********************************************************************
#define echoPin 2 // Echo Pin
#define trigPin 3 // Trigger Pin
#define soundPin 4 // Playback Pin
#define waittime 30 // playback waittime
#define dt 10 // trigger time
#define therm 24 // therm
#define LED 13 // if <10.0cm , blink LED13
#define LIMIT 50 // LIMIT distance 10cm

double Duration = 0; //受信した間隔
double Distance = 0; //距離

void setup() {
Serial.begin( 9600 );
pinMode( echoPin, INPUT );
pinMode( trigPin, OUTPUT );
pinMode( soundPin, OUTPUT );
digitalWrite( soundPin, LOW );
pinMode( LED, OUTPUT );
}
void is10cm(double dist)
{
  if (dist < LIMIT)
  {
    digitalWrite( LED, HIGH);
    digitalWrite( soundPin, HIGH);
    delay( waittime ); //この行がなくても動いた。
    digitalWrite( soundPin, LOW);
  } else
    digitalWrite( LED, LOW);
}
void loop() {
  digitalWrite(trigPin, LOW); 
  delayMicroseconds(2); 
  digitalWrite( trigPin, HIGH ); //超音波を出力0
  delayMicroseconds(dt); //
  digitalWrite( trigPin, LOW );
  Duration = pulseIn( echoPin, HIGH ); //センサからの入力
  if (Duration > 0) {
    Duration = Duration/2; //往復距離を半分にする
    Distance = Duration*(331.45+therm*0.6)*100/1000000; // 音速を340m/sに設定
    Serial.print("Distance:");
    Serial.print(Distance);
    Serial.println(" cm");
    is10cm(Distance);
  }
  delay(200);
}
```
##動作の様子

https://www.youtube.com/watch?v=se6gwbmA264

一応、「お帰りっス」と言ってます。聞こえるかな？
windows環境設定メモ

毎回、何の作業をするかなどを忘れがちなので
必ず毎回これするなーみたいな内容を忘れないようにメモとして残しておく。

もし同じ状況のひとがいればこれを見て「自分もこの作業わすれていた！」などを気づくきっかけになれば幸いです。

##### 不要なアプリケーションのアンインストール

デフォルトで入っているものって不要なものが多いですよねー。。
PCによっても違うと思うので詳細は書かないでおきます。毎回調べましょう

win11だと、「プログラムの追加と削除」では一部のアプリが表示されていないため、コントロールパネルの「プログラムと機能」でも不要アプリがないか確認すると良い

削除したもの
- onedrive
- ゲーム系

##### IMEの変更

普段GoogleIMEを使っているので変更。

またmacのように
「変換」を「ひらがなに入力切替」
「無変換」を「IMEを無効化」
に割り当てるように変更している

単語登録も移行する

##### 電源設定の変更

スリープに勝手にならないようにoffにする

##### win11の右クリックメニューを旧仕様に戻す

https://pc-karuma.net/right-click-context-menu-back-on-windows-11/

##### win11のエクスプローラーのホームを削除

~~https://www.billionwallet.com/windows11/file-explorer-windows-11/remove-home-navigation-pane-in-file-explorer-windows11/#remove-home-navigation-pane-in-file-explorer-windows11-2~~ 消えなかった・・
~~https://www.billionwallet.com/windows11/file-explorer-windows-11/home-quick-access-file-explorer-windows-11/#home-quick-access-file-explorer-windows-11-1~~ 消えなかった・・

##### ブラウザのインストール

vivaldiを使っていてアカウントによる同期機能でかんたんに移行できるのホント便利・・・

##### 圧縮解凍ソフトのインストール

- 7zip使ってます
    - https://std9.jp/articles/01fp1cyphrgt39v0ct0szv8jk4 よりダブルクリックで展開まで行えるようにせってい

##### capslockをctrlキーに

1. https://learn.microsoft.com/ja-jp/sysinternals/downloads/ctrl2cap よりダウンロード => 解凍
2. コマンドプロンプトを管理者権限で開き、 `ctrl2cap.exe /install` を実行
3. 再起動


##### AppDataに保持しているデータの移行

`${Userディレクトリ}/AppData/Roaming/` などにアプリの設定などを保存していたりする

ローカルのファイルパスを参照している場合もあるため一部置換なども必要だったりする

##### 拡張子表示・隠しファイル表示

エクスプローラの表示タブから変更

##### タスクバー

- 検索ボックスを非表示に
- ニュースと関心事項を無効に
- タスクビューボタンを非表示に
- ピン留めするアプリケーションを変更

##### スタートアップメニュー

起動時に自動起動したいものなどをショートカットなどで設置する

`AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup`

##### 送る メニュー

エクスプローラで `shell:sendto` と入力すると送るメニューの内容を変更できる

##### スタートメニューを整理

ここらへんは最後でもいいかも

##### 規定のプログラムの設定

ある程度のところは設定しておく

- テキストエディタ
    - txt, md, json
- ブラウザ
    - html, pdf
- csvエディタ
    - csv, txv

##### コマンドプロンプトにてlsやpwdなどunixコマンドを用意

https://qiita.com/r12tkmt/items/b552d41bfe47d275b13a

##### windowsの警告音を消す

rloginなどでタブキー時に警告音なるのがしんどいので警告音ごと消す

https://ex1.m-yabe.com/archives/3804#

##### エクスプローラの右クリック「新規登録」の不要なもの削除

https://ascii.jp/elem/000/004/155/4155459/

- win11だとビットマップイメージはregeditで設定ではなくアプリ側による制御のようで、ペイントアプリをアンインストールしなければならない

##### タスクバー右部のシステムトレイアイコンの表示

slackなどを始め、一部のものがシステムトレイアイコンのうち隠れているため、
`windowsのシステム（「Win + i」キー） > 個人用設定 > タスクバー > その他のシステムトレイアイコン`
にて常時表示しておくものを選択できる
AWS 認定 DevOps エンジニア – プロフェッショナルに合格したので勉強方法を書いておく

AWS 認定 DevOps エンジニア – プロフェッショナルに合格したので、勉強方法を備忘として書いておきます。参考になれば幸いです。

職業：現在インフラエンジニア6年目でAWSをメインに設計構築をするようになって、2年くらい。
最近はもっぱらオンプレミスからAWSへの移行などのコンサルをやることが多いです。
AWSをやる前は、VMwareやWindows、Linuxなどいろいろやってましたが、
今では、AWSが得意！と言えるくらいになってます。

他のAWS関連の資格：
　ソリューションアーキテクトアソシエイト(SAA)(2018年取得)
　SysOpsアドミニストレータアソシエイト(SOA)(2019年取得)
　ソリューションアーキテクトプロフェッショナル(SAP)(2020年取得)
　セキュリティ – 専門知識（SCS）(2021年取得)
　デベロッパーアソシエイト（DVA）(2021年取得)
　クラウドプラクティショナー（CLF）(2021年取得)

https://qiita.com/Regryp/items/0645fb976655262e9229

https://qiita.com/Regryp/items/2066ffca878e1726aa3c

https://qiita.com/Regryp/items/19f85ca4aec1940ca106

勉強期間:１ヶ月くらい
私の場合、集中して長時間時間を取るということが苦手で、ほぼ毎日３０分〜４０分程度の時間をとってやっていました。

#試験について
DVA、SAPを取得している私としては、DVAの勉強である程度、開発に関するAWS関連サービスの知識は覚えていたので、特段難しさはあまりありませんでした。DVAの復習と、CloudFormation、Codeシリーズ、ElasticBeanstalkなどのデプロイ手法を中心に勉強しました。DVAの資格を直近で取得していたことが一番役立ったので、DVAの資格を先に取得することをおすすめします。

#試験までに何をやるか
###1.「AWS 認定試験に備える」を参照する
これは基本です。どの試験にも共通しますが、出題範囲、見るべきドキュメント、トレーニングが列挙されています。
基本的に私の勉強方法は以下URLのリンク先を潰していくことがメインとなります。
学習のヒントとして、出題範囲や、参考とするドキュメントなど事細かにリンクが載っていますので、
最初に見ることをおすすめします。

https://aws.amazon.com/jp/certification/certification-prep/

###2.試験ガイド、サンプル問題を読む
出題される分野、配分、問題の形式をしっかり読みましょう。
配分は以下のとおりです。

分野 1: SDLC の自動化 22%
分野 2: 構成管理および Infrastructure as Code 19%
分野 3: 監視およびロギング 15%
分野 4: ポリシーと標準の自動化 10%
分野 5: インシデントおよびイベントへの対応 18%
分野 6: 高可用性、フォールトトレランス、およびディザスタリカバリ 16%

[試験ガイド](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-sa-pro/AWS-Certified-Solutions-Architect-Professional_Exam-Guide.pdf)
[サンプル問題](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-sa-pro/AWS-Certified-Solutions-Architect-Professional_Sample-Questions.pdf)


###3.公式トレーニングを受ける
無料でデジタルトレーニングが受けられます。
私はいつもこのトレーニングをとっかかりにして勉強しています。求められるスキルやサンプル問題などの解説もしてくれるので、自身に足りない分野など勉強の方向性をイメージしやすいです。
分野ごとの基本的な解説、練習問題、模擬試験を受けることができますので、イントロとしてはちょうど良いレベル感です。ただし、このトレーニングを受けたからといって試験に受かるというわけではなく、更に深堀りして勉強することが必要です。
[Exam Readiness: AWS Certified DevOps Engineer – Professional (Japanese)](https://www.aws.training/Details/eLearning?id=40664)

###4.問題集を解く
aws WEB問題集で学習しようのサイトにて、DOPの問題を2周しました。
やはり、問題集を解くことが一番ためになります。試験で求められる知識をチェックできる、間違えた問題から苦手な分野、深堀りすべきドキュメントが参照できるというところがあるので、一番おすすめです。

https://aws.koiwaclub.com/

Udemyの問題集も購入して解いて見ました。
※セールのときに購入するのがおすすめです。
ちょっと日本語が怪しかったかなぁ・・・

https://www.udemy.com/course/aws-devops-dop-c01-2020/


###5.ホワイトペーパー、よくある質問、BlackBeltを見る
全体的に苦手な分野を軽く目を通すレベルでよいかなと思います。
私の場合、CloudFormation、Lambda、CodeシリーズあたりのBlackBelt、よくある質問を軽く眺めました。

https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/#management-admin

#最後に
苦手な開発系再びでしたが、前回のDVAの対策をしっかり実施したおかげか、それほど難しく感じませんでした。
DVAを受験された方はぜひ間髪入れずに受けることをおすすめします。
ちなみに、結果は、910点
なかなか良いスコアではないでしょうか。
次回、DBS編書きます〜
「オブジェクト指向でなぜつくるのか」

# TL;DR
「オブジェクト指向でなぜつくるのか」を読んだまとめ。
https://www.amazon.co.jp/dp/4822284654

# 「オブジェクト指向」が生まれるまでの歴史
WIP

# 「オブジェクト指向」とは？
- 以前までに普及していた構造化言語にはない下記の三つの仕組みが備わっている言語
    - カプセル化（クラス）
    - ポリモーフィズム
    - 継承
- 構造化言語では解決できなかったグローバル変数の乱用と再利用性の貧弱さを解消している
    - グローバル変数を利用しない仕組み
    - 共通サブルーチン以外の方法で再利用性を高める仕組み

# オブジェクト指向の三大要素
## ①カプセル化（クラス）
### ①-1 まとめる
- クラスを宣言することによって関連する変数と処理をまとめることができる
    - まとめた時の変数を「インスタンス変数」、処理を「メソッド」という
- 関連する処理をまとめることによって処理の分類と部品化ができ、プログラムの見通しが向上する
- 変数やメソッドはクラス内で一意であればよいので命名が明解、簡略になる

### ①-2 隠す
- アクセス修飾子を用いることによってインスタンス変数やメソッドへの参照を制御し、影響範囲を狭めることができる
    - グローバル変数のように「どこから参照されているかわからない」といった状況を減らすことができる

### ①-3 たくさん作る
- クラスを一度定義すれば実行時にいくつでもインスタンスを作成することができる
- インスタンスはそれぞれ独立しているので、あるインスタンスの呼び出しは他のインスタンスに影響を及ぼさない
- インスタンスを複数作成することによって同じ種類の情報を複数同時に扱う処理でも、シンプルにその処理を記述できる

## ②ポリモーフィズム
## ③継承
VQGAN+CLIPでGenerative Artしてみる

最近Twitterで見かける機械学習を用いたアート作品が気になっていたので、試してみました。
使ったのはVQGAN+CLIPです。

VQGANとCLIPとは
>ベクトル量子化(VQ)を用いたVAEである「VQ-VAE」を、敵対的生成ネットワーク(GAN)に発展させた新しい画像生成モデルが「VQGAN」です。このVQGANと、テキストと画像という異なるデータを結びつけるニューラルネットワークの「CLIP」を組み合わせることで、「入力したテキストから画像を生成するモデル」をライアン・モールトンさんが作成しています。
[画像生成AIはアートのあり方を変えてしまうのか？-GIGAZINE](https://gigazine.net/news/20210726-vqgan-clip-generate-iamge/)

だそうで、つまりテキストを入力するとそれに合わせてマシンが画像を作ってくれるのです。すごい。
そんでもってそれを誰でも使えるように公開していらっしゃいます。
[VQGAN+CLIP (z+quantize method con augmentations, interfaz amigable).ipynb](https://colab.research.google.com/drive/1go6YwMFe5MX6XM9tv-cnQiSTU50N9EeT)

こちらで書かれている説明通りに進めたら簡単にできました。
[Help: Generate images with VQGAN + CLIP](https://tuscriaturas.miraheze.org/wiki/Ayuda:Generar_im%C3%A1genes_con_VQGAN%2BCLIP)

#手順

簡単にまとめるとこんな感じ。
① Parametrosセルのtextosに好きなテキストを入力
② 一番上のLicensed under the MIT Licenseというセルから順番にRunしていく
③ Hacer la ejecución...というセルをRunすると画像が生成される（50イテレーションごとに1枚ずつ画像が増えていきます）
④ 十分だなと思ったHacer la ejecución...のセルを停止する

動画でDLしたいとき
⑤ Genera un vídeo con los resultadosの1つ目のセルをRunした後、2つ目のセルRunではブラウザで確認、3つ目のセルRunでは動画がダウンロードされる

調整したい場合はParametrosをいじればOKです。

#やってみた

入力テキスト
` a fantasy world vray unreal engine hyperrealistic` 
実行結果
![a fantasy world vray unreal engine hyperrealistic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704563/43f5367c-01f7-b4bf-8a12-9f528b6a2e16.png)

入力テキスト
` star wars hokusai katsushika` 
実行結果
![star wars hokusai katsushika.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704563/9ba91d35-1d9c-1a09-28cf-7ff654a55de6.png)
入力テキスト
` star wars Klimt style` 
実行結果
![star wars klimt style.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704563/54fc1b57-63a0-008c-6c1c-500d43bf18cb.png)

どれもイテレーションは400くらいです。
#補足

ちなみにvray unreal engine hyperrealisticというのは、いい感じな出力結果を出すための魔法の言葉です。
いろんな人がVQGAN+CLIPをhackするために編み出しています。
ほかにも、アーティストのスタイルであれば

>Beksinski style / Dali style / Van Gogh style / Giger style / Monet style / Klimt / Katsuhiro Otomo style / Goya [r 4] / Miguel Angel (Sistine Chapel style) / Joaquin Sorolla style / Moebius style / in Raphael style (sometimes contributes to improve the lines of the faces).

とか色々あるみたいです。詳しくはこちらのUse adjectivesで見れます。
[Help: Generate images with VQGAN + CLIP](https://tuscriaturas.miraheze.org/wiki/Ayuda:Generar_im%C3%A1genes_con_VQGAN%2BCLIP)
Ruby　配列と繰り返し処理

#目次
今回は、以下のテーマを書いていきたいと思います。

- 配列
- 繰り返し
- ハッシュ

#配列
配列とは、値をまとめて管理する方法です。変数の箱が連続して並んだイメージです。配列の要素には前から0,1,2,,というように数字が与えられており、インデックス番号と言います。これを利用して要素を取り出したり削除したりします。

```ruby
foods = ["Rice","Ramen","Sushi"]
puts foods[1]
puts "好きな食べ物:#{foods[2]}"
#=>Ramen
#=>好きな食べ物:Sushi
```
上記の例だと、foods[0]が"Rice",foods[1]が"Ramen",foods[2]が"Sushi"に対応しています。

#繰り返し
繰り返し処理の一つにeach分があります。配列の要素が一つづつ変数に代入されて、each文の中の処理を実行する形になっています。
以下のプログラムだと、配列foodsの各要素を変数foodに代入して、putsで出力する処理を実行しています。

```ruby
foods = ["Rice","Ramen","Sushi"]

foods.each do |food|
  puts "食べ物:#{food}"
end

#=>食べ物:Rice
#=>食べ物:Ramen
#=>食べ物:Sushi
```

#ハッシュ
ハッシュとは、それぞれの値にキーというものを対応づけてデータを管理する方法です。ここでは扱いませんが、ハッシュ関数は入力されたデータに対して対応するデータを返す関数です。そのハッシュ関数により得られた値をハッシュ値と言います。
さて、Rubyでハッシュを記述するときは、
&nbsp;&nbsp;&nbsp;{キー値:, 値}
のように記述します。下のプログラムだと、キー値nameに対応する値"Rice"が出力されていることがわかると思います。

```ruby
foods = {name:"Rice",gram:100}
puts foods[:name]
puts foods[:gram]
#=> Rice
#=> 100
```

配列とハッシュを組み合わせて、食べ物とグラム数を出力するプログラムを以下にしまします。each文で配列の要素を取り出して、さらにキー値のnameとgramに対応する値を取り出して出力しています。

```ruby
foods = [
  {name:"Rice",gram:100},
  {name:"Sushi",gram:200},
  {name:"Ramen",gram:300},
  {name:"Udon",gram:400},
  {name:"Soba",gram:500}
  ]

foods.each do |food|
  puts "-----"
  puts food[:name]
  puts food[:gram]
end
#実行結果
=begin
-----
Rice
100
-----
Sushi
200
-----
Ramen
300
-----
Udon
400
-----
Soba
500
=end
```

#最後に
今回も見ていただきありがとうございました。配列やハッシュは重要な概念なので、興味があれば自ら調べて深掘りして見ましょう。今後も学んだことを共有していきたいと思いますので、よろしくお願いします。