OmniAICreator/Qiita-1.07M huggingface dataset:
Pythonで、OCTAのudfファイル名を操作する

#Pythonで、re、osモジュールを使ってファイル名を一括で処理する。

簡単なプログラムですが、OCTAを使用していて、UDFファイルのみを取り出して、ファイル名を一括で処理したい時があるので、覚えで作りました。

###ファイル名に一括で分類名を付ける。

`re`: 正規表現モジュール
`re.compile()`を使うと、その中の文字列を正規表現にコンパイルしてオブジェクトを作成する。
`reg_exit = re.compile(keyword)`　は、`compile`で、正規表現にコンパイルするキーワードを指定することで、正規表現になる。このオブジェクトを、`reg_exit`に入れる。

`re.search()`: 文字列すべてが検索対象。
`os`: ファイルやディレクトリの操作ができる。
`os.rename(a,b)`: `a`のファイル名を`b`に変更する

`for name in file_list:`で、ファイル名を一つずつ取り出して`name`に入れる。
`if reg_exit.search(name):`で、取り出したファイル名の中に、正規表現にコンパイルしたキーワードがあるかどうかを判別する。
`udf_file.append(name)` は、キーワードのあったファイルをリストに加える。
`os.rename(file, category+file)`　は、ファイル名(`file`)にキーワード(`category`)を加える

```PYTHON:OCTAでのファイル名に一括で分類名をつける
#モジュールをimportする
import os
import re
#ディレクトリー内のファイルのリストを作る.

file_list = os.listdir()
udf_file = []

reg_exit = re.compile(r'(.udf)$')

for name in file_list:
    if reg_exit.search(name):
        udf_file.append(name) 
 

#分類名を指定（category）して、ファイル名に追加（os.rename）する
category = 'カテゴリー10_'
for file in udf_file:
    os.rename(file, category+file)
```
C言語　ALDS1_2_A　Bubble Sort

##問題
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_2_A&lang=ja

##概要
- 安定なソート
- 順番が逆になっている隣接要素がなくなるまで、次の処理を繰り返す。
    - 配列の末尾から隣接する要素を順番に比べていき、大小関係が逆ならば交換する。
- バブルソートの交換回数は反点数、または転倒数と呼ばれ、列の乱れ具合を示す。

##コード

```c
#include <stdio.h>

static void swap(int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

static void print_array(int array[], int array_len)
{
    for (int i = 0; i < array_len; i++)
    {
        printf("%d", array[i]);
        if (i != array_len - 1)
            printf(" ");
    }
    printf("\n");
}

/* バブルソート */
int bubble_sort_count(int A[], int N)
{
    int count = 0;

    for (int i = 0; i < N - 1; i++)
        for (int j = 0; j + 1 < N - i; j++)
            if (A[j] > A[j + 1])
            {
                swap(&A[j], &A[j+ 1]);
                count++;
            }
    print_array(A, N);
    return count;
}

int main(void)
{
    int N;
    int A[100];

    scanf("%d", &N);
    for (int i = 0; i < N; i++)
        scanf("%d", &A[i]);

    printf("%d\n", bubble_sort_count(A, N));

    return 0;
}
```

##ポイント
A[j] < A[j-1]
を
A[j] <= A[j-1]としてしまうと、安定ではなくなる。

##所感
バブルソート勘違いしていて、別のやり方をずっとバブルソートだと思っていた。隣り合う値を交換していく。

自分なりの書き方とか試行していると、時間かかる。

所要時間80分

【復習】

- 2020/04/05
    - OK、イメージ持ててた
    - 実装はしてない
AWS Client VPNとSoftEtherVPNを比べてみた

## はじめに
AWS Client VPN と SoftetherVPN をそれぞれ使う機会があったので、比べてみた個人的な感想です。

