Post Reply 
garbage day
11-01-2024, 08:11 AM
Post: #1
garbage day
My old brain struggles for something clever for this. The garbage company used to provide an annual chart for their customers, but will no longer be doing so. Needed is a ppl program that, when run, would reveal whether to put out the "recycling" or "organics" container with the weekly garbage on collection day, recurring on the same day of the week, every month, each year.

This past week, "organics' was collected. Maybe a start date, and a simple flip/flop routine is all that is needed; but somehow, I sense more information is probably required in order not to lose track over time! If the program would run on the emulator, it would be a very convenient feature! The program should be able to be run on any day of the affected week prior to, or on the collection day.

Thank you, if you can help with such a program. It sounds simple enough, probably is, and hopefully interesting enough to inspire ideas in this forum!
Find all posts by this user
Quote this message in a reply
11-02-2024, 03:28 AM (This post was last modified: 11-02-2024 03:29 AM by john gustaf stebbins.)
Post: #2
RE: garbage day
The following program returns a string, either "Recycling" or "Not Recycling". (We get our compost picked up every week, but recycling only every other week.) You would want to change "Not Recycling" to "Organics"

The variable keydate needs a recycling pickup day in YYYY.MMDD format.

Code:

EXPORT RECYCLE()
BEGIN

LOCAL keydate = 2024.1028, r;

IF CAS.irem( CAS.iquo(DDAYS(keydate,Date)-1,7),2)==1 THEN
r := "Recycling"
ELSE
r := "Not Recycling"
END;
RETURN r;

END;

513016415223221833242338122322514610315
Find all posts by this user
Quote this message in a reply
11-02-2024, 08:23 AM
Post: #3
RE: garbage day
Brilliant! Thank you,very much. Your idea is very clever! I think it might also be useful to include the date of the collection in the return value, as well. Something like:

