論理ゲートの処理をPowerShellで実装した

# 論理ゲートの処理をPowerShellで実装した

恥ずかしながら、FEに出てくるような基礎がしっかりしていない＆暗記がてんでダメなので、
PowerShellを書きながら理解を深めることにした。
また、Pesterでユニットテストを書いて実行した。

## 参考にさせていただいた記事

* [論理ゲートをPythonで作ってCPUを学ぶ(第１回)](https://qiita.com/tatmius/items/a49d9dfcdd148499d77f)

* [PowerShellでユニットテスト(Pester)]
(https://qiita.com/Kosen-amai/items/1f36ce59a768e7f9e869)

* [PowershellでPesterを使ってテストしてみた]
(https://blog.nakajix.jp/entry/2013/12/26/005443)

## 使用した言語・ツール
PowerShell：V5.1
Pester：テスト用フレームワーク
Visual Studio Code

## 実装した論理ゲート
* 論理積：AND

```PowerShell
function Conjunction($a, $b){
    // 1同士で乗算した場合のみ1を返す
    $c = $a * $b
    return $c
}
```
* 論理和：OR

```PowerShell
function Disjunction($a, $b){
    // 引数で受けた値を足して1以上になる場合は1を返す
    if (($a + $b) -ge 1){
        return 1
    }else{
        return 0
    }
}
```
* 否定：NOT

```PowerShell
function Negation($a){
    // 引数で受けた値を反転する
    if ($a -eq 0){
        return 1
    }
    else{
        return 0
    }
}
```
* 否定論理積：NAND

```PowerShell
function NonConjunction($a, $b){
    // 論理積を出す
    $c = Conjunction $a $b
    // 否定にして値を反転する
    $d = Negation $c
    return $d
}
```

* 否定論理和：NOR

```PowerShell
function NonDisjunction($a, $b){
    // 論理和を出す
    $c = Disjunction $a $b
    // 否定にして値を反転する
    $d = Negation $c
    return $d
}
```

* 排他的論理和：XOR

```PowerShell
function ExclusiveDisjunction($a, $b){
    // 引数で受けた値を足して、値が1になる場合のみ1を返す
    if ($a + $b -eq 1){
        return 1
    }
    else{
        return 0
    }
}
```

* おまけ：バリデーション処理(0か1のみ有効とする処理)

```PowerShell
function Validation($val){
    if(([String]$val).Length -ne 1){
        Write-Host -message "Validation Check Error: please assign length 1 data!"
        return -1        
    }
    if(($val -eq 0) -Or ($val -eq 1)){
        return 0
    }
    else{
        Write-Host -message "Validation Check Error: please assign 0 or 1!"
        return -1
    }
}
```

## Pesterでユニットテストを書いて実行した

PesterはPowerShellのコードをテストするためのフレームワーク。
自分が使用しているPowerShellのV5.1には搭載されてた。
セットアップの手順については、上掲の参考URLをご確認いただけたら。

以下は実装したコードの例、論理積を出すConjection関数。

* 製品コード

```PowerShell:PesterTest1.ps1
function Conjunction($a, $b){
    $c = $a * $b
    return $c
}
```

* テストコード

テストケースとしては、以下の真理値表に出てくる4ケースを実施。

### 真理値表
|  A  |  B  |  Z  |
|:---:|:---:|:---:|
|  1  |  1  |  1  |
|  1  |  0  |  0  |
|  0  |  1  |  0  |
|  0  |  0  |  0  |


```PowerShell:PesterTest1.Tests.ps1
Describe "Conjunctionの動作確認" {
    Context "正常系の確認"{
        It "1 1なら1が返るはず" {
            Conjunction 1 1 | Should Be 1
        }
        It "1 0なら0が返るはず" {
            Conjunction 1 0 | Should Be 0
        }
        It "0 1なら0が返るはず" {
            Conjunction 0 1 | Should Be 0
        }
        It "0 0なら0が返るはず" {
            Conjunction 0 0 | Should Be 0
        }
    }
}
```

* ユニットテスト結果

期待値どおりの結果が得られた。

```PowerShell:Pestertest.log(任意)
Describing Conjunctionの動作確認
   Context 正常系の確認
    [+] 1 1なら1が返るはず 56ms
    [+] 1 0なら0が返るはず 10ms
    [+] 0 1なら0が返るはず 14ms
    [+] 0 0なら0が返るはず 10ms
```

## 所感
### 論理ゲート
* 処理をコードに落とし込んでみると、どういう動きなのかがよく分かるなと実感。
* 書いてみると、非常にシンプルな処理で構成されていることが分かった。
* そのためか、コードもシンプルで再利用可能なものになったかと思う。
* (CPUには無い機構だと思うけど)論理ゲートに入る前にバリデーションを行うイメージで、処理を実装した。異常値になる0と1以外の値をはじく想定にしたため各論理ゲートのテストケースを削減できた。本来のあるべき論的にはどうなのかな、というのは気になるところではあるものの、今回のケースにおいては悪い施策ではなかったと思慮。

### Pester
* PowerShellのV5.1に搭載されているので、楽して導入に進めた。
* Pesterのひな型を作るまでは上掲のURL通りだったのだけど、もともとのソースファイルからテスト用製品ファイルのPesterTest1.ps1にコピぺしてテストを進めた。これは正しいやり方だったのか疑問。コードが2重になったし無駄な操作だったと思う。
* テストコードの実装は非常に楽だった。Visual Studio Codeありがとうという感じ。

## 本件で作成したソースコード(GitHub)
[LogicGates_by_PowerShell]
(https://github.com/Massas/LogicGates_by_PowerShell)

---