派遣事務員の迷走

派遣事務員コロ子。会社の犬。顔出しNG。常に迷走している。

FizzBuzzで覚えるVBA(いろんなFizzBuzzを紹介するよ)

こんにちは。
派犬事務員のコロです。

FizzBuzzにハマるウサ子

2回目の講座の宿題FizzBuzzにウサ子がドハマりして、毎日のようにいろんなFizzBuzzが送り付けられてきたので、変なの優秀なのを紹介します~。

FizzBuzzとはプログラミングの練習問題のこれ↓

数字を1から順に100までデバッグ出力します。
ただし
・数字が3の倍数のときには数字の代わりに「Fizz
・数字が5の倍数のときには数字の代わりに「Buzz」
・数字が3の倍数かつ5の倍数のときには代わりに「FizzBuzz
と出力するようにしてください。

多分全部で20~30個あったと思う。
新しい構文が出てくるたびにFizzBuzzが送られてきて、ウサ子曰く「FizzBuzzVBAを覚えた」らしい。
VBAを勉強してるけど「なかなか使うところがない」という人はいろんなFizzBuzzを考えてみよう。

毎日のように送られてきたFizzBuzz


回答1(足し算バージョン)
習得できると思われるスキル
①ループ
②If文
へんてこレベル:★

Sub FizzBuzz1()

    Dim x As Long: x = 3
    Dim y As Long: y = 5
    Dim z As Long: z = x * y
    
    Dim i As Long
    For i = 1 To 100
    
        If i = z Then
            Debug.Print "FizzBuzz"
            x = x + 3
            y = y + 5
            z = z + 15
        ElseIf i = y Then
            Debug.Print "Buzz"
            y = y + 5
        ElseIf i = x Then
            Debug.Print "Fizz"
            x = x + 3
        Else
            Debug.Print i
        End If
        
    Next i

End Sub

おお!Modを使わないタイプ!
全部足し算で考える。


回答2(ブール比較バージョン)
習得できると思われるスキル
①If文(Trueのとき処理を行う)
へんてこレベル:★

Sub FizzBuzz2()

    Dim x As Boolean
    Dim y As Boolean
    Dim z As Boolean
    Dim i As Long
    For i = 1 To 100
        x = i Mod 3 = 0
        y = i Mod 5 = 0
        z = i Mod 15 = 0
        If z = True Then
            Debug.Print "FizzBuzz"
        ElseIf y = True Then
            Debug.Print "Buzz"
        ElseIf x = True Then
            Debug.Print "Fizz"
        Else
            Debug.Print i
        End If
    Next i

End Sub

「IF 式 Then」の式がTrueのとき処理を行う、とういうのを理解していて良い。
「 If z = True Then」は、zはTrueなので「 If z Then」と書くのがスマートかも。


回答3(周期バージョン)
習得できると思われるスキル
①Select Case文
Select Case文の優れているところは、Orで繋ぐ条件式が複数の場合はカンマ「,」で繋げて書けるトコ。
へんてこレベル:★

Sub FizzBuzz3()

    Dim i As Long
    Dim cnt As Long
    Dim loopcnt As Long
    
    For i = 1 To 100
    
        cnt = cnt + 1
        
        Select Case cnt
        Case 3, 6, 9, 12
            Debug.Print "Fizz"
        Case 5, 10
            Debug.Print "Buzz"
        Case 15
            Debug.Print "FizzBuzz"
            cnt = 0
            loopcnt = loopcnt + 1
        Case Else
            Debug.Print cnt + 15 * loopcnt
        End Select
    
    Next i
    
End Sub

考え方は、15で一周期。

回答4(掛け算バージョン)
習得できると思われるスキル
①四則演算?
へんてこレベル:★★

Sub FizzBuzz4()

    Dim x As Long, y As Long, z As Long
    x = 3
    y = 5
    z = x * y
    
    Dim ch1 As Long, ch2 As Long, ch3 As Long
    ch1 = 1
    ch2 = 1
    ch3 = 1
    
    Dim i As Long
    For i = 1 To 100
        If i = z * ch1 Then
            Debug.Print "FizzBuzz"
            ch1 = ch1 + 1
            ch2 = ch2 + 1
            ch3 = ch3 + 1
        ElseIf i = y * ch2 Then
            Debug.Print "Buzz"
            ch2 = ch2 + 1
        ElseIf i = x * ch3 Then
            Debug.Print "Fizz"
            ch3 = ch3 + 1
        Else
            Debug.Print i
        End If
    Next i
    
