# ==========================================================================
# Easter — ARC-style
#
# This example computes the date of Easter Sunday in the Gregorian calendar.
# For each year in a sample range, it applies the classic computus step by
# step, explains the resulting month and day, and then checks independent
# properties of the result: cycle bounds, remainder bounds, and the legal
# Easter date window in March or April.
# ==========================================================================

@prefix : <https://example.org/easter-arc#> .
@prefix math: <http://www.w3.org/2000/10/swap/math#> .
@prefix log: <http://www.w3.org/2000/10/swap/log#> .
@prefix string: <http://www.w3.org/2000/10/swap/string#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<> rdfs:comment """This ARC-style version keeps the Gregorian computus from the original example and reports, for each sample year, an Answer, a Reason Why, and a set of independent Checks.""" .

:y2026 a :Case; :year 2026 .
:y2027 a :Case; :year 2027 .
:y2028 a :Case; :year 2028 .
:y2029 a :Case; :year 2029 .
:y2030 a :Case; :year 2030 .
:y2031 a :Case; :year 2031 .
:y2032 a :Case; :year 2032 .
:y2033 a :Case; :year 2033 .
:y2034 a :Case; :year 2034 .
:y2035 a :Case; :year 2035 .

:goldenRemainder :value 0 .
:goldenRemainder :value 1 .
:goldenRemainder :value 2 .
:goldenRemainder :value 3 .
:goldenRemainder :value 4 .
:goldenRemainder :value 5 .
:goldenRemainder :value 6 .
:goldenRemainder :value 7 .
:goldenRemainder :value 8 .
:goldenRemainder :value 9 .
:goldenRemainder :value 10 .
:goldenRemainder :value 11 .
:goldenRemainder :value 12 .
:goldenRemainder :value 13 .
:goldenRemainder :value 14 .
:goldenRemainder :value 15 .
:goldenRemainder :value 16 .
:goldenRemainder :value 17 .
:goldenRemainder :value 18 .

:epactRemainder :value 0 .
:epactRemainder :value 1 .
:epactRemainder :value 2 .
:epactRemainder :value 3 .
:epactRemainder :value 4 .
:epactRemainder :value 5 .
:epactRemainder :value 6 .
:epactRemainder :value 7 .
:epactRemainder :value 8 .
:epactRemainder :value 9 .
:epactRemainder :value 10 .
:epactRemainder :value 11 .
:epactRemainder :value 12 .
:epactRemainder :value 13 .
:epactRemainder :value 14 .
:epactRemainder :value 15 .
:epactRemainder :value 16 .
:epactRemainder :value 17 .
:epactRemainder :value 18 .
:epactRemainder :value 19 .
:epactRemainder :value 20 .
:epactRemainder :value 21 .
:epactRemainder :value 22 .
:epactRemainder :value 23 .
:epactRemainder :value 24 .
:epactRemainder :value 25 .
:epactRemainder :value 26 .
:epactRemainder :value 27 .
:epactRemainder :value 28 .
:epactRemainder :value 29 .

:weekdayRemainder :value 0 .
:weekdayRemainder :value 1 .
:weekdayRemainder :value 2 .
:weekdayRemainder :value 3 .
:weekdayRemainder :value 4 .
:weekdayRemainder :value 5 .
:weekdayRemainder :value 6 .

:slot_m3_d22 :monthNum 3; :day 22 .
:slot_m3_d23 :monthNum 3; :day 23 .
:slot_m3_d24 :monthNum 3; :day 24 .
:slot_m3_d25 :monthNum 3; :day 25 .
:slot_m3_d26 :monthNum 3; :day 26 .
:slot_m3_d27 :monthNum 3; :day 27 .
:slot_m3_d28 :monthNum 3; :day 28 .
:slot_m3_d29 :monthNum 3; :day 29 .
:slot_m3_d30 :monthNum 3; :day 30 .
:slot_m3_d31 :monthNum 3; :day 31 .
:slot_m4_d1 :monthNum 4; :day 1 .
:slot_m4_d2 :monthNum 4; :day 2 .
:slot_m4_d3 :monthNum 4; :day 3 .
:slot_m4_d4 :monthNum 4; :day 4 .
:slot_m4_d5 :monthNum 4; :day 5 .
:slot_m4_d6 :monthNum 4; :day 6 .
:slot_m4_d7 :monthNum 4; :day 7 .
:slot_m4_d8 :monthNum 4; :day 8 .
:slot_m4_d9 :monthNum 4; :day 9 .
:slot_m4_d10 :monthNum 4; :day 10 .
:slot_m4_d11 :monthNum 4; :day 11 .
:slot_m4_d12 :monthNum 4; :day 12 .
:slot_m4_d13 :monthNum 4; :day 13 .
:slot_m4_d14 :monthNum 4; :day 14 .
:slot_m4_d15 :monthNum 4; :day 15 .
:slot_m4_d16 :monthNum 4; :day 16 .
:slot_m4_d17 :monthNum 4; :day 17 .
:slot_m4_d18 :monthNum 4; :day 18 .
:slot_m4_d19 :monthNum 4; :day 19 .
:slot_m4_d20 :monthNum 4; :day 20 .
:slot_m4_d21 :monthNum 4; :day 21 .
:slot_m4_d22 :monthNum 4; :day 22 .
:slot_m4_d23 :monthNum 4; :day 23 .
:slot_m4_d24 :monthNum 4; :day 24 .
:slot_m4_d25 :monthNum 4; :day 25 .

