Menu
Coddy logo textTech

最長継続日数

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」を追跡するパターンは、多くの問題で繰り返し登場します。一度認識すれば、永遠に自分のものです。

challenge icon

チャレンジ

中級

入力を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' として出力
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

ロジックとフローのすべてのレッスン

自分で練習してみよう: Swiftプレイグラウンド