September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -1,44 +1,47 @@
-- TEST -----------------------------------------------------------------------
on run
fiveWeekends(1900, 2100)
end run
-- FIVE WEEKENDS --------------------------------------------------------------
-- fiveWeekends :: Int -> Int -> Record
on fiveWeekends(fromYear, toYear)
set lstYears to range(fromYear, toYear)
set lstYears to enumFromTo(fromYear, toYear)
-- yearMonthString :: (Int, Int) -> String
script yearMonthString
on lambda(lstYearMonth)
on |λ|(lstYearMonth)
((item 1 of lstYearMonth) as string) & " " & ¬
item (item 2 of lstYearMonth) of ¬
{"January", "", "March", "", "May", "", ¬
"July", "August", "", "October", "", "December"}
end lambda
end |λ|
end script
-- addLongMonthsOfYear :: [(Int, Int)] -> [(Int, Int)]
script addLongMonthsOfYear
on lambda(lstYearMonth, intYear)
on |λ|(lstYearMonth, intYear)
-- yearMonth :: Int -> (Int, Int)
script yearMonth
on lambda(intMonth)
return {intYear, intMonth}
end lambda
on |λ|(intMonth)
{intYear, intMonth}
end |λ|
end script
lstYearMonth & ¬
map(yearMonth, my longMonthsStartingFriday(intYear))
end lambda
end |λ|
end script
-- leanYear :: Int -> Bool
script leanYear
on lambda(intYear)
on |λ|(intYear)
0 = length of longMonthsStartingFriday(intYear)
end lambda
end |λ|
end script
set lstFullMonths to map(yearMonthString, ¬
@ -46,32 +49,26 @@ on fiveWeekends(fromYear, toYear)
set lstLeanYears to filter(leanYear, lstYears)
return {{|number|:length of lstFullMonths}, ¬
{{|number|:length of lstFullMonths}, ¬
{firstFive:(items 1 thru 5 of lstFullMonths)}, ¬
{lastFive:(items -5 thru -1 of lstFullMonths)}, ¬
{leanYearCount:length of lstLeanYears}, ¬
{leanYears:lstLeanYears}}
end fiveWeekends
-- longMonthsStartingFriday :: Int -> [Int]
on longMonthsStartingFriday(intYear)
-- startIsFriday :: Int -> Bool
script startIsFriday
on lambda(iMonth)
on |λ|(iMonth)
weekday of calendarDate(intYear, iMonth, 1) is Friday
end lambda
end |λ|
end script
filter(startIsFriday, [1, 3, 5, 7, 8, 10, 12])
end longMonthsStartingFriday
---------------------------------------------------------------------------
-- GENERIC FUNCTIONS
-- calendarDate :: Int -> Int -> Int -> Date
on calendarDate(intYear, intMonth, intDay)
tell (current date)
@ -81,6 +78,50 @@ on calendarDate(intYear, intMonth, intDay)
end tell
end calendarDate
-- GENERIC FUNCTIONS ----------------------------------------------------------
-- enumFromTo :: Enum a => a -> a -> [a]
on enumFromTo(m, n)
set {intM, intN} to {fromEnum(m), fromEnum(n)}
if intM > intN then
set d to -1
else
set d to 1
end if
set lst to {}
if class of m is text then
repeat with i from intM to intN by d
set end of lst to chr(i)
end repeat
else
repeat with i from intM to intN by d
set end of lst to i
end repeat
end if
return lst
end enumFromTo
-- fromEnum :: Enum a => a -> Int
on fromEnum(x)
set c to class of x
if c is boolean then
if x then
1
else
0
end if
else if c is text then
if x "" then
id of x
else
missing value
end if
else
x as integer
end if
end fromEnum
-- filter :: (a -> Bool) -> [a] -> [a]
on filter(f, xs)
tell mReturn(f)
@ -88,7 +129,7 @@ on filter(f, xs)
set lng to length of xs
repeat with i from 1 to lng
set v to item i of xs
if lambda(v, i, xs) then set end of lst to v
if |λ|(v, i, xs) then set end of lst to v
end repeat
return lst
end tell
@ -100,7 +141,7 @@ on foldl(f, startValue, xs)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to lambda(v, item i of xs, i, xs)
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
@ -112,25 +153,12 @@ on map(f, xs)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to lambda(item i of xs, i, xs)
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- range :: Int -> Int -> [Int]
on range(m, n)
if n < m then
set d to -1
else
set d to 1
end if
set lst to {}
repeat with i from m to n by d
set end of lst to i
end repeat
return lst
end range
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
@ -139,7 +167,7 @@ on mReturn(f)
f
else
script
property lambda : f
property |λ| : f
end script
end if
end mReturn

View file

@ -0,0 +1,38 @@
Public Sub Main()
Dim aMonth As Short[] = [1, 3, 5, 7, 8, 10, 12] 'All 31 day months
Dim aMMStore As New String[] 'To store results
Dim siYear, siMonth, siCount As Short 'Various variables
Dim dDay As Date 'To store the day to check
Dim sTemp As String 'Temp string
For siYear = 1900 To 2100 'Loop through each year
For siMonth = 0 To 6 'Loop through each 31 day month
dDay = Date(siYear, aMonth[siMonth], 1) 'Get the date of the 1st of the month
If WeekDay(dDay) = 5 Then aMMStore.Add(Format(dDay, "mmmm yyyy")) 'If the 1st is a Friday then store the result
Next
Next
For Each sTemp In aMMStore 'For each item in the stored array..
Inc siCount 'Increase siCount
If siCount < 6 Then Print aMMStore[siCount] 'If 1 of the 1st 5 dates then print it
If siCount = 6 Then Print String$(14, "-") 'Print a separator
If siCount > aMMStore.Max - 4 Then Print aMMStore[siCount - 1] 'If 1 of the last 5 dates then print it
Next
Print gb.NewLine & "Total months = " & Str(siCount) 'Print the number of months found
siCount = 0 'Reset siCount
sTemp = aMMStore.Join(",") 'Put all the stored dates in one string joined by commas
aMMStore.Clear 'Clear the store for reuse
For siYear = 1900 To 2100 'Loop through each year
If Not InStr(sTemp, Str(siYear)) Then 'If the year is not in the stored string then..
Inc siCount 'Increase siCount (Amount of years that don't have 5 weekend months)
aMMStore.Add(Str(siYear)) 'Add to the store
End If
Next
Print gb.NewLine & "There are " & Str(siCount) &
" years that do not have at least one five-weekend month" 'Print the amount of years with no 5 weekend months
Print aMMStore.Join(",") 'Print the years with no 5 weekend months
End

View file

@ -0,0 +1,47 @@
import Data.Time (Day, fromGregorian, gregorianMonthLength)
import Data.Time.Calendar.WeekDate (toWeekDate)
import Data.List.Split (chunksOf)
import Data.List (intercalate)
-- MONTHS WITH FIVE WEEKENDS --------------------------------------------------
fiveFridayMonths :: Integer -> [(Integer, Int)]
fiveFridayMonths y =
[1 .. 12] >>=
\m ->
[ (y, m)
| isFriday (fromGregorian y m 1)
, gregorianMonthLength y m == 31 ]
isFriday :: Day -> Bool
isFriday d =
let (_, _, day) = toWeekDate d
in day == 5
-- TEST -----------------------------------------------------------------------
main :: IO ()
main = do
let years = [1900 .. 2100]
xs = fiveFridayMonths <$> years
lean =
concat $
zipWith
(\months year ->
[ year
| null months ])
xs
years
n = (length . concat) xs
(putStrLn . intercalate "\n\n")
[ "How many five-weekend months 1900-2100 ?"
, '\t' : show n
, "First five ?"
, '\t' : show (concat (take 5 xs))
, "Last five ?"
, '\t' : show (concat (drop (n - 5) xs))
, "How many lean years ? (No five-weekend months)"
, '\t' : show (length lean)
, "Which years are lean ?"
, unlines (('\t' :) <$> fmap (unwords . fmap show) (chunksOf 5 lean))
]

View file

@ -1,7 +1,6 @@
(function () {
'use strict';
// longMonthsStartingFriday :: Int -> Int
function longMonthsStartingFriday(y) {
return [0, 2, 4, 6, 7, 9, 11]
@ -11,7 +10,6 @@
});
}
// range :: Int -> Int -> [Int]
function range(m, n) {
return Array.apply(null, Array(n - m + 1))
@ -53,5 +51,4 @@
},
null, 2
);
})();

