OmniAICreator/Qiita-1.07M huggingface dataset:
TwitterのDMの取得でちょっとハマった話

#概要
TwitterのDMをAPI経由で取得しようとしたらちょっと手間取りました。
解決方法を書いておきます。

#結論
DMのアクセスにはAPIの権限変更と**APIキーの再生成**が必要。
再生成が必要なのを見落としていました。。。

#ハマった流れ
1. https://api.twitter.com/1.1/direct_messages/events/list.json にGETリクエストを投げてDM取得しようとした。
2. "code":93,"message":"This application is not allowed to access or delete your direct messages." が返ってきて怒られる。
3. 公式HPを確認する。アクセス権は3段階あり、DMアクセスには設定変更が必要と書いてある。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545683/8c276bca-62fd-5981-7230-8f32cdcc4ffa.png)
4. 設定変更してみる。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545683/9a6dc64a-a783-99ad-9ea2-b9e0d84f9f54.png)

5. 再確認する。
6. やっぱりだめ。"code":93,"message":"This application is not allowed to access or delete your direct messages." が返ってきて怒られる。
7. HTTPのレスポンスヘッダーを見ろと書いてある。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545683/82b13c07-482c-1c6b-f49f-a1cb636268ab.png)
8. 見てみたら'x-access-level': 'read-write'になってて変わってなかった。
9. もう一度ドキュメントを確認してみると、**APIキーの再生成しろってちゃんと書いてある。。。**![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545683/177dd4fe-1281-b541-06b8-a1d5d680ffd4.png)
10. 再生成する。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545683/6639c484-7c12-5d7c-5ca9-dd7a169ea0a8.png)
11. 'x-access-level': 'read-write-directmessages'に変わっており、取得できた！

#まとめ
ハマったらちゃんと公式ドキュメントを読みましょう。（自戒の念を込めて）
読解メモ: PHP RFC: Make constructors and destructors return void