{"Wednesday, 11/5/2024, "Recycling"}

But, I don't know how to go about it, any thoughts? I, very much, appreciate your contribution!
Find all posts by this user
Quote this message in a reply
11-02-2024, 03:50 PM (This post was last modified: 11-04-2024 06:16 AM by Albert Chan.)
Post: #4
RE: garbage day
Based from a known Recycling date, we can estimate weeks since then
Below both formulas will work for current century.

Δw = round((365.25*(Δy + Δm/12) + Δd)/7)
Δw = round((365.25*Δy + 30.5*Δm + Δd)/7)         ; just as good

max_error(days from Δy) = 0.75     ; for current century
max_error(days from Δm) = 2.5      ; 30.5 - 28 = 2.5 days
max_error(estimated days) = 3.25 < 3.5


Example: 11/5/2024 is Recycling Day, we check 30 weeks later.

lua> date(day(2024,11,5) + 7*30)
2025      6      3      2

--> Δy, Δm, Δd = 1, -5, -2

Δw = round((365.25*Δy + 30.5*Δm + Δd)/7) = round(210.75/7) = 30

Or, if we are interested only for Δw parity

Δw (mod 2) ≡ round((2.5*(Δy/2 + Δm) + Δd)/7) ≡ round(-13.25/7) ≡ -2 ≡ 0

Of course, fastest is lookup a calendar for week number
Find all posts by this user
Quote this message in a reply
11-02-2024, 06:12 PM (This post was last modified: 11-02-2024 06:13 PM by john gustaf stebbins.)
Post: #5
RE: garbage day
(11-02-2024 08:23 AM)DrD Wrote:  Brilliant! Thank you,very much. Your idea is very clever! I think it might also be useful to include the date of the collection in the return value, as well. Something like:

{"Wednesday, 11/5/2024, "Recycling"}

But, I don't know how to go about it, any thoughts? I, very much, appreciate your contribution!

To do this you would probably want to move the calculation I did in the IF statement and break it up a bit to calculate the new date. This is off the cuff, but CAS.iquo(DDAYS(keydate,Date)-1,7) calculates the number of weeks since the keydate. Add 1 to that and multiply by 7 to get days until the next pickup. You can then use DATEADD to get the date.

DAYOFWEEK could be used to calculate the day (though it gives a numerical result you would probably need to use to pull from a list of day names). Easier is just to code in the date name in your return value.

If your collection company is like mine and delays their schedule a day for certain holidays, it could get quite complicated to compensate for that. Smile

513016415223221833242338122322514610315
Find all posts by this user
Quote this message in a reply
11-03-2024, 05:53 AM
Post: #6
RE: garbage day
Albert Chan:

Thank you for taking time to analyze this problem. I spent a couple of days thinking about it, hoping a straight forward and simple idea would pop into mind. My goal was to display the date, (and which collection material would be required), as program output. As is often the case, the simple gives way to reality!

Within the days {Monday through Saturday}, a weekly recurring pickup day is assigned to a customer. The pickup day might get modified by inclement weather, holiday, or some external event not under anyone's direct control. That wouldn't be much of a customer problem to deal with, since it is only a one time/week schedule shift, or a change to the regular pickup day.

From an algorithmic perspective, the different number of days in each month, allowance for leap year, and necessity to change due to a business decision, are things that also need to be considered.

john gustaf stebbins got the bulk of the problem solved! Namely, by running the program, at any time during the objective week, his program will display which collection item is expected. That's the most important thing. Having the date shown, would also let a customer know that the program is also on track with the calendar week. I'm very thankful for his efforts, I certainly wasn't getting anywhere!

Drd
Find all posts by this user
Quote this message in a reply
11-04-2024, 05:21 PM (This post was last modified: 11-04-2024 11:02 PM by Albert Chan.)
Post: #7
RE: garbage day
I made mistakes for a 'forever' formula, thus post removed, and start over.
I was playing with error = lo .. high, not realized Δy, Δm sign can be switched.
Maximum error is bigger, due to symmetry.

There are 97 leap years in 400 years, 97/400 = 0.2425
It so happen 365.2425 * 400 = 146097 = 7*20871 days, exactly.
If we can prove formula correct for 400 years, it is 'forever' correct.

Brute force check for days error, if key year end's in 00
Note: keydate day number doesn't matter, it can be anything!
Δd does not change. This is why I use d0=0 for brute force check.

Code:
function key_year_error(y0)
    local e1, e2, y, m, d, d1, d2 = 0, 0
    for m0 = 1,12 do
        local kd = day(y0,m0,0) -- key date
        for w=7,146097,7 do     -- weeks for 400 years
            y,m,d = date(kd+w)  -- exact date
            d1 = 365.2425*((y-y0) + (m-m0)/12) + d
            d2 = 365.2425*(y-y0) + 30.5*(m-m0) + d
            if abs(e1) < abs(w-d1) then e1=w-d1 end
            if abs(e2) < abs(w-d2) then e2=w-d2 end
        end
    end
    return e1, e2
end

lua> for y=0,300,100 do printf("%03d %8.4f %8.4f\n", y, key_year_error(y)) end
000  -2.9825   -2.9775
100  -3.6644   -3.7275
200  -3.4144   -3.4775
300   3.6644    3.7275

Both estimated weeks formulas work if key year is divisible by 200, with errors within 3.5 days.



It would be nice if we can just look up "good" key date from calendar.
Lets shift only months instead, and check if it would still work for 400 years.

Code:
function key_month_error(m0)
    local e1, e2, y, m, d, d1, d2 = 0, 0
    for y0 = 0,399 do
        local kd = day(y0,m0,0) -- key date
        for w=7,146097,7 do     -- weeks for 400 years
            y,m,d = date(kd+w)  -- exact date
            d1 = 365.2425*((y-y0) + (m-m0)/12) + d
            d2 = 365.2425*(y-y0) + 30.5*(m-m0) + d
            if abs(e1) < abs(w-d1) then e1=w-d1 end
            if abs(e2) < abs(w-d2) then e2=w-d2 end
        end
    end
    return e1, e2
end

lua> for m=1,12 do printf("%-3d %8.4f %8.4f\n", m, key_month_error(m)) end
1    -3.8288    -3.9550
2    -4.3919    -4.4550
3     4.3919     4.4550
4     3.8288     3.9550
5     4.2656     4.4550
6     3.7025     3.9550
7     4.1394     4.4550
8     3.5762     3.9550
9    -3.5762     3.4550
10    3.4500     3.9550
11   -3.7025     3.4550
12    3.3237     3.9550


We have a few options here, all brute force confirmed valid.
(month close to February error would be bad, as expected)

Δw = round((365.2425*(Δy + Δm/12) + Δd)/7), work if key month = 10, 12
Δw = round((365.2425*Δy + 30.5*Δm + Δd)/7), work if key month = 9, 11

It is arbitrary, I pick 'forever' formula with least days error.

Δw = round((365.2425*(Δy + Δm/12) + Δd)/7), key month = December

For previous keydate = 2024/11/5, move down calendar by 4 rows --> 2024/12/3 (no math)

Or, we keep the same keydate, but only "make" the month as December.

2024/11/5 ≡ 2024/12/(5-30) ≡ 2024/12/(-25)
Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: 1 Guest(s)