paiza 抹殺世界C問題「機械の総合病院 」をテストコード


# 抹殺世界
https://paiza.jp/botchi/

# 問題文要約
>PAIZA病院の、パスワードの条件として三つ決められた
・長さが 6 以上 
・英字と数字の両方を含む必要がある。文字列は半角英字あるいは半角数字で構成された文字列である。
・同じ文字を 3 つ以上連続で使用することはできない。なお、英字の大文字と小文字は区別する必要はない。

与えられたパスワードは正しいかどうかを調べたい


## 大枠
テストコード

```spec/paiza_lebel_C_spec.rb
require 'spec_helper'

RSpec.describe Lebel_C do
    it "文字列の長さが6以上" do
      result = Lebel_C.new.pass_check1(word: "DjZGrduN8Mj4") 
      expect(result).to eq true 
    
      false_pass = Lebel_C.new(word: "aaaaa")
      expect(false_pass.pass_check1).to eq false
    end
end
```
テストされるコード

```lib/paiza_lebel_C.rb
class Lebel_C
    def pass_check1(word:)
      # 中身
    end
end
```

# メソッドの中身
## 条件１：長さが6以上 
```lib/paiza_lebel_C.rb
class Lebel_C
    def pass_check1(word:)
        word.size >= 6
    end
end
```

```
$ bundle exec rspec
1 example, 0 failures
```
条件1クリア

## 条件２：　文字列は英字と数字の両方を含む
文字列として渡されるがその中に0~9の数値の形がある。それらと、英字があるかどうかを判定したい。数値の形をしているかを調べたいだけで、integerクラスである必要はないので文字列ママの比較

```lib/paiza_lebel_C.rb

    def pass_check1(word:)
        word.size >= 6
    end

    def pass_check2(word:)
        pass = word.split("")    //文字列にeach使えないので分割して配列にする
        int = false                  //　0~9の数字があるか判定させる
        str = false                  //a~zの英字があるかを判定させる
        pass.each do |p|
            if %W(1 2 3 4 5 6 7 8 9 0).include?(p)
              int = true
            else
              str = true
            end
        end
        if int == true && str == true
            true
        else
            false
        end
    end
```

テストコード

```spec/paiza_lebel_C_spec.rb
require 'spec_helper'

RSpec.describe Lebel_C do
    it "文字列の長さが6以上か？" do
      result = Lebel_C.new.pass_check1(word: "DjZGrduN8Mj4") 
      expect(result).to eq true  

      false_pass = Lebel_C.new(word: "aaaaa")
      expect(false_pass.pass_check1).to eq false
    end

    it "文字列に数字と英字が含まれているか？" do
        false_pass = Lebel_C.new(word: "abcdefg")
        expect(false_pass.pass_check2).to eq false

        false_pass = Lebel_C.new(word: "12456789")
        expect(false_pass.pass_check2).to eq false

        expect(password.pass_check2).to eq true
    end
end
```
```
$ bundle exec rspec
2 example, 0 failures
```
条件２もクリア

##  条件３：　大文字小文字の区別なく、同じ文字を3回連続で使用することはできない
```lib/paiza_lebel_C.rb
    def pass_check1(password:)
        password.size >= 6
    end

    def pass_check2(word:)
        pass = word.split("")    
        int = false                 
        str = false                  
        pass.each do |p|
            if %W(1 2 3 4 5 6 7 8 9 0).include?(p)
              int = true
            else
              str = true
            end
        end
        if int == true && str == true
            true
        else
            false
        end
    end

    def pass_check3(word:)
        pass = word.split("")
        the_same = 0             //同じ文字が続いた回数を数える
        before_word = ""         //一つ前の文字を入れて比較させる
        pass.each do |p|
            if before_word == p
                the_same += 1
            elsif before_word.casecmp(p) == 0 //同じなら0が帰ってくる
                the_same += 1
            else
                the_same = 0
            end
            before_word = p
            break if the_same == 2           //同じ文字が三回続いたらeachを抜ける
        end
        the_same < 2
     end
```
リファレンスcasecmp (String)
https://ref.xaio.jp/ruby/classes/string/casecmp

テストコード

```spec/paiza_lebel_C_spec.rb
require 'spec_helper'

RSpec.describe Lebel_C do
    it "文字列の長さが6以上か？" do
      result = Lebel_C.new.pass_check1(word: "DjZGrduN8Mj4") 
      expect(result).to eq true  

      false_pass = Lebel_C.new(word: "aaaaa")
      expect(false_pass.pass_check1).to eq false
    end

    it "文字列に数字と英字が含まれているか？" do
        false_pass = Lebel_C.new(word: "abcdefg")
        expect(false_pass.pass_check2).to eq false

        false_pass = Lebel_C.new(word: "12456789")
        expect(false_pass.pass_check2).to eq false

        expect(password.pass_check2).to eq true
    end

    it "三回同じ文字が続いていないか？" do
        false_pass = Lebel_C.new(word: "aAaAa")
        expect(false_pass.pass_check3).to eq false

        false_pass = Lebel_C.new(word: "a11111a")
        expect(false_pass.pass_check3).to eq false

        expect(password.pass_check3).to eq true
    end
end
```

```
$ bundle exec rspec
3 example, 0 failures
```
終了

## リファクタリング
最終コード(見やすくなったか？)

```lib/paiza_lebel_C.rb
class Lebel_C

    def initialize(word:)
      @password = word
    end
    
    def pass_check1
        @password.size >= 6
    end

    def pass_check2
        pass = @password.split("")
        int = false
        str = false
        pass.each do |p|
            if %W(1 2 3 4 5 6 7 8 9 0).include?(p)
              int = true
            else
              str = true
            end
        end
        if int == true && str == true
            true
        else
            false
        end
    end

    def pass_check3
        pass = @password.split("")
        the_same = 0
        before_word = ""
        pass.each do |p|
            if before_word.casecmp(p) == 0
                the_same += 1
            elsif before_word == p
                the_same += 1
            else
                the_same = 0
            end
            before_word = p
            break if the_same == 2
        end
        the_same < 2
    end
end
```

```spec/paiza_lebel_C_spec.rb
require 'spec_helper'

RSpec.describe Lebel_C do
  let(:password) { Lebel_C.new(word: "DjZGrduN8Mj4") }

  describe '文字列の長さ' do
    it "6以上" do
        expect(password.pass_check1).to eq true
    end

    it "6以下" do
        false_pass = Lebel_C.new(word: "abc")
        expect(false_pass.pass_check1).to eq false
    end
  end

  describe '文字列に数字と英字の両方が含まれているか？' do
    it "含まれている" do
        expect(password.pass_check2).to eq true
    end

    it "含まれていない" do
        false_pass = Lebel_C.new(word: "abcdefg")
        expect(false_pass.pass_check2).to eq false

        false_pass = Lebel_C.new(word: "12456789")
        expect(false_pass.pass_check2).to eq false
    end
  end

  describe '同じ文字が3回続いている？' do
    it "続いている" do
        false_pass = Lebel_C.new(word: "aAaAa")
        expect(false_pass.pass_check3).to eq false

        false_pass = Lebel_C.new(word: "a11111a")
        expect(false_pass.pass_check3).to eq false
    end

    it "続いていない" do
        expect(password.pass_check3).to eq true
    end
  end
end
```

コードの書き方は、「今はこれが精一杯」ということですが、何か間違いあればご指摘ください

見てくれてありがとう！