Biorhythms: Difference between revisions
(Python example) |
|||
Line 408: | Line 408: | ||
Emotional day 11 : 62.3% (up but falling, next transition 1863-11-22) |
Emotional day 11 : 62.3% (up but falling, next transition 1863-11-22) |
||
Mental day 5 : 81.4% (up and rising, next peak 1863-11-22) |
Mental day 5 : 81.4% (up and rising, next peak 1863-11-22) |
||
</pre> |
|||
=={{header|Python}}== |
|||
<lang python> |
|||
""" |
|||
Python implementation of |
|||
http://rosettacode.org/wiki/Biorhythms |
|||
""" |
|||
from datetime import date, timedelta |
|||
from math import floor, sin, pi |
|||
def biorhythms(birthdate,targetdate): |
|||
""" |
|||
Print out biorhythm data for targetdate assuming you were |
|||
born on birthdate. |
|||
birthdate and targetdata are strings in this format: |
|||
YYYY-MM-DD e.g. 1964-12-26 |
|||
""" |
|||
# print dates |
|||
print("Born: "+birthdate+" Target: "+targetdate) |
|||
# convert to date types - Python 3.7 or later |
|||
birthdate = date.fromisoformat(birthdate) |
|||
targetdate = date.fromisoformat(targetdate) |
|||
# days between |
|||
days = (targetdate - birthdate).days |
|||
print("Day: "+str(days)) |
|||
# cycle logic - mostly from Julia example |
|||
cycle_labels = ["Physical", "Emotional", "Mental"] |
|||
cycle_lengths = [23, 28, 33] |
|||
quadrants = [("up and rising", "peak"), ("up but falling", "transition"), |
|||
("down and falling", "valley"), ("down but rising", "transition")] |
|||
for i in range(3): |
|||
label = cycle_labels[i] |
|||
length = cycle_lengths[i] |
|||
position = days % length |
|||
quadrant = int(floor((4 * position) / length)) |
|||
percentage = int(round(100 * sin(2 * pi * position / length),0)) |
|||
transition_date = targetdate + timedelta(days=floor((quadrant + 1)/4 * length) - position) |
|||
trend, next = quadrants[quadrant] |
|||
if percentage > 95: |
|||
description = "peak" |
|||
elif percentage < -95: |
|||
description = "valley" |
|||
elif abs(percentage) < 5: |
|||
description = "critical transition" |
|||
else: |
|||
description = str(percentage)+"% ("+trend+", next "+next+" "+str(transition_date)+")" |
|||
print(label+" day "+str(position)+": "+description) |
|||
biorhythms("1943-03-09","1972-07-11") |
|||
</lang> |
|||
{{out}} |
|||
<pre> |
|||
Born: 1943-03-09 Target: 1972-07-11 |
|||
Day: 10717 |
|||
Physical day 22: -27% (down but rising, next transition 1972-07-12) |
|||
Emotional day 21: valley |
|||
Mental day 25: valley |
|||
</pre> |
</pre> |
||
Revision as of 20:25, 29 December 2020
You are encouraged to solve this task according to the task description, using any language you may know.
For a while in the late 70s, the pseudoscience of biorhythms was popular enough to rival astrology, with kiosks in malls that would give you your weekly printout. It was also a popular entry in "Things to Do with your Pocket Calculator" lists. You can read up on the history at Wikipedia, but the main takeaway is that unlike astrology, the math behind biorhythms is dead simple.
It's based on the number of days since your birth. The premise is that three cycles of unspecified provenance govern certain aspects of everyone's lives – specifically, how they're feeling physically, emotionally, and mentally. The best part is that not only do these cycles somehow have the same respective lengths for all humans of any age, gender, weight, genetic background, etc, but those lengths are an exact number of days! And the pattern is in each case a perfect sine curve. Absolutely miraculous!
To compute your biorhythmic profile for a given day, the first thing you need is the number of days between that day and your birth, so the answers in Days between dates are probably a good starting point. (Strictly speaking, the biorhythms start at 0 at the moment of your birth, so if you know time of day you can narrow things down further, but in general these operate at whole-day granularity.) Then take the residue of that day count modulo each of the the cycle lengths to calculate where the day falls on each of the three sinusoidal journeys.
The three cycles and their lengths are as follows:
Cycle Length Physical 23 days Emotional 28 days Mental 33 days
The first half of each cycle is in "plus" territory, with a peak at the quarter-way point; the second half in "minus" territory, with a valley at the three-quarters mark. You can calculate a specific value between -1 and +1 for the kth day of an n-day cycle by computing sin( 2πk / n ). The days where a cycle crosses the axis in either direction are called "critical" days, although with a cycle value of 0 they're also said to be the most neutral, which seems contradictory.
The task: write a subroutine, function, or program that will, given a birthdate and a target date, output the three biorhythmic values for the day. You may optionally include a text description of the position and the trend (e.g. "up and rising", "peak", "up but falling", "critical", "down and falling", "valley", "down but rising"), an indication of the date on which the next notable event (peak, valley, or crossing) falls, or even a graph of the cycles around the target date. Demonstrate the functionality for dates of your choice.
Example run of my Raku implementation: <lang sh>raku br.raku 1943-03-09 1972-07-11</lang>
- Output:
Day 10717: Physical day 22: -27% (down but rising, next transition 1972-07-12) Emotional day 21: valley Mental day 25: valley
Double valley! This was apparently not a good day for Mr. Fischer to begin a chess tournament...
Factor
<lang factor>USING: calendar calendar.parser formatting io kernel math math.constants math.functions ;
- days-between ( ymd-str ymd-str -- n )
[ ymd>timestamp ] bi@ time- duration>days abs ;
- trend ( pos len -- str ) / 4 * floor 3 divisor? "↑" "↓" ? ;
- percent ( pos len -- x ) [ 2pi * ] [ / sin 100 * ] bi* ;
- .day ( days cycle-length day-type -- )
write [ mod ] keep [ drop ] [ percent ] [ trend ] 2tri " day %d: %.1f%%%s\n" printf ;
- .biorhythm ( ymd-str ymd-str -- )
2dup "Born %s, Target %s\n" printf days-between dup "Day %d\n" printf [ 23 "Physical" .day ] [ 28 "Emotional" .day ] [ 33 "Mental" .day ] tri ;
"1809-02-12" "1863-11-19" .biorhythm</lang>
- Output:
Born 1809-02-12, Target 1863-11-19 Day 20003 Physical day 16: -94.2%↓ Emotional day 11: 62.3%↓ Mental day 5: 81.5%↑
Go
<lang go>package main
import (
"fmt" "log" "math" "time"
)
const layout = "2006-01-02" // template for time.Parse
var cycles = [3]string{"Physical day ", "Emotional day", "Mental day "} var lengths = [3]int{23, 28, 33} var quadrants = [4][2]string{
{"up and rising", "peak"}, {"up but falling", "transition"}, {"down and falling", "valley"}, {"down but rising", "transition"},
}
func check(err error) {
if err != nil { log.Fatal(err) }
}
// Parameters assumed to be in YYYY-MM-DD format. func biorhythms(birthDate, targetDate string) {
bd, err := time.Parse(layout, birthDate) check(err) td, err := time.Parse(layout, targetDate) check(err) days := int(td.Sub(bd).Hours() / 24) fmt.Printf("Born %s, Target %s\n", birthDate, targetDate) fmt.Println("Day", days) for i := 0; i < 3; i++ { length := lengths[i] cycle := cycles[i] position := days % length quadrant := position * 4 / length percent := math.Sin(2 * math.Pi * float64(position) / float64(length)) percent = math.Floor(percent*1000) / 10 descript := "" if percent > 95 { descript = " peak" } else if percent < -95 { descript = " valley" } else if math.Abs(percent) < 5 { descript = " critical transition" } else { daysToAdd := (quadrant+1)*length/4 - position transition := td.Add(time.Hour * 24 * time.Duration(daysToAdd)) trend := quadrants[quadrant][0] next := quadrants[quadrant][1] transStr := transition.Format(layout) descript = fmt.Sprintf("%5.1f%% (%s, next %s %s)", percent, trend, next, transStr) } fmt.Printf("%s %2d : %s\n", cycle, position, descript) } fmt.Println()
}
func main() {
datePairs := [][2]string{ {"1943-03-09", "1972-07-11"}, {"1809-01-12", "1863-11-19"}, {"1809-02-12", "1863-11-19"}, // correct DOB for Abraham Lincoln } for _, datePair := range datePairs { biorhythms(datePair[0], datePair[1]) }
}</lang>
- Output:
Born 1943-03-09, Target 1972-07-11 Day 10717 Physical day 22 : -27.0% (down but rising, next transition 1972-07-12) Emotional day 21 : valley Mental day 25 : valley Born 1809-01-12, Target 1863-11-19 Day 20034 Physical day 1 : 26.9% (up and rising, next peak 1863-11-23) Emotional day 14 : critical transition Mental day 3 : 54.0% (up and rising, next peak 1863-11-24) Born 1809-02-12, Target 1863-11-19 Day 20003 Physical day 16 : -94.3% (down and falling, next valley 1863-11-20) Emotional day 11 : 62.3% (up but falling, next transition 1863-11-22) Mental day 5 : 81.4% (up and rising, next peak 1863-11-22)
Julia
<lang julia>using Dates
const cycles = ["Physical" => 23, "Emotional" => 28,"Mental" => 33] const quadrants = [("up and rising", "peak"), ("up but falling", "transition"),
("down and falling", "valley"), ("down but rising", "transition")]
function tellfortune(birthday::Date, date = today())
days = (date - birthday).value target = (date - Date(0)).value println("Born $birthday, target date $date\nDay $days:") for (label, length) in cycles position = days % length quadrant = Int(floor((4 * position) / length)) + 1 percentage = round(100 * sinpi(2 * position / length), digits=1) transition = target - position + (length * quadrant) ÷ 4 trend, next = quadrants[quadrant] description = (percentage > 95) ? "peak" : (percentage < -95) ? "valley" : (abs(percentage) < 5) ? "critical transition" : "$percentage% ($trend, next $next $(Date(0) + Dates.Day(transition)))" println("$label day $position: $description") end println()
end
tellfortune(Date("1943-03-09"), Date("1972-07-11")) tellfortune(Date("1809-01-12"), Date("1863-11-19")) tellfortune(Date("1809-02-12"), Date("1863-11-19"))
</lang>
- Output:
Born 1943-03-09, target date 1972-07-11 Day 10717: Physical day 22: -27.0% (down but rising, next transition 1972-07-12) Emotional day 21: valley Mental day 25: valley Born 1809-01-12, target date 1863-11-19 Day 20034: Physical day 1: 27.0% (up and rising, next peak 1863-11-23) Emotional day 14: critical transition Mental day 3: 54.1% (up and rising, next peak 1863-11-24) Born 1809-02-12, target date 1863-11-19 Day 20003: Physical day 16: -94.2% (down and falling, next valley 1863-11-20) Emotional day 11: 62.3% (up but falling, next transition 1863-11-22) Mental day 5: 81.5% (up and rising, next peak 1863-11-22)
Nim
<lang Nim>import math import strformat import times
type Cycle {.pure.} = enum Physical, Emotional, Mental
const
Lengths: array[Cycle, int] = [23, 28, 33]
Quadrants = [("up and rising", "peak"), ("up but falling", "transition"), ("down and falling", "valley"), ("down but rising", "transition")]
DateFormat = "YYYY-MM-dd"
- ---------------------------------------------------------------------------------------------------
proc biorythms(birthDate: DateTime; targetDate: DateTime = now()) =
## Display biorythms data. Arguments are DateTime values.
echo fmt"Born {birthDate.format(DateFormat)}, target date {targetDate.format(DateFormat)}" let days = (targetDate - birthDate).inDays echo "Day ", days
for cycle, length in Lengths:
let position = int(days mod length) let quadrant = int(4 * position / length) let percentage = round(100 * sin(2 * PI * (position / length)), 1)
var description: string if percentage > 95: description = "peak" elif percentage < -95: description = "valley" elif abs(percentage) < 5: description = "critical transition" else: let (trend, next) = Quadrants[quadrant] let transition = targetDate + initDuration(days = (quadrant + 1) * length div 4 - position) description = fmt"{percentage}% ({trend}, next {next} {transition.format(DateFormat)})"
echo fmt"{cycle} day {position}: {description}"
echo ""
- ---------------------------------------------------------------------------------------------------
proc biorythms(birthDate, targetDate = "") =
## Display biorythms data. Arguments are strings in ISO format year-month-day. let date = if targetDate.len == 0: now() else: targetDate.parse(DateFormat) biorythms(birthDate.parse(DateFormat), date)
- ———————————————————————————————————————————————————————————————————————————————————————————————————
when isMainModule:
biorythms("1943-03-09", "1972-07-11") biorythms("1809-01-12", "1863-11-19") biorythms("1809-02-12", "1863-11-19")</lang>
- Output:
Born 1943-03-09, target date 1972-07-11 Day 10717 Physical day 22: -27.0% (down but rising, next transition 1972-07-12) Emotional day 21: valley Mental day 25: valley Born 1809-01-12, target date 1863-11-19 Day 20034 Physical day 1: 27.0% (up and rising, next peak 1863-11-23) Emotional day 14: critical transition Mental day 3: 54.1% (up and rising, next peak 1863-11-24) Born 1809-02-12, target date 1863-11-19 Day 20003 Physical day 16: -94.2% (down and falling, next valley 1863-11-20) Emotional day 11: 62.3% (up but falling, next transition 1863-11-22) Mental day 5: 81.5% (up and rising, next peak 1863-11-22)
Perl
<lang perl>use strict; use warnings; use DateTime;
use constant PI => 2 * atan2(1, 0);
my %cycles = ( 'Physical' => 23, 'Emotional' => 28, 'Mental' => 33 ); my @Q = ( ['up and rising', 'peak'],
['up but falling', 'transition'], ['down and falling', 'valley'], ['down but rising', 'transition'] );
my $target = DateTime->new(year=>1863, month=>11, day=>19); my $bday = DateTime->new(year=>1809, month=> 2, day=>12);
my $days = $bday->delta_days( $target )->in_units('days');
print "Day $days:\n"; for my $label (sort keys %cycles) {
my($length) = $cycles{$label}; my $position = $days % $length; my $quadrant = int $position / $length * 4; my $percentage = int(sin($position / $length * 2 * PI )*1000)/10; my $description; if ( $percentage > 95) { $description = 'peak' } elsif ( $percentage < -95) { $description = 'valley' } elsif (abs($percentage) < 5) { $description = 'critical transition' } else { my $transition = $target->clone->add( days => (int(($quadrant + 1)/4 * $length) - $position))->ymd; my ($trend, $next) = @{$Q[$quadrant]}; $description = sprintf "%5.1f%% ($trend, next $next $transition)", $percentage; } printf "%-13s %2d: %s", "$label day\n", $position, $description;
}</lang>
- Output:
Day 20003: Emotional day 11: 62.3% (up but falling, next transition 1863-11-22) Mental day 5: 81.4% (up and rising, next peak 1863-11-22) Physical day 16: -94.2% (down and falling, next valley 1863-11-20)
Phix
<lang Phix>include timedate.e
constant cycles = {"Physical day ", "Emotional day", "Mental day "},
lengths = {23, 28, 33}, quadrants = {{"up and rising", "peak"}, {"up but falling", "transition"}, {"down and falling", "valley"}, {"down but rising", "transition"}}
procedure biorhythms(string birthDate, targetDate)
timedate bd = parse_date_string(birthDate,{"YYYY-MM-DD"}), td = parse_date_string(targetDate,{"YYYY-MM-DD"}) integer days = floor(timedate_diff(bd, td, DT_DAY)/(60*60*24)) printf(1,"Born %s, Target %s\n",{birthDate,targetDate}) printf(1,"Day %d\n",days) for i=1 to 3 do integer len = lengths[i], posn = remainder(days,len), quadrant = floor(posn/len*4)+1 atom percent = floor(sin(2*PI*posn/len)*1000)/10 string cycle = cycles[i], desc = iff(percent>95 ? " peak" : iff(percent<-95 ? " valley" : iff(abs(percent)<5 ? " critical transition" : "other"))) if desc == "other" then timedate t = adjust_timedate(td,timedelta(days:=floor(quadrant/4*len)-posn)) string transition = format_timedate(t,"YYYY-MM-DD"), {trend,next} = quadrants[quadrant] desc = sprintf("%5.1f%% (%s, next %s %s)", {percent, trend, next, transition}) end if printf(1,"%s %2d : %s\n", {cycle, posn, desc}) end for printf(1,"\n")
end procedure
constant datePairs = {
{"1943-03-09", "1972-07-11"}, {"1809-01-12", "1863-11-19"}, {"1809-02-12", "1863-11-19"} // correct DOB for Abraham Lincoln
} for i=1 to length(datePairs) do biorhythms(datePairs[i][1], datePairs[i][2]) end for</lang>
- Output:
Born 1943-03-09, Target 1972-07-11 Day 10717 Physical day 22 : -27.0% (down but rising, next transition 1972-07-12) Emotional day 21 : valley Mental day 25 : valley Born 1809-01-12, Target 1863-11-19 Day 20034 Physical day 1 : 26.9% (up and rising, next peak 1863-11-23) Emotional day 14 : critical transition Mental day 3 : 54.0% (up and rising, next peak 1863-11-24) Born 1809-02-12, Target 1863-11-19 Day 20003 Physical day 16 : -94.3% (down and falling, next valley 1863-11-20) Emotional day 11 : 62.3% (up but falling, next transition 1863-11-22) Mental day 5 : 81.4% (up and rising, next peak 1863-11-22)
Python
<lang python> """
Python implementation of
http://rosettacode.org/wiki/Biorhythms
"""
from datetime import date, timedelta from math import floor, sin, pi
def biorhythms(birthdate,targetdate):
""" Print out biorhythm data for targetdate assuming you were born on birthdate. birthdate and targetdata are strings in this format: YYYY-MM-DD e.g. 1964-12-26 """ # print dates print("Born: "+birthdate+" Target: "+targetdate) # convert to date types - Python 3.7 or later birthdate = date.fromisoformat(birthdate) targetdate = date.fromisoformat(targetdate) # days between days = (targetdate - birthdate).days print("Day: "+str(days)) # cycle logic - mostly from Julia example cycle_labels = ["Physical", "Emotional", "Mental"] cycle_lengths = [23, 28, 33] quadrants = [("up and rising", "peak"), ("up but falling", "transition"), ("down and falling", "valley"), ("down but rising", "transition")] for i in range(3): label = cycle_labels[i] length = cycle_lengths[i] position = days % length quadrant = int(floor((4 * position) / length)) percentage = int(round(100 * sin(2 * pi * position / length),0)) transition_date = targetdate + timedelta(days=floor((quadrant + 1)/4 * length) - position) trend, next = quadrants[quadrant] if percentage > 95: description = "peak" elif percentage < -95: description = "valley" elif abs(percentage) < 5: description = "critical transition" else: description = str(percentage)+"% ("+trend+", next "+next+" "+str(transition_date)+")" print(label+" day "+str(position)+": "+description)
biorhythms("1943-03-09","1972-07-11") </lang>
- Output:
Born: 1943-03-09 Target: 1972-07-11 Day: 10717 Physical day 22: -27% (down but rising, next transition 1972-07-12) Emotional day 21: valley Mental day 25: valley
R
Also creates a plot showing past and future 30-day cycles
<lang R>bioR <- function(bDay, targetDay) {
bDay <- as.Date(bDay) targetDay <- as.Date(targetDay) n <- as.numeric(targetDay - bDay) cycles <- c(23, 28, 33) mods <- n %% cycles bioR <- c(sin(2 * pi * mods / cycles)) loc <- mods / cycles current <- ifelse(bioR > 0, ': Up', ': Down') current <- paste(current, ifelse(loc < 0.25 | loc > 0.75, "and rising", "and falling")) df <- data.frame(dates = seq.Date(from = targetDay - 30, to = targetDay + 30, by = 1)) df$n <- as.numeric(df$dates - bDay) df$P <- sin(2 * pi * (df$n %% cycles[1]) / cycles[1]) df$E <- sin(2 * pi * (df$n %% cycles[2]) / cycles[2]) df$M <- sin(2 * pi * (df$n %% cycles[3]) / cycles[3]) plot(df$dates, df$P, col = 'blue', main = paste(targetDay, 'Biorhythm for Birthday on', bDay), xlab = "", ylab = "Intensity") points(df$dates, df$E, col = 'green') points(df$dates, df$M, col = 'red') abline(v = targetDay) legend('topleft', legend = c("Phys", "Emot", "Ment"), col =c("blue", "green", "red"), cex = 0.8, pch = 21) cat(paste0('Birthday = ', as.character(bDay), '\nTarget Date = ', as.character(targetDay), '\n', n, ' days', '\nPhysical = ', mods[1], current[1], '\nEmotional = ', mods[2], current[2], '\nMental = ', mods[3], current[3]))
}
bioR('1943-03-09', '1972-07-11')</lang>
- Output:
Birthday = 1943-03-09 Target Date = 1972-07-11 10717 days Physical = 22: Down and rising Emotional = 21: Down and falling Mental = 25: Down and rising
Raku
<lang raku>#!/usr/bin/env raku my %cycles = ( :23Physical, :28Emotional, :33Mental ); my @quadrants = [ ('up and rising', 'peak'),
('up but falling', 'transition'), ('down and falling', 'valley'), ('down but rising', 'transition') ];
sub MAIN($birthday, $date = Date.today()) {
if !$birthday { die "Birthday not specified.\n" ~ "Supply --birthday option or set \$BIRTHDAY in environment.\n"; }
my ($bday, $target) = ($birthday, $date).map: { Date.new($_) }; my $days = $target - $bday;
say "Day $days:"; for %cycles.sort(+*.value)».kv -> ($label, $length) { my $position = $days % $length; my $quadrant = floor($position / $length * 4); my $percentage = floor(sin($position / $length * 2 * π )*1000)/10; my $description; if $percentage > 95 { $description = 'peak'; } elsif $percentage < -95 { $description = 'valley'; } elsif abs($percentage) < 5 { $description = 'critical transition' } else { my $transition = $target + floor(($quadrant + 1)/4 * $length) - $position; my ($trend, $next) = @quadrants[$quadrant]; $description = "$percentage% ($trend, next $next $transition)"; } say "$label day $position: $description"; }
}</lang>
- Output:
$ br 1809-01-12 1863-11-19 Day 20034: Physical day 1: 26.9% (up and rising, next peak 1863-11-23) Emotional day 14: critical transition Mental day 3: 54% (up and rising, next peak 1863-11-24)
REXX
The daysbet2 (REXX program) is used (invoked on line 3 of this program) to calculate the number of days between two dates,
where the dates can be in several formats:
, (a comma) indicates today's date * (an asterisk) indicates today's date yyyy-mm-dd where yyyy may be a 2- or 4-digit year, mm may be a 1- or 2-digit month, dd may be a 1- or 2-digit day of month mm/dd/yyyy (as above) mm/dd (as above), but the current year is assumed dd\mm\yyyy (as above) dd\mm (as above), but the current year is assumed
It is usual to use the birth date of a person. <lang>/*REXX pgm shows the states of a person's biorhythms (physical, emotional, intellectual)*/ parse arg birthdate targetDate . /*obtain one or two dates from the C.L.*/ days= daysbet2(birthdate targetDate) /*invoke the 2nd version of a REXX pgm.*/ if days==0 then do; say; say 'The two dates specified are exacty the same.'; exit 1
end
cycles= 'physical emotional intellectual' /*the names of each biorhythm cycle*/ cycle = 'negative neutral positive' /* " states of " " " */ @.1= 23; @.2= 28; @.3= 33 /* " # of days in " " " */ pid2= pi() * 2 * days /*calculate pi * t * number─of─days. */
do j=1 for 3 state= 2 + sign( sin( pid2 / @.j) ) /*obtain state for each biorhythm cycle*/ say 'biorhythm for the' right(word(cycles,j),12) "cycle is" word(cycle, state) end /*j*/ /* [↑] get state for each biorhythm. */
exit 0 /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ pi: pi= 3.1415926535897932384626433832795028841971693993751058209749445923078; return pi r2r: return arg(1) // (pi() * 2) /*normalize radians ──► a unit circle. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ sin: procedure; parse arg x; x= r2r(x); _= x; numeric fuzz min(5, max(1, digits() -3))
if x=pi * .5 then return 1; if x==pi*1.5 then return -1 if abs(x)=pi | x=0 then return 0; q= x*x; z= x do k=2 by 2 until p=z; p= z; _= -_ *q/(k*k+k); z= z+_; end; return z</lang>
- output when using the input of: 6/9/1946
Note: today's date is being used, today is the 6th of September, 2020.
biorhythm for the physical cycle is positive biorhythm for the emotional cycle is neutral biorhythm for the intellectual cycle is negative
Ruby
<lang Ruby>require 'date' CYCLES = {physical: 23, emotional: 28, mental: 33}
def biorhythms(date_of_birth, target_date = Date.today.to_s)
days_alive = Date.parse(target_date) - Date.parse(date_of_birth) CYCLES.each do |name, num_days| cycle_day = days_alive % num_days state = case cycle_day when 0, num_days/2 then "neutral" when (1.. num_days/2) then "positive" when (num_days/2+1..num_days) then "negative" end puts "%-10s: cycle day %2s, %s" % [name, cycle_day.to_i, state] end
end
biorhythms("1943-03-09", "1972-07-11") </lang>
- Output:
physical : cycle day 22, negative emotional : cycle day 21, negative mental : cycle day 25, negative
Tcl
A graphing version using Tcl+Tk: <lang tcl>#!/usr/bin/env wish
- Biorhythm calculator
set today [clock format [clock seconds] -format %Y-%m-%d ] proc main [list birthday [list target $today]] {
set day [days-between $birthday $target]
array set cycles { Physical {23 red} Emotional {28 green} Mental {33 blue} }
set pi [expr atan2(0,-1)]
canvas .c -width 306 -height 350 -bg black .c create rectangle 4 49 306 251 -outline grey .c create line 5 150 305 150 -fill grey .c create line 145 50 145 250 -fill cyan .c create text 145 15 -text "$target" -fill cyan .c create text 145 30 -text "(Day $day)" -fill cyan set ly 305 foreach {name data} [array get cycles] { lassign $data length color .c create text 60 $ly -anchor nw -text $name -fill $color set pos [expr $day % $length] for {set dd -14} {$dd <= 16} {incr dd} { set d [expr $pos + $dd] set x [expr 145 + 10 * $dd] .c create line $x 145 $x 155 -fill grey set v [expr sin(2*$pi*$d/$length)] set y [expr 150 - 100 * $v] if {$dd == 0} { .c create text 10 $ly -anchor nw \ -text "[format %+04.1f%% [expr $v * 100]]" -fill $color } if [info exists ox] { .c create line $ox $oy $x $y -fill $color } set ox $x set oy $y } unset ox oy set ly [expr $ly - 25] } pack .c
}
proc days-between {from to} {
expr int([rd $to] - [rd $from])
}
- parse an (ISO-formatted) date into a day number
proc rd {date} {
lassign [scan $date %d-%d-%d] year month day set elapsed [expr $year - 1] expr {$elapsed * 365 + floor($elapsed/4) - floor($elapsed/100) + floor($elapsed/400) + floor( (367*$month-362)/12 ) + ($month < 3 ? 0 : ([is-leap $year] ? -1 : -2)) + $day}
}
proc is-leap {year} {
expr {$year % 4 == 0 && ($year % 100 || $year % 400 == 0)}
}
main {*}$argv</lang>
- Output:
Output of <lang sh>wish br.wish 1809-02-12 1863-11-19</lang> - Lincoln's biorhythms at Gettysburg: https://i.imgur.com/U2izZOM.png
VBA
<lang vb>Function Biorhythm(Birthdate As Date, Targetdate As Date) As String
'Jagged Array TextArray = Array(Array("up and rising", "peak"), Array("up but falling", "transition"), Array("down and falling", "valley"), Array("down but rising", "transition"))
DaysBetween = Targetdate - Birthdate
positionP = DaysBetween Mod 23 positionE = DaysBetween Mod 28 positionM = DaysBetween Mod 33
'return the positions - just to return something Biorhythm = CStr(positionP) & "/" & CStr(positionE) & "/" & CStr(positionM)
quadrantP = Int(4 * positionP / 23) quadrantE = Int(4 * positionE / 28) quadrantM = Int(4 * positionM / 33)
percentageP = Round(100 * Sin(2 * WorksheetFunction.Pi * (positionP / 23)), 1) percentageE = Round(100 * Sin(2 * WorksheetFunction.Pi * (positionE / 28)), 1) percentageM = Round(100 * Sin(2 * WorksheetFunction.Pi * (positionM / 33)), 1)
transitionP = Targetdate + WorksheetFunction.Floor((quadrantP + 1) / 4 * 23, 1) - positionP transitionE = Targetdate + WorksheetFunction.Floor((quadrantE + 1) / 4 * 28, 1) - positionE transitionM = Targetdate + WorksheetFunction.Floor((quadrantM + 1) / 4 * 33, 1) - positionM
Select Case True
Case percentageP > 95 textP = "Physical day " & positionP & " : " & "peak" Case percentageP < -95 textP = "Physical day " & positionP & " : " & "valley" Case percentageP < 5 And percentageP > -5 textP = "Physical day " & positionP & " : " & "critical transition" Case Else textP = "Physical day " & positionP & " : " & percentageP & "% (" & TextArray(quadrantP)(0) & ", next " & TextArray(quadrantP)(1) & " " & transitionP & ")"
End Select
Select Case True
Case percentageE > 95 textE = "Emotional day " & positionE & " : " & "peak" Case percentageE < -95 textE = "Emotional day " & positionE & " : " & "valley" Case percentageE < 5 And percentageE > -5 textE = "Emotional day " & positionE & " : " & "critical transition" Case Else textE = "Emotional day " & positionE & " : " & percentageE & "% (" & TextArray(quadrantE)(0) & ", next " & TextArray(quadrantE)(1) & " " & transitionE & ")"
End Select
Select Case True
Case percentageM > 95 textM = "Mental day " & positionM & " : " & "peak" Case percentageM < -95 textM = "Mental day " & positionM & " : " & "valley" Case percentageM < 5 And percentageM > -5 textM = "Mental day " & positionM & " : " & "critical transition" Case Else textM = "Mental day " & positionM & " : " & percentageM & "% (" & TextArray(quadrantM)(0) & ", next " & TextArray(quadrantM)(1) & " " & transitionM & ")"
End Select
Header1Text = "Born " & Birthdate & ", Target " & Targetdate Header2Text = "Day " & DaysBetween
'Print Result Debug.Print Header1Text Debug.Print Header2Text Debug.Print textP Debug.Print textE Debug.Print textM Debug.Print ""
End Function</lang>
- Output:
Born 09.03.1943, Target 11.07.1972 Day 10717 Physical day 22 : -27% (down but rising, next transition 12.07.1972) Emotional day 21 : valley Mental day 25 : valley Born 12.02.1809, Target 19.11.1863 Day 20003 Physical day 16 : -94.2% (down and falling, next valley 20.11.1863) Emotional day 11 : 62.3% (up but falling, next transition 22.11.1863) Mental day 5 : 81.5% (up and rising, next peak 22.11.1863) Born 12.01.1809, Target 19.11.1863 Day 20034 Physical day 1 : 27% (up and rising, next peak 23.11.1863) Emotional day 14 : critical transition Mental day 3 : 54.1% (up and rising, next peak 24.11.1863)
Wren
<lang ecmascript>import "/date" for Date import "/fmt" for Fmt
var cycles = ["Physical day ", "Emotional day", "Mental day "] var lengths = [23, 28, 33] var quadrants = [
["up and rising", "peak"], ["up but falling", "transition"], ["down and falling", "valley"], ["down but rising", "transition"]
]
var biorhythms = Fn.new { |birthDate, targetDate|
var bd = Date.parse(birthDate) var td = Date.parse(targetDate) var days = (td - bd).days Date.default = Date.isoDate System.print("Born %(birthDate), Target %(targetDate)") System.print("Day %(days)") for (i in 0..2) { var length = lengths[i] var cycle = cycles[i] var position = days % length var quadrant = (position / length * 4).floor var percent = ((2 * Num.pi * position / length).sin * 1000).floor / 10 var descript = (percent > 95) ? " peak" : (percent < -95) ? " valley" : (percent.abs < 5) ? " critical transition" : "other" if (descript == "other") { var transition = td.addDays(((quadrant + 1) / 4 * length).floor - position) var tn = quadrants[quadrant] var trend = tn[0] var next = tn[1] descript = Fmt.swrite("$5.1f\% ($s, next $s $s)", percent, trend, next, transition) } Fmt.print("$s $2d : $s", cycle, position, descript) } System.print()
}
var datePairs = [
["1943-03-09", "1972-07-11"], ["1809-01-12", "1863-11-19"], ["1809-02-12", "1863-11-19"] // correct DOB for Abraham Lincoln
] for (datePair in datePairs) biorhythms.call(datePair[0], datePair[1])</lang>
- Output:
Born 1943-03-09, Target 1972-07-11 Day 10717 Physical day 22 : -27.0% (down but rising, next transition 1972-07-12) Emotional day 21 : valley Mental day 25 : valley Born 1809-01-12, Target 1863-11-19 Day 20034 Physical day 1 : 26.9% (up and rising, next peak 1863-11-23) Emotional day 14 : critical transition Mental day 3 : 54.0% (up and rising, next peak 1863-11-24) Born 1809-02-12, Target 1863-11-19 Day 20003 Physical day 16 : -94.3% (down and falling, next valley 1863-11-20) Emotional day 11 : 62.3% (up but falling, next transition 1863-11-22) Mental day 5 : 81.4% (up and rising, next peak 1863-11-22)