View file

@ -0,0 +1,60 @@
(() => {
// longMonthsStartingFriday :: Int -> [Int]
const longMonthsStartingFriday = y =>
filter(m => (new Date(Date.UTC(y, m, 1)))
.getDay() === 5, [0, 2, 4, 6, 7, 9, 11]);
// Years -> YearMonths
// fullMonths :: [Int] -> [String]
const fullMonths = xs =>
foldl((a, y) => a.concat(
map(m => `${y.toString()} ${[
'January', '', 'March', '', 'May', '',
'July', 'August', '', 'October', '', 'December'
][m]}`, longMonthsStartingFriday(y))
), [], xs);
// leanYears :: [Int] -> [Int]
const leanYears = years =>
filter(y => longMonthsStartingFriday(y)
.length === 0, years);
// GENERIC ----------------------------------------------------------------
// A list of functions applied to a list of arguments
// <*> :: [(a -> b)] -> [a] -> [b]
const ap = (fs, xs) => //
[].concat.apply([], fs.map(f => //
[].concat.apply([], xs.map(x => [f(x)]))));
// enumFromTo :: Int -> Int -> [Int]
const enumFromTo = (m, n) =>
Array.from({
length: Math.floor(n - m) + 1
}, (_, i) => m + i);
// filter :: (a -> Bool) -> [a] -> [a]
const filter = (f, xs) => xs.filter(f);
// foldl :: (b -> a -> b) -> b -> [a] -> b
const foldl = (f, a, xs) => xs.reduce(f, a);
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f);
// show :: a -> String
const show = x => JSON.stringify(x, null, 2);
// TEST -------------------------------------------------------------------
const [lstFullMonths, lstLeanYears] = ap(
[fullMonths, leanYears], [enumFromTo(1900, 2100)]
);
return show({
number: lstFullMonths.length,
firstFive: lstFullMonths.slice(0, 5),
lastFive: lstFullMonths.slice(-5),
leanYearCount: lstLeanYears.length
});
})();

