CodeIQ:秘伝のタレ

私自身が表題の問題を解いた時のプログラムについて解説します。
問題の詳細は「秘伝のタレ」(CodeIQ)を参照してください。

問題の概要

問題を引用します。
株式会社スパゲッティシステムでは、システムの保守性の低さが常々問題になっていました。
システムの複雑度を判定するプログラムを開発することになりました。

仕様
・システム開発開始時の循環的複雑度は0です
・毎月、固定値の循環的複雑度が一回加算されます
・循環的複雑度加算後の合計が任意のしきい値を超えた時点でリファクタリングを一回行います。任意の循環的複雑度が減算されます
・各月において、リファクタリング後に循環的複雑度が75より大きい場合は、その月でシステムの開発は打ち切りとし、 "good bye" を出力します
・循環的複雑度が75以下で最終月を終えた場合は最終月を終えたときの循環的複雑度の合計を出力します
・最終月の循環的複雑度の合計が0より小さくなった場合は合計を0とします
(各月ではマイナスのまま計算する)
標準入力
・以下のフォーマットで一行入力されます

1度に追加される循環的複雑度,リファクタリングによって1度に解消される循環的複雑度,システムの運用月数,リファクタリングを行う判断基準となる循環的複雑度
※各数値は正の整数で、 0-50 の間で与えられます

例:
10,7,18,30
標準出力
・循環的複雑度が75より大きくなった場合は "good bye" という文字列を出力して処理を終了してください
 (ダブルクォートは含みません)
・循環的複雑度が75以下で最終月を終えた場合は最終月を終えたときの循環的複雑度を出力してください

例(入力の例に対する出力の例)

75
※各月の内訳
1ヶ月目 追加分 10 リファクタリング分 0 合計 10
2ヶ月目 追加分 10 リファクタリング分 0 合計 20
3ヶ月目 追加分 10 リファクタリング分 0 合計 30
4ヶ月目 追加分 10 リファクタリング分 7 合計 33
5ヶ月目 追加分 10 リファクタリング分 7 合計 36
6ヶ月目 追加分 10 リファクタリング分 7 合計 39
7ヶ月目 追加分 10 リファクタリング分 7 合計 42
8ヶ月目 追加分 10 リファクタリング分 7 合計 45
9ヶ月目 追加分 10 リファクタリング分 7 合計 48
10ヶ月目 追加分 10 リファクタリング分 7 合計 51
11ヶ月目 追加分 10 リファクタリング分 7 合計 54
12ヶ月目 追加分 10 リファクタリング分 7 合計 57
13ヶ月目 追加分 10 リファクタリング分 7 合計 60
14ヶ月目 追加分 10 リファクタリング分 7 合計 63
15ヶ月目 追加分 10 リファクタリング分 7 合計 66
16ヶ月目 追加分 10 リファクタリング分 7 合計 69
17ヶ月目 追加分 10 リファクタリング分 7 合計 72
18ヶ月目 追加分 10 リファクタリング分 7 合計 75

その他の仕様
・標準入力の末尾には改行があります
・標準出力の末尾に改行をつけてください
・標準入力の仕様で説明した内容以外の入力は行われません(不正入力に対するチェックは不要)

Samples
各月内訳の部分は説明のためのもので、実際に実装するときは該当内容を出力する必要はありません

Sample1
Input
10,7,18,30

75

各月内訳
1ヶ月目 追加分 10 リファクタリング分 0 合計 10
2ヶ月目 追加分 10 リファクタリング分 0 合計 20
3ヶ月目 追加分 10 リファクタリング分 0 合計 30
4ヶ月目 追加分 10 リファクタリング分 7 合計 33
5ヶ月目 追加分 10 リファクタリング分 7 合計 36
6ヶ月目 追加分 10 リファクタリング分 7 合計 39
7ヶ月目 追加分 10 リファクタリング分 7 合計 42
8ヶ月目 追加分 10 リファクタリング分 7 合計 45
9ヶ月目 追加分 10 リファクタリング分 7 合計 48
10ヶ月目 追加分 10 リファクタリング分 7 合計 51
11ヶ月目 追加分 10 リファクタリング分 7 合計 54
12ヶ月目 追加分 10 リファクタリング分 7 合計 57
13ヶ月目 追加分 10 リファクタリング分 7 合計 60
14ヶ月目 追加分 10 リファクタリング分 7 合計 63
15ヶ月目 追加分 10 リファクタリング分 7 合計 66
16ヶ月目 追加分 10 リファクタリング分 7 合計 69
17ヶ月目 追加分 10 リファクタリング分 7 合計 72
18ヶ月目 追加分 10 リファクタリング分 7 合計 75