この記事は @carrotRakko が [PHP RFC: Make constructors and destructors return void](https://wiki.php.net/rfc/make_ctor_ret_void) を読み解いて自分なりにまとめなおしたものです。

英語の解釈や PHP の仕様/実装などなどについて間違っている部分を見つけたらご指摘くださると幸いです。

この記事を書いている時点で読んでいるリビジョンは [2020/07/02 23:13 のもの](https://wiki.php.net/rfc/make_ctor_ret_void?rev=1593731618) です。

# `__construct()` の返り値の型指定

型指定の仕方を3パターン考えてみます↓

1. 型指定なし: `__construct()`
1. 型指定あり & `void`: `__construct(): void`
1. 型指定あり & `void` 以外: `__construct(): bool`

## PHP 7.4.x では（事実）

| 型指定の仕方 | どうなる |
| --- | --- |
| 型指定なし: `__construct()` | 問題なし |
| 型指定あり & `void`: `__construct(): void` | Fatal error |
| 型指定あり & `void` 以外: `__construct(): bool` | Fatal error |

## PHP 8.0 では（提案）

| 型指定の仕方 | どうなる |
| --- | --- |
| 型指定なし: `__construct()` | 問題なし |
| 型指定あり & `void`: `__construct(): void` | 問題なし |
| 型指定あり & `void` 以外: `__construct(): bool` | Fatal error |

## PHP 8.1/9.0 では（提案）

**PHP 8.0 では（提案）** と同じです。

| 型指定の仕方 | どうなる |
| --- | --- |
| 型指定なし: `__construct()` | 問題なし |
| 型指定あり & `void`: `__construct(): void` | 問題なし |
| 型指定あり & `void` 以外: `__construct(): bool` | Fatal error |

# `__construct()` に返り値の型指定をしなかった場合

暗黙的に返り値の型指定とみなされるパターンを2つ考えてみます↓

1. なにも指定していないとみなされる（そのまま）: 文法違反ですが強いて言うなら `__construct(): void|mixed`
1. `void` を指定したとみなされる: `__construct(): void` とみなされる

## PHP 7.4.x では（事実）

なにも指定していないとみなされる（そのまま）: 文法違反ですが強いて言うなら `__construct(): void|mixed`

## PHP 8.0 では（提案）

なにも指定していないとみなされる（そのまま）: 文法違反ですが強いて言うなら `__construct(): void|mixed`

## PHP 8.1/9.0 では（提案）

`void` を指定したとみなされる: `__construct(): void` とみなされる

# `__construct()` から値を返した場合

PHP の怒り方を3パターン考えてみます↓

1. 怒られない
1. `Deprecated`
1. `Fatal error`

## PHP 7.4.x では（事実）

怒られない

## PHP 8.0 では（提案）

`Deprecated`

## PHP 8.1/9.0 では（提案）

`Fatal error`
Qiita初心者 記事初投稿時 注意点（早期にQiita投稿ページのプレビュー機能を使おう）

## はじめに

- Qiitaの記事をよく参考にさせてもらっているので、何か記事として載せて役立てることがあればと思い、書き方の勉強を始めました。

- 今回、自分が経験した、初心者がはじめて記事を投稿する場合の注意点を示します。

- 記事を書きたいと思っている初心者の方の参考になれば幸いです。

  

## 行ったこと

- 投稿のために書き方を調べたらMarkdown記法で書く必要があるとわかったので、どうせ調べるなら、これを最初の記事にしようと、Markdown記法を調べながら記事に書いてました。
- まとまったところでQiitaのサイトの投稿用のページを開いて、作った記事案をコピーして投稿しようとしたところ、無理があることに気づきました。
- このため、Markdown記法については諦め、今回の記事に切り替えました。



## 初心者が初めてQiita投稿を考えたとき、注意したほうが良いこと（私の失敗から）

### １．まずは、Qiitaサイトの投稿用ページを開いてみよう！

- 記事を書く前に、Qiitaを開いたときに右上にある「投稿する」ボタンを押して、投稿用のページ（[https://qiita.com/drafts/new](https://qiita.com/drafts/new)）を開いてみましょう。
- 私は記事を書き終えてから開いてみたので、下記２～４のような余計な労力を使ったり、失敗したりしてしまいました。

### ２．投稿用ページのMarkdownエディタを使ってみよう！

- 投稿用ページはMarkdownエディタになっており、簡単な記事を書くのであれば、本エディタでも十分と思われます。まずは、使ってみましょう。

### ３．他のMarkdownエディタアプリを使う場合でも、投稿用ページでプレビューを確認しながら進めよう！

- 操作性等の好みで他のMarkdown用エディタを使用する場合でも、投稿用ページでプレビューを確認しながら進めましょう。
- 他のエディタアプリ上での表示イメージと、上記の投稿用ページでのプレビューとMarkdown記法の使用可能な範囲、表示イメージが異なるかもしれません。あとで、同じような修正を繰り返さなくて済むように、新たな記法使い始める場合などに、投稿用ページのプレビューを確認しながら進めましょう。

### ４．Markdown記法は使いながらおぼえよう！

- Markdown記法は、いくつも記事が載っているので調べて２~３読めば十分かもしれませんし、知ってて損はないので、まずは、勉強しても良いかもしれません。しかし、上記の投稿用ページにも「Markdownの書き方」および「もっと詳しく知りたい方はこちら」というのが載っていて、簡潔だけど載っている記法だけででも結構書けてしまうような気がします。
- まずは、これを見て書きながら、不足のものがでたらその都度調べ、Qiita上でのプレビューを確認しながらのほうが効率が良い気がします。





----
2020/07/03 初稿
real force keybord keyLK キーロック解除

「Left Ctrlと Caps Lock を入れ替える」機能
ショートカットキーは、 Fn + F12 です。

「Left Ctrlと Caps Lock を入れ替える」機能は、一般人にはあまり必要ない気がしますし、 左手だけで Ctrl+Z などを多用する人にはむしろ不要な機能でしょう。

PC操作でほとんどキーボードから手を離さないような人たちに需要がありそうです。つまり、Windows で GUI を使っているにも関わらず、HJKL での上下移動を使用し、『コピペ』や『操作を一つ戻す』などで Right Ctrl を使用する（右手小指 or 右手薬指で Ctrl、左手で ZXCV などを押し下げる）人たちにとっては、Left Ctrl の入力がしやすくなるので、便利なのかなと思います。

「キーのロック」
ショートカットキーは、 c です。

キーのロックは、デフォルトでは win と Esc が無効になります。どちらも、ゲーム中に間違って押してしまうと困るキーです。

なんでこんなクソ機能がついているか、謎。


# 上記やってもうまく動かない場合

realforce の アプリを入れて以下をやると良い

![keybord.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/d7b3df86-c478-b483-56d6-3560075acfa4.png)
headerの画像を上下中央寄せする方法

まず、HTMLを記載するとこんな感じです。

```html
<div class="p-header__logo">
  <img src="img/header/logo/logo120.png" alt="">
</div>
```

```css
.p-header__logo {
   height: 90px;
   display: flex;
   align-items: center;
  & img {
    height: 70px;
    display: block;
    }
} 

```
img要素を囲んでいる親要素に
display: flex;
align-items: center;

を追加すると上下中央揃いになる。
読書要点「プリンシプルオブプログラミング」第7章

# 第7章 法則

ここで言う法則とは、ソフトウェア開発で陥りやすい罠のことである。
こうするとこうなるという、否定的な結果を生み出す経験則である。
望ましくない結果とそれにつながる行動の因果関係を把握しておくことで、未然に問題を防ぐことができるかもしれない。

### ブルックスの法則

スケジュールが遅れているからと言って安易な人員追加を行うと、さらに遅延を招き、火に油を注ぐ結果となる。
プロジェクトの工数は人×月の人月で管理されることが多いが、この人と月は可換ではない。
人数が多くなった場合、作業の独立性が低いほど生産性は直線的には増加しないし、人数分の教育コストもかかる。

スケジュール的に遅れが出た場合は人員を追加するのではなくリスケジュールするべきである。
人員の追加もメンバーに無理をかけるのもデメリットが大きいことだと認識しなければならない。

### コンウェイの法則

ソフトウェアの構造であるアーキテクチャは、それを作った組織の情報を反映する。
ソフトウェアの設計は、組織構造が持つ文脈に従ってアーキテクチャを構成しがちである。

本来は効率的なアーキテクチャを設計した後で組織を構成するのが良い。
組織に依存したアーキテクチャより、よいアーキテクチャを作った上でそれに組織構造を適合させていくほうが明らかに効率が良い。

### 割れた窓の法則

放置された割れた窓は、次第に建物全体へ悪影響を波及させることになる、という法則である。
ソフトウェアでもこれは同様で、小さな欠陥を放置してしまうと、それを気がついた人に投げやりな感覚を植えてしまい、ソフトウェア全体を腐敗へと進めていくループに陥ってしまう。
長く放置されている欠陥はそれ自体が些細なものであっても、それを見る人を「自分がちゃんとやっても仕方がない」「どうせ誰も見ていない」といった感覚にさせる。

設計、意思決定、コードなど、欠陥を作らないようにすべきだし生じた場合は速やかに直すべきである。
悪いところは見つけたら即座に直す、修正できなくても問題点のある箇所を把握しておく。
悪い部分を放置しないというチームの雰囲気がソフトウェアの腐敗を防ぐ。

### エントロピーの法則

自然現象の議論ではエンタルピーとエントロピーを合わせた自由エネルギーの増減に着目することは一般的である。
特にエントロピーに着目してみれば、系の安定化とエントロピーの増大は基本的にセットで発生する。
複雑な定義を持つエントロピーだが、エントロピーは物理学の文脈では乱雑さの指標とされる。
ここで、ソフトウェアの複雑さの増大に伴う無秩序さをエントロピーと捉えるとすると、ソフトウェア開発でもエントロピーが増大しコードが無秩序になるのは自然な傾向である。

エントロピーが増大しやすい傾向や兆候を掴み、そこに自然的ではなく人為的な操作を加えることでエントロピーの増大を抑えることになる。
硬いコード、脆いコード、移植性のないコード、扱いにくいコード、複雑なコード、繰り返しの多いコード、わかりにくく不透明なコードなど、危険な箇所を抑えるようにしたい。
開発への取り組み方に、エントロピーの増大に対応しやすい手法を採用することも良い対策である。

### 80-10-10の法則

当初の要求から進めた時、全体の作業の80%は短時間で実現することができる。
しかし、残り20%のうち10%は実現可能だがコストがかかり、さらに残り10%は実現が不可能である。
もし100%を要求された場合、かなり泥臭い作業によって実現していく道を行くことになる。
プログラミングに万能薬がないことは周知の通りで、泥臭いやり方が必要なケースは少なからずあることは受け入れなければならない。
また、ピンポイントの要求に応えてくれる専門的なツールが存在する場合もあるので、効率化する道も模索しながら地道な作業に取り組んでいきたい。

### ジョシュアツリーの法則

名前を知らなければ気にならないものでも、名前を認識した途端にそれが見えるようになり、気が付けるようになるという法則である。
目に見えない概念的なものでも命名することで意識できるようになることも多い。
チームでユビキタス言語を使用し、認識に要するコストを削減していきたい。

### セカンドシステム症候群

セカンドバージョンはもっとも危険性の高いバージョンである。
プログラマがその開発に慣れてきて多くの機能を追加した結果、コードの品質が落ちる上に使い勝手も悪いものになるというケースが多い。
クライアントもプログラマも、慣れてきたからといってあれこれ手を付けるのではなく、ユーザー目線で本当にセカンドバージョンに必要なものをイメージしたい。
もちろんセカンドバージョン以降の開発でも留意する必要がある。

### 車輪の再発明

すでに存在していて利用できるものは作らない。
工数が無駄になるし、たいてい既存の広く使われているものは品質も良い。
仮に出来上がったとして、標準の規格を無視した独自路線は、移植性がなくあまり使い勝手が良くならない可能性も高い。
知識不足でうっかり作ってしまったというケースや作りたいから作ったというケースが考えられる。

あくまで本来やるべき作業に注目し、作らなくていい部分は作らないということを徹底したい。

### ヤクの毛刈り

ヤクという毛量が多い牛の一種がいる。
ヤクの毛刈りをすると、あまりの毛量の多さに体になかなか到達しない。
プログラミングで問題を取り組んでいるときも、次々と別の問題が発覚して当初の問題にたどり着かないことがしばしばある。
この全体像の見えてこないヤクの毛刈りはストレスのたまる作業である。

こうなってしまったら早々に問題から切り上げるのが良い。
時間に対するリターンが割に合わないことも多い。
切り上げるときは他の人が同じ轍を踏まないように備忘録を残すと良い。

どうしてもヤクの毛刈りに立ち向かわなければならないときは脳がオーバーフローしてしまわないように問題を整理しながら進めたい。
JavaScript: EventTargetでイベントを送受信する方法

この投稿ではJavaScriptの`EventTarget`を使って、ブラウザ上でイベントを送信したり受信したりする方法を紹介します。

サーバサイドでNode.jsを使っていると、ビルトインライブラリにeventsがあり、[EventEmitter]クラスでイベントの送受信ができて便利ですが、これはNode.js固有のものなのでブラウザでは使えません。代わりに、クライアントサイドでは[EventTarget]を使うことで、EventEmitterのようなことができます。

[EventEmitter]: https://nodejs.org/api/events.html
[EventTarget]: https://developer.mozilla.org/ja/docs/Web/API/EventTarget

## EventTargetは多くのブラウザが対応

`EventTarget`は、多くのブラウザが対応しており、特に外部ライブラリのインストールを必要としません。

<img width="1054" alt="CleanShot 2020-07-03 at 10.01.46@2x.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889/cde6849c-5b02-963c-cd12-0a346634e77b.png">

## EventTargetの基本的な使い方

まず、`EventTarget`を`new`します。

```js
const events = new EventTarget()
```

イベントを受信するイベントリスナーの登録は、`addEventListener`メソッドでします:

```js
const fooListener = ({ type, detail }) => console.log({ type, detail })
events.addEventListener('foo', fooListener)
```

イベントリスナーの第一引数のオブジェクトにはいろいろな情報が入ってきますが、`type`プロパティと`detail`プロパティは重要です。`type`プロパティにはイベント名が、`detail`プロパティには送信されたイベントのカスタムデータが入ってきます。

イベントを送信するには、`dispatchEvent`メソッドを使います:

```js
events.dispatchEvent(new CustomEvent('foo', { detail: 'message1' }))
```

`dispatchEvent`の第一引数は、`CustomEvent`です。`CustomEvent`コンストラクタには第一引数にイベント名、第二引数の`detail`プロパティに一緒に送りたいカスタムデータを入れます。上の例では`detail`に文字列を入れていますが、配列やオブジェクトでも大丈夫です。

以上の基本的な使い方を踏まえて、イベントの送受信をする簡単なサンプルコードが次です:

```js
// EventTargetの作成
const events = new EventTarget()

// イベントリスナーの登録
const fooListener = ({ type, detail }) => console.log({ type, detail })
events.addEventListener('foo', fooListener)

// イベントの送信
events.dispatchEvent(new CustomEvent('foo', { detail: 'message1' }))
events.dispatchEvent(new CustomEvent('foo', { detail: 'message2' }))
events.dispatchEvent(new CustomEvent('foo', { detail: 'message3' }))
```

これを実行すると、3つのイベントが送信され、イベントリスナーはその3イベントを受信します。Chromeでの実行結果は次のようになります:

![CleanShot 2020-07-03 at 10.12.22@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889/ab0ba54d-a6c8-a426-c272-71cc00abf0b5.png)

以上が、EventTargetの基本的な使い方です。

## 関連ページ

* [EventTarget - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/EventTarget)
【Kotlin】BottomNavigationViewの上(top)のスペースを削除する方法

|  変更前|  変更後  |
| ---- | ---- |
|![Screenshot_1593738325.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648721/dc1eff9e-5f6f-872e-922a-4f6929c91aec.png)|![Screenshot_1593738394.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648721/cacfb372-4407-c0b9-237f-935ae691d9ca.png)|


### 対応策
`activity_main_menu.xml`をコードで描画し、
`android:paddingTop="?attr/actionBarSize"`を削除する

下記が変更前です。

```kotlin
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="?attr/actionBarSize">
```

下記が変更後です。

```kotlin
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
```
【SAPUI5】Inputにてfocusアウト時にカンマ付き数値に変換

##はじめに
sap.ui.core.format.NumberFormatを使用し、数値をカンマ付き数値に変換する方法を紹介します。
この例ではInputの入力内容変更時にカンマつけの処理が実装されるようにしています。

##NumberFormatを使ってみる
###1. "sap/ui/core/format/NumberFormat"を読み込み

```NumberFormat.controller.js
sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"sap/ui/core/format/NumberFormat"
], function (Controller, NumberFormat) {

```
###2. oIntNumberFormatを定義
```NumberFormat.controller.js

	var oIntNumberFormat = NumberFormat.getIntegerInstance({
		maxFractionDigits: 0,
		groupingEnabled: true
	}, sap.ui.getCore().getConfiguration().getLocale());
```
###3. ファンクションを定義
```NumberFormat.controller.js
	intformat: function (value) {
			return oIntNumberFormat.format(value);
	}
```
###4. ファンクションを呼び出し
```NumberFormat.view.xml
	<Input id="input" change="onChange" width="15rem"/>
```
```NumberFormat.controller.js
	onChange: function() {
			// Inputボックスの入力内容を取得
			var text = this.getView().byId("input").getValue();
			// カンマつけして画面へ再設定
			this.getView().byId("input").setValue(this.intformat(text));
		}
```
##実行結果
下記のように、フォーカスアウト時に、カンマ付き数値に変換することができました。
今回の例では、数値以外を入力することはありませんでしたが、数値以外の文字列が入力される
可能性がある場合は考慮が必要となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656065/a92ca6fc-a024-2312-e664-6f3c9733497d.png)
サクッとSambaサーバーを立てちゃお

###はじめに
　Sambaを立てるたびに何か文献にあたってはを繰り返している自分に向けての記事です。設定はあんまり凝らないので、内容は「何番煎じだよ」という感じなのですが、説明がわかりやすいなと思った方だけストックにでも入れといてください。

###環境
OS:ubuntu20.04
samba:Version 4.11.6-Ubuntu

###インストール
何はともあれアプデです

```bash
$ sudo apt update && sudo apt upgrade
```


次は`apt install`です。

```bash
$ sudo apt install samba -y
```
これで先ほどの環境で書かれているバージョンが入ります。(2020/7/2時点)

今回はホームディレクトリに共有フォルダを作る場合を考えましょう。

```bash
$ mkdir ~/Share
```

設定ファイルをいじりましょう。好きなテキストエディタを使ってください。

```bash
$ sudo nano /etc/samba/smb.conf
```
以下の内容をファイルの一番下の方に記述します。pathの名前は変えてね。

```
[Share]
  comment = SHARE
  path = /home/user/Share
  read only = yes
  browsable = yes
  force user = asana
  guest ok = yes

```
それぞれの意味は

```
comment: 共有した際に名前とは別に表示される文字列。win10の場合はエクスプローラー上でマウスオーバーしたときに表示されます。
path: そのまま。フルパスで書こう。
read only: 読み込みだけにするかどうか。
browsable: browseableのエイリアス。利用可能な共有の一覧に表示させるかどうかを決めます。
force user: どの人の権限でファイルにアクセスすることにするかを定める。使っているユーザー名で設定すると便利。
guest ok: アクセスの際に資格情報を要求するか。
```
他にもいろいろプロファイル項目はあります。知りたい方は日本Sambaユーザー会の最新マニュアルページをみましょう。

　パスワードをつける場合はこのコマンドを使いましょう。ログインしているLinuxユーザーのIDとパスワードと同一になります。`user`の部分は適切に変更してください。

```
$ sudo smbpasswd -a user
```

以下のコマンドでconfファイルの整合性をチェックできます。

```
$ testparm
```

最後に設定ファイルを適用させるために再起動しましょう

```
$ sudo systemctl restart smbd nmbd
```

これでおしまいです。



###おわりに

　お疲れさまでした、これで最低限の準備は整ったはずです。ですが自分の躓いた点に関して書かれていない所があるのでまた記事を新たに書くかもしれません。ここまでお読みくださってありがとうございました。
SlackAPIでのメッセージ送信でのメッセージ上限を調べてみた

# 前提条件
Blocks UIを使った場合なので、その場合以外は検証はしてません。詳しくは一番下の検証ソースの`create_send_message`のとこ見てください。

# 経緯
AWSのLambdaでSlack通知をしたいなと思った時に、`400: Bad Request`なエラーが出た。送る文字数を少ない時は送信できてたので調査してみる。どうでもいいけどSlackはもうちょっと親切なエラーメッセージ返して欲しい。

```python

Response:
{
  "errorMessage": "HTTP Error 400: Bad Request",
  "errorType": "HTTPError",
  "stackTrace": [
    "  File \"/var/task/lambda_function.py\", line 57, in lambda_handler\n    post_slack(create_send_message(test_message))\n",
    "  File \"/var/task/lambda_function.py\", line 236, in post_slack\n    with urllib.request.urlopen(request) as response:\n",
    "  File \"/var/lang/lib/python3.8/urllib/request.py\", line 222, in urlopen\n    return opener.open(url, data, timeout)\n",
    "  File \"/var/lang/lib/python3.8/urllib/request.py\", line 531, in open\n    response = meth(req, response)\n",
    "  File \"/var/lang/lib/python3.8/urllib/request.py\", line 640, in http_response\n    response = self.parent.error(\n",
    "  File \"/var/lang/lib/python3.8/urllib/request.py\", line 569, in error\n    return self._call_chain(*args)\n",
    "  File \"/var/lang/lib/python3.8/urllib/request.py\", line 502, in _call_chain\n    result = func(*args)\n",
    "  File \"/var/lang/lib/python3.8/urllib/request.py\", line 649, in http_error_default\n    raise HTTPError(req.full_url, code, msg, hdrs, fp)\n"
  ]
}
```


# 結論
メッセージ上限は3000文字だ！


# 参考

検証ソースです。AWS Lambda上で実施したものを適当に抜粋したので動かないかもしれません。

```python

import json
import urllib
import os

TEXT_LEN = 3000 # ここを適当に変える

def lambda_handler(event, context):
    test_message= 'A' * TEXT_LEN
    post_slack(create_send_message(test_message))

    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

def create_send_message(message):
    return {
        "blocks": [
            {
                "type": "section",
                "text": {
                    "type": "mrkdwn",
                    "text": f"{message}"
                }
            }
        ]
    }

def post_slack(send_data):
    request = urllib.request.Request(
        os.environ['SLACK_WEBHOOK_URL_DEV'], 
        data=json.dumps(send_data).encode("utf-8"),
        method="POST"
    )
    with urllib.request.urlopen(request) as response:
        response_body = response.read().decode("utf-8")
```
【javascript】一言で、　Javascript　他ファイルの呼び出し　おまけ付き

##【ゴール】
他jsファイルを呼び出し、読み込む

##【メリット】
■javascript　理解度向上
■コードの可読性向上　整理出来るので


##【開発環境】
■ Mac OS catalina


##【コード】
**以下2点処理必要**


###①importを使用
＊読み込ませたいファイルに
＊ファイルの一番最初に記述
＊**’ ’**内は**ファイル名**

```js:hoge.js

import HogeHoge form './hogehoge';

class Hoge{
.
.
.
}

```

###②exportを使用
＊呼び出したいファイルに記述
＊ファイルの末尾に記述
＊default後は**クラス名**

```js:hogehoge.js
class HogeHoge{
.
.
.
}
export default HogeHoge;
```

##【番外編】定数、変数の呼び出し
＊**基本的には同じ**

###import

```js:hoge.js

import content form './hogehoge';

class Hoge{
.
.
.
}

```

###export


```js:hogehoge.js
class HogeHoge{

const content = "HogeHoge";
.
.
}
export default content;
```

ちなみに
**import:　輸入　持ち込む
export:　輸出、書き出す**
という意味です。


以上

##【合わせて読みたい】

■ 【javascript】　テンプレートリテラル とは　一言で。
https://qiita.com/tanaka-yu3/items/9b07bd9fc4126291be28

■ 【Javascript】 メソッド　まとめ　基礎基本コード　メモ
https://qiita.com/tanaka-yu3/items/2438798d159fa402b1d5

■ 【Javascript】JS　変数　定数　違い 　一言でまとめました
https://qiita.com/tanaka-yu3/items/51b8b0630a1e4e2d52c8
MariaDB が systemctl で起動できない問題の解決方法

Ubuntu 20.04 で mysql-server を削除してから、mariadb-server をインストールすると、MariaDB が systemctl で起動できないという問題が発生しました。

次の記事の通りに行って問題が解決しました。
[Ubuntuでmysql-serverをmariadb-serverで置き換えるとsystemd経由でmariadbが起動できない](https://narusejun.com/archives/24/)

問題発生時の状況
しばらく、MariaDB は動いているが、しばらくして止まります。

```text
$ sudo systemctl start mysql
Job for mariadb.service failed because a timeout was exceeded.
See "systemctl status mariadb.service" and "journalctl -xe" for details.
```

解決方法です。

```text
$ sudo aa-remove-unknown
Skipping profile in /etc/apparmor.d/disable: usr.sbin.rsyslogd
Removing '/usr/sbin/mysqld'
```

MariaDB を起動します。

```bash
sudo systemctl start mysql
```

2020-7-21 に同じ問題が発生しました。
トリガーとなったのは、カーネルを上げたことです。

次のようなログが出ていました。

```text
2020-07-21  9:52:49 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2020-07-21  9:52:49 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2020-07-21  9:52:49 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2020-07-21  9:52:49 0 [Note] InnoDB: Waiting for purge to start
```

しばらくは、mysql が動いているのですが、systemd がタイムアウトになり、mysql も停止します。

結局、解決方法は、

```text
$ sudo aa-remove-unknown
Skipping profile in /etc/apparmor.d/disable: usr.sbin.rsyslogd
Removing '/usr/sbin/mysqld'
```

2020-7-22 に同じ問題が発生しました。
>原因は再起動です。
>恒久的な解決でないことが分かりました。

次の対策を打ってみました。

```bash
sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld
sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/
```

参考ページ
[Ubuntu 18.04: AppArmorで強制アクセス制御](https://www.hiroom2.com/2018/05/06/ubuntu-1804-apparmor-ja/)
最短でAWS初心者（未経験含む）がソリューションアーキテクトアソシエイト（SAA）を取得するためにやること2選

こんにちは、みきおです。
タイトルの通り、初心者（未経験）だけどとにかく効率的にソリューションアーキテクトアソシエイト（SAA）を取得したい人の養分になればと思います。

# 対象
- 初心者（未経験）だけどSAAを取得したい人
- とにかく効率重視でSAAを取得したい人
- SAAを取得したい人
- Black Belt？なにそれ？だけどSAAを取得したい人
- 他の人がどんな勉強をしたか参考にしたい人

# はじめに
SAAを取得するためにやるべきことは大きく3つのステップに分けられます。

- AWSサービス群の全体の把握
- 各サービスの詳細の把握
- 試験対策

上記のうち、各サービスの詳細の把握と試験対策についてだいぶ被るので一つにまとめます。

# 1. AWSサービス群の全体の把握
<a target="_blank" href="https://www.amazon.co.jp/gp/product/4865941991/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4865941991&linkCode=as2&tag=ihmdevs-22&linkId=b7ef690da97f3f30d69fd7c862aed2a5">AWS認定アソシエイト3資格対策</a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=ihmdevs-22&l=am2&o=9&a=4865941991" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />をおすすめします。
3資格対策と銘打たれていますが、デベロッパーアソシエイトでは不十分でした。SAAについても[^1]下記書籍オンリーでは未経験者にはきついと思いますので、下記に続きます。
[^1]: SysOpsアドミニストレーターについては受けていないのでわかりません。

# 2. 各サービスの詳細の把握と試験対策
Udemyの[ソリューションアーキテクトアソシエイトの試験対策](https://www.udemy.com/course/aws-associate/)にて模擬試験を周回します。
全65問を回答後に各設問に対する答えと詳細な解説がついてきます。解説で理解できない部分をググるなりすると理解が深まってくるかと思います。
1周以上がマストで2周以上80~90%の正解率が出せればベストです。
心配性な方はUdemyのハンズオンもやってみてもいいかもしれませんが、動画が待ってられなかったのと聞き取りづらい箇所があったので私はあまりお勧めしませんしやってません。

# さいごに
勉強時間などを書いておきます。
平日:約1時間（だいたい週4ほど）
休日:約2~6時間
32~68時間くらいなので間をとって50時間くらいかなと思います。

配分は書籍（全体の把握）と模擬試験で半々くらいだったと思います。全体を把握するのに時間がかかりましたが、覚えがはやい方はもう少し短時間で済むかもしれません。

2020年4月ごろから勉強を始め、試験2週間前くらいから焦って本腰を入れて勉強し6月6日に取得しましたが計画的にやれば1か月では取得できるかと思います。
ちなみに1問1答形式でWEBに無料で公開してくれているサイトがあり、当初はできるだけお金をかけたくないとそれもやりこみましたが、必要経費とみなしてさっさとUdemyの模擬試験をやり込んでおけばよかったと思ってます。

多数の方が書かれていますが、Udemyはセールをやっているタイミング[^2]で購入するのがベストです。

デベロッパーアソシエイトの取得はオンライン試験を受けたので、その際の様子も今後記事にしたいと思います。
ちなみにSAA取得後にlambdaとdynamodbをバックにした[WEBアプリ](https://bookrank.ihmdevs.com/)を作りました。その後デベロッパーアソシエイトを取得しています。
WEBアプリの構成について簡易的ですが記事にしていますので、興味があればこちらもどうぞ。
[これから個人開発をはじめてみようと思っている人へおすすめしたいアレコレ2020](https://qiita.com/mikiotec/items/df77225f0522f13bc146)

[^2]: Udemyにログインしていない2窓目でみたらセールしてたりします。セール値が正規値段疑惑ありますよね。
Datadogとkubectl top podで取得できるpodのメモリ関連情報の差異について

## 概要

Kubernetesの監視にDatadogを利用しており、podごとのメモリ使用率を監視していたところ、想定していたメモリ使用率を大幅に超えているpodがあったため調査しました。


## 異変に気づいた時のエビデンス

今回はCluster Autoscalerのpodのメモリ使用率が他のpodよりも目についたため、これを中心に調査しました。
kubectl top podで見えるメモリ使用率が42Mi程度、Limitで設定しているメモリ割り当ては256Miのため、メモリ使用率は16%程度のはずが、Datadogから取得できるメモリ使用率は99%以上となっていました。

### kubectl top podで見えるメモリ使用量

```bash
$ kubectl top pod -n kube-system cluster-autoscaler-xxxx
NAME                                  CPU(cores)   MEMORY(bytes)
cluster-autoscaler-xxxx               2m           42Mi
 
 
$ kubectl describe node ip-０００-０００-０００-０００.ap-northeast-1.compute.internal
~~~~中略
  Namespace                   Name                                   CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------                   ----                                   ------------  ----------  ---------------  -------------  ---
  kube-system                 cluster-autoscaler-xxxx                200m (5%)     200m (5%)   256Mi (3%)       256Mi (3%)     4d22h
```

### Datadogモニターで見えるメモリ使用量

Datadogではkubernetes.memory.usage_pctのメトリクスを利用しています。
以下はメモリ使用率のグラフなのですが、ほぼ100%に張り付いていることがわかります。
![スクリーンショット_単一のpodを指定.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316261/0c5688f1-f408-e145-4d98-fb20be7cebfd.jpeg)

コンテナのメモリ使用量を見ても252Mib使っており、メモリ使用率と同様に想定を大きく上回る値を計測していました。
![メモリ使用率_cluster_autoscaler_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316261/a399dc52-8f6c-ece7-c477-ac1ae199d84d.jpeg)


## 調査内容

### Datadogはpodのメモリ使用率をどのように算出しているか

kubectl top podで見えているメモリ使用率がおかしいという可能性も０ではなかったのですが、上記のkubectl get nodeの結果と、時間が経過してもOOMKillerでpodが死ぬことはなかったことから、Datadogで見えているメトリクスがおかしいと仮定して調査を行いました。

kubernetes.memory.usage_pctがどのようにメモリ使用量を算出しているかをDatadogのサポートデスクに問い合わせたところ、Datadogはkubelet API('/metrics/cadvisor')をみているとの回答を頂きました。

cAdvisorのmemory_usageがどのようにメモリ使用率を算出しているかについては、[issue](https://github.com/google/cadvisor/issues/913)で議論されていることと[ソースコード中のコメント](https://github.com/google/cadvisor/blob/master/info/v1/container.go#L366-L369)から、今現在アクティブであるかどうかにかかわらず、コールドキャッシュやSWAPなども含むアクティブではないメモリも使用率としてカウントしていることがわかりました。

また、issue内の以下のコメントから *working_set* というメトリクスを利用することで、非アクティブなメモリを除外したメモリ使用量を取得することができそうだということがわかります。

>memory_usage = RAM usage include pages that have not been accessed in a long time.
working set = memory usage - inactive memory.


## 対応

上記の調査から代替メトリクスとしてworking_setを利用したところ、kubectl top podで取得した時のメモリ使用量と同じ値を取得することができました。

![スクリーンショット 2020-06-29 17.22.41.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316261/8775fe0a-48ed-bf63-0861-fba088e8cac1.jpeg)

ただし、ここで確認した値はあくまで**メモリ使用量**で、監視したいメトリクスは**メモリ使用率**であるため、変換する必要あります。
メモリ使用率は、メモリ使用量とkubernetesマニフェストで指定しているメモリのリソースリミットから算出できるので、以下の計算結果の値を設定することでメモリ使用率が取得できそうです。

*memory.working_set / MemoryのLimitの設定値 * 100*

上記の計算式（memory.working_set / MemoryのLimitの設定値 * 100）を元にDatadog上で以下のように設定したところ、約16%と適切なメモリ使用率を取得することができました。

![スクリーンショット 2020-06-29 17.34.10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316261/c62e6f57-d568-7df7-7715-a408c0b1dece.jpeg)
【JavaScript】Base64変換ライブラリで速度対決

こんにちわ。
皆さんもBase64は使われているかと思います。
バイナリを文字列で表現できるのは何かと便利ですよね。

しかしJavaScriptには、こうサクっと1発でバイナリ配列とBase64文字列を変換できる実装が用意されていないので、何かしらの手を加える必要があります。

今回は、バイナリとBase64の相互変換を行える3つの方法について、どれが1番速いかを検証してみようと思います。


# 方法1, 標準実装
- [TextEncoder - MDN](https://developer.mozilla.org/ja/docs/Web/API/TextEncoder)
- [TextDecoder - MDN](https://developer.mozilla.org/ja/docs/Web/API/TextDecoder)
- [atob - MDN](https://developer.mozilla.org/ja/docs/Web/API/WindowBase64/atob)
- [btoa - MDN](https://developer.mozilla.org/ja/docs/Web/API/WindowBase64/btoa)

ライブラリを使わず、これらのブラウザ標準実装を組み合わせて変換します。

TextEncoder/TextDecoderは、文字列とUint8Arrayを相互変換してくれるAPIです。
そしてatob/btoaは、お馴染みBase64のブラウザ標準実装です。

この2つを組み合わせることにより、以下の流れでバイナリとBase64を変換できます。

**Uint8Array <=> BinaryString <=> Base64**

BinaryStringとは`0x00`~`0xFF`までの文字(制御文字含)で構成される文字列です。

バイナリを型付き配列やBlobとして扱うのが難しい時によく用いられる表現です。

そしてatob/btoaは、ちょうど`0x00`~`0xFF`までの文字を扱えます。
逆にこれしか扱えないので、Unicodeを扱う際によく問題となりますが...

TextEncoder/TextDecoder APIはクラスとして提供されるので、Base64向けの拡張クラスを作ってみました。

```js
// Base64 => Uint8Array
class Base64Encoder extends TextEncoder{
    constructor(){
        super();
    }

    encode(text){
        return super.encode(atob(text));
    }
}

// Uint8Array => Base64
class Base64Decoder extends TextDecoder{
    constructor(){
        super();
    }

    decode(buffer){
        return btoa(super.decode(buffer));
    }
}
```

Node.jsはどうするんだって...?
[最近話題](https://qiita.com/so99ynoodles/items/c3ba2a528052827e3b3c) のDenoさんが何とかしてくれるでしょう...知らんけど。


# 方法2, base64-js
- [base64-js -npm](https://www.npmjs.com/package/base64-js)

週間14,700,000ダウンロードの実績があるライブラリです。
恐らくこれが1番メジャーでしょうか。

メソッドは3つのみ、シンプルで使いやすいです。

Base64とUint8Arrayを相互変換できます。


# 方法3, js-base64
- [js-base64 -npm](https://www.npmjs.com/package/js-base64)

週間6,150,000ダウンロードの実績があるライブラリです。
2番手といったところでしょうか。

base64-jsと比べてライブラリ容量は大きめですが、メンテナンスは割と最近までされているようです。

こちらも、Base64とUint8Arrayを相互変換できます。


# 測定
以下のPCで測定を行いました。

- CORE2Quad Q9550
- DDR2-1066 4GB
- Windows7 32bit
- Google Chrome 83

部屋に転がってたPCなので、マシンスペックについては目を瞑ってもらいましょう...

元となるデータは、小さいと一瞬で終わってしまい比較にならないと予想したので、64MBのバイト配列でエンコード/デコードを行います。
これだけ大きいと、コールスタックやヒープなどのメモリ性能もついでに見れるかと思います。

```js
// 64MB
const test = new Uint8Array(1024 * 1024 * 64);

// 1. 標準実装
new Base64Encoder().encode(new Base64Decoder().decode(test));

// 2. base64-js
base64js.toByteArray(base64js.fromByteArray(test));

// 3. js-base64
Base64.toUint8Array(Base64.fromUint8Array(test));
```


# 結果
1. 標準実装 ... 1240 ms
2. base64-js ... 2870 ms
3. js-base64 ... ぴえん&#x1F97A;(5秒程の後にスタックオーバーフロー)

という結果になりました。

まじかよ！
ライブラリ使うより普通に標準実装を組み合わせた方が速いじゃん！

js-base64に至っては完走すら出来ませんでした。

ブラウザでBase64を扱うなら、標準実装もしくはbase64-jsを使うのが良さそうです。
go修行15日目 サードパーティ製パッケージを使う



## サードパーティパッケージのインストール
- 株価分析のためのパッケージ

https://github.com/markcheno/go-talib

### インストール

```
go get github.com/markcheno/go-talib
go get github.com/markcheno/go-quote
```

### インストールされる場所

```
PS C:\Users\yuta\go\src\github.com> ls .\markcheno\


    ディレクトリ: C:\Users\yuta\go\src\github.com\markcheno  


Mode                 LastWriteTime         Length Name      
----                 -------------         ------ ----       
d-----        2020/07/03      8:45                go-talib  

```

### サンプルコード

```golang

package main

import (
	"fmt"
	"github.com/markcheno/go-quote"
	"github.com/markcheno/go-talib"
)

func main() {
	spy, _ := quote.NewQuoteFromYahoo("spy", "2016-01-01", "2016-04-01", quote.Daily, true)
	fmt.Print(spy.CSV())
	rsi2 := talib.Rsi(spy.Close, 2)
	fmt.Println(rsi2)
}
```

出力

```
datetime,open,high,low,close,volume
2016-01-04 00:00,200.49,201.03,198.59,184.03,222353500.00
2016-01-05 00:00,201.40,201.90,200.05,184.34,110845800.00
2016-01-06 00:00,198.34,200.06,197.60,182.01,152112600.00
2016-01-07 00:00,195.33,197.44,193.59,177.64,213436100.00
```

パッケージ自体を呼ばせない場合

- importしたパッケージが呼ばれないとビルド時にエラーになるため

```golang

package main

import (
	"fmt"
	"github.com/markcheno/go-quote"
	_ "github.com/markcheno/go-talib"
)

func main() {
	spy, _ := quote.NewQuoteFromYahoo("spy", "2016-01-01", "2016-04-01", quote.Daily, true)
	fmt.Print(spy.CSV())
	// rsi2 := talib.Rsi(spy.Close, 2)
	// fmt.Println(rsi2)
}
```

## godoc

- ローカル環境でgodocを見ることができる
- Example関数などで自分で書いたコードをExampleとしてみることができる

### インストール

```
go get golang.org/x/tools/cmd/godoc
```

### 利用方法

```
godoc -http=:6060
```

### アクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/226fca25-e07a-8ef0-8a8e-d53be86fd1f9.png)
IM-LogicDesignerでタスク管理を外部システムと連携をしてみた

# 序文

現場で``DPS for sales``を導入し顧客管理や案件管理、タスク管理をはじめました。
顧客管理だけではなく、案件に対してTODO登録が出来る機能があります。
個人的にタスク管理サービスに興味があり調査をしていたのですが、
複数のサービスを行ったり来たりとオペレーションやタスク管理が非常に煩雑になりました。
その改善として``IM-LogicDesigner``を利用してタスク間の共有をしたので手順を紹介してみます。

# やったこと
1. タスク管理サービスのAPIを調べる
1. IM-LogicDesignerをちょっと触る
1. DPS for salesの挙動を調査する
1. IM-LogicDesignerでのtry & error  
1. 動作確認
1. 一連の連携処理を削除（後始末）


# 本文
全部を書くと長大なスケールの物語となるため、
IM-LogicDesignerの箇所だけピックアップします。

## どうやって連携するかを考えました
 -  タスク管理サービスはRESTのAPIでリクエストを処理できる
 -  ``DPS for sales``の登録処理はwebhockが無い（多分）
 -  ``DPS for sales``がiACスケジュールと連携する
 -  ``iAC``のスケジュール登録時に``IM-LogicDesigner``のトリガを起動出来る
 
ってことでIM-LogicDesignerでフローを作って連携させて見ました。
実態はiACとタスク管理サービスの連携となります。
せっかくなんで**ノンコーディング**での実現をめざしてみます。

## とりあえず連携
#### IM-LogicDesignerからRESTAPIを叩くユーザ定義を作る

対向システムのRESTパラメータを調査して入出力を決めます。
今回はPostmanで調査しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661245/d73fb3c1-a3e2-134e-8e3c-39b6fc75b9f6.png)

決定した入力と出力を定義します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661245/7e85a5f9-bcf5-2fd7-80fd-d1cd93a6b120.png)

ユーザ定義は終了です。
ここまでコーディングは**０ステップ**

#### LogicFlowの初期設定
LogicFlow開始時の入力パラメータを定義します
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661245/d3cc2733-7764-bc24-271c-1e47039e834c.png)


デバッグ時のパラメータ設定がめんどくさいので入力と同等構成のデバッグ用の定数します。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661245/1c82457a-87c8-1964-a6e2-344965e7363a.png)


#### Logicフローに組み込む

作ったユーザ定義をドラッグ＆ドロップでデザイン画面に配置、そのまま「開始」と「終了」に連結します。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661245/690e1973-802c-16d8-3326-23e4b0ac4691.png)

input/outputパラメータもGUIで連携します。
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661245/8b88efb9-9f42-c8fd-18dc-f64eb72d3544.png)


これでユーザ定義が組み込まれたLogicFlowの定義が終了です。
ここまでコーディングは**０ステップ**

#### 動作確認とデバッグ
省略

#### トリガ定義

トリガ定義でスケジュール登録時に発火する条件を定義する
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661245/fcadb222-fe18-5ca4-c716-9dc1bdc32c72.png)


フローとパラメータのマッピングをする
![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661245/ddcf1bb0-d4ef-0804-b753-7dfe0eb825c6.png)

トリガとフローが結合されたLogicFlowの定義が終了です。
ここまでコーディングは**０ステップ**

#### 実行
体力の限界と諸事情があり、ここで終了とします。
ここまでコーディングは**０ステップ**

最終的には以下の様なフローで実装しました。
![18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661245/a2255a8c-2b3b-f2a4-717f-db81b5225686.png)



# 終わりに

業務の休憩時間を利用して作った割にはちゃんと動きました。
その程度のコストで**標準で用意されている機能だけで他システム連携が出来る処理を実装できる**
と考えると結構な生産性を叩き出す可能性があるツールですね。
【Java】HashMapの最大値を取得する方法

## 開発環境・バージョン
・ホストOS: Windows10 Home
・ゲストOS: WSL2 Ubuntu20.04
・Java8

## 目的
keyの型がString, valueの型がIntegerのHashMapの最大値を取得すること

EntrySetメソッドを使って実装します。
以下は実際のコード

```java

public static void main(String[] args) {
  String arr[] = {"a", "a", "a", "a", "b", "b", "b", "c", "c", "d"};
  Map<String, Integer> map = new HashMap<>();

//配列の要素をマップに格納
  for (String string : arr) {
    if (map.get(string) == null) {
      map.put(string, 1);
    } else {
      map.put(string, map.get(string) + 1);
    }
  }

//最大値とそのときのキーを初期化
  String maxKey = null;
  Integer maxValue = 0;

//entrySetメソッドでマップのキーとValueを一つずつ取得
for (Map.Entry<String, Integer> entry : map.entrySet()) {

//最大値とValueを比較してValueが大きければ、そのときのキーとValueを代入
  if (entry.getValue() > maxValue) {
    maxKey = entry.getKey();
    maxValue = entry.getValue();
  }
}
System.out.println(maxKey + " : " + maxValue);
```

### 結果

```
a : 4
```

無事最大値を取得することができました。
最大値が複数あり全てを取得する場合はリストに格納すればよいでしょう。

entrySetのメリットは一度のループでキーとValueを両方取得できることですね。
bash の coproc について

# Overview

bash 4 から coprocess があるのを知ったので試してみます。
ざっくり言うと、メインプロセスと stdin/stdout を繋ぎながら、バックグラウンドでサブプロセスを起動できる機能です。

イメージ的には `cmd &` に近いですが、入出力が繋がってるのがイケてるポイントです。
具体的には、 `coproc` で起動すると、メインプロセス側の配列変数にファイルディスクリプタが割り当てられて、それがサブプロセスの stdin/stdout に繋がります。

```text:こんな感じ
                 +-- ${COPROC[1]}  --> stdin
                 +                      ↓
[main process] --+                 [sub process &]
                 +                      ↓
                 +-- ${COPROC[0]}  <-- stdout       
```

## cf.

詳しい使い方とかはこの辺見てください。

https://qiita.com/angel_p_57/items/7b54493e6e66aea01437
https://www.gnu.org/software/bash/manual/html_node/Coprocesses.html
https://unix.stackexchange.com/questions/86270/how-do-you-use-the-command-coproc-in-various-shells

あと bash と ksh zsh とかだと挙動が微妙に違うみたいです。
bash の縛りがきついｗ

# usage

具体的に見た方がたぶん理解が早いので、

## 1000行の tsv を `while read` で 1行ずつ csv に変換する場合

を考えてみます。

```bash:使用したバージョン
$ echo $BASH_VERSION
5.0.17(1)-release
```

なお、サブプロセスの出力がバッファリングされると詰まるので、awk で試してみます。
1行ずつ処理する際のパフォーマンスを確認したいので、awk の stdin に直接流し込むとかは今は忘れてください。

### coproc を使わないケース

1行ずつ読むたびに毎回 awk を起動するので、

```bash:nouse-coproc.sh
#!/bin/bash

seq -f '%04g' 3000 | paste - - - \
| while read x; do
    echo "$x" | awk -v OFS=, '{$1=$1; print $0; }'
done
```

けっこう時間がかかりますね。

```bash
$ time bash nouse-coproc.sh >/dev/null

real    0m2.685s
user    0m2.250s
sys     0m0.722s
```

### coproc を使うと

```bash:use-coproc.sh
#!/bin/bash

coproc hoge { awk -v OFS=, '{ $1=$1; print $0; fflush(); }' ; }

while read x; do
    echo "$x" >&${hoge[1]}
    read -u ${hoge[0]} a
    echo "$a"
done < <(seq -f '%04g' 3000 | paste - - -)

```

めっちゃ速くなります。

```bash
$ time bash use-coproc.sh >/dev/null

real    0m0.079s
user    0m0.054s
sys     0m0.023s
```

## なんで速くなるか

もう上に答え書いちゃったんですけど、
1行ずつ毎回プロセスを起動するときのオーバヘッドが遅くなる原因です。
このオーバヘッドは入力行数が増えれば増えるほど線形に増大していきます。

それに対して、 coproc は最初に1つだけプロセスを起動して、
1行ずつ stdin に流し込んで、処理結果を stdout から read していくので、
普通に stdin からコマンドに流し込むのと同じ効果があります。

シェル芸で1行ずつ処理する場合に捗りそうですね。

# appendix

## ファイルディスクリプタがプロセスをまたいで引き継げない問題

たぶん bash 縛りだと思うんでうけど、
サブプロセスにはファイルディスクリプタが引き継げず、直で fd 値を指定しても *不正なファイル記述子です* みたいなエラーになってしまいます。

なので `seq | while read x; do ...; done` でやろうとすると、パイプの先は別プロセスなので、残念ながら動きません。
代わりに `while read x; do ... ; done < <(seq)` のプロセス置換でやったのはこれが理由です。


## バッファリングについて

今回は awk の fflush() で挙動を確認しましたが、 stdbuf を使えばコマンドのバッファリングを切り替えられるみたいです。
https://linuxjm.osdn.jp/html/GNU_coreutils/man1/stdbuf.1.html

```bash:これだとNGだが
$ coproc hoge { tr $'\t' , ; }
```

```bash:こっちならOK
$ coproc hoge { stdbuf -oL  tr $'\t' , ; }
```

おわり。
Windows Terminal の colorScheme (defaults.json) でディレクトリの色が見づらいのでカスタム

目が疲れないためにも細かな colorScheme は大切です。

Windows Terminal の色設定はこちらを参照
https://docs.microsoft.com/ja-jp/windows/terminal/customize-settings/color-schemes


### 比較

"Tango Dark" が好みですが、設定すると色がこうなる
![wsl_color_before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1931/d5c5b33b-95f7-eed0-7326-672d81998d7a.png)
↓
![wsl_color_after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1931/60b85baf-fba8-105e-4f3f-dd4fcbf1c3ba.png)
見づらいディレクトリ (緑背景色) が青文字となり見やすくなる。


### 変更例: Tango Dark の場合
"Tango Dark" の色情報は Windows Terminal の設定を Alt を押しながら選ぶと、default.json が開き、そこに記述されているので、コピペしてくる。次に Settings.json 開いて次のように追記。

```json:settings.json
{
    // 省略
    "profiles":
    {
        "defaults":
        {},
        "list":
        [
            {
                "guid": "{xxxxxxxxxxxxxxxxxxxxxxxxx}",
                "hidden": false,
                "name": "Ubuntu-18.04",
                "source": "Windows.Terminal.Wsl",
                "colorScheme" : "Custom Tango Dark" // カスタム
            },
            // 省略
       ]
    },
    "schemes": [
        {
            "name": "Custom Tango Dark",
            "foreground": "#D3D7CF",
            "background": "#000000",
            "cursorColor": "#FFFFFF",
            "black": "#000000",
            "red": "#CC0000",
            "green": "#333", // ここディレクトリの背景色
            "yellow": "#C4A000",
            "blue": "#3BBEF2", // 青を明るくする
            "purple": "#75507B",
            "cyan": "#06989A",
            "white": "#D3D7CF",
            "brightBlack": "#555753",
            "brightRed": "#EF2929",
            "brightGreen": "#8AE234",
            "brightYellow": "#FCE94F",
            "brightBlue": "#729FCF",
            "brightPurple": "#AD7FA8",
            "brightCyan": "#34E2E2",
            "brightWhite": "#EEEEEC"
        }
    ]
}
```

以上
Uipath WEB上の特定文字によって動作を分岐したい

初心者です。
WEBアプリを使用していまして、繰り返し作業の自動化を目指しています。
繰り返し作業は実行出来ているんですが、
そのリストが無くなるとある特定文字が表示されます。
その文字が表示されたら作業終了という形にしたいと考えています。
現在下記のような内容で作成していますが、分岐がされないです。
![Screenshot_10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666791/c2d3532c-f9e2-ad53-0078-fdca815a7a6d.jpeg)
このような形で分岐したいと考えています。
設定内容は下記になります。
![Screenshot_11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666791/fa8d8907-8f2a-cb73-ee43-f48640389b05.jpeg)
![Screenshot_12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666791/d88a0a9d-59a6-5068-5180-824c5194e2aa.jpeg)
![Screenshot_13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666791/c152f97b-679c-f6e9-615e-e68d39c23ee4.jpeg)

要素としては、WEB上の特定文字です。
・要素の有無を検出
・フロー条件分岐
こちらの設定方法を教えて下さい。
ほんとに初心者の為変数など設定方法が分かりません。
プログラム自体が分かっていません。
どなたか教えて頂けないでしょうか？
宜しくお願い致します。
IMのドキュメント内にある様々な関数をまとめてみる その4

#IM開発備忘録

##IMのドキュメント内にある様々な関数をまとめてみる その4

###関数ボックスの日付関数

Formaには関数ボックスなるものが存在し、その中にFormaがサポートする様々な関数が存在する。
それらを駆使することで、比較的簡単にクライアント処理などを作り出すことができる。
バグもほぼない（私は確認したことがない）ので安全かつ高速に使える

その内の日付関数を以下にまとめる

####dateformat(日付書式への変換)

「数値」のフィールド識別ID「date1」に入力値「1349049600000」を入力する場合

```js:sample.js
dateformat(date1, “yyyy/MM/dd HH:mm”)
```

画面アイテムには**「2012/10/01 09:00」**と表示されます。



####accountDateformat(日付書式への変換)

「数値」のフィールド識別ID「date1」に入力値「1349049600000」を入力する場合

```js:sample.js
accountDateformat(date1, “yyyy/MM/dd HH:mm”)
```

画面アイテムには**「2012/10/01 09:00」**と表示されます。


####datevalue(日付時刻を表す数値への変換)

「文字列」のフィールド識別ID「date_num1」に入力値「2012/10/01」を入力する場合

```js:sample.js
datevalue(date_num1, “yyyy/MM/dd”) 
```

画面アイテムには**「1349017200000」**と表示されます。

####accountDatevalue(日付時刻を表す数値への変換)

「文字列」のフィールド識別ID「date_num1」に入力値「2012/10/01」を入力する場合

```js:sample.js
accountDatevalue(date_num1, “yyyy/MM/dd”)
```

画面アイテムには**「1349017200000」**と表示されます。



####today(現在日付の取得)

2012/10/01 09:00に表示した場合

```js:sample.js
today()
```

式評価結果のデータ型：日付　→ 画面アイテムには**「2012/10/01」**と表示されます。
式評価結果のデータ型：数値　→ 画面アイテムには**「1349017200000」**と表示されます


####accountToday(現在日付の取得)


2012/10/01 09:00に表示した場合

```js:sample.js
accountToday()
```

式評価結果のデータ型：日付　→ 画面アイテムには**「2012/10/01」**と表示されます。
式評価結果のデータ型：数値　→ 画面アイテムには**「1349017200000」**と表示されます。



####now(現在日時の取得)


2012/10/01 09:00に表示した場合

```js:sample.js
now()
```

式評価結果のデータ型：日付　→ 画面アイテムには**「2012/10/01」**と表示されます。
式評価結果のデータ型：数値　→ 画面アイテムには**「1349049600000」**と表示されます。



####accountNow(現在日時の取得)

2012/10/01 09:00に表示した場合

```js:sample.js
accountNow()
```

式評価結果のデータ型：日付　→ 画面アイテムには**「2012/10/01」**と表示されます。
式評価結果のデータ型：数値　→ 画面アイテムには**「1349049600000」**と表示されます。



####getDateFormat(日付フォーマットの取得)

画面アイテム「日付」のフィールド識別ID「calendar1」(calendar1には、日付フォーマットに”MM/dd/yyyy”を指定し、”10/01/2012”と表示されている)を指定する場合

```js:sample.js
getDateFormat(“calendar1”)
```

画面アイテムには**「MM/dd/yyyy」**と表示されます。



####getDateTime(エポックミリ秒の取得)

画面アイテム「日付」のフィールド識別ID「calendar1」を指定し、 2012/10/01 09:00に表示した場合

```js:sample.js
getDateTime(calendar1) 
```

画面アイテムには**「1349017200000」**と表示されます。



####getAccountDateformat(日付フォーマットの取得)

アカウントの日付標準表示用フォーマットに”yyyy/MM/dd”が指定されている場合

```js:sample.js
getAccountDateformat() 
```

画面アイテムには**「yyyy/MM/dd」**と表示されます。



####getAccountDateTimeformat(日時フォーマットの取得)

アカウントの日付標準表示用フォーマットに”yyyy/MM/dd”、タイムスタンプ表示フォーマットに”H:mm:ss”が指定されている場合

```js:sample.js
getAccountDateTimeformat()
```

画面アイテムには**「yyyy/MM/dd H:mm:ss」**と表示されます。



####timeDiff(時差の取得)

システムタイムゾーンとアカウントタイムゾーンが同じ場合

```js:sample.js
timeDiff() 
```

画面アイテムには**「0」**と表示されます。

####getAccountInputDateformat(日付フォーマットの取得)


アカウントの日付標準表示用フォーマットに”yyyy/MM/dd”が指定されている場合

```js:sample.js
getAccountDateformat() 
```

画面アイテムには**「yyyy/MM/dd」**と表示されます。



###他の記事

IMのドキュメント内にある様々なAPIをまとめてみる その１
https://qiita.com/ChrisKasahara/items/c3187249112e7114aa12

IMのドキュメント内にある様々なAPIをまとめてみる その２
https://qiita.com/ChrisKasahara/items/ac038ce0b704574ada16

IMのドキュメント内にある様々なAPIをまとめてみる その３
https://qiita.com/ChrisKasahara/items/b2b5724af834b85d6269
競技プログラミング練習記 No.32【ABC128練習】

初回 -> [はじめに](https://qiita.com/easychoco/items/a9ae28aca97cfe47091f)

[ABC128](https://atcoder.jp/contests/abc128)を解きました。
4完です！

|問題|時間|アルゴリズム|実行時間
|:-:|:-:|:-:|:-:|
| A |  1min |-| 7ms|
| B | 52min |std::map| 6ms|
| C | 26min |xor, bit全探索|11ms|
| D | 57min |シミュレーション| 8ms|

B問題なにがあったwww
って感じの時間の使い方ですね。



## A - Apple Pie
```c++
	int a, p;
	cin >> a >> p;
	cout << (a * 3 + p) / 2;
```
持っているリンゴをすべて欠片にして、アップルパイを作れば答えですね。

## B - Guidebook
``` c++
using P = pair<int, int>;

	int n, p;
	string s;
	cin >> n;
	map<string, vector<P>> rest;
	for(int i = 0; i < n; ++i)
	{
		cin >> s >> p;
		rest[s].emplace_back(P(p, i + 1));
	}
	for(const auto& r : rest)
	{
		auto vec = r.second;
		sort(vec.begin(), vec.end());
		for(auto it = vec.rbegin(); it != vec.rend(); ++it)
		{
			cout << it->second << endl;
		}
	}
```
歴代のB問題で最も時間をかけました笑
`multiset`つかそうやん。つかってみよう。って思って調べながらやってたらこの時間です。
しかも答えには`multiset`使っていないという。
型のエラーが多かったのと、思ったような実装ができなさそうだったのでやめました。

c++は型のエラーをするとめっちゃ怒られて、しかも怒られすぎて何が悪いのかすぐにわかりませんよね。
その点どうにかならないものか。。。

たぶん普通にやってたら10分程度だったかと思います。

`map<string, vector<P>>`を使って`key`ごとに分けて、そのあと`value`をソートしました。
`key`は昇順、`value`は降順にソートする必要があったのでこの解き方になっています。


## C - 	Switches
``` c++
	int n, m, k_size, s;
	cin >> n >> m;
	vector< vector<int> > k(m, vector<int>());
	vector<int> p(m);
	for(int i = 0; i < m; ++i)
	{
		cin >> k_size;
		for(int j = 0; j < k_size; ++j)
		{
			cin >> s;
			s--;
			k[i].emplace_back(s);
		}
	}
	for(int i = 0; i < m; ++i)
	{
		cin >> p[i];
	}

	int ans = 0;
	int mask = 1 << n;
	while(mask--, mask >= 0)
	{
		vector<int> sw(m, 0);
		for(int i = 0; i < m; ++i)
		{
			for(const auto& j : k[i])
			{
				sw[i] ^= ((mask & (1 << j)) > 0);
			}
		}
		if (sw == p) ans++;
	}
	cout << ans;
```

問題文より
>  on になっているスイッチの個数を 2 で割った余りが p_i に等しい時

とあるので、xorっぽいですね。
また、制約が`N, M = [1, 10]`とありますね。`O(2^n)`が間に合います。
xorっぽいということもあって、bit全探索が候補にあがります。

実際にこの問題はxor と bit全探索を使って解きます。
ここまでわかれば問題の通りに実装です。

`mask`にスイッチの状態を表して、` vector<int> sw(m, 0)` で `電球i`につながるスイッチの様子を表します。
この時に入力値`p`と`sw`が等しくなれば、電球がすべてついている状態となります。


## D - equeue


``` c++
	int n, k;
	cin >> n >> k;
	vector<int> v(n);
	for(int i = 0; i < n; ++i)
	{
		cin >> v[i];
	}

	ll ans = 0;
	for(int get_num = min(k, n); get_num >= 0; --get_num)
	{
		for(int start = -get_num; start <= 0; ++start)
		{
			ll sum = 0;
			vector<int> may_erase;
			for(int i = 0; i < get_num; ++i)
			{
				int val = v[start + i < 0 ? start + i + n : start + i];
				sum += val;
				if (val < 0) may_erase.emplace_back(val);
			}

			sort(may_erase.begin(), may_erase.end());
			int erase_num = min((int)may_erase.size(), k - get_num);
			ll erase_sum = 0;
			for(int i = 0; i < erase_num; ++i)
			{
				erase_sum += may_erase[i];
			}
			ans = max(ans, sum - erase_sum);
		}
	}
	cout << ans;
```
`deque`を使いそうな問題名ですが、使いませんでしたね笑。
`a`個取り出して`b`個戻すという処理を繰り返して、手元に残るプレゼントの総和を最大にします。
`a + b <= K`なので、これを満たす組み合わせをすべて試して総和を比較します。

シミュレーションの実装に時間がかかる問題ですね。。


以上です。ありがとうございました。
条件付きレンダリングって？

# 条件付きレンダリングてなだろう？
プログラミングにおいて複数の反応を用意して、一定の入力によって様々な出力へと変化するいわば**制御構文**というものがあります。これは一般的には`if文`を用いることで可能になるんですが私が今勉強しているVue.jsで条件付きレンダリングにおいては`v-if`や`v-else`というものを使って表現するらしい！
まぁ簡潔に言えば条件付きレンダリングとは**制御構文**であると言えますね！
## 百聞は一見に如かず！
とりあえず何かしらこの`v-if`とやらを使ってみるのが一番わかりやすいと思うのでサンプルプログラムを作ってみましょう。

```sample.html
<div id="app">
    <p v-if="flag" class="ok">
      This is correct display!
    </p>
    <p v-else class="ng">
      uncorrect display!!!!!!!
    </p>
  </div>
  <button onClick="doAction();">
    Click
  </button>
  <script>
    const data = {
      flag: true
    }
    const app = new Vue({
      el: '#app',
      data: data
    });

    function doAction() {
      data.flag = !data.flag;
    }
  </script>
```
こんな感じのことを書いといて、webで開くとこんな感じです...
![スクリーンショット 2020-07-03 6.23.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468800/a66363a9-83e8-c571-d6c7-b0e06482b5c2.png)
サーセン！背景のこと全く考えてなくて画像の境界線が分からなくなってるけど気にしないでくれると助かります
![スクリーンショット 2020-07-03 6.23.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468800/c72dc934-b667-0f9d-79b1-ffa20c447217.png)
プログラム自体は至って簡単なものです！
`flag`に格納されている値が`true`であれば`v-if`の方の表示がされます。ボタンを押すと`doAction`のメソッドが動き、`!data.flag`により`data`のなかの`flag`の値の否定、つまり`false`へ変化し`data.flag`へ格納します。したがって今度は値がfalseのため`v-else`の方の表示がされます。
書いて見ればなんてことないただのif文でしたな〜
## 言葉に騙されないで！
参考書とかで勉強してると時々「は⁉︎何これ！初めて聞いたはこの機能！」ということが多々あると思います。でも実際に書いて実行してみると意外と今回のようになんてことない**初歩中の初歩**だったりする。なんか難しい言葉が出てきたな〜とか思ったらとにかくプログラムを実際に書いてみる！これに限ることを学んだ今日この頃...
***この記事ほとんど書く必要なかった〜〜〜***


## 追記
条件付きレンダリングとはまぁDOMに直接レンダリングを行う条件を記述してあげることで条件次第で表示を切り替えるために使っているのかなという感想です。ん？日本語が難しい…
[php基礎] 　foreach文とif文を使って合計金額と最高価格を表示させる


```
$menus = array(
  array('name' => 'CURRY', 'price' => 900),
  array('name' => 'PASTA', 'price' => 1200),
  array('name' => 'COFFEE', 'price' => 600)
);
```
上記の配列の合計金額と最高金額を表示させる。
↓

```
$totalprice = 0;
$maxprice = 0;
$maxname = '';
foreach ($menus as $menu) {
  $name = $menu['name'];
  $price = $menu['price'];
  echo $name.'は'.$price.'円です';
  echo '<br>';
  $totalprice += $price;
  if ($maxprice < $price){
    $maxprice = $price;
    $maxname = $name;
  }
}
 echo '合計金額は'.$totalprice.'円です';
 echo '<br>';
 echo $maxname.'が最高価格で'.$maxprice.'円です';
```

＊foreach文の前に合計金額、最高価格、最高価格の商品名を定義させる。
＊foreach文中にif文を使って、price（比べる価格）がmaxprice（最高価格）より大きい時、maxpriceにpriceの値を再定義させる。またその商品名（name）をmaxmane（最高価格の商品名）に再定義させる。




※最高価格の商品名には空の文字列にクウォーテーションで定義しておく。
↓

```
$maxname = '';
```
contextlib.ContextDecorator

```py
import contextlib


# @contextlib.contextmanager
# def tag(name):
#     print('<{}>'.format(name))
#     yield
#     print('</{}>'.format(name))

class tag(contextlib.ContextDecorator):
    def __init__(self, name):
        self.name = name
        self.start_tag = '<{}>'.format(name)
        self.end_tag = '</{}>'.format(name)

    def __enter__(self):
        print(self.start_tag)

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(exc_type)
        print(exc_val)
        print(exc_tb)
        print(self.end_tag)


with tag('h2'):
    raise Exception('error')
    print('test')
```
実行結果：

```txt
h2>
<class 'Exception'>
error
<traceback object at 0x7fa12715e0f0>
</h2>
Traceback (most recent call last):
  File "/Users/hamazakiisao/PycharmProjects/python_programming/lesson.py", line 27, in <module>
    raise Exception('error')
Exception: error
```
辞書引きアルゴリズム入門

# はじめに
業務で自然言語処理をしていて何かと高速化を求められる場面が多く、辞書引きアルゴリズムという言葉に行き着いた。
自然言語処理界隈で深層学習が幅を利かせすぎているせいか、辞書引きアルゴリズムと聞いても同じようにピンとこない人の方が多そう。


# 辞書引きアルゴリズムとは
テキスト中の有り得る全ての部分文字列から辞書にある単語を引いてくるアルゴリズムのこと。
形態素解析とかの処理の裏側を支えている。
この道を極めるとMeCabとかJumanとかが作れるらしい。
例えば、abcという文字列が与えられた場合、部分文字列は以下のようになる。

- a
- b
- c
- ab
- bc
- abc

これらの部分文字列が辞書にあるかどうかを調べていく。
要するに文字列の中から辞書内の単語を引っ張ってくるアルゴリズム、といった感じである。

この部分文字列の列挙の計算量は$O(N\^2)$であるが、この時点でアプリケーションとして実用化には程遠い。($O(N)$が望ましい)

ちなみに、辞書はハッシュと呼ばれることもあるが、文字列のハッシュ値の計算に$O(N)$を要するので、結局$O(N^3)$かかってしまう。



# 高速化の例
そこで、何とか高速化しないといけない。
例として$共通接頭辞検索$というものがある。

これは「公務執行妨害」という文に対して

- 公
- 公務
- 公務執行
- 公務執行妨害

という同じ接頭辞を持つ文のうち、辞書に登録されている単語を引っ張ってくる処理である。

これはトライ木というデータ構造を用いて高速化されている。
(トライ木については、[ここ](https://algo-logic.info/trie-tree/)を参照)

```
 公
 |---end 
 務
 |---end
執行
 |---end
妨害
 |
end
```
「公」という文字が出てきたら、こんな感じに部分文字列をたどって検索できるようにしておく。
(endが出てきたらその時点で１単語として登録されている)

このトライ木の検索の計算量は$O(K)$である。(K：平均単語長)

共通接頭辞検索を用いることで、「大学辞めたい」という文章に対して、

- 「大」という文字について共通接頭辞検索
- 「学」という文字について共通接頭辞検索 
- (省略)

こんな感じで辞書引きができる。
これは$O(NK)$である。

## 豆知識
MeCabの中でもトライ木は使われているらしく、[ダブル配列](https://www.slideshare.net/higashiyama/ss-8738479)という最速のトライ木の実装方法が使用されているらしい。(リンク先はダブル配列のわかりやすいスライド)
[Darts](http://chasen.org/~taku/software/darts/)というC++のライブラリが公開されており、簡単にダブル配列が使えるようになっている。

次は、辞書を引いた後の処理にも焦点を当てたい。