Jump to content


Click the link below to see the new game I'm developing!


Photo
- - - - -

A bit of fun....


14 replies to this topic

#1 Glenn Meyers

Glenn Meyers

    ProIV Guru

  • Members
  • PipPipPipPipPip
  • 221 posts
  • Gender:Male
  • Location:St. Louis, MO, United States
  • Interests:I also raise African Gray Parrots and build hot rod automobiles.

Posted 19 December 2002 - 07:27 PM

Suppose we have a bit of fun.

What is the fastest logic for calculating the number of days in that month for any given date that the logic is executed?

For example...the logic would return 28 if the routine was run any day in February. 30 for September. Etc.

Oh, and Merry Christmas you lot!

Glenn

#2 Mike Schoen

Mike Schoen

    Expert

  • Members
  • PipPipPipPip
  • 198 posts
  • Gender:Male
  • Location:Guelph, Canada

Posted 19 December 2002 - 09:00 PM

convert yyyymm to string,
set dd to 31, cdate it to number
if > 0 done
try again fo 30,29,28

#3 Rick San Soucie

Rick San Soucie

    Member

  • Members
  • PipPip
  • 36 posts
  • Gender:Male
  • Location:Dallas, United States

Posted 20 December 2002 - 02:43 AM

Assumptions:

1) Using standard PRO-IV logic commands CDATE, PIC and CONV
2) Checking only within valid dates covered with CDATE
3) Date is entered into variable #D, stored in PRO-IV internal date format
4) Output is number of days, stored in string variable $DAYS
5) Looking for fewest logic statements


Logic:

