最長継続日数
CoddyのSwiftジャーニー「ロジックとフロー」セクションの一部。レッスン 35/56。
streak とは、habit が完了とマークされた連続する days のまとまりです。[1, 2, 3, 5, 6] の場合、最長の streak は 3(days 1-3)です。
sorted day リストがあれば、これを一度計算するのは単純な linear scan です。それぞれの day を直前のものと比較し、連続していれば現在の run を延長し、そうでなければリセットします。
func longestStreak(_ days: [Int]) -> Int {
let sorted = days.sorted()
var best = 0
var run = 0
var prev: Int? = nil
for d in sorted {
if let p = prev, d == p + 1 {
run += 1
} else {
run = 1
}
if run > best { best = run }
prev = d
}
return best
}「現在のrun + これまでのbest」を追跡するパターンは、多くの問題で繰り返し登場します。一度認識すれば、永遠に自分のものです。
チャレンジ
中級入力を1行読み込みます。habit:dayエントリをカンマで区切ったリストです。前のレッスンで作成したものと同じ辞書を構築し、各習慣について、1週間の中で最も長く連続した日数を計算します。
習慣をアルファベット順に、1行に1つずつ、次の形式で出力します。
<habit>: streak=<n>入力がread:1,read:2,read:3,read:5,workout:2,workout:4の場合、出力は次のようになります。
read: streak=3
workout: streak=1自分で試してみよう
var habits: [String: [Int]] = [:]
let ops = readLine()!.components(separatedBy: ",")
for op in ops {
let parts = op.components(separatedBy: ":")
let day = Int(parts[1])!
if !(habits[parts[0], default: []].contains(day)) {
habits[parts[0], default: []].append(day)
}
}
// TODO: 習慣ごとの最長ストリークを求め、名前でソートして 'name: streak=n' として出力
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
ロジックとフローのすべてのレッスン
自分で練習してみよう: Swiftプレイグラウンド