squiggle.c/scratchpad/plotting/c/histogram.c

87 lines
2.4 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#define MAX_SAMPLES 1000000
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: %s number_of_bins\n", argv[0]);
exit(EXIT_FAILURE);
}
int num_bins = atoi(argv[1]);
if (num_bins <= 0) {
fprintf(stderr, "Number of bins must be a positive integer.\n");
exit(EXIT_FAILURE);
}
int *bins = calloc(num_bins, sizeof(int));
double *samples = malloc(MAX_SAMPLES * sizeof(double));
if (bins == NULL || samples == NULL) {
fprintf(stderr, "Memory allocation failed.\n");
exit(EXIT_FAILURE);
}
double value, min_value = DBL_MAX, max_value = -DBL_MAX;
int sample_count = 0;
// Read numbers from stdin and store them into the samples array
while (sample_count < MAX_SAMPLES && scanf("%lf", &value) != EOF) {
samples[sample_count++] = value;
if (value < min_value) {
min_value = value;
}
if (value > max_value) {
max_value = value;
}
}
// Avoid division by zero for a single unique value
if (min_value == max_value) {
max_value++;
}
// Calculate bin width
double range = max_value - min_value;
double bin_width = range / num_bins;
// Fill the bins with sample counts
for (int i = 0; i < sample_count; i++) {
int bin_index = (int)((samples[i] - min_value) / bin_width);
if (bin_index == num_bins) {
bin_index--; // Last bin includes max_value
}
bins[bin_index]++;
}
// Calculate the scaling factor based on the maximum bin count
int max_bin_count = 0;
for (int i = 0; i < num_bins; i++) {
if (bins[i] > max_bin_count) {
max_bin_count = bins[i];
}
}
const int MAX_WIDTH = 50; // Adjust this to your terminal width
double scale = max_bin_count > MAX_WIDTH ? (double)MAX_WIDTH / max_bin_count : 1.0;
// Print the histogram
for (int i = 0; i < num_bins; i++) {
double bin_start = min_value + i * bin_width;
double bin_end = bin_start + bin_width;
printf(" [%4.1f, %4.1f): ", bin_start, bin_end);
int marks = (int)(bins[i] * scale);
for (int j = 0; j < marks; j++) {
printf("");
}
printf(" %d\n", bins[i]);
}
// Free the allocated memory
free(bins);
free(samples);
return 0;
}