**詳細な情報、手順などはどちらも公式ドキュメントが充実してるので、そちらを参照ください。**
[AWS Client VPN管理者ガイド](https://docs.aws.amazon.com/ja_jp/vpn/latest/clientvpn-admin/what-is.html)
[SoftEther VPN マニュアル](https://ja.softether.org/4-docs/1-manual)

## 比較してみる

#### 概要
|||
|---|---|
|**[AWS Client VPN](https://aws.amazon.com/jp/vpn/?nc2=h_ql_prod_nt_avpn)**|・プロトコル：OpenVPN<br>・フルマネージドなので管理が楽<br>・当たり前だが、AWS上にしか構築できない|
|**[SoftetherVPN](https://ja.softether.org/)**|・プロトコル：[色々。標準はSoftetherVPNプロトコル](https://ja.softether.org/3-spec#section_12)<br>　(標準プロトコルはMac非対応なので、Mac対応するなら OpenVPN,L2TP/IPsec等に変更する)<br>・SoftetherVPNサーバを立てる必要がある<br>・AWS以外の環境にも構築できる<br>[なんとWindows98,Solaris8なんかもサポートされている・・・](https://ja.softether.org/3-spec#section_19)<br>・[要求スペックがとても小さい](https://ja.softether.org/3-spec#section_22)<br>・開発は継続されている（最新ビルド:2020-03-20、2020-04-03時点）|

#### 構築
|||
|---|---|
|**AWS Client VPN**|AWSコンソールで クライアントVPNエンドポイント を作成、VPCに関連づける。|
|**SoftetherVPN**|任意の環境に SoftetherVPN Serverをインストールする。<br>※AWS上に構築する場合、コミュニティAMIが提供されているのでEC2インスタンスを起動するだけで使用可。|

#### 管理、設定
|||
|---|---|
|**AWS Client VPN**|クライアントVPNエンドポイントのコンソールで管理|
|**SoftetherVPN**|SoftetherVPNサーバ管理マネージャ を使用（任意の端末にインストールする）|

#### クライアントからの接続
|||
|---|---|
|**AWS Client VPN**|OpenVPNベースのVPNクライアント を使用。<br>AWSから公式クライアントもリリースされた。|
|**SoftetherVPN**|SoftetherVPNクライアント接続マネージャ を使用するのが楽。<br>Mac版は実験バージョンのため推奨しない、となっているのでOS標準クライアントを使用。|

#### 使い勝手、安定性、速度
詳細にデータ取って比較、とかはしてませんが。
どちらも使っていて気になるところは特に無し。

## 比較した感想

AWS上で運用するなら SoftetherVPNを選ぶ理由は特に無さそうなので AWS Client VPNを使うのが良い気がします。
AWS以外の環境でVPN構築するならSoftetherVPNは手軽で良いですね。
要求スペックが低く、古いOSもサポートしているあたり、すごいニッチな要件での利用も可能だけど考えたくはない。

まぁ、**好きなの使えば良いと思います**。
1.4.1 デバッグ機能 : ブレークポイント・プロファイラー

# 目次へのリンク


[MATLABによる画像処理・コンピュータービジョン入門目次](https://qiita.com/tohruk/items/e5f7939b622bcf2e3c4c)


# 概要


MATLABのエディターのブレークポイント機能およびプロファイラー機能を紹介します。



   -  ブレークポイント機能：プログラムを一時停止してデバッグできます。 
   -  プロファイラー機能： 関数ごとの実行時間を計測できます。 


対応ファイル：[I1_04_1_profilerTest.m](https://github.com/mathworks/MATLAB-IPCV-Eval-Kit-JP/blob/master/demo_files/I1_04_1_profilerTest.m)

# MATLABのエディターでMATLABプログラムを開く


今回はコードアナライザーの機能を知るために警告やエラーが含まれているコードを開きます。


```matlab:code
edit I1_04_1_profilerTest.m
```
# ブレークポイント


ブレークポイントはプログラムをある条件で一時停止し、その時点での変数の内容を確認できる機能です。




以下の3つの種類のブレークポイントがありますが、ここでは標準ブレークポイントを取り上げます。



   -  標準ブレークポイント 
   -  条件付きブレークポイント 
   -  エラー ブレークポイント 



プログラムが動作がおかしいときに各変数の値がどうなっているか確認するのに便利です。


## ブレークポイントの設定と値の確認


ブレークポイントをプログラムの行番号の右側をクリックし設定します。




もう一度クリックすると解除することができます。




設定したらプログラムを実行します。




ブレークポイントを設定した行に到達すると実行が中断され、値が参照できるようになります。




コマンドウィンドウで計算したりもできます。




![image_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14336/6b81b197-b3ea-9dee-c070-e6ea593d9286.png)


# プロファイラー


MATLABプログラムの実行が遅い場合、速度低下が起きている場所を特定するのに便利な機能です。




エディターの「実行および時間の計測」をクリックします。





![image_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14336/4655db77-b7a0-485c-53c8-da3bf0474699.png)




実行が終わると各関数の呼び出し回数や実行時間が表示されます。





![image_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14336/37b776ce-a5c4-bce8-00bd-efcd27606b84.png)




関数をクリックすると、どの処理が何回呼び出されているか、どこがボトルネックになっているか表示されます。
![image_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14336/fdcf77e4-ee39-bdca-0f85-9a1a43fecf06.png)


# まとめ


MATLABのエディターに内蔵されているブレークポイント機能およびプロファイラー機能を紹介しました。




プログラムがおかしい、デバッグしたいときにはブレークポイント機能を活用し、変数の値を確認しましょう。




また、MATLABプログラムが重い、遅いときにはプロファイラー機能を活用して、ボトルネックを見つけましょう。


# *参考*

   -  [プログラムのパフォーマンスの測定](https://www.mathworks.com/help/matlab/matlab_prog/measure-performance-of-your-program.html) 
   -  [パフォーマンス改善のためのプロファイリング](https://www.mathworks.com/help/matlab/matlab_prog/profiling-for-improving-performance.html) 

# *謝辞*


本記事は @eigs さんの[livescript2markdown](https://github.com/minoue-xx/livescript2markdown)を使わせていただいてます。


# 目次へのリンク


[MATLABによる画像処理・コンピュータービジョン入門目次](https://qiita.com/tohruk/items/e5f7939b622bcf2e3c4c)
M5ATOMでちょっと見栄えの良いサンプルを作った

#M5ATOMを買った
M5Stack社の新しい極小ESP32モジュールのM5ATOM、
ようやく技適が取れたバージョンが買えるようになりましたね。
うちにあるのが技適（ｒｙ

とりあえずサンプルコードを動かしてみようと思ったのですが、
なんか派手そうなLEDDisplayの方は暗黒しか表示されず、
LEDSetはLEDがひとつつくだけです。もうちょっと見栄えのいいものを！
というわけでサクッと作ってみました。

[M5ATOM random fade demo on Youtube](https://www.youtube.com/watch?v=TlTYHiWl-MM)

```arduino:M5AtomRandomFade.ino
#include "M5Atom.h"

void setup() {
  Serial.begin(9600);
  M5.begin(true, false, true);
  delay(50);
  M5.dis.drawpix(0, 0xf00000);
}
long color;
int r = 255;
int g = 255;
int b = 0;
void loop() {
  int rn = random(255);
  int gn = random(255);
  int bn = random(255);
  int rp = (rn - r) / 20;
  int gp = (gn - g) / 20;
  int bp = (bn - b) / 20;
  for (int i = 0; i < 20; i++) {
    r = r + rp;
    g = g + gp;
    b = b + bp;
    long gb = g << 16;
    long rb = r << 8;
    long bb = b << 0;
    color = rb + gb + bb;
    painting();
  }
}

void painting() {
  for (int x = 0; x < 25; x++) {
    Serial.print(r); Serial.print(";");
    Serial.print(g); Serial.print(";");
    Serial.print(b); Serial.print(";");
    Serial.println(color, HEX);
    M5.dis.drawpix(x, color);
  }
  delay(25);
  M5.update();
}
```
M5ATOMの環境が入っていればサクッと動くと思います。動いて。
LED全部がランダムなカラーにフェードします。

この小ささはいいですね。意外と裏にGPIO出ているので
何かと重宝しそうな気がします。
![IMG_8303.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521584/53306da0-28a8-416d-9711-8f43b90f26ac.jpeg)

うちの環境ではUpload Speedを115200にしないと転送できなかったので、
書き込みに失敗する人はお試しあれ。
http4sでCSVファイルをダウンロード

# はじめに
[http4s](https://http4s.org/)を使ってCSVファイルをダウンロードさせたかったけれども、全くと言っていいほど資料が出てこなかったので書いておく。

## 環境

- Scala: 12.13
- http4s: 0.21

# 結論
どうやらhttp4sに使われてる[fs2](https://github.com/functional-streams-for-scala/fs2)の`Stream`を利用してCSVの行を生成して適当なヘッダーを付けてレスポンスを返してやればよさそう（Excelで開きたかったら先頭にBomを付けてやる必要あり）。

# 例
適時importしてください。

```scala
val routes: HttpRoutes[IO] = HttpRoutes.of[IO] {
  case GET -> Root / "download" =>
    val bom = Stream.chunk(Chunk[Byte](0xef.toByte, 0xbb.toByte, 0xbf.toByte))
    val csv = Stream.evalSeq(List("a,b,c","1,2,3")).intersperse("\n").through(fs2.text.utf8Encode)
    val stream = bom ++ csv

    Ok(
      stream,
      `Content-Type`(MediaType.text.csv, Charset.`UTF-8`),
      `Content-Disposition`("attachment", Map("filename" -> "file.csv")))
}
```

これでブラウザからURLをたたけばCSVファイルがダウンロードされるはず。
puppeteerでユーザーによるクリックを待つ

# ユーザーによるクリックなどのイベントををpuppeteerで待ちたい
闇が深い場面な気はしますがpuppeteerを使ってクリックや入力などのイベントを受け取りたいことがあったとします。

そんな時にイベントを検知するスクリプトに苦戦したので関数として書き残しておきます。Promiseに対してresolveするだけの関数を作りpage.exposeFunctionで関数を公開し、evaluateで公開した関数をaddEventListenerを使って登録します。
半自動でパスワードなどは入力させたい時なんかに使ってください。
引数のmyEventNameは複数回実行する時に被らなければ何でも構いません。

```script.js
async function waitEvent(page,myEventName,eventType,elementId){
	return new Promise(async resolve=>{
		await page.exposeFunction(myEventName,()=>{resolve(myEventName);});
		await page.evaluate((elementId,eventType,myEventName)=>{
			document.getElementById(elementId).addEventListener(eventType,()=>{
				eval('window.'+myEventName+'();');
			});
		},elementId,eventType,myEventName);
	});
}

```

# 使い方
使用例です。
クリック以外のイベントにも使えます。
要素のイベントでは無い物が欲しければobserve等使えば行けるとは思います。

```example.js
var result_input = await waitEvent(page,'myclickEvent','click','buttonId');
```

jQueryのval()などからの変更はプログラム側から意図的にイベントが発生させない限り反応できないらしい。
クラウドのデプロイ先について調べてみた

|サービス名|概要|
|-----------------|------------------------------------------|
|AWS Elastic Computing Cloud|AmazonのIaas|
|AWS Elastic Beanstalk|AmazonのPaas|
|Google App Engine|GoogleのPaas|
|Google Compute Engine|GoogleのIaas|
|Microsoft Azure App Service|MicrosoftのPaas|
|Zenlogic|ソフトバンクグループ会社のIaas|
|AnalyticMart on Demand|三菱電機のPaas|
|NEC Cloud|NECのIaas／Paas|
|heroku|Heroku社のIaas|
|Firebase|GoogleのmBaaS|
|ConoHa|GMOのIaas|
|Netlify|静的コンテンツ配信サービス|
|ロリポップ|GMOペパボが出しているUnixのIaas。WordpressでHPを公開したりメールサーバ向けのよう|

###AWS Elastic Computing Cloud



###AWS Elastic Beanstalk
AmazonのPaas。EC2にプラスして、ロードバランサ、ファイアウォール、DBなどのプラスαのインフラを纏めてバンドルしてくれる。ソースコードをバージョン管理してスイッチすることもできる。コンソール画面でも操作できるので非エンジニアでも運用者にアサインできる？

###Google App Engine
ウェブアプリケーションを開発およびホスティングするための、フルマネージド型のサーバーレスプラットフォーム。
アプリの開発では複数の一般的な言語、ライブラリ、フレームワークからの選択が可能で、開発したアプリのインスタンスのサーバー プロビジョニングとスケーリングは App Engine によってオンデマンドで行われます。

コンテナ技術で40msecとかでスケールアウトができる？
ブルーグリーンデプロイメント：新しい環境をデプロイして、問題なければLBとかでごっそり入れ替える。それを特別な設定なしにできるようになっている。

###Google Compute Engine


###Microsoft Azure App Service
https://azure.microsoft.com/ja-jp/
"Web Apps" "Mobile Apps" "Functions" "API Apps"のアプリケーション群の総称。

#####"Web Apps"
Webアプリをデプロイするマネージドサーバ。.Net、Java、node.js、python、phpに対応している
#####"Mobile Apps"
モバイルアプリをデプロイするマネージドサーバ。
#####"Functions(Logic Apps)"
関数実行基盤。
#####"API Apps"
RESTAPIの実行基盤。でもLogic Appsとの違いがよくわからん。

###Zenlogic
https://www.idcf.jp/rentalserver/
レンタルサーバ。Yahooのクラウド基盤を使用した共有サーバー形態とAWSを利用した専用サーバー形態がある。
WebサイトによるGUI管理ができる。sshでCUI操作はできない模様？

###AnalyticMart on Demand
https://www.mind.co.jp/news/2013/0723.html
データ分析向けSaas？

###NEC Cloud
https://jpn.nec.com/cloud/index.html
IaasとPaasの２つの形態がある？

###heroku（ヘロク）
https://jp.heroku.com/
PaaS。GitHubと連携してデプロイができる。主要な言語に対応している。

###Firebase
https://firebase.google.com/
mBaas。モバイルアプリのバックエンドサービス基盤。

###ConoHa
GMOが出しているIaas。WordpressでHPを公開したりメールサーバ向けのよう。	
https://www.conoha.jp/

###Netlify（ネットリファイ）
https://www.netlify.com/
GitHubと連携させた自動デプロイができる。PHPなどは動かせないのでWordpressを構築することはできない。

###ロリポップ
https://lolipop.jp/
HPやメール向けのレンタルサーバ。通信許可されているポートもガチガチに固められている。
うわさのYチャネルにQRVしてみる

#はじめに
朝ガストメンバーの交流のためのAルームというプライベートルームを設置していますが、コロナ騒ぎで、朝ガストのアイボール会が開催できないために、そのAルームでロールコールを行おうと考えています。
そのための接続設定を解説します。

#圏央道友会のNoraVRページでClientソフトをダウンロード
Android端末で、下記URLページで、NoraVR Client Sample⑭をダウンロードします。


2019/07/28 NoraVR Client Sample⑭
https://1drv.ms/u/s!Alt6WCVd8Pgfomlu4Mlvwj0l_htx

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531121/135d4378-b4c7-7a67-ce47-71fc1d3d5ce8.png)

下記警告が出ますが、OKで保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531121/42a158e2-cbea-6a17-1f8b-ef4b91b34562.png)


#NoraVR Client Sample⑭をインストール
次に保存すると、自動的にインストールするか聞いてきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531121/f089a6e3-4d60-46fb-fc6d-33add453c73f.png)

インストールします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531121/035ce451-fbb7-710b-c5f0-de0190f00fb4.png)

開くをクリックするとアプリが起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531121/934424aa-e6fd-7418-e0cf-5c12aa26e013.png)

#NoraVR Client Sample⑭の設定
configボタンをクリックして、設定画面で必要項目を入力します。
下記画面を参考に自分のコールサインに置き換えて設定ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531121/58325b92-e814-d107-2a99-394938f59d66.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531121/606bad2e-0265-db4a-1d69-688278194005.png)

設定したら、SAVEをタップします。
#Yチャネルへの接続設定
Use GatewayのスイッチをまずONにします。
まず、切断設定をやります。

「_______U」( _を７個にU)をTOに指定して、カーチャンクします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531121/3323c8ed-8fe3-6ebd-3f98-0ec1bc456d84.png)

画面下のMicGainの上のメッセージがUNLINKになっていればOKです。

次に「XLX129YL」をTOに指定して、カーチャンクします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531121/d12fac19-80e2-0f59-6d55-0d18d1c3c331.png)


画面下のMicGainの上のメッセージがXLX129 Y LINKEDになってればOKです。

次にTOをCQCQCQにするためにTOのちょっと下の(CQCQCQ)スイッチをいれます。
USE GATEWAYもONにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531121/90c22019-9bfa-0405-c1c3-ce3e56d5b3b2.png)

これでQRV出来るようになりました。

#おわりに
今回は、朝ガス限定の公開NoraVRサーバを使いました。
Dockerコンテナ上のaws-cli環境でAWS Error Message: Signature expiredが表示されたときの対処方法

## はじめに
dockerコンテナ上のaws-cli環境で`aws sts get-caller-identity`をしたら、時間がずれてるとおこられたので、また起きた時用メモ。


## どうしてかわかんないけど、こうなった
① An error occurred

```
root@xxxxxxx:/home# aws sts get-caller-identity
An error occurred (SignatureDoesNotMatch) when calling the GetCallerIdentity dentity operation: Signature expired: 20200323T231737Z is now earlier200324T0 than 20200324T002325Z (20200324T003825Z - 15 min.)
```

② 本当にずれてるのか確認してみる。ちなみにこの時午前10時ちょっと前。

```
root@xxxxxxx:/home# date
Fri Apr 02 23:30:39 UTC 2020
```

③ UTCだとよく分からないからJSTに変えてみる。

```
root@xxxxxxx:/home# TZ=-9 date '+%a %b %d %H:%M:%S JST %Y'
root@xxxxxxx:/home# date 
Fri Apr 03 08:33:30 JST 2020
```

ずれてた。1時間半も。

## 修正方法

1.　検索ボックスに「Hyper-V マネージャー」を入力して選択。

![hyper-v manager01](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491542/10d922f2-7ca5-a243-1e6c-6fb47febb227.png)


<br>
<br>

2.　DockerDesktop VM の「設定」を選択
![hyper-v manager02](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491542/bd479447-b8a5-ef49-4e8c-1255095f62b1.png)

<br>
<br>

3.　管理 の 統合サービスを選択して「時刻の同期」にチェックを入れる。
（※もともとチェックが入っている時は一度外して適用。その後チェックを入れてもう一度適用。）

![hyper-v manager03](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491542/db964582-8447-4ec5-240d-c7dd49bc4fee.png)

<br>
<br>

## おわりに
この後、エラーが消えて解決！めでたし！
AzureでVMにリモートデスクトップでログイン時にMFAしようとしてハマった話

# はじめに
AzureでWindowsVMのメンテナンス時にリモートデスクトップ接続するわけですが、「いまどき２要素認証は必須だよね」ということで調べてみました。
RD Gatewayを踏み台にする構成でできそうだなあと軽い気持ちで始めましたが、がっつりハマりました。

環境の構築は、マイクロソフト公式の以下の記事を参考にしました。
[ネットワーク ポリシー サーバー (NPS) 拡張機能と Azure AD を使用したリモート デスクトップ ゲートウェイ インフラストラクチャの統合](https://docs.microsoft.com/ja-jp/azure/active-directory/authentication/howto-mfa-nps-extension-rdg)

この記事では、最後は「リモート デスクトップ Web アクセス」で動作確認して終わりになっていますが安心してください。リモートデスクトップクライアントからのアクセスでも問題なくできます。（リモートデスクトップクライアントには、セカンダリ認証のPIN番号を入れるという画面が出てこないので、MicrosoftのAuthenticator アプリの利用が必須です。）

また、VMにログインするユーザをAzure ADに登録する必要があるため、「Active Directory ドメイン サービス (ADDS) 」とAzure AD Connectを使用しています。

と、この辺りで後悔し始めます。「ログイン時に２要素認証したいだけなのに・・・」
実際に構築したいシステムよりも大掛かりになってしまいました。

#前提条件
MAFを行いたいユーザ毎にAzure Active Directory Premium1以上のライセンスが必要です。

なのですが、Azure portalからは購入できません。office365ポータルで購入する必要があります。これがわかるまで、サポート窓口でたらい回しにされました。

office365を契約していなくてもAzureのアカウントを作成するとoffice365に自動的に紐つけられるようです。

以下のURLにAzureのアカウントでログインします。
[office365 portal](https://portal.office.com/Adminportal/Home#/homepage)


#ハマった点その１
[ネットワーク ポリシー サーバー (NPS) 拡張機能と Azure AD を使用したリモート デスクトップ ゲートウェイ インフラストラクチャの統合](https://docs.microsoft.com/ja-jp/azure/active-directory/authentication/howto-mfa-nps-extension-rdg)の手順通りに構築したのですが２要素認証の通知がAuthenticator アプリに来ません。
RADIUSサーバ（NPS 拡張機能がインストールされている NPS サーバー）でパケットキャプチャを行ってみましたが、そもそもEAPoL（RADIUS認証の要求）のパケットを受信していません。
これは、Windows Server 2019サーバの問題のようです。

以下の記事を参考に設定を変更しました。
[Windows Server 2019のネットワークポリシーサーバーでRADIUS認証が失敗する](https://qrunch.net/@armband/entries/gAWOm2G1SZp7MIf9?ref=qrunch)

コマンドプロンプトで以下のコマンドを叩きます。

```shell-session
>sc sidtype IAS unrestricted  
[SC] ChangeServiceConfig2 SUCCESS  
```
#ハマった点その２
これでできるかと思ったのですがMAFの認証でエラーになります。
リモートデスクトップからは、Active Directory ドメイン サービス (ADDS) のドメインユーザでログインするのですが、Azure ADのドメイン名と異なっているとMAFの認証で失敗します。
これを回避するために、NPS の拡張機能の代替ログイン IDを使用するように設定します。

[Multi-Factor Authentication の NPS の拡張機能の詳細構成オプション]
(https://docs.microsoft.com/ja-jp/azure/active-directory/authentication/howto-mfa-nps-extension-advanced)

これって、直接レジストリを編集する必要があるし、そもそも何を設定していいかよくわかりません。
色々試行錯誤していて諦めかけた時、Authenticator アプリに認証の通知が飛んできました。

例えば、
LDAP_ALTERNATE_LOGINID_ATTRIBUTEにmailを設定します。
Active Directory ドメイン サービス (ADDS)でユーザのmail属性をAzure ADのドメインユーザ名にします。

これで、mailに書かれたユーザでMAF認証が行われます。

#最後に
このシステムを構築するために、以下の４つのサーバを作成しました。小規模なシステムには向かないと思います。
	• RDGatewayサーバ
	• ネットワーク ポリシー サーバ
	• Active Directory ドメイン サービス (ADDS) サーバ
	• Azure AD Connectサーバ
今回は、すべて異なるVMに配置しました。RDGatewayサーバとネットワーク ポリシー サーバは、別のVMに配置する必要があるようですが、そのほかは、同じVMに配置できるかもしれません。

最近知ったのですが、Azure Bastionという便利なものが・・・
[Rails]httpからhttpsにリダイレクトする方法

#はじめに
オリジナルサービスを作成した際に、httpで作成しておりパスワードを入れる時に
「このサイトは危険です！」みたいな警告が流れてきました。
これは。と思い、URLを見ると**http**のままになっていました。パスワード打つ時にこんな警告が流れるともうそのサイト使いたくならないですよね笑

#結論
単純ですが、 `config/environments/production.rb`　にこの一文を書き足す・または修正するだけでhttps化できました。
 
```ruby:config/environments/production.rb
config.force_ssl = true
```

#まとめ
railsってなんでもありますね。ほんとすごい。
他にも設定することがあるのかもしれませんが、特に現状は問題なく経過しています。
PythonでPDFファイルのテーブルデータを読み取る

## PDFデータ
世の中の人はPDFが大好きなようで、嫌い嫌いと言っていても扱わざるを得ません。しかし、それに何時間もかけるのはちょっと・・・と思うのが人の常です。PDFの表データをしかないというケースもありますが、そのような際に便利な[tabula-py](https://pypi.org/project/tabula-py/)という超便利なライブラリがあったのでメモしておきます。    
     
[https://github.com/chezou/tabula-py](https://github.com/chezou/tabula-py)
## tabulaにかんして

tabulaはPDFの表を抽出するためのJavaのライブラリです。tabula-pyはそのラッパとなっております。そのため、利用するためにはJavaのインストールが必要です。     
      
Javaをインストールした後、下のようにするとPythonのライブラリが利用できます。     
     
```
$ pip install tabula-py
```

## 利用方法
利用方法は簡単で、read_pdf関数を用いるとPDFファイルにある表が読み込めます。事例には厚生労働省の新型コロナウイルス陽性者数(チャーター便帰国者を除く)と[PCR検査実施人数](https://www.mhlw.go.jp/content/10906000/000618483.pdf)を用います。 

```python

from tabula import read_pdf

df = read_pdf("https://www.mhlw.go.jp/content/10906000/000618483.pdf")

```

表の読み込み結果は下のように表示されます。     
     
![read_pdf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85433/3e27608b-df0f-d1b9-fada-98886245bc7f.png)

複数表があるため上のようになります。次に取得する表を指定します。    
     
![table1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85433/843ce04b-557b-f632-7bda-2416d942fec2.png)
   
上を見るとわかりますが、表はpandasのデータテーブルの形になっています。超便利ですね。このPDFファイルでは2列にデータが分かれているため、表をがっちゃんこする必要があります。この際もデータテーブルなのでpandasのconcat関数を用いることができます。    
     
![table2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85433/3aae8eae-ff0b-903e-df61-26634d605975.png)
     
データフレームであるため、可視化も容易です。    
     
![table3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85433/57972d38-7988-e172-9fc0-3db202f07ce5.png)

という感じで、tabula-pyを使うことで、PDFの表データも簡単に取れますね！
ChromeへのVue.js devtoolsの導入方法

# 概要

「Vue.js devtools」をChromeに入れると、デバッグ作業が快適になるよ！、って話。

# インストール方法

「Vue.js devtools」でGoogle検索すると、Chromeウェブストアの以下のURLがヒットするので、クリックしてジャンプ。

https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=ja

インストール時に「アクセスしたウェブサイト上にある自分の全データの読み取りと変更をこの拡張機能に許可します。」って聞かれるので「はい」と許可。
**許可したくない場合**は、いったん「いいえ」で拒否った後に次のようにする。

Chromeメニューの「拡張機能＞Vue.js devtools＞詳細＞サイトへのアクセス」を開いて、「特定のサイト」を選択して「`http://127.0.0.1/*`」などと入れる。Vue.jsのデバッグを行う時のローカルサーバーは、通常は「`http://127.0.0.1:8080/`」になるので、このローカルサーバー上のデータに対して**のみ**読み取りと変更を許可すればOK。

![特定のサイトに対してのみ許可する](https://gyazo.com/1763338d6859c9a197f761c2b9c1632f.jpeg)

状態を反映するため、いったんChromeを再起動する。

後は、Vue.jsの開発用ローカルサーバーを起動していつものように「`http://127.0.0.1:8080/`」へアクセスする。

F12キーで「ディベロッパーツール」を開いて、「Memory」等のタブの右端に（無い場合は「＞＞」をクリックして展開する）、「Vue」を開く（※許可したURL以外では「Vue」タブは表示されない）。

すると、次のようにデバッグできる。変数の状態をその場で確認できる。便利♪
![変数の値などをその場で確認できる](https://gyazo.com/07a94d1850323f832953a8d806020df7.jpeg)


以上ー。
重複しない任意長のランダム文字列を生成する方法

## TL;DR
高速で安全、手軽にランダム文字列を生成したいときは[ai/nanoid](https://github.com/ai/nanoid)を使う。

## 特徴
[README.md](https://github.com/ai/nanoid#nano-id)より意訳しています。

- **手軽**：サイズ108bytes (min & gzip)、依存パッケージ無し
- **高速**：[UUID](https://www.npmjs.com/package/uuid)より[40%速い](https://github.com/ai/nanoid#benchmark)
- **安全**：[重複しづらく](https://github.com/ai/nanoid#comparison-with-uuid)、[予測されにくく、偏りが小さい](https://github.com/ai/nanoid#security)
- **短い**：`[a-zA-Z0-9_-]`を使うので生成される文字列を安全に短くできる
- **多言語**：`Node.js`以外にも[14のプログラミング言語で利用](https://github.com/ai/nanoid#other-programming-languages)できる

## 使い方

デフォルトでは`[a-zA-Z0-9_-]`から21文字で生成されます。

```js
import { nanoid } from 'nanoid'
nanoid() //=> "yVQk_rn0A60LXcOR-2voE"
```

### 非同期に生成する

```js
import { nanoid } from 'nanoid/async'
async function createUser () {
  user.id = await nanoid()
}
```

### 任意の長さにする

短くするほど重複しやすくなるので注意してください。
[重複しやすさを簡易計算できるサイト](https://zelark.github.io/nano-id-cc/)もあるので参考にしましょう。

```js
nanoid(10) //=> "3juqViJh32"
nanoid(3)  //=> "eEh"
```

### 出現する文字を絞る

`customAlphabet`の引数に使いたい文字と文字長を指定すると、ランダム文字列生成関数が作れます。

```js
import { customAlphabet } from 'nanoid'
const randomColor = customAlphabet('1234567890abcdef', 6)
font.color = `#${randomColor()}` //=> "#a1ea8e"
```

ちなみに、[CyberAP/nanoid\-dictionary](https://github.com/CyberAP/nanoid-dictionary)というパッケージを利用すれば、使いたい文字に指定できる頻出パターンが入っています。

 - `numbers`：0〜9の数字
 - `lowercase`：小文字の英字
 - `uppercase`：大文字の英字
 - `nolookalikes`：`a-zA-Z0-9`から見間違いやすい`1`, `l`, `I`, `0`, `O`, `o`, `u`, `v`, `5`, `S`, `s`を取り除いたもの

## 記事執筆時点のバージョン

```js
// $ cat node_modules/nanoid/package.json | jq '{ name, version }'
{
  "name": "nanoid",
  "version": "3.0.2"
}
```
GithubにてPullRequestとIssueの通知を簡潔に得る設定

Webhooksや、Pull Reminders を利用してSlack通知をしてましたが、Issueへのメンションがなかなか気づきにくかったりしたので、@nakajiman から聞いたGithubだけで通知管理する方法をまとめる。

この設定だけすれば、Issue通知、Pull Request通知はすべてGithub Notification だけを気にしてれば良くなります。

僕は、毎日始業直後と就業直前に 右上のベルマークの Notification を確認してます。

# 通知設定

## Notifications

- Automatic watching のチェックは外す
- Participating, Watching は 「Web and Mobile」にチェクを入れる。（メール通知も欲しい人はチェックする」
- Dependabot alerts はすべてチェック外す
  - 脆弱性のアラートが必要な人はチェックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38134/49ed4251-4363-44f3-b911-de5b891f5087.png)
https://github.com/settings/notifications

## Watching

リポジトリをすべて消す（自分の管理リポジトリはつけておいたほうが良いです）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38134/c83792bf-c5ab-c06f-3378-f50d8d608a44.png)
https://github.com/watching

# あとは、右上のベルマークの通知を日々見るだけ

このページの Inboxにすべて必要なものだけ通知されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38134/39bb5545-9e66-3a5a-40fc-a0b6ee60d335.png)

https://github.com/notifications/beta?query=is%3Aunread
Pythonでカレントディレクトリをスクリプトのディレクトリに固定

# 実行中のカレントディレクトリをスクリプトがあるディレクトリに固定

vscode上で実行するときなど、実行時のディレクトリがスクリプトがおいてあるディレクトリでないときなどがある。

そのときにファイル処理などを行うと、ファイルのパスを適切に設定しないと、ファイルが見つからずエラーが起こってしまう。

そのときはこれをファイルの一番上に追加するとうまくいく。

```python:sample.py

import os

os.chdir(os.path.dirname(os.path.abspath(__file__)))
```

1. `__file__`でスクリプトのパスを取得
1. `os.path.abspath()`で絶対パスに変更
1. `os.path.dirname()`でパスからそのディレクトリを取得
1. `os.chdir()`でそのディレクトリにカレントディレクトリを変更

こうすることで、どこから実行してもスクリプトがあるディレクトリからの相対パスでファイルの読みこみを行うことができる。

:::note info
[pathlib](https://docs.python.org/ja/3.13/library/pathlib.html)を利用したよりシンプルな実装 (追記: 2025/6/14)

```python:sample.py
import os
from pathlib import Path

os.chdir(Path(__file__).parent)
```
:::
nullを条件にしたクエリでデータを取ってくる方法 in ruby and firebase

# 一覧表示させるためにwhereを使う

```hogehoge.rb
    def self.all
        list = collection.where("format", "=", null).order(:created_at).get
    end
```

上記のような形でformatというフィールドにnullを持ったドキュメントを全て持ってくるようなクエリを作るようなコードを書いているつもりなのですが、null部分がundefinedのエラーが出てきてしまい、取得することができなさそうなんですね。

ここの記事には、

[Firestore select where a field is null [duplicate]
](https://stackoverflow.com/questions/52431050/firestore-select-where-a-field-is-null/52431108)

>  it is not possible to index on a field that is NOT in the document

と書いてあるし、無理なのかとも思ったんですが、更に下の方には、

> However there is a workaround which consists in querying documents that contain properties with a null value data type

とあるので、いけそうでもある。

## 解決策
**rubyではnullってnilで表すんだわ**
そう、これですね。ruby上ではnullを扱うにはnilにするのでした。

```hogehoge.rb
    def self.all
        list = collection.where("format", "=", nil).order(:created_at).get
    end
```

とすれば、firebaseからnullを条件にしてドキュメントを取ってくることができました。

## おまけ
データを取得してくる時にコレクションに対して、インデックスがないから作れという形でエラーが出ることがあります。

```
9: The query requires an index. You can create it here: 長ったらしいURL
```

こんな感じのエラーが出るので、URLをコピペすると、firebaseコンソールに飛び、インデックスを作成するためのダイアログが開くので、ポチッと押してインデックスがビルドされるのを待ってください。ビルドには数分かかります。しばらく経ってまだビルド中みたいになっていてもコンソール自体に更新かけると終わってたりします。
dayjsで存在しない日付をバリデーションする

moment.jsをお使いの皆さんには`isValid`関数があるじゃんとお思いでしょう。
dayjsはmoment.jsのAPIと高い互換性を持ちますがこの関数に関しては挙動が異なるみたいです。

```js
dayjs('2020/02/31', 'YYYY/MM/DD').isValid() // true
moment('2020/02/31', 'YYYY/MM/DD').isValid() // false
```

dayjsではフォーマットが可能かどうかだけを判断してるみたいで、日付が存在するかは判定してない。
なので以下のようなメソッドを作ることで日付の存在をチェックできます。

```js
const validate = (date, format) => {
  return dayjs(date, format).format(format) === date;
}
validate('2020/02/31', 'YYYY/MM/DD') // false
```

なぜこれで判定ができるのかというと、dayjsはフォーマットを行うと`2020/02/31`は`2020/03/02`に変換されます。
なので、もとの値と比較してズレていると存在しない日付という判定が行えるということでした。
会社から毎朝の検温要請で作ってみたもの

個人的に使用するために作成しました。
 朝の検温メモが面倒、家族で体温情報を共有。

検温システム　スマートスピーカーからグループLINEに通知
https://note.com/ak09z/n/ne51faf662731

会社から毎朝の検温要請で作ってみたもの
https://ameblo.jp/ak09z/entry-12586711484.html
ShinyのReactive Programmingの整理

# はじめに
Shinyを勉強し始めました。Reactive Programmingが、少しわからなかったので自分用のメモを書きます。

##Reactive Programmingとは
パフォーマンスの高いShinyアプリを作成するためには、
1. リアクティブソース
2. コンダクター
3. エンドポイント
の３つを理解する必要があります。

###1.リアクティブソース
いわゆる「input」のことです。
これには、「textInput」,「sliderInput」,「selectInput」,「dateInput」などがあります。

###2.コンダクター
リアクティブソースとエンドポイントをつなげる関数のようなものです（と、理解しています）
負荷が大きい処理に対して使用されるものです。
これは、reactive関数を使って処理していきます。

###3.エンドポイント
いわゆる「output」のことです。
これには、renderXXX系の処理が該当します。例えば「renderText」「renderPlot」「renderTable」などです。

###３つの整理
renderXXXは、呼び出されるたびにrenderXXX内の処理がすべて実行されます。そのため、負荷が大きい処理がrenderXXX内に含まれていると、アプリが重くなってしまいます。そのため、コンダクターを使用することで処理を軽くします。

##Reactive関数の実例
BMIを計算する例を考えてみます。
BMI = 身長 / 体重* 体重
による計算することが可能です。

下記は、Reactive関数を使わない例です。
`renderText`の中に、BMIの計算を書いています。
これですと、`renderText`のたびに計算が実行されるため、処理が重くなってしまいます。

```R:Reactive関数を使わない例.r
server <- function(input, output, session) {
  output$bmi <- renderText({
    bmi <- input$weight/(input$height^2)
    paste("あなたのBMIは", round(bmi, 1),"です。")
  })
```

下記は、Reactive関数を使う例です。
`renderText`外に処理を記述しています。
また、プログラム自体の可読性も高くなったように見えます（もっと複雑なプログラムだと、わかりやすいのかも・・？？）

```R:Reactive関数を使った例.r
server <- function(input, output, session) {
  BMI_calc <- reactive({
    input$weight/(input$height^2)
  })
  output$bmi <- renderText({
    bmi <- BMI_calc()
    paste("あなたのBMIは", round(bmi, 1),"です。")
  })
```


#おわりに
Reactiveの考え方が少しわかったような気がします。この他にもObserveや、Delay、EventReactive、Isolationなどなど、まだまだ色々な関数があるので、見ていきたいと思います。
画面拡大&注釈で講演などに役立ツール ZoomIt ！

# ZoomItの紹介
講演や画面共有などで画面が小さく見にくい時に拡大、見て欲しい所をマーク＆注釈できるツールです。

## 使い方
1. [ZoomIt](https://docs.microsoft.com/ja-jp/sysinternals/downloads/zoomit)をダウンロード
2. ダウンロードした```.zip```ファイルを好きな場所に展開して```ZoomIt.exe```を実行
3. 以下のショートカットキーで画面拡大や注釈などの操作ができます。

##### ズーム
マウス位置を中心にズームするモードです。

| ショートカットキー | 機能 |
|:---:|:---:|
|Ctrl + 1|ズーム開始|
|Up|ズームイン|
|Down|ズームアウト|
|左クリック|描画開始|

##### 描画
画面に線を描いたり、注釈を入れるモードです。

| ショートカットキー | 機能 |
|:---:|:---:|
|Ctrl + 2|描画開始|
|左ドラック|線を描く|
|Shift + 左ドラック|直線を書く|
|Ctrl + 左ドラック|矩形を書く|
|T|テキスト入力|
||ペン色変更|
|R|赤|
|G|緑|
|B|青|
|Y|黄|
|O|オレンジ|
|P|ピンク|

##### カウントダウンタイマー
講演など開始時間までのタイマーを表示する。
タイマー時間は```Options > Break > Timer```で設定

| ショートカットキー | 機能 |
|:---:|:---:|
|Ctrl + 3|カウントダウンタイマー表示|

##### ライブズーム
動画再生中、停止せずにズームするモードです。

| ショートカットキー | 機能 |
|:---:|:---:|
|Ctrl + 4|ライブズーム開始|
|Ctrl + Up|ズームイン|
|Ctrl + Down|ズームアウト|

## 終わり
講演以外でも普段のビデオ通話で画面共有する時にも役に立つのでぜひ使って見てください！
【Swift】Modalで表示した子画面の閉じるイベントを親画面で検知する

#概要
iOS13からModalで画面遷移した際のアニメーションが変更されました。
それによって、Modal画面を閉じた際に動くライフサイクルメソッドが変わりました。
(今まではViewWillAppearが動いていたので、そこで更新等の処理を書いていた人も多いはず。困った、、、)

Modalで表示した子画面の閉じるイベントを親画面で検知する方法を備忘として残しておきます。

#環境
Xcode: 11.4
Swift: Swift5

#手順1
適当なViewControllerクラスを2つ用意します。
今回は遷移元を「ParentViewController」遷移先を「ChildViewController」としたいため、以下4ファイルを作成します。

・ParentViewController.swit
・Parent.storyboard
・ChildViewController.swit
・Child.storyboard

Parent.storyboardのInitialViewControllerに「ParentViewController」を、
Child.storyboardのInitialViewControllerに「ChildViewController」をそれぞれ設定してください。

```ParentViewController.swift
import UIKit

final class ParentViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()
  }
}
```

```ChildViewController.swift
import UIKit

final class ChildViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()
  }
}
```


#手順2
ChildViewControllerが閉じた際のイベントは以下のメソッドで検知可能です。

```.swift
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
```

「UIAdaptivePresentationControllerDelegate」に準拠することで使用可能です。
ParentViewControllerに以下を実装します。

```ParentViewController.swift
import UIKit

final class ParentViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()

    let storyboard = UIStoryboard.init(name: "Child", bundle: nil)
    guard let vc = storyboard.instantiateInitialViewController() else {
      fatalError("Can not generate vc.")
    }
    // delegateを設定
    vc.presentationController?.delegate = self
    self.present(vc, animated: true, completion: nil)
  }
}

extension ParentViewController: UIAdaptivePresentationControllerDelegate {
  func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
    // ChildViewControllerのDismissを検知
    print("Closed.")
  }
}
```

#最後に
iOS13が出てから半年以上経っているのに調べるまで知りませんでした。
ライフサイクルメソッドに書かなくていいので実装がスッキリしますね！
誰かのお役に立てれば幸いです！
文字列を使って関数を定義する

# やりたいこと
`"x + y * sin(z)"` のような式（もしくはプログラム）を表す文字列を使って関数を定義したい．
関数名と引数となる変数名はわかっていることにする．
つまり，

```julia
name  = "f"
args  = ["x", "y", "z"]
prog  = "x + y * sin(z)"
```

この3つを使って，

```julia
f(x, y, z) = x + y * sin(z)
```
のような関数定義がやりたい．

バージョンは1.4.0.


# 実装
`name` と `args` と `prog` から関数を定義する文字列を作って，`Meta.parse()`して`eval()`すればOK.
引数部分は`join()`を使って`args`の要素間にコンマを挟んで連結してあげる．

```julia
str = "$(name)($(join(args, ","))) = $(prog)"
eval(Meta.parse(str))
```

実際にやってみるとこんな感じに．

```julia
julia> name = "f";

julia> args = ["x", "y", "z"];

julia> prog = "x + y * sin(z)";

julia> str = "$(name)($(join(args, ","))) = $(prog)"
"f(x,y,z) = x + y * sin(z)"

julia> eval(Meta.parse(str))
f (generic function with 1 method)

julia> f(1, 2, π)
1.0000000000000002

julia> f(1, 2, π/2)
3.0
```
Remove Duplicates from Sorted Array

20200403
第二問
做此题之前需要理解的时间空间复杂度
时空复杂度：
o(1), o(n), o(logn), o(nlogn)是算法的时空复杂度的表示。它不仅仅可以用于表示时间复杂度，也用于表示空间复杂度。
O后面的括号中有一个函数f(n)表示为（O(f(n))），它指明某个算法的耗时/耗空间与数据增长量之间的关系。其中的n代表输入数据的量。
时间复杂度O(1)：
是最低的时空复杂度，也就是耗时/耗空间与输入数据大小无关，无论输入数据增大多少倍，耗时/耗空间都不变。 哈希算法就是典型的O(1)时间复杂度，无论数据规模多大，都可以在一次计算后找到目标（注释：在不考虑发生冲突的情况下）
时间复杂度为O(n)：
就代表数据量增大几倍，耗时也增大几倍。例如常见的遍历算法。
时间复杂度O(n^2)：
就代表数据量增大n倍时，耗时增大n的平方倍，这是比线性更高的时间复杂度。比如冒泡排序，就是典型的O(n^2)的算法，对n个数排序，需要扫描n×n次。
时间复杂度O(logn)：
当数据增大n倍时，耗时增大logn倍（这里的log是以2为底的，比如，当数据增大256倍时，耗时只增大8倍，是比线性还要低的时间复杂度）。二分查找就是O(logn)的算法，每找一次排除一半的可能，256个数据中查找只要找8次就可以找到目标。
时间复杂度O(nlogn)：
就是n乘以logn，当数据增大256倍时，耗时增大256*8=2048倍。这个复杂度高于线性低于平方。归并排序就是O(nlogn)的时间复杂度。
原文链接：https://blog.csdn.net/BIackMamba/java/article/details/90741470

テーマ：

```ruby:
Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

Example 1:

Given nums = [1,1,2],

Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.

It doesn't matter what you leave beyond the returned length.
Example 2:

Given nums = [0,0,1,1,1,2,2,3,3,4],

Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively.

It doesn't matter what values are set beyond the returned length.
Clarification:

Confused why the returned value is an integer but your answer is an array?

Note that the input array is passed in by reference, which means modification to the input array will be known to the caller as well.

Internally you can think of this:

　　　　// nums is passed in by reference. (i.e., without making a copy)
　　　　int len = removeDuplicates(nums);

　　　　// any modification to nums in your function would be known by the caller.
　　　　// using the length returned by your function, it prints the first len elements.
　　　　　for (int i = 0; i < len; i++) {
    　　　　　　　　print(nums[i]);
　　　　　}
```
思路：


```ruby:
使用快慢指针来记录遍历的坐标。

开始时这两个指针都指向第一个数字

如果两个指针指的数字相同，则快指针向前走一步

如果不同，则两个指针都向前走一步

当快指针走完整个数组后，慢指针当前的坐标加 1 就是数组中不同数字的个数

```
答え：
Javescript

```ruby:
/**
 * @param {number[]} nums
 * @return {number}
 */
    var removeDuplicates = function(nums) {
    const numsLength = nums.length;
    if(numsLength == 0) return 0;
    //被动指针
    let slowP = 0;
    for(let fastP = 0; fastP < nums.length; fastP++){
        if(nums[fastP] != nums[slowP]){
            slowP++;
            //重构数组（用下一个指针的值覆盖重复元素）
            nums[slowP] = nums[fastP];
        }
    }
    //返回值：最后数组的长度
    return slowP + 1;
};
```
R "Rglpk" package installation 

## R "Rglpk" installation memo
```
sudo dnf install glpk glpk-devel
wget https://cran.r-project.org/src/contrib/Rglpk_0.6-4.tar.gz
tar xvf Rglpk_0.6-4.tar.gz
cd Rglpk
sudo R CMD INSTALL Rglpk
```

glpk-devel も必要です。
リップルエフェクト付きの角丸ボタンの作り方


色や角の丸みはお好みで

```button.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorAccent">
    <item>
        <shape
            android:shape="rectangle">
            <solid android:color="@color/colorPrimary"/>
            <corners android:radius="25dp"/>
        </shape>
    </item>
</ripple>

```
GitLabでVS2019プロジェクトを自動ビルドするようにしてみた

GitLab で VS2019プロジェクトを自動でビルドするようにしてみました。

# 環境

- Windows 10 Home
- GitLab CE 12.8.6
- GitLab Runner 12.9.0
- Git for Windows 2.25.1
- Visual Studio Community 2019

# フォルダ構成

|ファイル/フォルダ|内容|
|:--|:--|
|TestProject_VS2019/|VS2019プロジェクトフォルダ|
|.gitignore|Git無視リストファイル|
|.gitlab-ci.yml|GitLab CI 設定ファイル|
|build.bat|ビルド用バッチファイル|
|README.md|説明ファイル|

# ファイルの内容

## .gitignore

不要なものもありますが、使いまわしています。

```
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/Assets/AssetStoreTools*

# Autogenerated VS/MD solution and project files
ExportedObj/
*.csproj
*.unityproj
# *.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd

# Unity3D generated meta files
*.pidb.meta

# Unity3D Generated File On Crash Reports
sysinfo.txt

# Builds
*.apk
*.unitypackage

# Visual Studio
.vs
Release/
Debug/
```

## .gitlab-ci.yml

GitLabにPUSHしたらビルドが走るようにしています。
同じPCにGitLab-Runnerをインストールして、Shared Runnerとして登録しています。

```
before_script:
  - chcp 65001
  - '"C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/Common7/Tools/VsDevCmd.bat"'

stages:
  - build

job_build01:
  stage: build
  script:
    - echo "Start build"
    - ./build.bat
    - echo "Finish build"
  tags:
    - shared-runner
  artifacts:
    paths:
      - TestProject_VS2019/Release/TestProject_VS2019.exe
      - TestProject_VS2019/Debug/TestProject_VS2019.exe
    expire_in: 1 week
```

## build.bat

ReleaseとDebugを順番にビルドしています。

```
SET MSBUILD="C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe"

%MSBUILD% TestProject_VS2019\TestProject_VS2019.sln -t:Rebuild -p:Configuration=Release -p:Platform="x86"
if %errorlevel% neq 0 (
  echo "build Release failed"
  goto :error_exit
)
%MSBUILD% TestProject_VS2019\TestProject_VS2019.sln -t:Rebuild -p:Configuration=Debug -p:Platform="x86"
if %errorlevel% neq 0 (
  echo "build Debug failed"
  goto :error_exit
)

goto :success_exit

:error_exit
echo "Error!!"
exit /b 1

:success_exit
echo "Finish!"
exit /b 0
```

# 実行結果

![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30731/eb3558bb-c7f6-f889-3059-5afbd565fe52.jpeg)

# まとめ

GitLab で自動ビルドするようにしてみました。
同様にして、自動テストも入れたりすれば、効率よく作業ができるようになりそうです。
「1億人のSNSマーケティング」 #1億SNS 要約メモ

#SNS時代のマーケティング手法
かつて私たちが情報を得る時は、TVやラジオ、本といった1対nの構造でした。
それが、SNSが誕生し情報化社会となったことで誰もがパーソナルメディアとなり、n対nという構造が生まれています。
そんなSNS社会において、企業や個人がSNSを活用してマーケティングの諸活動を行うことは避けられません。

「1億人のSNSマーケティング」は、
SNSマーケティングってなに？成果を上げるには？シェアされる秘密って？と思う人に向けて分かりやすく説明している本です。

#1ページに簡単にまとめてみた。
![S__1703938.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613060/4b252ac1-b970-a50f-22ab-30331ef0dc3b.jpeg)

本の内容を簡単にまとめてみました。
この本は、イラストをまじえて分かりやすく整理して書かれているのと、具体的な手法のお話も多いので概念的な話をピックアップして書きました。
要するに、SNSマーケティングは、SNSの中の人としてただ運用したり、広告を出すだけでなくその商材となる製品やサービスについて、「シェアされるのか」「話題になるのか」を意識する必要があるということが重要です。
そのために考えるべき視点を整理してくれているので分かりやすかったです。
1ページにメモしているのは以下の内容です。
・SNSマーケをしようと思った時に本当に活用できるか？どう活用するか？を考える3つの考え方
・シェアされるには？どういう点を意識する？という視点
・SNSマーケティングを行ったあと、どうやって分析するか？という視点、方法


##（補足）SNSマーケティングを活用する際に使える3つの考え方
①消費顔分析
考える際の視点は「自社の事業はどのようにSNSを活用できそうか」ということです。
「会話に上がるかどうか」「他者は絡むか？」の観点で想像してみます。
社会的な振る舞いと顧客の表情を思い浮かべながらシミュレーションをしてみる分析方法です。
そうすることで、自社のビジネスやサービスがSNSマーケティングでうまく活用できるかどうかを考えることができます。
もし、今の時点で「真顔消費」な商材であれば、商品自体に話題化できる要素を組み込んだり、面白いコミュニケーションを仕掛け「ネタ消費」としてみるアイデアに繋げるヒントにもなります。

②トリプルメディア
どこならユーザーと接点を持てるのか、どこなら理想のメッセージが伝達されやすいかなどメディア特性別に分類し、そこにおけるSNSの役割を整理します。

*オウンドメディア...企業や組織が所有する自社メディア。
*ペイドメディア...広告費を支払って掲載してもらう媒体
*アーンドメディア...消費者の口コミ等の情報発信によって評判を積み重ねられるメディア

③PESSO
実際のSNS活用余地をより具体的に整理するための考え方。
商材を取り巻くユーザー行動と予算感によってもどの活用がやりやすいかが変わるため、
最適なメディア活動のアプローチを模索します。

##机の上に常に置いておきたい
SNSチャネル別の活用方法や、分析方法など具体的な説明について、
写真やイラストを用いて分かりやすく説明されています。
こういう方法もあるのか。と目を通して置くことで、この商材、サービスはこの方法を使っているんだな..と気づきやすくなるなぁと勉強になりました。
実際にSNSマーケティングを実践する際にも参考になる、教科書的な内容だと思います。
良書でした！

#本のリンク
https://www.amazon.co.jp/dp/B08561L3CD/ref=cm_sw_r_tw_dp_U_x_sWPHEb5CV9TTB
【rspec】confirmダイアログのテスト

# 開発環境
ruby '2.6.3'
rails '6.0.2'


## railsでconfirmダイアログのテストをする。
* `accept_confirm`だけで表示内容の確認とOKを押してくれる
* [Method: Capybara::Session#accept_confirm](https://www.rubydoc.info/github/jnicklas/capybara/Capybara/Session:accept_confirm)

```ruby:systemテスト
  context "削除する" do
    it "投稿消去" do
      click_button "消去する"
      expect{
        expect(page.accept_confirm).to eq "本当に削除しますか？"
        expect(page).to have_content "レビューを消去しました。"
        }. to change(@user.posts, :count).by(-1)
    end
  end
```

## 注意点
* expectのブロック内にひとつ以上のexpectもしくはfindを入れないと、ダイアログが表示されてacceptされる前に次へ進んでしまうので注意が必要です。
つまり

```ruby:systemテスト
  context "削除する" do
    it "投稿消去" do
      click_button "消去する"
      expect{
        expect(page.accept_confirm).to eq "本当に削除しますか？"
        expect(page).to have_content "レビューを消去しました。"
　　　　　# ↑この一文かsleepが必要です。
        }. to change(@user.posts, :count).by(-1)
    end
  end
```
* [テストが失敗する場合はsleep等でテストを停止させてみる](https://qiita.com/jnchito/items/607f956263c38a5fec24#%E3%83%86%E3%82%B9%E3%83%88%E3%81%8C%E5%A4%B1%E6%95%97%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%AFsleep%E7%AD%89%E3%81%A7%E3%83%86%E3%82%B9%E3%83%88%E3%82%92%E5%81%9C%E6%AD%A2%E3%81%95%E3%81%9B%E3%81%A6%E3%81%BF%E3%82%8B)　

# その他

```slim:slim
= button_to "消去する",post_path(@post), method: :delete, data: {confirm: "本当に削除しますか？"}
```

```ruby:コントローラー
  def destroy
    @post = current_user.posts.find(params[:id])
    flash[:notice] = "レビューを消去しました。"
    @post.destroy
    redirect_to user_path(current_user.id)
  end
```
fetch-mock-jestを使用したreduxのテスト

以下のドキュメントを参考にしつつ
https://redux.js.org/recipes/writing-tests/#action-creators
http://www.wheresrhys.co.uk/fetch-mock/#usageusage-with-jest


jestの設定ファイルに

```javascript

jest.mock('node-fetch', () => require('fetch-mock-jest').sandbox());
```

テストファイルにはfetchMockをセット。

```javascript

import * as actions from '../fetchActions';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
const fetchMock = require('node-fetch');
```

```javascript

it('should create GET_USER_SUCCESS when user fetching is done', function() {
  fetchMock.getOnce('path:/user', {
    body: { user: { name: 'ABC', id: 123 } },
  });

  const expectedActions = [
    { type: actionTypes.GET_USER },
    { type: actionTypes.GET_USER_SUCCESS,
      data: {
        user: { name: 'ABC', id: 123 },
      },
      status: 200,
    }
  ];

  return store.dispatch(actions.getUser()).then(() => {
    // return of async actions
    expect(store.getActions()).toEqual(expectedActions);
  });
});

```

isomorphic-fetchを使用している場合、上記の`node-fetch`を`isomorphic-fetch`に置き換えてテスト可能。
画像ファイルの種類を判別するDataのExtension

Swiftでファイルを取扱う際、`URL`であれば`pathExtension`で拡張子を取得することができます。しかし`Data`からファイルの種類を特定する場合、基本機能だけでは不可能です。[NSDataから判別する記事](https://qiita.com/dondoko-susumu/items/3421926f68d1c3a80909)を書いている方がいたので、これを元に`Data`から画像の種別を特定するExtensionを作成しました。

## コード全貌 (+解説)

```Swift
extension Data {
    enum ImageType: String, CaseIterable {
        case jpg
        case png
        case gif
        case bmp

        var header: UInt8 {
            switch self {
            case .jpg:
                return 0xff

            case .png:
                return 0x89

            case .gif:
                return 0x47

            case .bmp:
                return 0x42
            }
        }

        var `extension`: String {
            return "." + rawValue
        }
    }

    var imageType: ImageType? {
        var values = [UInt8](repeating: 0, count: 1)
        copyBytes(to: &values, count: 1)
        return ImageType.allCases.first { $0.header == values[0] }
    }
}
```

画像ファイルの種別はバイナリデータのヘッダを見ればわかる(らしい)ので、その情報を持つ`enum ImageType`を定義しておき、`var imageType`内で実際のヘッダとの比較を行っています。判別する画像の種類を増やしたいときは`enum ImageType`の`case`を追加すればよいです。楽ですね。



## まとめ

正直バイナリとか触ったことなくて不安しかないので、間違い等あればご指摘お願いします...



## 参考文献

- [画像ファイルのフォーマットをバイナリデータ処理で判別](https://support.asteria.com/hc/ja/articles/229087987-画像ファイルのフォーマットをバイナリデータ処理で判別)
- [JPEGファイルの構造](https://hp.vector.co.jp/authors/VA032610/JPEGFormat/StructureOfJPEG.htm)
- [Data - Foundation | Apple Developer Documantation](https://developer.apple.com/documentation/foundation/data)
- [[Swift]画像形式をNSDataと拡張子から判別する](https://qiita.com/dondoko-susumu/items/3421926f68d1c3a80909)
- [Finding image type from NSData or UIImage](https://stackoverflow.com/questions/4147311/finding-image-type-from-nsdata-or-uiimage)
C言語　ALDS1_1_A　Insertion Sort

##問題
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_1_A&lang=ja

##コード

```c
#include <stdio.h>

static void print_array(int array[], int array_len)
{
    for (int i = 0; i < array_len; i++)
    {
        printf("%d", array[i]);
        if (i != array_len - 1)
            printf(" ");
    }
    printf("\n");
}

static void swap(int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int main(void)
{
    int N;
    int A[100];

    scanf("%d", &N);
    for (int i = 0; i < N; i++)
        scanf("%d", &A[i]);

    /* 出力 */
    print_array(A, N);

    /* 挿入ソート */
    for (int i = 1; i < N; i++)
    {
        for (int j = i - 1; j >= 0; j--)
            if (A[j] > A[j + 1])
                swap(&A[j], &A[j + 1]);
        print_array(A, N);
    }
    return 0;
}
```

##所感

- 配列は「ソート済みの部分列」と「未ソートの部分列」とに分けられる。
- int j = i - 1で、ソート済みのところを計算しないようにする。
- 比べるのは、常に隣り合う数

所要時間50分

【復習】

- 2020/04/05
    - ソート済み配列へのj--で下がっていくイメージを持ててなかった
tmuxでペインを快適に移動する

調べてもあまり出てこなかったので備忘録がてら残しておきます。
人によっては他のキーバインドと衝突するかもしれないのでその場合は適宜修正してみてください。


```.tmux.conf
bind -n C-h select-pane -L
bind -n C-l select-pane -R
bind -n C-j select-pane -D
bind -n C-k select-pane -U
```

例えば、`bind -n C-h select-pane -L` はCtrlキーとhキーを同時に押した時にLeftのペインに移動するというのを表しています。
[AWS]AWS Certified DevOps - Professional に合格しました！イエイ！


##はじめに
先日AWS Certified DevOps - Professionalに無事合格でき、AWS認定試験5冠を達成できたので、勉強した内容を共有します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205092/97f5c017-0cd5-be8c-0eba-14639588b19a.png)

https://www.certmetrics.com/amazon/public/transcript.aspx?transcript=S02T92E111EQ1VGR

##試験については下記のような感じ

```
AWS 認定 DevOps エンジニア – プロフェッショナル試験は、AWS 環境のプロビジョニング、運用、管理において 2 年以上の経験を持つ、DevOps エンジニア担当者を対象としています 

認定によって検証される能力

- AWS で継続的デリバリーのシステムと手法を実装して管理する
- セキュリティコントロール、ガバナンスプロセス、コンプライアンス検証を実装し、自動化する
- AWS でのモニタリング、メトリクス、ログ記録システムを定義し、デプロイする
- 高可用性、スケーラビリティ、自己修復機能を備えたシステムを AWS プラットフォームで実装する
- 運用プロセスを自動化するためのツールの設計、管理、維持を行う

推奨される知識と経験

- 1 つ以上のハイレベルプログラム言語でのコード開発の経験
- 高度に自動化されたインフラストラクチャの構築経験
- オペレーティングシステムの管理経験
- 最新の開発および運用のプロセスと方法論に対する理解
```


##何故受けたか
1. プロ制覇したい欲望に駆られた
2. Codeシリーズ、SAMを使用する機会が出てきたため
3. ログの分析に興味があり、適切なログ管理方法を学ぶため



##勉強内容

- AWS公式トレーニング（無料）
  - 一番最初にやるべき、何をどう聞かれるのか理解する（一番参考になる）
    - https://www.aws.training/Details/eLearning?id=40664 （問題形式のトレーニング）
- Black Belt
  - サービスの最初の理解としてこちらのPDFを読む。感覚で理解できればOK
- よくある質問
  - そもそもこのサービスは何の目的で利用するかを理解する
- ユーザガイド
  - AWS公式のサービスリファレンス
  - 大体ここに書いてあることが試験で聞かれる印象
  - 今回試験を受けるにあたり下記サービスについては一通り読んだ
        - Code*シリーズ
        - Cloudformation
        - Elastic Beanstalk
        - Opsworks
Cloudwatch
- Jonbonseの模擬試験
    - JonBonseはUdemy内で最も良い模擬試験作ってる
    - 模擬テストが2つあり、解説が丁寧なのでおすすめ！
    - 模擬テストをアウトプットの中心にしつつ、ホワイトペーパー・ユーザガイドで知識を補う感じ
- Hands on　
    - https://www.udemy.com/course/aws-certified-devops-engineer-professional-hands-on/
    - 試験範囲を一通りHands on形式で教えてくれる。
    - めちゃめちゃ丁寧なので、長い
    - 自分の触ったことないサービスや知識が足りない箇所を重点的に勉強した。
- AWSコンソール画面
  - 実際のAWSサービスを触ってみてどのようなOptionがあるのか理解した
- 役立ったサイト
  - https://jayendrapatil.com/ 
  - AWSの認定資格についてまとめてくれる人のブログ

##感想

試験内容が非常に実務に沿っていて、AWSが何を理解してほしいか伝わってきた。

1. マルチリージョン・マルチアカウントでの開発
2. ログを吐き出してからの挙動と分析
3. セキュアなDevOps環境構築方法
4. マルチアカウント管理

だいたい上記をしっかり勉強して、ユーザガイド読めば受かる印象でした。
今回点数は860だったので、理解できないことを再度学習し継続的な知識のキャッチアップに努めたい。

試験前にチョコラBBハイパーを飲んでおくと、集中が途切れない気がする。
pythonにおけるGraphvizの簡単なまとめ(macの場合のみ解説)

## Graphvizのインストール手順

1.　homebrewでgraphvizをmacにインストール

```
brew install graphviz
```

2.　pipでgraphvizをインストール

```
pip install graphviz
```


## ノードを生成

__コード__

```python
from graphviz import Digraph

# pngとして出力
dg = Digraph(format='png')

dg.node('1') # 1というラベルがついたノードを設定

dg.node('2') # 2というラベルがついたノードを設定

dg.render('./test/dgraph1') # テストフォルダにdgraphという名前で保存(拡張子は書かない)
```
__出力結果__

![dgraph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328421/26219280-d91e-d088-14c8-1504ef202485.png)

## エッジを生成

__コード__

```
from graphviz import Digraph

dg = Digraph(format='png')

dg.node('1') # 1というラベルがついたノードを設定
dg.node('2') # 2というラベルがついたノードを設定

dg.edge('1','2') # ノード1 からノード2に向かって矢印を描く

dg.render('./test/dgraph2') # テストフォルダにdgraphという名前で保存
```

__出力結果__

![dgraph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328421/ec8a5692-b410-32d9-d12f-9d4e18582344.png)


## ノードの形（shape）を変更

形の種類は[こちら](https://www.graphviz.org/doc/info/shapes.html)を参照


__コード__

```
from graphviz import Digraph

dg = Digraph(format='png')

# デフォルトを○に設定
dg.attr("node", shape="circle")

dg.node('1') # 1というラベルがついたノードを設定(○)
dg.node('2') # 1というラベルがついたノードを設定（○）
dg.node('3',shape='box') # 特定のノードを□に変更


dg.render('./test/dgraph') # テストフォルダにdgraphという名前で保存
```
__出力結果__

![dgraph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328421/7e730ba1-a049-5d12-7c24-86249f2b4d92.png)




## 参考文献
[Mac : Pythonでgraphvizを使う方法【インストールから動作確認まで】](https://tech-diary.net/python-graphviz-mac/)
[PythonとGraphvizでノードのフォントサイズを指定する](http://kyle-in-jp.blogspot.com/2018/12/pythongraphviz_46.html)
[Node Shapes](https://www.graphviz.org/doc/info/shapes.html)
【初心者向け】FizzBuzz問題

##環境,前提
Ruby 2.5.1
MacOS Mojave Ver.10.14.6

本記事はRubyがインストールされた前提の記事です。
Rubyをインストールしたあと、とにかくRubyをいろいろ触ってみて慣れていくための記事です。お役に立てば幸いです。



# 採用試験に出ました。

採用試験で実際に出題されたのでやはり大事なのかなと思い今回記録に残します。

# FizzBuzz問題とは？
1から30まで順に数えて出力して行き、3で割り切れる数は「Fizz」5で割り切れる数は「Buzz」両方で割り切れる数は「FizzBuzz」と出力する、ようにプログラムを書く問題です。

これが書けるか書けないかでプログラマー志願者を仕分けられるようになったようです。実際今でも使われていますから押さえておいて損はないと思います。[FizzBuzz詳細](https://ja.wikipedia.org/wiki/Fizz_Buzz)


# 私が書いたコード
実際の試験では「言語は問わない、形式も自由」だったので今回はRubyのWhile文を用いてやってみます。

```FizzBuzz.rb
i=1

while i <=30

  if i%15==0
    puts "FizzBuzz"
  elsif i%3==0
    puts "Fizz"
  elsif i%5==0
    puts "Buzz"
  else
    puts i
  end

  i+=1
  
end

```

他にもfor文やeach文でも実現可能なのでぜひやってみてください！！