Оглавление > Считаем воскресенья (F#)
15.03.2023

Считаем воскресенья (F#)

Дана следующая информация (однако, вы можете проверить ее самостоятельно):

1 января 1900 года - понедельник.
В апреле, июне, сентябре и ноябре 30 дней.
В феврале 28 дней, в високосный год - 29.
В остальных месяцах по 31 дню.
Високосный год - любой год, делящийся нацело на 4, однако последний год века (ХХ00) является високосным в том и только том случае, если делится на 400.
Сколько воскресений выпадает на первое число месяца в двадцатом веке (с 1 января 1901 года до 31 декабря 2000 года)?

Решение

  1. Из условия нам известно, что 1.1.1900 это понедельник, примем его за точку отсчета (день 0)
  2. Первое число января 1901 это день 365
  3. Первое число февраля - день 396
  4. и так далее вычислим все первые числа месяца как смещение от дня 0, делая поправки на високосные года
  5. вычислим день недели для каждого дня как остаток от деления на 7, тогда 0 = понедельник, 1 = вторник, ... , 6 = воскресенье
  6. найдем количество каждого из дней недели
  7. выведем количество воскресений в качестве ответа
let days_in_month year =
    [ 31
      (if year % 4 = 0 then 29 else 28)
      31
      30
      31
      30
      31
      31
      30
      31
      30
      31 ]

let solv =
    [ 1901..2000 ]
    |> List.collect days_in_month
    |> List.scan (+) 365
    |> List.take 1200
    |> List.countBy (fun d -> d % 7)
    |> Map.ofList

let answer = solv[6]

printfn $"the answer is {answer}" //the answer is 171
  • days_in_month - количество дней в месяцах года
  • solv:
    1. собираем все длины месяцев в массив (List.collect)
    2. вычисляем нарастающий итог начиная с 365 (List.scan)
    3. отбрасываем послений элемент, т.к. scan вернет один лишний элемент (1.1.2001)
    4. подсчитываем количество, используя остаток от деления в качестве ключа
    5. преобразуем в Map для возможности обращения по ключу
  • кому интересно, solv =
    map [(0, 172); (1, 171); (2, 173); (3, 169); (4, 173); (5, 171); (6, 171)]
    
    реже всего 1-е число месяца выпадало на четверг - 169 раз, а чаще всего - на среду и пятницу - по 173 раза