2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[メモ]数値を1から順番に、ただしある数値で割り切れる時のみ特定の文字列を出力するプログラム(Kotlin)

Last updated at Posted at 2020-02-14

※2020/2/17 追記しました

以下のような課題に触れる機会があったので、備忘録として解決方法を残しておきます。

課題: 
指定した数値まで1から順番に出力するプログラムを以下の条件を守った上で作成せよ。

① 3で割り切れる数字の時は文字列「A」を出力せよ
② 5で割り切れる数字の時は文字列「B」を出力せよ
③ 3と5で割り切れる数字の時は文字列「AB」を出力せよ

咄嗟に作成したプログラム


fun outNum(maxNum: Int) {
    var result = ""
    for(i in 1..maxNum) {
        if(i % 3 == 0 && i % 5 != 0) {
            result += "A\n"
        } else if(i % 5 == 0 && i % 3 != 0) {
            result += "B\n"
        } else if(i % 3 == 0 && i % 5 == 0) {
            result += "AB\n"
        } else {
            result += i
        }
    }
    println(result)
}

う〜ん、これはひどい!

我ながらひどい。
このままでは

「7で割り切れる時と11で割り切れる時も別の文字列を出力するよう改修せよ」

とか言われた時に目も当てられないif文になってしまいます。

それを踏まえた上で冷静に作成し直したプログラム


fun outNum(maxNum: Int) {
    var result = ""
    for(i in 1..maxNum) {
        if(getDisivleNumber(i).isEmpty()) {
            result += i
        } else {
            getDisivleNumber(i).forEach { disivle ->
               result += when(disivle) {
                    3 -> "A"
                    5 -> "B"
                    else -> ""
                }
            }
        }
        result += "\n"
    }
    
    println(result)
}

/**
* 指定した数値の約数をリスト化して返す
*/
fun getDisivleNumber(num: Int): MutableList<Int> {    
    val list = listOf(3,5)
    val arrays:MutableList<Int> = mutableListOf()
    list.forEach { i ->
        if(num % i == 0) {
            arrays.add(i)
        }
    }
    return arrays
}

こんな感じです。
これなら後々文字列出力する約数が追加された時でも楽に対応できます。

2020/2/17 追記

頂いたコメントから、上記のコードではまだ問題があることがわかりました。

例:約数をgetDisivleNumber関数とoutNum関数の中でそれぞれ指定しているので、追加や修正があった場合、両方を修正しないとエラーになる 等

ほとんど頂いたコメントのソースコードの転載になりますが、問題を修正したプログラムを以下に記載いたします。


fun main(args: Array<String>) {
    printlnDivisorNum(100)
}

fun printlnDivisorNum(maxCount: Int) {
    val divisorList = listOf(
        3 to "A",
        5 to "B",
        7 to "C",
        11 to "D"
    )
    // 拡張関数を使い文字列を生成し、順番に出力する
    for(num in 1..maxCount) {
        println(num.toDivisorText(divisorList))
    }
}

/**
* Intの拡張関数
* 引数の数値リストに自身を割り切れる数値が含まれている場合は
* それに対応する文字列を、(※複数含まれる場合は文字列を連結する)
* 含まれない場合は自身を文字列として返す
*/
fun Int.toDivisorText(divisorList: List<Pair<Int, String>>): String = 
    buildString {
        divisorList.forEach { (num, text) ->
            if(this@toDivisorText % num == 0) {
                append(text)
            }
        }
    }.takeIf { it.isNotEmpty() }
        ?: toString()

※約数に7と11を追加しています

上記コードの出力例

1
2
A
4
B
A
C
8
A
B
D
A
13
C
AB
16
17
A
19
B
AC
D
23
A
B
26
A
C
29
AB
31
32
AD
34
BC
A
37
38
A
B
41
AC
43
D
AB
46
47
A
C
B
A
52
53
A
BD
C
A
58
59
AB
61
62
AC
64
B
AD
67
68
A
BC
71
A
73
74
AB
76
CD
A
79
B
A
82
83
AC
B
86
A
D
89
AB
C
92
A
94
B
A
97
C
AD
B

拡張関数やbuildString, takeIfの使い方などとても勉強になりました。
ありがとうございます。

2
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?