View file

@ -0,0 +1,14 @@
cal_j:(_jd[19000101]+!(-/_jd 21010101 19000101)) / enumerate the calendar
is_we:(cal_j!7) _lin 4 5 6 / identify friday saturdays and sundays
m:__dj[cal_j]%100 / label the months
mi:&15=+/'is_we[=m] / group by month and sum the weekend days
`0:,"There are ",($#mi)," months with five weekends"
m5:(?m)[mi]
`0:$5#m5
`0:,"..."
`0:$-5#m5
y:1900+!201 / enumerate the years in the range
y5:?_ m5%100 / label the years of the months
yn5:y@&~y _lin y5 / find any years not in the 5 weekend month list
`0:,"There are ",($#yn5)," years without any five-weekend months"
`0:,1_,/",",/:$yn5

View file

@ -0,0 +1,27 @@
// version 1.0.6
import java.util.*
fun main(args: Array<String>) {
val calendar = GregorianCalendar(1900, 0, 1)
val months31 = arrayOf(1, 3, 5, 7, 8, 10, 12)
val monthsWithFive = mutableListOf<String>()
val yearsWithNone = mutableListOf<Int>()
for (year in 1900..2100) {
var countInYear = 0 // counts months in a given year with 5 weekends
for (month in 1..12) {
if ((month in months31) && (Calendar.FRIDAY == calendar[Calendar.DAY_OF_WEEK])) {
countInYear++
monthsWithFive.add("%02d".format(month) + "-" + year)
}
calendar.add(Calendar.MONTH, 1)
}
if (countInYear == 0) yearsWithNone.add(year)
}
println("There are ${monthsWithFive.size} months with 5 weekends")
println("The first 5 are ${monthsWithFive.take(5)}")
println("The final 5 are ${monthsWithFive.takeLast(5)}")
println()
println("There are ${yearsWithNone.size} years with no months which have 5 weekends, namely:")
println(yearsWithNone)
}

View file

