This program calculates and displays a 30-day biorhythm analysis for a user-specified start date, computing Physical (23-day), Emotional (28-day), and Intellectual (33-day) cycles using sine functions scaled to a range of ±20. The user enters birth date and start date in month/day/year format, and the program derives the day-count difference to feed into the cycle calculations via GOSUB routines at lines 770–820. The code uses cumulative day-of-year arrays (A() and F(), which are duplicated and identical) to convert calendar dates to Julian-style day numbers with the formula at lines 830–840. Several notable anomalies are present: the Intellectual cycle at line 770 correctly uses period 33, but the Physical cycle at line 810 incorrectly uses period 28 (same as Emotional), and the sort/print loop for plotting biorhythm positions on screen (lines 1470–1650) contains control-flow bugs that prevent correct column-ordered output. Summary statistics at line 2510–2530 report total days, hours, and approximate heartbeats since birth before looping back to restart.
Program Analysis
Program Structure
The program is divided into several logical phases:
- Initialisation (lines 10–430): Arrays and strings are set up — cumulative day-of-year offsets in
A()andF(), month name strings inM$(), and day-name strings inX$()andD$(). - User input (lines 440–740): Prompts for analysis duration (
ZA), start date (M,D,Y), birth date (MB,DB,YB), and user name (A$). - Date calculation (lines 830–870): Converts calendar dates to a linear day count (
TandTB); computes the age in days (X = T - TB). - Header printing (lines 1120–1310): Prints title, start date, birth date, and cycle legend.
- Main biorhythm loop (lines 1350–1940): For each day, calls GOSUB routines to compute cycle values, attempts to sort positions for tabular output, and advances the date.
- Closing summary (lines 2500–2560): Displays total days, hours, and estimated heartbeats since birth, then restarts.
Cycle Calculation Subroutines
Three GOSUB routines compute biorhythm values as integers in the range −20 to +20:
| Line | Variable | Cycle | Period used | Correct period |
|---|---|---|---|---|
| 770 | NI | Intellectual | 33 | 33 ✓ |
| 790 | NE | Emotional | 28 | 28 ✓ |
| 810 | NP | Physical | 28 | 23 ✗ |
The Physical cycle subroutine at line 810 uses a period of 28 days instead of the correct 23, making it identical to the Emotional cycle. This is a straightforward copy-paste bug.
Date-to-Day Conversion
Lines 830–840 use a compact formula to convert a calendar date to a sequential day number:
T = INT(D + 365.25*Y + A(M) + 0.01*M - 0.01)
The 365.25*Y term approximates leap years; the small 0.01*M and offset corrections fine-tune month boundary alignment. The cumulative day-of-year array A() stores the day number at which each month begins (January=0, February=31, etc.). Notably, array F() is initialised to identical values at lines 290–400 but is later reused as a column-position array for the print loop — a recycling of an array name that may cause confusion.
Day-of-Week Calculation
Lines 870 and 1150 compute the day of the week for the birth date and start date respectively:
RB = TB - 1 - INT((TB-1)/7)*7
This is a modulo-7 operation yielding a value 0–6, used to index into X$() and D$() for full and abbreviated day names.
Column Sort and Print Loop — Key Bugs
Lines 1470–1650 attempt to sort the four plot positions (F(1)–F(4) for median, I, E, P markers) into left-to-right screen order, then print them with TAB. Several serious bugs prevent correct operation:
- The inner sort loop (lines 1490–1600) jumps to
GOTO 1600on the true branch of line 1490, skipping the swap at lines 1530–1580 entirely — the sort never executes a swap. - Line 1500 sets
F(I)=0and clearsF$(I)when two positions are equal, but also falls through incorrectly due to missingGOTO. - The print loop at lines 1620–1650 prints
TAB(F(I))andTAB(F(J)), butJis the inner loop variable left over from the sort loop (value 4 after exit), not an independent iterator — so onlyF(J)withJ=4is printed on every iteration.
Date Advancement Logic
Lines 1700–1920 advance the date by one day, handling month-end rollovers. However the structure has significant flow issues:
- Line 1720 checks
IF M=40(never true for a valid month) alongside correct 30-day month checks usingRM(which is initialised to 0 and never updated, so the conditionRM=60etc. is also always false). - Lines 1740 and 1760 handle February leap-year and non-leap-year cases but are only reachable if the preceding
IFat 1720 does not branch — since the branch target is 1800, these lines are effectively dead code; the program always reaches 1780 and setsL=31. - The variable
RHis used at line 1690 (LET R=RH) but is never assigned after line 59 initialises it to 0, so the day-of-week display never advances.
Duplicate Array Initialisation
Arrays A() (lines 60–160) and F() (lines 290–400) are initialised to exactly the same cumulative day-of-year values. The loop at lines 410–430 iterates over A(I) but merely assigns each element to the scalar A, discarding every value — it performs no useful work. The same applies to the loops at lines 950–970 and 1050–1110 for X$() and M$().
Closing Summary
After the loop completes, lines 2510–2530 print motivational statistics. Note that X at this point has been incremented by 0.5 each half-iteration (line 1660), so the expression X-1 will not equal the integer day count. The heartbeat estimate uses XS*24*90 — approximately 90 beats per minute is reasonable but the factor should be *60*60*24*~70 beats/day; the formula as written gives beats per hour rather than total beats.
Notable Idioms and Observations
INT(M),INT(D),INT(Y)at lines 610–630 guard against fractional input values.- The sub-day half-step iteration at line 1660 (
LET X=X+.5) with the guard at 1670 (IF INT(X)<>X THEN GOTO 1360) is an attempt to interpolate between days for smoother sine calculation, but since the print routine is re-entered at 1350 on the half-step, it effectively doubles the output rows. - Line 1180 contains a malformed PRINT statement:
"M$(M)STR$ (D)"is a string literal rather than evaluated expressions, so the starting date is never actually printed correctly. - Line 1260 prints
STR$(64)and the literal(35)— this appears to be an attempt to print a divider line but produces the string"64"followed by35.
Content
Source Code
10 REM "BIORYTHM"
20 CLEAR
21 LET L=0
30 DIM A(12)
35 DIM X$(7)
40 DIM M$(12)
45 DIM D$(7)
48 LET Z=0
50 DIM F(12)
53 LET R=0
55 DIM F$(12)
58 LET RH=0
59 LET RM=0
60 LET A(1)=0
70 LET A(2)=31
80 LET A(3)=59
85 LET A(4)=90
90 LET A(5)=120
100 LET A(6)=151
110 LET A(7)=181
120 LET A(8)=212
130 LET A(9)=243
140 LET A(10)=273
150 LET A(11)=304
160 LET A(12)=334
170 LET M$(1)="JAN"
180 LET M$(2)="FEB"
190 LET M$(3)="MAR"
200 LET M$(4)="APR"
210 LET M$(5)="MAY"
220 LET M$(6)="JUN"
230 LET M$(7)="JUL"
240 LET M$(8)="AUG"
250 LET M$(9)="SEP"
260 LET M$(10)="OCT"
270 LET M$(11)="NOV"
280 LET M$(12)="DEC"
290 LET F(1)=0
300 LET F(2)=31
310 LET F(3)=59
320 LET F(4)=90
330 LET F(5)=120
340 LET F(6)=151
350 LET F(7)=181
360 LET F(8)=212
370 LET F(9)=243
380 LET F(10)=273
390 LET F(11)=304
400 LET F(12)=334
410 FOR I=1 TO 12
420 LET A=A(I)
430 NEXT I
440 CLS
450 PRINT
460 PRINT
470 PRINT
480 PRINT
490 PRINT "THIS PROGRAM WILL PRINT OUT YOUR PERSONAL BIO-RYTHM AALYSIS"
500 PRINT "FOR A 30 DAY PERIOD STARTING AT ANY DAY YOU SELECT"
510 PRINT "DATES SHOULD BE ENTERED MONTH, DAY, YEAR"
520 PRINT "EX. 7,4,76"
530 PRINT "FOR HOW MANY DAYS DO YOU WANT YOUR BIO-RYTHM ANALYSIS?"
540 INPUT ZA
550 PRINT ZA
560 PRINT "WHAT IS THE DATE AT WHICH YOU WOULD LIKE THE 30 DAY AALYSIS TO START?"
570 INPUT M
580 INPUT D
590 INPUT Y
600 PRINT M ,D ,Y
610 LET M=INT (M)
620 LET D=INT (D)
630 LET Y=INT (Y)
640 PRINT "WHAT IS THE DATE OF YOUR BIRTH"
650 INPUT MB
660 INPUT DB
670 INPUT YB
680 PRINT MB ,DB ,YB
690 LET MB=INT (MB)
700 LET DB=INT (DB)
710 LET YB=INT (YB)
720 PRINT "WHAT IS YOUR NAME"
730 INPUT A$
740 PRINT A$
750 PRINT
760 GOTO 830
770 LET NI=INT (20*SIN (2*PI*X/33)+.5)
780 RETURN
790 LET NE=INT (20*SIN (2*PI*X/28)+.5)
800 RETURN
810 LET NP=INT (20*SIN (2*PI*X/28)+.5)
820 RETURN
830 LET T=INT (D+365.25*Y+A(M)+.01*M-.01)
840 LET TB=INT (DB+365.25*YB+A(MB)+.01*MB-.03)
850 LET X=T-TB
860 LET V=INT ((40-LEN (A$))/2)
870 LET RB=TB-1-INT ((TB-1)/7)*7
880 LET X$(1)="MONDAY"
890 LET X$(2)="TUESDAY"
900 LET X$(3)="WEDNESDAY"
910 LET X$(4)="THURSDAY"
920 LET X$(5)="FRIDAY"
930 LET X$(6)="SATURDAY"
940 LET X$(7)="SUNDAY"
950 FOR I=1 TO 7
960 LET X$=X$(I)
970 NEXT I
980 LET D$(1)="MON"
990 LET D$(2)="TUE"
1000 LET D$(3)="WED"
1010 LET D$(4)="THU"
1020 LET D$(5)="FRI"
1030 LET D$(6)="SAT"
1040 LET D$(7)="SUN"
1050 FOR I=1 TO 7
1060 LET D$=D$(I)
1070 NEXT I
1080 LET S=0
1090 FOR I=1 TO 12
1100 LET M$=M$(I)
1110 NEXT I
1120 CLS
1130 PRINT
1140 PRINT "THIS IS A ";ZA;" DAY BIO-RYTHM ANALYSIS FOR ";A$
1150 LET R=T-1-INT ((T-1)/7)*7
1160 LET LE=21+LEN (X$(R))+LEN (M$(M))+LEN (STR$ (D))+LEN (STR$ (Y))
1170 LET V2=INT ((64-LE)/2)
1180 PRINT "STARTING DATE";X$(R);"M$(M)STR$ (D)";"19;"
1190 PRINT STR$ (YB)
1200 PRINT
1210 LET LL=LEN (X$(RB))+LEN (M$(MB))
1220 LET LB=LL+18
1230 LET VB=INT ((64-LB)/2)
1240 PRINT "BIRTH DATE ";X$(RB),M$(MB),STR$ (DB),"19"
1250 PRINT STR$ (YB)
1260 PRINT STR$ (64),(35)
1270 PRINT "(P)STANDS FOR PHYSICAL CYCLE"
1280 PRINT "(I) STANDS FOR INTELLECTUAL CYCLE"
1290 PRINT "(E)STANDS FOR EMOTIONAL CYCLE"
1300 PRINT "WHENEVER A CYCLE CROSSES THE MEDIAN LINE, THIS IS A CRITICAL DAY"
1310 PRINT "%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*BE CAREFUL%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*"
1340 PRINT " DOWN CRITICAL UP"
1350 PRINT D$(R);D;M$(M)
1360 LET F(1)=42
1370 LET F$(1)="*"
1380 GOSUB 770
1390 LET F(2)=42+NI
1400 LET F$(2)="I"
1410 GOSUB 790
1420 LET F(3)=42+NE
1430 LET F$(3)="E"
1440 GOSUB 810
1450 LET F(4)=42+NP
1460 LET F$(4)="P"
1470 FOR I=1 TO 3
1480 FOR J=I+1 TO 3
1490 IF F(I)<F(J) THEN GOTO 1600
1500 IF F(I)=F(J) THEN LET F(I)=0
1510 LET F$(I)=""
1515 LET F$(J)="X"
1520 GOTO 1600
1530 LET Q=F(I)
1540 LET Q$=F$(I)
1550 LET F(I)=F(J)
1560 LET F$(I)=F$(J)
1570 LET F(J)=Q
1580 LET F$(J)=Q$
1600 NEXT J
1610 NEXT I
1620 FOR I=1 TO 4
1630 PRINT TAB (F(I))
1640 PRINT TAB (F(J))
1650 NEXT I
1660 LET X=X+.5
1670 IF INT (X)<>X THEN GOTO 1360
1680 IF Z=ZA-1 THEN GOTO 2500
1690 LET R=RH
1700 IF R=7 THEN LET R=0
1710 LET D=D+1
1720 IF M=40 OR RM=60 OR RM=90 OR RM=11 THEN LET L=30
1730 GOTO 1800
1740 IF M=2 AND Y/4=INT (Y/4) THEN LET L=29
1750 GOTO 1800
1760 IF M=2 THEN LET L=28
1770 GOTO 1800
1780 LET L=31
1800 IF D>L THEN LET D=D-L
1810 LET M=M+1
1820 GOTO 1900
1830 PRINT
1840 LET Z=ZH
1850 GOTO 1350
1900 IF M=13 THEN LET M=1
1910 LET Z=Z+1
1920 GOTO 1350
1930 LET Z=Z+1
1940 GOTO 1350
2500 PRINT
2510 PRINT "IT HAS BEEN ";X-1;" DAYS OR ";(X-1)*24;" HOURS SINCE YOU WERE BORN"
2520 LET XS=X
2530 PRINT "OR APPROX, ";XS*24*90;" HEARTBEAT SINCE THE DAY OF YOUR BIRTH"
2540 INPUT QR
2550 CLEAR
2560 GOTO 10
3000 STOP
3010 SAVE "1016%9"
3020 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
