Rebol3 Code Examplex


Five weekends

Count months that contain five weekends.

Rebol [
    title: "Rosetta code: Five weekends"
    file:  %Five_weekends.r3
    url:   https://rosettacode.org/wiki/Five_weekends
    note:  "Based on Hinjo's Red version"
]

five-weekends: function/with [
    "Show all months that have five full weekends."
    start [integer!] "Start year"
    end   [integer!] "End year"
][
    boring-years: total-fw-months: awesome-years: 0
    for year start end 1 [
        fw-months: clear []
        ;; A month has five weekends when its first day is a Saturday (weekday 7)
        foreach month long-months [
            if 1 = get-day year month 1 6 [
                ++ total-fw-months
                append fw-months month-names/:month
            ]
        ]
        prin  ajoin [as-yellow year ": "]
        print switch count: length? fw-months [
            0 [
                ++ boring-years
                as-red "Boring year!"
            ]
            1 [
                ajoin ["1 month:  " fw-months]
            ]
            2 [
                ++ awesome-years
                ajoin [as-green count " months: " ajoin/with fw-months ", "]
            ]
        ]  
    ]
    print-horizontal-line
    print ["Total five-weekend months:               " total-fw-months]
    print ["Total years with no five-weekend months: " boring-years ]
    print ["Total years with 2+ five-weekend months: " awesome-years]
][
    ;; Return the day-of-month for the Nth weekday in a given month,
    ;; or NONE if that occurrence falls outside the month.
    get-day: function [
        year     [integer!]
        month    [integer!]
        week     [integer!]
        weekday  [integer!]
    ][
        date: to-date reduce [1 month year] ; first-of-month
        ;; Rebol weekday is Mon=1 .. Sun=7; shift to Sun=1 .. Sat=7
        weekday-1st: (date/weekday + 1) % 7
        ;; Days from the 1st to the target weekday in the requested week
        offset: (week - 1) * 7 + (weekday - weekday-1st)
        target-date: date + offset
        ;; Return the day number only if it still falls within the same month or none
        if target-date/month = month [target-date/day]
    ]
    month-names: system/locale/months
    ;; Months with 31 days are the only ones that can hold five full weekends
    long-months: [1 3 5 7 8 10 12]
]

five-weekends 1900 2100