This commit is contained in:
Krzysztof Rudnicki 2024-09-16 16:21:54 +02:00
commit a060b615c8
7 changed files with 189 additions and 3 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2022 Krzysztof Rudnicki
Copyright (c) 2024 Krzysztof Rudnicki
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

1
C/misc/split/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
split

31
C/misc/split/Makefile Normal file
View File

@ -0,0 +1,31 @@
# Compiler
CC = gcc
# Compiler flags
CFLAGS = -Wall -O3 -march=native -flto -fomit-frame-pointer
# Libraries
LIBS = -ljpeg
# Source files
SRCS = main.c
# Output executable
TARGET = split
# Default target
all: $(TARGET)
# Link and compile the program
$(TARGET): $(SRCS)
$(CC) $(CFLAGS) -o $(TARGET) $(SRCS) $(LIBS)
# Clean up build artifacts
clean:
rm -f $(TARGET)
# Install the program (optional)
install: $(TARGET)
install -m 755 $(TARGET) /usr/local/bin/
.PHONY: all clean install

96
C/misc/split/main.c Normal file
View File

@ -0,0 +1,96 @@
#include <stdio.h>
#include <stdlib.h>
// Function to calculate symmetric weights for both even and odd N
void calculate_symmetric_weights(int N, double middle_weight, double* factors, double* weights) {
int half_N = N / 2;
int i;
weights[half_N] = middle_weight; // Middle value for symmetry
// Calculate left side weights
if (factors) {
for (i = 0; i < half_N; i++) {
if (i == 0) {
weights[half_N - i - 1] = middle_weight + factors[i];
} else {
weights[half_N - i - 1] = weights[half_N - i] + factors[i];
}
}
} else {
for (i = 0; i < half_N; i++) {
weights[half_N - i - 1] = middle_weight - (i + 1);
}
}
// Mirror left side weights to right side
for (i = 0; i < half_N; i++) {
weights[half_N + i + 1] = weights[half_N - i - 1];
}
}
// Function to scale the weights so that their sum is proportional to X
void scale_to_total(double X, double* weights, int N, double* distances) {
double total_weight = 0;
int i;
// Calculate the total weight
for (i = 0; i < N; i++) {
total_weight += weights[i];
}
double base_unit = X / total_weight;
// Scale weights
for (i = 0; i < N; i++) {
distances[i] = base_unit * weights[i];
}
}
// Function to split X into N parts symmetrically
void split_x_into_n_symmetrically(double X, int N, double* factors, double* distances) {
double* weights = (double*)malloc(N * sizeof(double));
calculate_symmetric_weights(N, 1.0, factors, weights);
scale_to_total(X, weights, N, distances);
free(weights);
}
// Function to split X into N parts, with a specific middle value
void split_x_into_n_middle(double X, int N, double middle_value, double* distances) {
double* weights = (double*)malloc(N * sizeof(double));
calculate_symmetric_weights(N, middle_value, NULL, weights);
scale_to_total(X, weights, N, distances);
free(weights);
}
// Example usage
int main() {
int N = 5;
double X = 100;
double middle_value = 5.0;
double distances[5];
// Example usage for split_x_into_n_middle
split_x_into_n_middle(X, N, middle_value, distances);
printf("Split values (with middle value = %.2f):\n", middle_value);
for (int i = 0; i < N; i++) {
printf("%.2f ", distances[i]);
}
printf("\n");
// Example usage for split_x_into_n_symmetrically
double factors[2] = {1.0, 2.0};
split_x_into_n_symmetrically(X, N, factors, distances);
printf("Split values (symmetric with factors):\n");
for (int i = 0; i < N; i++) {
printf("%.2f ", distances[i]);
}
printf("\n");
return 0;
}

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2022 Krzysztof Rudnicki
Copyright (c) 2024 Krzysztof Rudnicki
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2022 Krzysztof Rudnicki
Copyright (c) 2024 Krzysztof Rudnicki
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -0,0 +1,58 @@
def calculate_symmetric_weights(N, middle_weight, factors=None):
"""
Calculate symmetric weights for both even and odd N.
N: Number in which to split.
middle_weight: The middle value for symmetry.
factors: If provided, controls the difference in weights (used for the `split_x_into_n_symmetrically` function).
Must have length N // 2 or N // 2 - 1 depending on N.
"""
half_N = N // 2
weights_left = [middle_weight]
if factors:
for factor in factors:
next_weight = weights_left[-1] + factor
weights_left.append(next_weight)
else:
for i in range(half_N - 1):
weights_left.append(middle_weight - (i + 1))
if N % 2 == 0:
weights = weights_left[::-1] + weights_left
else:
weights = weights_left[::-1] + [middle_weight] + weights_left
return weights
def scale_to_total(X, weights):
"""
Scale the weights so that their sum is proportional to X.
X: Total value to distribute.
weights: The list of weights to be scaled.
"""
total_weight = sum(weights)
base_unit = X / total_weight
distances = [base_unit * weight for weight in weights]
return distances
def split_x_into_n_symmetrically(X, N, factors):
"""
X: Total value to distribute.
N: Number in which we split.
factors: List controlling the difference in weights between consecutive days.
Must have length of N // 2 (if N is odd) or (N // 2 - 1) (if N is even).
"""
weights = calculate_symmetric_weights(N, middle_weight=1, factors=factors)
return scale_to_total(X, weights)
def split_x_into_n_middle(X, N, middle_value):
"""
X: Total value to distribute.
N: Number in which we split.
middle_value: Value of the middle number (the biggest weight).
"""
weights = calculate_symmetric_weights(N, middle_weight=middle_value)
return scale_to_total(X, weights)