Count how many months are having a full 31 days by counting knuckles
Jelly, 21 bytes
ḅ12r/ị7RḂṁ12¤żC$S×⁼Ṣ$
Takes input like [[y, m], [y, m]]
.
Try it online!
How it works
ḅ12r/ị7RḂṁ12¤żC$S×⁼Ṣ$ Main link. Argument: [[a, b], [c, d]]
ḅ12 Unbase 12; yield [x, y] := [ 12a + b, 12c + d].
r/ Reduce by range; yield [x, ..., y].
¤ Combine the five links to the left into a niladic chain.
7 Set the return value to 7.
R Range; yield [1, 2, 3, 4, 5, 6, 7].
Ḃ Bit; yield [1, 0, 1, 0, 1, 0, 1].
ṁ12 Mold 12; repeat the Booleans to create an array of length
12. Yields [1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1].
ị At-index; yield the elements of the array to the right at
the indices (1-based and modular) of the array to the left.
$ Combine the two links to the left into a monadic chain.
C Complement; map t -> 1-t over the array.
ż Zip the original array with the complements.
S Take the sum of each column.
$ Combine the two links to the left into a monadic chain.
Ṣ Sort [[a, b], [c, d]].
⁼ Compare the result with [[a, b], [c, d]], yielding 1 if
the input is sorted, 0 if not.
× Multiply the results to both sides.
Python 2, 92 90 86 80 bytes
lambda a,b,c,d:[(bin(2741)[2:]*(c+1-a))[b-1:-12+d or None].count(x)for x in'10']
Try it online!
6 more by converting to a lambda, with thanks to @math_junkie for the idea. Now outputs a list containing the two numbers.
Previous non-lambda version (86 bytes)
a,b,c,d=input()
for x in'10':print(bin(2741)[2:]*(c+1-a))[b-1:-12+d or None].count(x),
Try it online old!
2 saved with thanks to @ovs for helping me get rid of the len(k)
. I hadn't thought about using None
.
Input is a list of integers in the format y1,m1,y2,m2
Some credit due to @KeerthanaPrabhakaran who got bin(2741)[2:]
before I did which saves 1 byte over hard coding the binary string.
JavaScript (ES6), 70 68 67 64 bytes
Takes input as two integers in yyyymm
format, in currying syntax (a)(b)
. Outputs an array of two integers [knuckles, grooves]
.
a=>g=(b,c=d=0)=>a>b?[c,d-c]:g(--b,c+!((b%=100)>11||b/.87&!!++d))
Formatted and commented
a => // main function: takes start date (a) as input / returns g
g = ( // recursive function g, which takes:
b, // - b = end date
c = d = 0 // - c = number of knuckles
) => // and also keeps track of: d = total number of months
a > b ? // if a is greater than b:
[ c, d - c ] // stop recursion and return the final result
: // else:
g( // do a recursive call to g():
--b, // - decrement the end date
c + // - increment the # of knuckles if
!( // both of these conditions are false:
(b %= 100) // - the end month (now stored in b in 0-based indexing)
> 11 || // is greater than 11
b / 0.87 & !!++d // - the number of days in this month is not 31
) // (at the same time, d is incremented if the first
) // condition is false)
Test cases
NB: The third test case is not included in this snippet, because it won't work unless your browser has Tail Call Optimization enabled.
let f =
a=>g=(b,c=d=0)=>a>b?[c,d-c]:g(--b,c+!((b%=100)>11||b/.87&!!++d))
console.log(f(201703)(201902)); // 14 10
console.log(f(201701)(202008)); // 26 18
console.log(f(201802)(201803)); // 1 1
console.log(f(201601)(201601)); // 1 0
console.log(f(201612)(201611)); // 0 0