/usr/share/lifelines/bday_cover.ll is in lifelines-reports 3.0.61-2build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | /*
* @progname bday_cover.ll
* @version 1 of 1994-11-02
* @author Andrew Deacon
* @category
* @output Text
* @description
A novelty report that lists on which days of the year people were born
and how many people share the same birthday. All valid birthdays
are considered. A valid birthday is one where the extracted birthday,
performed using extractdate(), has a month in the range 1-12 and a day
within that month.
This program works only with LifeLines.
The output is not sorted. The following are examples of
how to sort the output using UNIX sort:
# sort by frequency
sort +2n +0M bday.out
sort +2nr +0M bday.out
# sort by month
sort -M bday.out
*/
global(julian)
global(daysinmonth)
proc main ()
{
table(day_counts)
list(day_list)
/* Formats/modes for date functions */
monthformat(3) dayformat(1) dateformat(1)
set(julian, 0) /* change to use Julian dates */
/* Initialize counters */
set(totaldays, 0) set(totalmonths, 0) set(totalbirths, 0)
/* Iterate over whole database */
forindi (indi, num) {
/* if birthday recorded for individual */
if (bth, birth(indi)) {
/* Extract birthday for individual */
extractdate(bth, birthday, birthmonth, birthyear)
call get_days_in_month(birthday, birthmonth, birthyear)
/* if valid birthday */
if (and(gt(birthday, 0), le(birthday, daysinmonth))) {
/* Extract the month name and day */
set(bday, concat(substring(stddate(birth(indi)),1,6)," "))
/* if existing birthday found - just increment */
if(nmatch, lookup(day_counts, bday)) {
set(nmatch, add(nmatch, 1))
}
/* else new birthday - insert */
else {
set(totaldays, add(totaldays,1))
enqueue(day_list, bday)
set(nmatch, 1)
}
insert(day_counts, bday, nmatch)
set(totalbirths, add(totalbirths,1))
/* Extract the month name */
set(bmon, concat(substring(stddate(birth(indi)),1,4),"**"))
/* if existing birth month found - just increment */
if(nmatch, lookup(day_counts, bmon)) {
set(nmatch, add(nmatch, 1))
}
/* else new birth month - insert */
else {
set(totalmonths, add(totalmonths,1))
enqueue(day_list, bmon)
set(nmatch, 1)
}
insert(day_counts, bmon, nmatch)
}
}
}
/* Write report to file - use Unix sort to sort output! */
"Distribution of birth days\n\n"
"Month & day Frequency\n\n"
forlist(day_list, bday, num) {
bday
set(nmatch, lookup(day_counts, bday))
col(sub(25, strlen(d(nmatch))))
d(nmatch) "\n"
}
"Total birthdays in database: " d(totalbirths) "\n"
"Total days (out of 366) : " d(totaldays) "\n"
"Total months (out of 12) : " d(totalmonths) "\n"
}
proc get_days_in_month(birthday, birthmonth, birthyear)
{
/* code from a routine in "dates" by Jim Eggert */
/* procedure sets global variable daysinmonth */
set(daysinmonth, 31)
if (or(le(birthmonth, 0), gt(birthmonth, 12)))
{ set(daysinmonth, 0) }
elsif (or(or(eq(birthmonth, 9), eq(birthmonth, 4)),
or(eq(birthmonth, 6), eq(birthmonth, 11))))
{ set(daysinmonth, 30) }
elsif (eq(birthmonth, 2)) {
if (and(eq(mod(birthyear, 4), 0),
or(julian, or(ne(mod(birthyear, 100), 0),
eq(mod(birthyear, 400), 0)))))
{ set(daysinmonth, 29) }
else
{ set(daysinmonth, 28) }
}
else
{ set(daysinmonth, 31) }
}
/*
Sample output:
sorted by sort +2nr +0M sample.output and then edited
Distribution of birthdays
Total birthdays in database: 374
Total days (out of 366) : 236
Total months (out of 12) : 12
Month & day Frequency
AUG 12 6
SEP 12 5
FEB 10 4
MAR 03 4
APR 12 4
JUN 17 4
JAN 06 3
JAN 18 3
JAN 29 3
........
*/
/*
Below is a simple C program hack to check if your values
are similar to those generated randomly by the program.
Extract the program from these comment to compile and execute.
Change the RSEED to do different tests; change the ITERATIONS
to vary accuracy. Can also change the NUM_DAYS_REQUIRED
to the value obtained for your database and check if the people
required is similar.
#define RSEED 1576
#define NUM_DAYS 365
#define NUM_DAYS_REQUIRED NUM_DAYS
#define ITERATIONS 2000
#define FALSE 0
#define TRUE 1
static int days[NUM_DAYS];
static int num_got;
static int running_total;
int get_day() {
return rand() % NUM_DAYS;
}
do_it() {
int i;
int j;
int r;
for (i = 0; i < NUM_DAYS; i++) {
days[i] = FALSE;
}
num_got = 0;
i = 0;
while (num_got < NUM_DAYS_REQUIRED) {
i++;
r = get_day();
if (!days[r]) {
days[r] = TRUE;
num_got++;
}
}
printf("Required %d people to cover %d days.\n",i, NUM_DAYS_REQUIRED);
running_total = running_total + i;
}
main() {
int i;
running_total = 0;
srand(RSEED);
for (i = 0; i < ITERATIONS; i++) {
do_it();
}
printf("Average was %d.\n",(int)(running_total/ITERATIONS));
}
*/
|