summaryrefslogtreecommitdiffstats
path: root/2023-2/L03/mitsuo/fun.cpp
diff options
context:
space:
mode:
Diffstat (limited to '2023-2/L03/mitsuo/fun.cpp')
-rw-r--r--2023-2/L03/mitsuo/fun.cpp408
1 files changed, 408 insertions, 0 deletions
diff --git a/2023-2/L03/mitsuo/fun.cpp b/2023-2/L03/mitsuo/fun.cpp
new file mode 100644
index 0000000..6f5fe0e
--- /dev/null
+++ b/2023-2/L03/mitsuo/fun.cpp
@@ -0,0 +1,408 @@
+#include <iomanip>
+#include <cstring>
+#include <algorithm> // find
+#include "fun.hpp"
+
+using namespace std;
+
+void lecturaDeProductos(const char *archivo, char ***&productos, int *&stocks, double *&precios) {
+ ifstream in(archivo);
+ if (!in) {
+ cerr << "Error: no se pudo abrir el archivo.\n";
+ exit(1);
+ }
+
+ // read (stack memory)
+ char code[MAXLEN];
+ char description[MAXLEN];
+ double price;
+ int qty;
+
+ productos = NULL;
+ stocks = NULL;
+ precios = NULL;
+ size_t size = 0; // size of the parallel arrays
+
+ int i;
+ for (i = 0; true; i++) {
+ in.getline(code, MAXLEN, ',');
+ in.getline(description, MAXLEN, ',');
+ in >> price; in.get();
+ in >> qty; in.get();
+ if (!in) {
+ break;
+ }
+
+ // memory allocation "por incrementos"
+ if (i == size) {
+ increase_size_productos(productos, stocks, precios, size);
+ }
+ productos[i] = crea_producto(code, description); // "code" is the "Primary Key" of the parallel arrays
+ stocks[i] = qty;
+ precios[i] = price;
+ }
+}
+
+void increase_size_productos(char ***& productos, int *& stocks, double *& precios, size_t &size) {
+ if (!productos) {
+ // init
+ size = INCREMENTO;
+ productos = new char ** [size];
+ stocks = new int [size];
+ precios = new double [size];
+
+ productos[0] = NULL;
+ return;
+ }
+ /* In LP1 increments are 5 by 5. This has time complexity N^2 and space
+ complexity N. On the other hand, exponential increase of array size
+ has time complexity n*log(n), with space complexity of N. Much better. */
+ size *= 2;
+ char *** productos_tmp = new char ** [size];
+ int * stocks_tmp = new int [size];
+ double * precios_tmp = new double [size];
+
+ int i;
+ for (i = 0; i < size && productos[i]; i++) {
+ productos_tmp[i] = productos[i];
+ stocks_tmp[i] = stocks[i];
+ precios_tmp[i] = precios[i];
+ }
+ productos_tmp[i] = NULL;
+
+ delete [] productos;
+ delete [] stocks;
+ delete [] precios;
+ productos = productos_tmp;
+ stocks = stocks_tmp;
+ precios = precios_tmp;
+}
+
+char **crea_producto(char * code, char * description) {
+ char * field1 = new char [strlen(code) + 1];
+ char * field2 = new char [strlen(description) + 1];
+
+ strcpy(field1, code);
+ strcpy(field2, description);
+
+ return new char * [2] {field1, field2};
+}
+
+void pruebaDeLecturaDeProductos(const char *archivo, char ***productos, int *stock, double *precios) {
+ ofstream out(archivo);
+ if (!out) {
+ cerr << "Error: no se pudo abrir archivo.\n";
+ exit(1);
+ }
+
+ char ** producto;
+ int i;
+ for (i = 0; i < MAX && (producto = productos[i]); i++) {
+ out << left;
+ out << setw(12) << producto[0];
+ out << setw(72) << producto[1];
+ out << right << setprecision(2) << fixed;
+ out << setw(8) << stock[i];
+ out << setw(12) << precios[i];
+ out << '\n';
+ }
+}
+
+void lecturaDePedidos(const char *archivo, int *& fechas, char ***& grouped_producto, int ***& grouped_dniqty) {
+ ifstream in(archivo);
+ if (!in) {
+ cerr << "Error: no se pudo abrir el archivo.\n";
+ exit(1);
+ }
+
+ int date, dd, mm, yy;
+ char code[MAXLEN];
+ int dni;
+ int qty;
+
+ fechas = NULL;
+ grouped_producto = NULL;
+ grouped_dniqty = NULL;
+ size_t size = 0; // size of the parallel arrays
+ size_t size2[MAX] = {}; // size of internal parallel arrays (level 2)
+
+ int n, i = 0;
+ while (true) {
+ in.getline(code, MAXLEN, ',');
+ in >> dni; in.get();
+ in >> qty; in.get();
+ in >> dd; in.get(); in >> mm; in.get(); in >> yy; in.get();
+ date = yy*10000 + mm*100 + dd;
+ if (!in) {
+ break;
+ }
+
+ // memory allocation "por incrementos"
+ if (i == size) {
+ increase_size_pedidos(fechas, grouped_producto, grouped_dniqty, size);
+ }
+
+ int * dniqty = new int [2] {dni, qty};
+ char * code_mem = new char [strlen(code) + 1]; strcpy(code_mem, code);
+
+ insert_pedido(i, date, code_mem, dniqty, fechas, grouped_producto, grouped_dniqty, size2);
+ }
+ qsort_pedidos(fechas, grouped_producto, grouped_dniqty, 0, i - 1);
+}
+
+void increase_size_pedidos(int *& fechas, char ***& grouped_producto, int ***& grouped_dniqty, size_t &size) {
+ if (!fechas) {
+ // init
+ size = INCREMENTO;
+ fechas = new int [size];
+ grouped_producto = new char ** [size];
+ grouped_dniqty = new int ** [size];
+
+ fechas[0] = 0;
+ return;
+ }
+ /* In LP1 increments are 5 by 5. This has time complexity N^2 and space
+ complexity N. On the other hand, exponential increase of array size
+ has time complexity n*log(n), with space complexity of N. Much better. */
+ size *= 2;
+ int * f = new int [size];
+ char *** gp = new char ** [size];
+ int *** gd = new int ** [size];
+
+ int i;
+ for (i = 0; i < size && fechas[i]; i++) {
+ f[i] = fechas[i];
+ gp[i] = grouped_producto[i];
+ gd[i] = grouped_dniqty[i];
+ }
+ f[i] = 0;
+
+ delete [] fechas;
+ delete [] grouped_producto;
+ delete [] grouped_dniqty;
+ fechas = f;
+ grouped_producto = gp;
+ grouped_dniqty = gd;
+}
+
+void insert_pedido (
+ int & n,
+ int date, char * code_mem, int * dniqty,
+ int * fechas, char *** grouped_producto, int *** grouped_dniqty,
+ size_t * size2
+) {
+ // find if date is already in the list
+ int i;
+ for (i = 0; i < n; i++) {
+ if (fechas[i] == date) {
+ break;
+ }
+ }
+ if (i == n) {
+ // new date
+ fechas[i] = date;
+ grouped_producto[i] = NULL;
+ grouped_dniqty[i] = NULL;
+ size2[i] = 0;
+ fechas[++n] = 0; // update reference (n) and list terminator (0)
+ }
+
+ // make sure there is space for the product (in the nested list (#2)) before adding it to the date (at `fechas[i]`)
+ int i2;
+ for (i2 = 0; grouped_producto[i] && grouped_producto[i][i2]; i2++)
+ ;
+ if (i2 == size2[i]) {
+ increase_size_pedidos_fecha(grouped_producto[i], grouped_dniqty[i], size2[i]);
+ }
+ grouped_producto[i][i2] = code_mem;
+ grouped_dniqty[i][i2] = dniqty;
+ i2 += 1;
+ grouped_producto[i][i2] = NULL;
+}
+
+/* qsort: sort v[left]...v[right] into increasing order
+
+ Quicksort.
+ Ref.:
+ * The C Programming Language (ANSI C) - pg. 87)
+ * https://en.wikipedia.org/wiki/Quicksort
+*/
+void qsort_pedidos(int * v1, char *** v2, int *** v3, int left, int right) {
+ int i, last;
+
+ /* do nothing if array has less than 2 elements */
+ if (left >= right)
+ return;
+
+ swap_pedidos(v1, v2, v3, left, (left + right) / 2);
+ last = left;
+
+ /* partition */
+ for (i = left + 1; i <= right; i++) {
+ if (v1[i] < v1[left]) {
+ swap_pedidos(v1, v2, v3, ++last, i);
+ }
+ }
+
+ swap_pedidos(v1, v2, v3, left, last); /* reset partition element */
+ qsort_pedidos(v1, v2, v3, left, last - 1);
+ qsort_pedidos(v1, v2, v3, last + 1, right);
+}
+
+void swap_pedidos(int * v1, char *** v2, int *** v3, int left, int right) {
+ int t1 = v1[left];
+ char ** t2 = v2[left];
+ int ** t3 = v3[left];
+
+ v1[left] = v1[right];
+ v2[left] = v2[right];
+ v3[left] = v3[right];
+
+ v1[right] = t1;
+ v2[right] = t2;
+ v3[right] = t3;
+}
+
+void increase_size_pedidos_fecha(char **& productos, int **& dniqtys, size_t &size) {
+ if (!productos) {
+ // init
+ size = INCREMENTO;
+ productos = new char * [size];
+ dniqtys = new int * [size];
+
+ productos[0] = NULL;
+ return;
+ }
+ /* In LP1 increments are 5 by 5. This has time complexity N^2 and space
+ complexity N. On the other hand, exponential increase of array size
+ has time complexity n*log(n), with space complexity of N. Much better. */
+ size *= 2;
+ char ** p = new char * [size];
+ int ** d = new int * [size];
+
+ int i;
+ for (i = 0; i < size && productos[i]; i++) {
+ p[i] = productos[i];
+ d[i] = dniqtys[i];
+ }
+ p[i] = NULL;
+
+ delete [] productos;
+ delete [] dniqtys;
+ productos = p;
+ dniqtys = d;
+}
+
+void pruebaDeLecturaDePedidos(const char *archivo, int *fechaPedidos, char ***codigoPedidos, int ***dniCantPedidos) {
+ ofstream out(archivo);
+ if (!out) {
+ cerr << "Error: no se pudo abrir archivo.\n";
+ exit(1);
+ }
+
+ int fecha;
+ int i, j;
+ for (i = 0; i < MAX && (fecha = fechaPedidos[i]); i++) {
+ out << "FECHA: " << fecha << '\n';
+ char ** productos = codigoPedidos[i];
+ int ** dniqtys = dniCantPedidos[i];
+ for (j = 0; j < MAX && productos[j]; j++) {
+ int dni = dniqtys[j][0];
+ int qty = dniqtys[j][1];
+ char * code = productos[j];
+
+ out << right << setprecision(2) << fixed;
+ out << setw(2) << j + 1 << ") ";
+ out << left;
+ out << setw(12) << dni;
+ out << setw(12) << code;
+ out << setw(12) << qty;
+ out << '\n';
+ }
+ }
+}
+
+void reporteDeEnvioDePedidos(const char *archivo,
+ char ***productos, int *stocks, double *precios, // productos parallel arrays
+ int *fechaPedidos, char ***codigoPedidos, int ***dniCantPedidos // pedidos parallel arrays
+) {
+ ofstream out(archivo);
+ if (!out) {
+ cerr << "Error: no se pudo abrir archivo.\n";
+ exit(1);
+ }
+
+ int fecha;
+ int i, j;
+ for (i = 0; i < MAX && (fecha = fechaPedidos[i]); i++) {
+ int dd = fecha % 100;
+ int mm = fecha / 100 % 100;
+ int yy = fecha / 10000;
+ out << " REPORTE DE ENTREGA DE PEDIDOS\n"
+ "=====================================================================================================================================\n"
+ ;
+ out << "FECHA: " << dd << "/" << mm << "/" << yy << '\n';
+ out << "=====================================================================================================================================\n"
+ "No. DNI Producto Cantidad Precio Total de ingresos\n"
+ "-------------------------------------------------------------------------------------------------------------------------------------\n"
+ ;
+
+ char ** pedido_productos = codigoPedidos[i];
+ int ** dniqtys = dniCantPedidos[i];
+
+ double served_income = 0;
+ double not_served_income = 0;
+ for (j = 0; j < MAX && pedido_productos[j]; j++) {
+ int dni = dniqtys[j][0];
+ int qty = dniqtys[j][1];
+ char * code = pedido_productos[j];
+
+ int i_product = busca_producto(productos, code);
+ char * name = productos[i_product][1];
+ int * stock = &stocks[i_product];
+ double price = precios[i_product];
+
+ int qty_served;
+ if (*stock >= qty) {
+ qty_served = qty;
+ *stock -= qty;
+ } else {
+ qty_served = *stock;
+ *stock = 0;
+ }
+ served_income += qty_served * price;
+ not_served_income += (qty - qty_served) * price;
+
+ out << right << setprecision(2) << fixed;
+ out << setw(2) << j + 1 << ") ";
+ out << left;
+ out << setw(12) << dni;
+ out << setw(12) << code;
+ out << setw(64) << name;
+ out << right << setprecision(2) << fixed;
+ out << setw(12) << qty_served;
+ out << setw(12) << price;
+ if (qty_served == 0) {
+ out << left;
+ out << setw(12) << " SIN STOCK";
+ } else {
+ out << setw(12) << price * qty_served;
+ }
+ out << '\n';
+ }
+ out << right << setprecision(2) << fixed;
+ out << "-------------------------------------------------------------------------------------------------------------------------------------\n";
+ out << "Total ingresado: " << served_income << '\n';
+ out << "Total perdido por falta de stock: " << not_served_income << '\n';
+ }
+}
+
+int busca_producto(char *** productos, char * producto) {
+ for (int i = 0; productos[i]; i++) {
+ if (strcmp(productos[i][0], producto) == 0) {
+ return i;
+ }
+ }
+ return -1;
+
+} \ No newline at end of file