{$mode delphi}{$if fpc_fullversion < 30301}{$error needs 3.3.1}{$ifend}
{$modeswitch implicitfunctionspecialization}
{$modeswitch functionreferences}
uses sysutils;
type
ESetException = class(Exception);
dayname = (Monday, Tuesday, Wednesday,Thursday, Friday, Saturday, Sunday);
daynames = set of dayname;
monthname = (January, February, March,April, May, June, July, August, September, October, November, December);
monthnames = set of monthname;
const
workweek:daynames = [Monday, Tuesday, Wednesday,Thursday, Friday];
weekend:daynames = [Saturday, Sunday];
winter:monthnames = [December, January, February];
spring:monthnames = [March,April, May];
summer:monthnames = [June, July, August];
fall:monthnames = [September, October, November];
function popcount<T{:set}>(const aSet:T): integer; inline;
type
// 128 bits - octword
poword = ^oword;oword = record a,b:qword;end;
// 256 bits - hexword
phword = ^HWord;HWord = record a,b,c,d:qword;end;
var
a,b,c,d:qword;
begin
if GetTypeKind(T) = tkSet then
// * MUST* dereference!!!
case SizeOf(aSet) of
1 : Result := popcnt(PByte(@aSet)^); // 8
2 : Result := popcnt(PWord(@aSet)^); // 16
4 : Result := popcnt(PCardinal(@aSet)^); // 32
8 : Result := popcnt(PQword(@aSet)^); // 64
16 : begin // 128
a:= poword(@aSet)^.a;
b:= poword(@aSet)^.b;
Result := popcnt(a)+popcnt(b);
end;
32 :begin // 256
a:= phword(@aSet)^.a;
b:= phword(@aSet)^.b;
c:= phword(@aSet)^.c;
d:= phword(@aSet)^.d;
Result := popcnt(a)+popcnt(b)+popcnt(c)+popcnt(d);
end;
else
raise ESetException.Create('Set too large');
end
else raise ESetException.Create('Not a set');
end;
begin
writeln(popcount(weekend));
writeln(popcount(workweek));
writeln(popcount(summer));
end.