Gas mileage compiler - (nf)
ajs at hpfcla.UUCP
ajs at hpfcla.UUCP
Sat Jan 7 18:36:57 AEST 1984
#N:hpfcla:43600003:000:9109
hpfcla!ajs Jan 5 22:16:00 1984
Due to the response to my article in net.auto, I'm posting a gas mileage
compiler, manual page, and cute (but undocumented) shell script here,
the proper place for it. It's not a shell archive; sorry, you'll have
to unpack this manually. Also, the manual page has never been through
nroff -- WYSIWYG (what you see is what you get). Enjoy!
Alan Silverstein, Hewlett-Packard Fort Collins Systems Division, Colorado
{ihnp4 | hplabs}!hpfcla!ajs, 303-226-3800 x3053, N 40 31'31" W 105 00'43"
---------- gas.c ----------
/*
* Read raw gas mileage data and print statistics.
*
* See the manual page for more information.
*
* Copyright Hewlett-Packard Company, 1984. Permission is granted for
* unlimited modification, use, and distribution, except that this software
* may not be sold for profit directly nor as part of any software package.
* This software is made available with no warranty of any kind, express
* or implied.
*
* Author:
* Alan Silverstein, Hewlett-Packard Fort Collins Systems Division
* {ihnp4 | hplabs}!hpfcla!ajs
*/
#include <stdio.h>
#define ANNUAL 0 /* for printline() */
#define TOTAL -1
/*
* Line formats:
*/
char *HEAD =
"NUM DATE DAYS MILEAG MILES GALS COST PL MPG MPD CPG CPD\n";
char *SEP =
"=== ====== ==== ====== ===== ===== ====== == ==== === ==== =====\n";
char *LINE0 = "%3d %6d %7d\n";
char *LINE = "%3d %6d %5d %7d %6d %6.1f %7.2f %2s";
char *LINET = " %5d %6d %6.1f %7.2f ";
char *AVG = " %5.1f %5.0f %5.2f %5.2f";
int cflag; /* chart requested? */
char *myname; /* how invoked */
long Adays = 0; /* annual subtotals */
long Amiles = 0;
float Agallons = 0;
float Adollars = 0;
long Tdays = 0; /* grand totals */
long Tmiles = 0;
float Tgallons = 0;
float Tdollars = 0;
/****************************************************************/
main (argc, argv)
int argc;
char **argv;
{
long fields; /* number read in */
long number; /* current line number */
long prevdate; /* previous date */
long date; /* current date */
long days; /* since previous */
long prevodom; /* previous odometer */
long odometer; /* current odometer */
long miles; /* since previous */
long dgallons; /* current decigallons */
float gallons; /* current gallons */
long pennies; /* current cost */
float dollars; /* dollars and cents */
char place[3]; /* where bought */
/*
* Check args and open input file:
*/
myname = *argv++;
if (cflag = (! strcmp (*argv, "-c")))
{
argc--;
argv++;
}
if (argc != 2)
usage();
if (freopen (*argv, "r", stdin) == NULL)
{
fprintf (stderr, "%s: can't open %s\n", myname, *argv);
exit (1);
}
/*
* Print header and first line:
*/
printf (HEAD);
printf (SEP);
/*
* Read lines and print data:
*/
for (number = 0; ; number++)
{
fields = scanf ("%d%d%d%d%s", &date, &odometer, &dgallons,
&pennies, place);
if (fields == EOF)
break;
if (fields != 5)
{
fprintf (stderr, "%s: invalid input line %d\n",
myname, number);
exit (1);
}
if (number == 0) /* first line only */
printf (LINE0, 0, date, odometer);
else {
days = julian (date) - julian (prevdate);
miles = odometer - prevodom;
gallons = dgallons / 10.0;
dollars = pennies / 100.0;
if ((date / 10000) != (prevdate / 10000)) /* new year */
printline (ANNUAL, 0, Adays, 0, Amiles,
Agallons, Adollars, "");
printline (number, date, days, odometer, miles,
gallons, dollars, place);
}
prevdate = date;
prevodom = odometer;
} /* for */
printline (ANNUAL, 0, Adays, 0, Amiles, Agallons, Adollars, "");
printline (TOTAL, 0, Tdays, 0, Tmiles, Tgallons, Tdollars, "");
}
/****************************************************************
* Tell correct usage:
*/
usage ()
{
fprintf (stderr, "usage: %s [-c] gasdatafile\n", myname);
exit (1);
}
/****************************************************************
* Convert to Julian date (within century):
*/
julian (date)
long date; /* number in YYMMDD format */
{
static days[] = { /* days before starts of months */
0, 31, 59, 90, 120, 151,
181, 212, 243, 273, 304, 334
};
long year = (date / 10000);
long month = (date / 100) % 100;
long day = (date % 100);
long leap = (year / 4) - (((year % 4) == 0) && (month < 3));
return ((year * 365) + (days [month - 1]) + day + leap);
}
/****************************************************************
* Print one line (data, subtotal, or total):
* Increments [sub]totals as needed.
*/
printline (number, date, days, odometer, miles, gallons, dollars, place)
long number; /* line num or type */
long date; /* if normal line */
long days; /* delta or total */
long odometer; /* if normal line */
long miles; /* delta or total */
float gallons; /* current or total */
float dollars; /* current or total */
char *place; /* if normal line */
{
int normal = ((number != ANNUAL) && (number != TOTAL));
if (normal)
{
printf (LINE, number, date, days, odometer, miles,
gallons, dollars, place);
Adays += days; /* increment subtotals */
Amiles += miles;
Agallons += gallons;
Adollars += dollars;
} else {
if (number == ANNUAL)
printf ("\n"); /* no need before TOTAL */
printf (LINET, days, miles, gallons, dollars);
if (number == ANNUAL) /* increment totals */
{
Tdays += Adays;
Tmiles += Amiles;
Tgallons += Agallons;
Tdollars += Adollars;
Adays = 0;
Amiles = 0;
Agallons = 0;
Adollars = 0;
}
}
days += (days < 1); /* don't divide by zero */
printf (AVG, (miles / gallons), (miles / (days + 0.0)),
(dollars / gallons), (dollars / days));
if (normal)
{
if (cflag) /* add chart to right */
{ long mpg = (miles / gallons + 0.5);
printf ("%*s*\n", mpg, "");
} else
printf ("\n");
} else
printf ("\n\n");
}
---------- gas.1 ----------
GAS(1) HP EXPERIMENTAL GAS(1)
NAME
gas -- gas mileage "compiler"
SYNOPSIS
gas [-c] gasdatafile
DESCRIPTION
This program reads lines of gas mileage data from a file and
"compiles" it to a final form (e.g., prints a report). Each
input line is of the form:
DATE ODOMETER DECIGALLONS PENNIES PLACE
Fields are separated by white space. DATE is the date gas
was bought (YYMMDD == year, month, day). ODOMETER is the
mileage reading to the nearest mile. DECIGALLONS is the
gallons and tenths bought, without a decimal point. PENNIES
is the cost of the gas, again without a decimal point. PLACE
is a two-character alpha field, free-form, representing the
brand name of the gas. For example:
840105 50345 84 1132 EX
The first input line is an initialization entry; only DATE
and ODOMETER must be valid.
The output starts with two header lines followed by data
lines. Each input line generates one output line containing
these fields:
NUM DATE DAYS MILEAG MILES GALS COST PL MPG MPD CPG CPD
NUM is a sequence number. DATE is the same as before; DAYS
is the number of days elapsed since the last DATE. MILEAG is
as before; MILES is the elapsed mileage. GALS is the gallons
and tenths (with decimal point); COST is the dollars and
cents; PL is the place. MPG and MPD are the miles per gallon
and per day, respectively. CPG and CPD are the cost per
gallon and per day. All averages are rounded as appropriate
and division by zero DAYS is avoided.
Each time the year changes, the program inserts a special
line showing subtotals for DAYS, MILES, GALS, and COST, and
averages for MPG, MPD, CPG, and CPD. A similar grand totals
line is printed at the end.
The output format just fits in 80 columns. The -c (chart)
option causes the program to add blanks and stars to the
right of each detail line, so as to chart the MPG (try it).
This output fits in 132 columns as long as your MPG isn't
incredibly high.
DIAGNOSTICS
Prints an appropriate error message to standard error and
returns nonzero if invoked wrong, if it can't open
gasdatafile, or if any input line doesn't scan correctly.
AUTHOR
Alan Silverstein, Hewlett-Packard Fort Collins Systems Division
{ihnp4 | hplabs}!hpfcla!ajs
(Distributed to USENET on 840105)
---------- gaspl ----------
# Script to show statistics on places gas was bought.
file=gasdata # where to read data.
awk <$file ' NR > 1 {print $5}' | # get places from "real" lines.
sort |
uniq -c | # count each type.
sort -nr | # show greatest first.
sed \
-e "s/66/Phillips 66/" \
-e "s/76/Union 76/" \
-e "s/AR/Arco/" \
-e "s/CH/Chevron/" \
-e "s/CO/Conoco/" \
-e "s/EX/Exxon/" \
-e "s/HU/Husky/" \
-e "s/MO/Mobil/" \
-e "s/PE/Pester/" \
-e "s/RO/Royal/" \
-e "s/SH/Shell/" \
-e "s/SI/Sinclair/" \
-e "s/SK/Skelly/" \
-e "s/TE/Texaco/" \
-e "s/VI/Vickers/" | # unabbreviate places.
awk ' {print; sum += $1}
END {printf ("%4d\n", sum)} # add a total.
'
More information about the Comp.sources.unix
mailing list