# --------
# Computus
# --------

{ ?Case a :Case; :year ?Y.
  (?Y 19) math:remainder ?J.
  (?Y 100) math:integerQuotient ?K; math:remainder ?H.
  (?K 4) math:integerQuotient ?M; math:remainder ?N.
  ((?K 8)!math:sum 25) math:integerQuotient ?P.
  (((?K ?P)!math:difference 1)!math:sum 3) math:integerQuotient ?Q.
  ((((((19 ?J)!math:product ?K)!math:sum ?M)!math:difference ?Q)!math:difference 15)!math:sum 30)
      math:remainder ?R.
  (?H 4) math:integerQuotient ?S; math:remainder ?U.
  ((32 (2 ?N)!math:product (2 ?S)!math:product ?R!math:negation ?U!math:negation)!math:sum 7)
      math:remainder ?V.
  ((?J (11 ?R)!math:product (22 ?V)!math:product)!math:sum 451)
      math:integerQuotient ?W.
  ((?R ?V (7 ?W)!math:product!math:negation 114)!math:sum 31)
      math:integerQuotient ?X; math:remainder ?Z.
  (?Z 1) math:sum ?DAY.
}
=>
{ ?Case
    :j ?J;
    :k ?K;
    :h ?H;
    :m ?M;
    :n ?N;
    :p ?P;
    :q ?Q;
    :r ?R;
    :s ?S;
    :u ?U;
    :v ?V;
    :w ?W;
    :monthNum ?X;
    :day ?DAY;
    :z ?Z. } .

{ ?Case :monthNum 3. } => { ?Case :monthName "March". } .
{ ?Case :monthNum 4. } => { ?Case :monthName "April". } .

# ------------------
# Independent checks
# ------------------

{ ?Case :j ?J. :goldenRemainder :value ?J. }
    => { ?Case :check1 "C1 OK - the Golden Number remainder j is inside the 0–18 cycle.\n" . } .

{ ?Case :r ?R. :epactRemainder :value ?R. }
    => { ?Case :check2 "C2 OK - the epact-style remainder r is inside the 0–29 cycle.\n" . } .

{ ?Case :v ?V. :weekdayRemainder :value ?V. }
    => { ?Case :check3 "C3 OK - the weekday adjustment v is inside the 0–6 cycle.\n" . } .

{ ?Case :monthNum ?M; :monthName ?Name. }
    => { ?Case :check4 "C4 OK - the final month is a valid Easter month (March or April).\n" . } .

{ ?Case :monthNum ?M; :day ?D.
  ?Slot :monthNum ?M; :day ?D. }
    => { ?Case :check5 "C5 OK - the final date is inside the legal Gregorian Easter window.\n" . } .

# ----------------
# ARC-style report
# ----------------

{ ?Case :year ?Y; :monthName ?Month; :day ?Day;
        :j ?J; :k ?K; :q ?Q; :r ?R; :v ?V; :monthNum ?X; :z ?Z;
        :check1 ?C1; :check2 ?C2; :check3 ?C3; :check4 ?C4; :check5 ?C5.
  (
    "Easter — Gregorian computus\n\n"
    "=== " ?Y " ===\n"
    "Answer\n"
    "Easter Sunday falls on " ?Month " " ?Day ".\n\n"
    "Reason Why\n"
    "For year " ?Y ", the computus gives j=" ?J ", k=" ?K ", q=" ?Q
    ", r=" ?R ", v=" ?V ", and final month/day numbers x=" ?X ", z=" ?Z ". "
    "Because the day is z+1, the resulting Easter date is " ?Month " " ?Day ".\n\n"
    "Check\n"
    ?C1 ?C2 ?C3 ?C4 ?C5
  ) string:concatenation ?Block. }
    =>
{ :report log:outputString ?Block. } .