Sample2
Input
10,7,19,30

good bye

各月内訳
1ヶ月目 追加分 10 リファクタリング分 0 合計 10
2ヶ月目 追加分 10 リファクタリング分 0 合計 20
3ヶ月目 追加分 10 リファクタリング分 0 合計 30
4ヶ月目 追加分 10 リファクタリング分 7 合計 33
5ヶ月目 追加分 10 リファクタリング分 7 合計 36
6ヶ月目 追加分 10 リファクタリング分 7 合計 39
7ヶ月目 追加分 10 リファクタリング分 7 合計 42
8ヶ月目 追加分 10 リファクタリング分 7 合計 45
9ヶ月目 追加分 10 リファクタリング分 7 合計 48
10ヶ月目 追加分 10 リファクタリング分 7 合計 51
11ヶ月目 追加分 10 リファクタリング分 7 合計 54
12ヶ月目 追加分 10 リファクタリング分 7 合計 57
13ヶ月目 追加分 10 リファクタリング分 7 合計 60
14ヶ月目 追加分 10 リファクタリング分 7 合計 63
15ヶ月目 追加分 10 リファクタリング分 7 合計 66
16ヶ月目 追加分 10 リファクタリング分 7 合計 69
17ヶ月目 追加分 10 リファクタリング分 7 合計 72
18ヶ月目 追加分 10 リファクタリング分 7 合計 75
19ヶ月目 追加分 10 リファクタリング分 7 合計 78

Sample3
Input
50,5,10,30

good bye

各月内訳
1ヶ月目 追加分 50 リファクタリング分 5 合計 45
2ヶ月目 追加分 50 リファクタリング分 5 合計 90

Sample4
Input
5,50,7,10

0

1ヶ月目 追加分 5 リファクタリング分 0 合計 5
2ヶ月目 追加分 5 リファクタリング分 0 合計 10
3ヶ月目 追加分 5 リファクタリング分 50 合計 -35
4ヶ月目 追加分 5 リファクタリング分 0 合計 -30
5ヶ月目 追加分 5 リファクタリング分 0 合計 -25
6ヶ月目 追加分 5 リファクタリング分 0 合計 -20
7ヶ月目 追加分 5 リファクタリング分 0 合計 -15

私のプログラム

Rubyで解答しています。

#!/usr/bin/ruby

def solve(cmp, ref, mon, th)
	c = 0
	for _ in 0...mon
		c += cmp

		c -= ref if c > th

		return "good bye" if c > 75
	end

	ret = (c >= 0 ? c : 0)
	return ret.to_s
end

# main
while line = gets
	line.strip!
	next if line.empty?

	c, r, m, t = line.split(",").map{|a| a.to_i}
	puts solve(c, r, m, t)
end

解説

どうこういうことはなく、素直にやれば問題ありません。

main

入力値を数値にしてsolve()に渡します。

solve(cmp, ref, mon, th)

引数cmpは循環的複雑度、refはリファクタリングによって減少する循環的複雑度、monはシステムの運用月数、thはリファクタリングを行う判断基準となる循環的複雑度です。
cは循環的複雑度の合計値です。
mon回数ループし、まずcmpをcに加算します。
もし、それがthを超えたらrefだけcから引きます。
その結果が75を超えていたら"good by"を返却します。
ループが最後まで行って終わった場合、cが0未満なら0に切り上げ、そうでなければそのままを文字列にして返却します。

雑感

この出題者の問題は息抜きにちょうど良いです。