$D = CDATE(#D,'YYYYMM')
IF $D(5,6) = '12' THEN $D = '31' EXIT;
#N = CDATE($D(1,4) + PIC(CONV($D(5,6)) + 1,'99') + '01','YYYYMMD
$DAYS = CDATE(#N - 1,'DD')

#4 Rick San Soucie

Rick San Soucie

    Member

  • Members
  • PipPip
  • 36 posts
  • Gender:Male
  • Location:Dallas, United States

Posted 20 December 2002 - 02:46 AM

I made a transfer error. The logic should have read:

$D = CDATE(#D,'YYYYMM')
IF $D(5,6) = '12' THEN $DAYS = '31' EXIT;
#N = CDATE($D(1,4) + PIC(CONV($D(5,6)) + 1,'99') + '01','YYYYMMD
$DAYS = CDATE(#N - 1,'DD')

#5 Rob Donovan

Rob Donovan

    rob@proivrc.com

  • Admin
  • 1,652 posts
  • Gender:Male
  • Location:Spain

Posted 20 December 2002 - 02:50 AM

Rick,

It could be a problem with the forum not liking all those quotes and brackets. You could try with double quotes instead.. I'll take a look at it later.

Rob D.

#6 Cleve Haynes

Cleve Haynes

    Expert

  • Members
  • PipPipPipPip
  • 172 posts
  • Gender:Male

Posted 20 December 2002 - 09:11 AM

How about this global logic:

N PARMS(#D)

$M = CDATE(#D, 'MM')

WHILE CDATE(#D, 'MM') = $M
#D += 1
ENDWHILE

RETURN(CONV(CDATE(#D - 1, 'DD')))

#7 Jonathan Weeks

Jonathan Weeks

    Newbie

  • Members
  • Pip
  • 2 posts
  • Gender:Male
  • Location:London

Posted 20 December 2002 - 04:51 PM

#N = CONV(CDATE(CDATE(CDATE(@DATE,'YYYY')
+ PIC(REM(CONV(CDATE(@DATE,'MM')) + 1,12),'99')
+ '01','YYYYMMDD') - 1,'DD'))

:)

#8 Richard Bassett

Richard Bassett

    ProIV Guru

  • Members
  • PipPipPipPipPip
  • 707 posts
  • Gender:Not Telling
  • Location:Rural France

Posted 21 December 2002 - 12:12 PM

Very cute (although I think you may have omitted to increment the REM-expression to get a valid month).
Nothing's as simple as you think

#9 Richard Bassett

Richard Bassett

    ProIV Guru

  • Members
  • PipPipPipPipPip
  • 707 posts
  • Gender:Not Telling
  • Location:Rural France

Posted 21 December 2002 - 12:20 PM

If the operation is going to be done several times in a function, the fastest way is very probably the not-much-fun way eg:

Initialize an array with the number of days in each month..
DEFINE #MonthLength(12, 2.0)
#MonthLength(1) = 31
#MonthLength(2) = -99 [won't be using this one]
#MonthLength(3) = 31
etc..
Then when you need a day count use something classical like..
(I know, I know, leap centuries..
but there aren't any more within the range of ProIV)
$month = CDATE(#theDate, 'MM')
IF $month <> '02' THEN
#dayCount = #MonthLength(CONV($month))
ELSE
IF REM(CONV(CDATE(#theDate,'YYYY')), 4) = 0 THEN
#dayCount = 29
ELSE
#dayCount = 28
ENDIF
ENDIF
Or (under the influence of Jonathan) something like..
$date = CDATE(#theDate, 'YYYYMMDD')
IF $date(5,6) <> '02'
#dayCount = #MonthLength(CONV($date(5,6)))
ELSE
#dayCount = CONV( CDATE( CDATE($date(1,4) + '0301', 'YYYYMMDD') - 1, 'DD') )
ENDIF
A Merry Christmas to those who celebrate it
and Happy Holidays to those who don't
Nothing's as simple as you think

#10 Richard Bassett

Richard Bassett

    ProIV Guru

  • Members
  • PipPipPipPipPip
  • 707 posts
  • Gender:Not Telling
  • Location:Rural France

Posted 21 December 2002 - 12:39 PM

Oops - what I should have said was that it seems the increment should be outside the REM-expression :)
Nothing's as simple as you think

#11 Guest_Santa_*

Guest_Santa_*
  • Guests

Posted 21 December 2002 - 01:10 PM

You have a strange idea of fun?

No presents for you sonny......

#12 Richard Bassett

Richard Bassett

    ProIV Guru

  • Members
  • PipPipPipPipPip
  • 707 posts
  • Gender:Not Telling
  • Location:Rural France

Posted 23 December 2002 - 04:24 PM

Funny.
That's what my girlfriend said.

Is this better?
    STEP CONV(CDATE(@DATE, 'MM'))
1 #days = 31
2 #days = CDATE(CDATE(@DATE,'YYYY') + '03' + CDATE(@DATE, 'DD'), 'YYYYMMDD) - @DATE
3 #days = 31
4 #days = 30
5 #days = 31
6 #days = 30
7 #days = 31
8 #days = 31
9 #days = 30
10 #days = 31
11 #days = 30
12 #days = 31

Nothing's as simple as you think

#13 Ralph Gadsby

Ralph Gadsby

    Expert

  • Members
  • PipPipPipPip
  • 154 posts
  • Gender:Male
  • Location:United Kingdom

Posted 23 December 2002 - 05:33 PM

Mike Schoen was pipped at the post by Richard Bassett's last entry (which I modified to use CALL instead of STEP, to make the code reuseable in a loop).

The wooden spoon goes to Cleve Haynes, whose routine took almost 20 times as long as the winning entry and had to be changed to make it safe (call by reference).

Full results (in seconds) for 222308 iterations using a range of dates between 1/1/1800 and the current date are as follows:

R Bassett 2
M Schoen 4
R Bassett 6
R San Soucie 7
J Weeks 12
C Haynes 37

Ralph

#14 Jonathan Weeks

Jonathan Weeks

    Newbie

  • Members
  • Pip
  • 2 posts
  • Gender:Male
  • Location:London

Posted 31 December 2002 - 04:23 PM

String CASEs are faster than numerics:


CASE CDATE(#D,'MM')
WHEN '02':
#E = 28
#Y = CONV(CDATE(#D,'YYYY'))
IF REM(#Y,4) ELSE
#E += 1
IF REM(#Y,100) ELSE
#E -= 1
IF REM(#Y,400) ELSE #E += 1;
ENDIF
ENDIF
WHEN '04','06','09','11': #E = 30
OTHERWISE: #E = 31
ENDCASE


#15 Glenn Meyers

Glenn Meyers

    ProIV Guru

  • Members
  • PipPipPipPipPip
  • 221 posts
  • Gender:Male
  • Location:St. Louis, MO, United States
  • Interests:I also raise African Gray Parrots and build hot rod automobiles.

Posted 31 December 2002 - 06:50 PM

This is almost the solution I used.
I did the month conversion to a number for a bit faster comparisions:
#M = CONV(CDATE (#D,'MM'))
CASE #M .....etc.
I also inverted the order of case checking to check for the most likely scenario (months with 31 days) first.



Reply to this topic



  


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

Click the link below to see the new game I'm developing!