End Sub

掛ける数を増やすのか。なるほど。


回答5(文字列バージョン)
習得できると思われるスキル
①型の変換
へんてこレベル:★★★★★★★★★★
数値を文字列にして判定する。

Sub FizzBuzz5()

    Dim i As Long
    Dim stri As String
    
    For i = 1 To 100
    
        'iを15で割った数値を文字列に変換する
        stri = Cstr(Round((i / 15), 10))

        If Len(stri) = 1 Then
            Debug.Print "FizzBuzz"
        ElseIf Len(stri) = 3 Then
            Debug.Print "Fizz"
        Else
            If Mid(stri, 3, 1) = Mid(stri, 4, 1) Then
                Debug.Print "Buzz"
            Else
                Debug.Print i
            End If
        End If

    Next i
End Sub

え?っと思った人。これを見て欲しい。

A列の値を15で割ると、なんか法則があるっぽい。

A列の値が3の倍数のとき:「0.2」「0.4」など文字列にすると3文字(点も1文字になる)
A列の値が5の倍数のとき:「0.333・・」「0.666・・・」など、3文字目と4文字目が同じ値
A列の値が15の倍数のとき:「1」「2」「3」など1文字

おお!!これはなかなか思いつかない!
ちなみに
i=1のとき
stri = Cstr(i / 15)
だと「6.66666666666667E-02」となってしまうので
stri = Cstr(Round((i / 15), 10 ) )と少数以下を10桁にして指数表示にならないように工夫したらしい。
でも、なんで1/15のときだけ指数表示になるんだろう?


回答6(イベントプロシージャもどきバージョン)
習得できると思われるスキル
①Functionプロシージャ
へんてこレベル:★★★★★★★★★
「Functionプロシージャはワークシート関数としても使えますよ。」とは言ったけど、こんなのを作るとは!


「はい、入れました」


「イミディエイトウインドウを見るのね?」

えっ!!イベントプロシージャ?
と思ったらFunction関数!

Function StartFizzBuzz(ByVal x As String) As String

    If x <> "" Then
        Call FizzBuzz
        StartFizzBuzz = "イミディエイトウィンドウを見てね"
    Else
        StartFizzBuzz = "A1セルに何か入れて"
    End If

End Function

'************************************************************
Sub FizzBuzz()

    Dim i As Long
    
    For i = 1 To 100
    
        If i Mod 15 = 0 Then
            Debug.Print "FizzBuzz"
        ElseIf i Mod 5 = 0 Then
            Debug.Print "Buzz" 
        ElseIf i Mod 3 = 0 Then
            Debug.Print "Fizz"
        Else
            Debug.Print i
        End If
        
    Next i

End Sub

B1セルに自作のFuction関数を入れて、引数をA1セルにする。

A1セルに値が入ってる場合はイミディエイトウインドウにFizzBuzzを出力する、という仕組み。
なんか簡易イベントプロシージャって感じ。すごい!
めちゃめちゃびっくり!



回答8(足し算しばりバージョン)
へんてこレベル:★★★★

Sub FizzBuzz8()

    Dim i As Long
    Dim num1 As Long
    Dim num2 As Long
    Dim num3 As Long
    Dim num4 As Long
    num1 = 3
    num2 = num1 + 3
    num3 = num2 + 3
    num4 = num3 + 3
    Dim num5 As Long
    Dim num6 As Long
    Dim num7 As Long
    num5 = 5
    num6 = num5 + 5
    num7 = num6 + 5
    Dim x As Long
    x = 15
    
    For i = 1 To 100
    
        If i = num7 Then
            Debug.Print "FixxBuzz"
            num7 = num7 + x
        ElseIf i = num6 Then
            Debug.Print "Buzz"
            num6 = num6 + x
        ElseIf i = num5 Then
            Debug.Print "Buzz"
            num5 = num5 + x
        ElseIf i = num4 Then
            Debug.Print "Fizz"
            num4 = num4 + x
        ElseIf i = num3 Then
            Debug.Print "Fizz"
            num3 = num3 + 1
        ElseIf i = num2 Then
            Debug.Print "Fizz"
            num2 = num2 + x
        ElseIf i = num1 Then
            Debug.Print "Fizz"
            num1 = num1 + x
        Else
            Debug.Print i
        End If
        
    Next i

End Sub


回答9(引き算しばりバージョン)
へんてこレベル:★★★★