@ -1,26 +0,0 @@
#lang racket
(require srfi/19)
(define long-months '(1 3 5 7 8 10 12))
(define days #(sun mon tue wed thu fri sat))
(define (week-day date)
(vector-ref days (date-week-day date)))
(define (five-weekends-a-month start end)
(for*/list ([year (in-range start (+ end 1))]
[month long-months]
[date (in-value (make-date 0 0 0 0 31 month year 0))]
#:when (eq? (week-day date) 'sun))
date))
(define weekends (five-weekends-a-month 1900 2100))
(define count (length weekends))
(displayln (~a "There are " count " weeks with five weekends."))
(displayln "The first five are: ")
(for ([w (take weekends 5)])
(displayln (date->string w "~b ~Y")))
(displayln "The last five are: ")
(for ([w (drop weekends (- count 5))])
(displayln (date->string w "~b ~Y")))

View file

@ -1,13 +0,0 @@
There are 201 weeks with five weekends.
The first five are:
Mar 1901
Aug 1902
May 1903
Jan 1904
Jul 1904
The last five are:
Mar 2097
Aug 2098
May 2099
Jan 2100
Oct 2100

View file

@ -0,0 +1,89 @@
! TRANSLATION OF FREEBASIC VERSION ;
BEGIN
INTEGER PROCEDURE WD(M, D, Y); INTEGER M, D, Y;
BEGIN
! ZELLERISH
! 0 = SUNDAY, 1 = MONDAY, 2 = TUESDAY, 3 = WEDNESDAY
! 4 = THURSDAY, 5 = FRIDAY, 6 = SATURDAY
;
IF M < 3 THEN ! IF M = 1 OR M = 2 THEN ;
BEGIN
M := M + 12;
Y := Y - 1
END;
WD := MOD(Y + (Y // 4)
- (Y // 100)
+ (Y // 400)
+ D + ((153 * M + 8) // 5), 7)
END WD;
! ------=< MAIN >=------
! ONLY MONTHS WITH 31 DAY CAN HAVE FIVE WEEKENDS
! THESE MONTHS ARE: JANUARY, MARCH, MAY, JULY, AUGUST, OCTOBER, DECEMBER
! IN NR: 1, 3, 5, 7, 8, 10, 12
! THE 1E DAY NEEDS TO BE ON A FRIDAY (= 5)
;
TEXT PROCEDURE MONTHNAMES(M); INTEGER M;
MONTHNAMES :- IF M = 1 THEN "JANUARY"
ELSE IF M = 2 THEN "FEBRUARY"
ELSE IF M = 3 THEN "MARCH"
ELSE IF M = 4 THEN "APRIL"
ELSE IF M = 5 THEN "MAY"
ELSE IF M = 6 THEN "JUNE"
ELSE IF M = 7 THEN "JULY"
ELSE IF M = 8 THEN "AUGUST"
ELSE IF M = 9 THEN "SEPTEMBER"
ELSE IF M = 10 THEN "OCTOBER"
ELSE IF M = 11 THEN "NOVEMBER"
ELSE IF M = 12 THEN "DECEMBER"
ELSE NOTEXT;
INTEGER M, YR, TOTAL, I, J;
INTEGER ARRAY YR_WITHOUT(1:200);
TEXT ANSWER;
FOR YR := 1900 STEP 1 UNTIL 2100 DO ! GREGORIAN CALENDAR ;
BEGIN
ANSWER :- NOTEXT;
FOR M := 1 STEP 2 UNTIL 12 DO
BEGIN
IF M = 9 THEN M := 8;
IF WD(M, 1, YR) = 5 THEN
BEGIN
ANSWER :- ANSWER & MONTHNAMES(M) & ", ";
TOTAL := TOTAL + 1
END
END;
IF ANSWER =/= NOTEXT THEN
BEGIN
OUTIMAGE;
OUTINT(YR, 4); OUTTEXT(" | ");
OUTTEXT(ANSWER.SUB(1, ANSWER.LENGTH - 2)) ! GET RID OF EXTRA " ," ;
END
ELSE
BEGIN
I := I + 1;
YR_WITHOUT(I) := YR
END
END;
OUTIMAGE;
OUTTEXT("NR OF MONTH FOR 1900 TO 2100 THAT HAS FIVE WEEKENDS ");
OUTINT(TOTAL, 0);
OUTIMAGE;
OUTIMAGE;
OUTINT(I, 0);
OUTTEXT(" YEARS DON'T HAVE MONTHS WITH FIVE WEEKENDS");
OUTIMAGE;
FOR J := 1 STEP 1 UNTIL I DO
BEGIN
OUTINT(YR_WITHOUT(J), 0); OUTCHAR(' ');
IF MOD(J, 8) = 0 THEN OUTIMAGE
END;
OUTIMAGE
END.

View file

@ -0,0 +1,4 @@
var [const] D=Time.Date, r=L();
foreach y,m in ([1900..2100],[1..12]){
if (D.daysInMonth(y,m)==31 and 5==D.weekDay(y,m,1)) r.append(String(y,"-",m))
}

View file

@ -0,0 +1,3 @@
r:=[[(y,m); [1900..2100];
[1..12],{D.daysInMonth(y,m)==31 and 5==D.weekDay(y,m,1)};
{String(y,"-",m)}]];

View file

@ -0,0 +1,7 @@
var [const] D=Time.Date, r=L();
foreach y in ([1900..2100]){ yes:=True;
foreach m in ([1..12]){
if (D.daysInMonth(y,m)==31 and 5==D.weekDay(y,m,1)) { yes=False; break; }
}
if (yes) r.append(y)
}

View file

@ -0,0 +1,5 @@
var yes, r=[[(y,m);
[1900..2100];
[1..12],{if(m==1)yes=True; if(D.daysInMonth(y,m)==31 and 5==D.weekDay(y,m,1)) yes=False; True},
{if (m==12) yes else False};
{y}]]