Sub FizzBuzz9()

    Dim i As Long
    Dim x As Long
    Dim y As Long
    Dim z As Long
    Dim th As Long
    Dim fi As Long
    Dim ft As Long
    th = 3
    fi = 5
    ft = 15
    Dim nt As Long
    Dim tt As Long
    Dim nn As Long
    For i = 1 To 100
        If i - ft - x = 0 Then
            Debug.Print "FizzBuzz"
            nt = 90
            x = NewFizzBuzz(x, i, ft, nt)
            y = x
            z = x
        ElseIf i - 5 - y = 0 Then
            Debug.Print "Buzz"
            tt = 100
            y = NewFizzBuzz(y, i, fi, tt)
        ElseIf i - 3 - z = 0 Then
            Debug.Print "Fizz"
            nn = 99
            z = NewFizzBuzz(z, i, th, nn)
        Else
            Debug.Print i
        End If
    Next i

End Sub

'***************************************************************************************************

Function NewFizzBuzz(ByVal x As Long, ByVal i As Long, ByVal mn As Long, ByVal cn As Long) As Long

    Dim cnt1 As Long
    cnt1 = 100
    Dim j As Long
    Dim l As Long
    Dim m As Long
    m = i
    If x = 0 Then
        For j = 1 To 100
            cnt1 = cnt1 - mn
            If cnt1 < mn Then
                Exit For
            End If
        Next j
        j = j - 1
    Else
        For l = 1 To 100
            m = m - mn
            If m = 0 Then
                Exit For
            End If
        Next l
        For j = 1 To 100
            cnt1 = cnt1 - mn
            If cnt1 < mn Then
                Exit For
            End If
        Next j
        j = j - l
    End If
    Dim k As Long
    For k = 1 To j
        cn = cn - mn
    Next k
    x = cn
    NewFizzBuzz = x
    
End Function


回答10(中級バージョン)
習得できると思われるスキル
①ループでのカウンタ変数の指定数の増減
②配列

Sub FizzBuzz10()

    Dim arr(0 To 100) As String
    
    '配列に代入
    Dim i As Long
    
    For i = 0 To 100 Step 3
        arr(i) = "Fizz"
    Next i
    
    For i = 0 To 100 Step 5
        If arr(i) = "" Then
            arr(i) = "Buzz"
        Else
            arr(i) = "FizzBuzz"
        End If
    Next i
    
    'イミディエイトウインドウに出力
    For i = 1 To 100
        If arr(i) = "" Then
            Debug.Print i
        Else
            Debug.Print arr(i)
        End If
    Next i

End Sub


回答11(意味不明バージョン)

Sub FizzBuzz11()

    Dim i As Long
    Dim j As Long
    Dim k As Long
    Dim l As Long
    k = 1
    
    For i = 1 To 100
        For j = 1 To 5
            If j = 1 Then
                For l = 1 To 3
                    If i Mod 3 = 0 Then
                        Debug.Print "Fizz"
                        i = i + 1
                    Else
                        Debug.Print i
                        i = i + 1
                    End If
                Next l
            ElseIf j = 2 Then
                For l = 1 To 3
                    If i Mod 3 = 0 Then
                        Debug.Print "Fizz"
                        i = i + 1
                    ElseIf i Mod 3 = 2 Then
                        Debug.Print "Buzz"
                        i = i + 1
                    Else
                        Debug.Print i
                        i = i + 1
                    End If
                Next l
            ElseIf j = 3 Then
                For l = 1 To 3
                    If i Mod 3 = 0 Then
                        Debug.Print "Fizz"
                        i = i + 1
                    Else
                        Debug.Print i
                        i = i + 1
                    End If
                Next l
            ElseIf j = 4 Then
                For l = 1 To 3
                    If i = 101 Then
                        Exit Sub
                    Else
                        If i Mod 3 = 0 Then
                            Debug.Print "Fizz"
                            i = i + 1
                        ElseIf i Mod 3 = 1 Then
                            Debug.Print "Buzz"
                            i = i + 1
                        Else
                            Debug.Print i
                            i = i + 1
                        End If
                    End If
                Next l
            ElseIf j = 5 Then
                For l = 1 To 3
                    If i Mod 3 = 0 Then
                        Debug.Print "FizzBuzz"
                    Else
                        Debug.Print i
                        i = i + 1
                    End If
                Next l
            End If
        Next j
        j = 1
    Next i

End Sub

他にも意味不明なのが多数。
確かにFizzBuzz楽しいけど、こんなにハマる人初めて見た・・・。

みんなの凄いFizzBuzzがあったら教えてね。