From 2734c905ea6d5c6f7d269142da9fdd0a2395595c Mon Sep 17 00:00:00 2001 From: mlamzira Date: Mon, 26 Feb 2024 10:33:31 +0100 Subject: [PATCH 1/6] Create main.c --- submissions/mlamzira/main.c | 263 ++++++++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 submissions/mlamzira/main.c diff --git a/submissions/mlamzira/main.c b/submissions/mlamzira/main.c new file mode 100644 index 00000000..d0754503 --- /dev/null +++ b/submissions/mlamzira/main.c @@ -0,0 +1,263 @@ +#include +#include +#include +#include + +typedef struct City City; +typedef struct Product Product; +typedef struct Buffer Buffer; + +struct Product { + char name[30]; + double price; + Product *next; + Product *previous; +}; + +struct Buffer { + char name[30]; + char productName[30]; + double priceSum; +}; + +struct City { + char name[30]; + double priceSum; + double mostExpensivePrice; + Product *first; + Product *tail; + int productCount; +}; + +float parseFloat(char floatValue[]); + +void readCity(char *str, Buffer *buffer); + + +City *binarySearch(City *cities[], int n, char *targetName); + +void addProduct(City *pCity, char *product, double price); + +int main() { + FILE *input = fopen("../input.txt", "r"); + FILE *sortedCities = fopen("../sorted-cities.txt", "r"); + FILE *output = fopen("../output.txt", "w"); + + char cityLine[50]; + City *cities[101]; + int k = 0; + while (fgets(cityLine, sizeof(cityLine), sortedCities) != NULL) { + City *city = (City *) malloc(sizeof(City)); + cityLine[strcspn(cityLine, "\n")] = 0; + strcpy(city->name, cityLine); + city->priceSum = 0; + strcpy(city->name, cityLine); + city->mostExpensivePrice = 100; + cities[k] = city; + k++; + } + + Buffer *buffer = (Buffer *) malloc(sizeof(Buffer *)); + City *cheapestCity = NULL; + + char line[256]; // Buffer for each line + while (fgets(line, sizeof(line), input) != NULL) { + line[strcspn(line, "\n")] = 0; + readCity(line, buffer); + + City *currentCity = binarySearch(cities, 101, buffer->name); + currentCity->priceSum += buffer->priceSum; + addProduct(currentCity, buffer->productName, buffer->priceSum); + } + + for (int i = 0; i < 101; ++i) { + City *currentCity = cities[i]; + if (cheapestCity == NULL || cheapestCity->priceSum > currentCity->priceSum) { + cheapestCity = currentCity; + } + + } + + fprintf(output, "%s %.2f\n", cheapestCity->name, cheapestCity->priceSum); + + Product *tmp = cheapestCity->first; + while (tmp != NULL) { + fprintf(output, "%s %.2f\n", tmp->name, tmp->price); + tmp = tmp->next; + } + + fclose(sortedCities); + fclose(input); + fclose(output); + return 0; +} + +void addProduct(City *pCity, char *productName, double price) { + if (pCity->productCount < 5) { + Product *newProduct = (Product *) malloc(sizeof(Product)); + strcpy(newProduct->name, productName); + newProduct->price = price; + + if (pCity->productCount == 0) { + pCity->first = newProduct; + pCity->tail = newProduct; + } else if (pCity->productCount == 1) { + if ((pCity->first->price > price) || (pCity->first->price == price && strcmp(productName, pCity->first->name) < 0)) { + Product *oldFirst = pCity->first; + pCity->first = newProduct; + newProduct->next = oldFirst; + oldFirst->previous = newProduct; + pCity->tail = oldFirst; + } else { + pCity->first->next = newProduct; + newProduct->previous = pCity->first; + pCity->tail = newProduct; + } + } else { + Product *tmp1 = pCity->first; + Product *tmp2 = tmp1->next; + + if ((tmp1->price > price) || (tmp1->price == price && strcmp(productName, tmp1->name) < 0)) { + pCity->first = newProduct; + tmp1->previous = newProduct; + newProduct->next = tmp1; + } else { + while (tmp2 != NULL) { + if ((tmp1->price < price && tmp2->price > price) || (tmp1->price < price && tmp2->price == price && strcmp(productName, tmp2->name) < 0)) { + tmp1->next = newProduct; + newProduct->previous = tmp1; + tmp2->previous = newProduct; + newProduct->next = tmp2; + break; + } + if (tmp2->next == NULL) { + tmp2->next = newProduct; + newProduct->previous = tmp2; + pCity->tail = newProduct; + break; + } + tmp1 = tmp2; + tmp2 = tmp2->next; + } + } + + } + pCity->productCount++; + } else { + if (price <= pCity->mostExpensivePrice) { + Product *last = pCity->tail; + pCity->tail = pCity->tail->previous; + pCity->tail->next = NULL; + free(last); + last = NULL; + + Product *newProduct = (Product *) malloc(sizeof(Product)); + strcpy(newProduct->name, productName); + newProduct->price = price; + + Product *tmp1 = pCity->first; + Product *tmp2 = tmp1->next; + + if ((tmp1->price > price) || (tmp1->price == price && strcmp(productName, tmp1->name) < 0)) { + pCity->first = newProduct; + tmp1->previous = newProduct; + newProduct->next = tmp1; + } else { + while (tmp2 != NULL) { + if ((tmp1->price < price && tmp2->price > price) || (tmp1->price < price && tmp2->price == price && strcmp(productName, tmp2->name) < 0)) { + tmp1->next = newProduct; + newProduct->previous = tmp1; + tmp2->previous = newProduct; + newProduct->next = tmp2; + break; + } + if (tmp2->next == NULL) { + tmp2->next = newProduct; + newProduct->previous = tmp2; + pCity->tail = newProduct; + break; + } + tmp1 = tmp2; + tmp2 = tmp2->next; + } + } + } + } + pCity->mostExpensivePrice = pCity->tail->price; +} + +City *binarySearch(City *cities[], int n, char *targetName) { + int low = 0; + int high = n - 1; + + while (low <= high) { + int mid = low + (high - low) / 2; + int res = strcmp(cities[mid]->name, targetName); + + if (res == 0) { + return cities[mid]; + } + + if (res < 0) { + low = mid + 1; + } else { + high = mid - 1; + } + } +} + +short cTos(char digitC) { + return digitC - '0'; +} + +float parseFloat(char *floatValue) { + + unsigned long length = strlen(floatValue); + if (length == 6) { + return 100; + } + + int commandIndex = -1; + for (int i = 0; i < length; ++i) { + if (floatValue[i] == '.') { + commandIndex = i; + break; + } + } + + if (length == 5 && commandIndex == 2) { + return (cTos(floatValue[0]) * 10) + + cTos(floatValue[1]) + + (cTos(floatValue[3]) * 0.1) + + (cTos(floatValue[4]) * 0.01); + } + + if (length == 4 && commandIndex == 2) { + return (cTos(floatValue[0]) * 10) + + cTos(floatValue[1]) + + (cTos(floatValue[3]) * 0.1); + } + + if (length == 4 && commandIndex == 1) { + return cTos(floatValue[0]) + + (cTos(floatValue[2]) * 0.1) + + (cTos(floatValue[3]) * 0.01); + } + + if (length == 3 && commandIndex == 1) { + return cTos(floatValue[0]) + + (cTos(floatValue[2]) * 0.1); + } + return 0; + +} + +void readCity(char *str, Buffer *buffer) { + char *token; + token = strtok(str, ","); + strcpy(buffer->name, token); + token = strtok(NULL, ","); + strcpy(buffer->productName, token); + token = strtok(NULL, ","); + buffer->priceSum = parseFloat(token); +} From 65b8a9c0cdc908e72f79f761434ff99ed2cabee7 Mon Sep 17 00:00:00 2001 From: mlamzira Date: Mon, 26 Feb 2024 10:34:19 +0100 Subject: [PATCH 2/6] Update main.c --- submissions/mlamzira/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/submissions/mlamzira/main.c b/submissions/mlamzira/main.c index d0754503..40092c4f 100644 --- a/submissions/mlamzira/main.c +++ b/submissions/mlamzira/main.c @@ -39,9 +39,9 @@ City *binarySearch(City *cities[], int n, char *targetName); void addProduct(City *pCity, char *product, double price); int main() { - FILE *input = fopen("../input.txt", "r"); - FILE *sortedCities = fopen("../sorted-cities.txt", "r"); - FILE *output = fopen("../output.txt", "w"); + FILE *input = fopen("./input.txt", "r"); + FILE *sortedCities = fopen("./sorted-cities.txt", "r"); + FILE *output = fopen("./output.txt", "w"); char cityLine[50]; City *cities[101]; From f43f2fafa35ab57b8cc9ba6b4da12ca6e3999d61 Mon Sep 17 00:00:00 2001 From: mlamzira Date: Mon, 26 Feb 2024 10:35:08 +0100 Subject: [PATCH 3/6] Create sorted-cities.txt --- submissions/mlamzira/sorted-cities.txt | 101 +++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 submissions/mlamzira/sorted-cities.txt diff --git a/submissions/mlamzira/sorted-cities.txt b/submissions/mlamzira/sorted-cities.txt new file mode 100644 index 00000000..c6c2e099 --- /dev/null +++ b/submissions/mlamzira/sorted-cities.txt @@ -0,0 +1,101 @@ +Agadir +Ahfir +Ait_Melloul +Akhfenir +Al_Hoceima +Aourir +Arfoud +Asilah +Assa +Azilal +Azrou +Bab_Berred +Bab_Taza +Ben_guerir +Beni_Mellal +Berkane +Berrechid +Bir_Anzerane +Bir_Lehlou +Bni_Hadifa +Bouarfa +Boujdour +Boulemane +Béni_Mellal +Casablanca +Chefchaouen +Chichaoua +Dakhla +Demnate +Drarga +El_Jadida +Errachidia +Essaouira +Fes +Figuig +Fquih_Ben_Salah +Goulmima +Guelmim +Guelta_Zemmur +Guercif +Guerguerat +Ifrane +Imzouren +Inezgane +Jerada +Jorf_El_Melha +Kalaat_MGouna +Kenitra +Khemisset +Khenifra +Khouribga +Ksar_El_Kebir +Ksar_es_Seghir +Laayoune +Larache +Layoune +Laâyoune +Marrakech +Meknes +Midar +Midelt +Mohammedia +Moulay_Bousselham +Nador +Ouarzazate +Ouazzane +Oujda +Oujda_Angad +Oulad_Teima +Rabat +Safi +Saidia +Sale +Sefrou +Settat +Sidi_Bennour +Sidi_Bouzid +Sidi_Ifni +Sidi_Kacem +Sidi_Slimane +Skhirate +Smara +Souk_Larbaa +Tafraout +Tan-Tan +Tangier +Taourirt +Tarfaya +Taroudant +Taza +Temara +Tetouan +Tichka +Tichla +Tiflet +Tinghir +Tiznit +Youssoufia +Zagora +Zemamra +had_soualem From 73b57e84c09f23d02a90ab9f52c21c4a85b0a878 Mon Sep 17 00:00:00 2001 From: mlamzira Date: Mon, 26 Feb 2024 10:38:32 +0100 Subject: [PATCH 4/6] Update main.c --- submissions/mlamzira/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/submissions/mlamzira/main.c b/submissions/mlamzira/main.c index 40092c4f..924a875e 100644 --- a/submissions/mlamzira/main.c +++ b/submissions/mlamzira/main.c @@ -1,7 +1,6 @@ #include #include #include -#include typedef struct City City; typedef struct Product Product; @@ -204,6 +203,8 @@ City *binarySearch(City *cities[], int n, char *targetName) { high = mid - 1; } } + + return NULL; } short cTos(char digitC) { From 3446897e180eed59dddaa2cca05c3590a10a9786 Mon Sep 17 00:00:00 2001 From: mlamzira Date: Thu, 29 Feb 2024 22:35:10 +0100 Subject: [PATCH 5/6] Delete submissions/mlamzira directory --- submissions/mlamzira/main.c | 264 ------------------------- submissions/mlamzira/sorted-cities.txt | 101 ---------- 2 files changed, 365 deletions(-) delete mode 100644 submissions/mlamzira/main.c delete mode 100644 submissions/mlamzira/sorted-cities.txt diff --git a/submissions/mlamzira/main.c b/submissions/mlamzira/main.c deleted file mode 100644 index 924a875e..00000000 --- a/submissions/mlamzira/main.c +++ /dev/null @@ -1,264 +0,0 @@ -#include -#include -#include - -typedef struct City City; -typedef struct Product Product; -typedef struct Buffer Buffer; - -struct Product { - char name[30]; - double price; - Product *next; - Product *previous; -}; - -struct Buffer { - char name[30]; - char productName[30]; - double priceSum; -}; - -struct City { - char name[30]; - double priceSum; - double mostExpensivePrice; - Product *first; - Product *tail; - int productCount; -}; - -float parseFloat(char floatValue[]); - -void readCity(char *str, Buffer *buffer); - - -City *binarySearch(City *cities[], int n, char *targetName); - -void addProduct(City *pCity, char *product, double price); - -int main() { - FILE *input = fopen("./input.txt", "r"); - FILE *sortedCities = fopen("./sorted-cities.txt", "r"); - FILE *output = fopen("./output.txt", "w"); - - char cityLine[50]; - City *cities[101]; - int k = 0; - while (fgets(cityLine, sizeof(cityLine), sortedCities) != NULL) { - City *city = (City *) malloc(sizeof(City)); - cityLine[strcspn(cityLine, "\n")] = 0; - strcpy(city->name, cityLine); - city->priceSum = 0; - strcpy(city->name, cityLine); - city->mostExpensivePrice = 100; - cities[k] = city; - k++; - } - - Buffer *buffer = (Buffer *) malloc(sizeof(Buffer *)); - City *cheapestCity = NULL; - - char line[256]; // Buffer for each line - while (fgets(line, sizeof(line), input) != NULL) { - line[strcspn(line, "\n")] = 0; - readCity(line, buffer); - - City *currentCity = binarySearch(cities, 101, buffer->name); - currentCity->priceSum += buffer->priceSum; - addProduct(currentCity, buffer->productName, buffer->priceSum); - } - - for (int i = 0; i < 101; ++i) { - City *currentCity = cities[i]; - if (cheapestCity == NULL || cheapestCity->priceSum > currentCity->priceSum) { - cheapestCity = currentCity; - } - - } - - fprintf(output, "%s %.2f\n", cheapestCity->name, cheapestCity->priceSum); - - Product *tmp = cheapestCity->first; - while (tmp != NULL) { - fprintf(output, "%s %.2f\n", tmp->name, tmp->price); - tmp = tmp->next; - } - - fclose(sortedCities); - fclose(input); - fclose(output); - return 0; -} - -void addProduct(City *pCity, char *productName, double price) { - if (pCity->productCount < 5) { - Product *newProduct = (Product *) malloc(sizeof(Product)); - strcpy(newProduct->name, productName); - newProduct->price = price; - - if (pCity->productCount == 0) { - pCity->first = newProduct; - pCity->tail = newProduct; - } else if (pCity->productCount == 1) { - if ((pCity->first->price > price) || (pCity->first->price == price && strcmp(productName, pCity->first->name) < 0)) { - Product *oldFirst = pCity->first; - pCity->first = newProduct; - newProduct->next = oldFirst; - oldFirst->previous = newProduct; - pCity->tail = oldFirst; - } else { - pCity->first->next = newProduct; - newProduct->previous = pCity->first; - pCity->tail = newProduct; - } - } else { - Product *tmp1 = pCity->first; - Product *tmp2 = tmp1->next; - - if ((tmp1->price > price) || (tmp1->price == price && strcmp(productName, tmp1->name) < 0)) { - pCity->first = newProduct; - tmp1->previous = newProduct; - newProduct->next = tmp1; - } else { - while (tmp2 != NULL) { - if ((tmp1->price < price && tmp2->price > price) || (tmp1->price < price && tmp2->price == price && strcmp(productName, tmp2->name) < 0)) { - tmp1->next = newProduct; - newProduct->previous = tmp1; - tmp2->previous = newProduct; - newProduct->next = tmp2; - break; - } - if (tmp2->next == NULL) { - tmp2->next = newProduct; - newProduct->previous = tmp2; - pCity->tail = newProduct; - break; - } - tmp1 = tmp2; - tmp2 = tmp2->next; - } - } - - } - pCity->productCount++; - } else { - if (price <= pCity->mostExpensivePrice) { - Product *last = pCity->tail; - pCity->tail = pCity->tail->previous; - pCity->tail->next = NULL; - free(last); - last = NULL; - - Product *newProduct = (Product *) malloc(sizeof(Product)); - strcpy(newProduct->name, productName); - newProduct->price = price; - - Product *tmp1 = pCity->first; - Product *tmp2 = tmp1->next; - - if ((tmp1->price > price) || (tmp1->price == price && strcmp(productName, tmp1->name) < 0)) { - pCity->first = newProduct; - tmp1->previous = newProduct; - newProduct->next = tmp1; - } else { - while (tmp2 != NULL) { - if ((tmp1->price < price && tmp2->price > price) || (tmp1->price < price && tmp2->price == price && strcmp(productName, tmp2->name) < 0)) { - tmp1->next = newProduct; - newProduct->previous = tmp1; - tmp2->previous = newProduct; - newProduct->next = tmp2; - break; - } - if (tmp2->next == NULL) { - tmp2->next = newProduct; - newProduct->previous = tmp2; - pCity->tail = newProduct; - break; - } - tmp1 = tmp2; - tmp2 = tmp2->next; - } - } - } - } - pCity->mostExpensivePrice = pCity->tail->price; -} - -City *binarySearch(City *cities[], int n, char *targetName) { - int low = 0; - int high = n - 1; - - while (low <= high) { - int mid = low + (high - low) / 2; - int res = strcmp(cities[mid]->name, targetName); - - if (res == 0) { - return cities[mid]; - } - - if (res < 0) { - low = mid + 1; - } else { - high = mid - 1; - } - } - - return NULL; -} - -short cTos(char digitC) { - return digitC - '0'; -} - -float parseFloat(char *floatValue) { - - unsigned long length = strlen(floatValue); - if (length == 6) { - return 100; - } - - int commandIndex = -1; - for (int i = 0; i < length; ++i) { - if (floatValue[i] == '.') { - commandIndex = i; - break; - } - } - - if (length == 5 && commandIndex == 2) { - return (cTos(floatValue[0]) * 10) - + cTos(floatValue[1]) - + (cTos(floatValue[3]) * 0.1) - + (cTos(floatValue[4]) * 0.01); - } - - if (length == 4 && commandIndex == 2) { - return (cTos(floatValue[0]) * 10) - + cTos(floatValue[1]) - + (cTos(floatValue[3]) * 0.1); - } - - if (length == 4 && commandIndex == 1) { - return cTos(floatValue[0]) - + (cTos(floatValue[2]) * 0.1) - + (cTos(floatValue[3]) * 0.01); - } - - if (length == 3 && commandIndex == 1) { - return cTos(floatValue[0]) - + (cTos(floatValue[2]) * 0.1); - } - return 0; - -} - -void readCity(char *str, Buffer *buffer) { - char *token; - token = strtok(str, ","); - strcpy(buffer->name, token); - token = strtok(NULL, ","); - strcpy(buffer->productName, token); - token = strtok(NULL, ","); - buffer->priceSum = parseFloat(token); -} diff --git a/submissions/mlamzira/sorted-cities.txt b/submissions/mlamzira/sorted-cities.txt deleted file mode 100644 index c6c2e099..00000000 --- a/submissions/mlamzira/sorted-cities.txt +++ /dev/null @@ -1,101 +0,0 @@ -Agadir -Ahfir -Ait_Melloul -Akhfenir -Al_Hoceima -Aourir -Arfoud -Asilah -Assa -Azilal -Azrou -Bab_Berred -Bab_Taza -Ben_guerir -Beni_Mellal -Berkane -Berrechid -Bir_Anzerane -Bir_Lehlou -Bni_Hadifa -Bouarfa -Boujdour -Boulemane -Béni_Mellal -Casablanca -Chefchaouen -Chichaoua -Dakhla -Demnate -Drarga -El_Jadida -Errachidia -Essaouira -Fes -Figuig -Fquih_Ben_Salah -Goulmima -Guelmim -Guelta_Zemmur -Guercif -Guerguerat -Ifrane -Imzouren -Inezgane -Jerada -Jorf_El_Melha -Kalaat_MGouna -Kenitra -Khemisset -Khenifra -Khouribga -Ksar_El_Kebir -Ksar_es_Seghir -Laayoune -Larache -Layoune -Laâyoune -Marrakech -Meknes -Midar -Midelt -Mohammedia -Moulay_Bousselham -Nador -Ouarzazate -Ouazzane -Oujda -Oujda_Angad -Oulad_Teima -Rabat -Safi -Saidia -Sale -Sefrou -Settat -Sidi_Bennour -Sidi_Bouzid -Sidi_Ifni -Sidi_Kacem -Sidi_Slimane -Skhirate -Smara -Souk_Larbaa -Tafraout -Tan-Tan -Tangier -Taourirt -Tarfaya -Taroudant -Taza -Temara -Tetouan -Tichka -Tichla -Tiflet -Tinghir -Tiznit -Youssoufia -Zagora -Zemamra -had_soualem From 04dfda45a00a6435ae975179293fb4640a611422 Mon Sep 17 00:00:00 2001 From: mlamzira Date: Thu, 29 Feb 2024 22:38:32 +0100 Subject: [PATCH 6/6] Create Main.java --- submissions/mlamzira/Main.java | 282 +++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 submissions/mlamzira/Main.java diff --git a/submissions/mlamzira/Main.java b/submissions/mlamzira/Main.java new file mode 100644 index 00000000..2c83ade9 --- /dev/null +++ b/submissions/mlamzira/Main.java @@ -0,0 +1,282 @@ +import java.io.*; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class Main { + static SortedCities sortedCities = new SortedCities(Stream.of( + "Agadir", "Ahfir", "Ait_Melloul", "Akhfenir", "Al_Hoceima", "Aourir", "Arfoud", + "Asilah", "Assa", "Azilal", "Azrou", "Bab_Berred", "Bab_Taza", "Ben_guerir", "Beni_Mellal", + "Berkane", "Berrechid", "Bir_Anzerane", "Bir_Lehlou", "Bni_Hadifa", "Bouarfa", "Boujdour", + "Boulemane", "Béni_Mellal", "Casablanca", "Chefchaouen", "Chichaoua", "Dakhla", "Demnate", + "Drarga", "El_Jadida", "Errachidia", "Essaouira", "Fes", "Figuig", "Fquih_Ben_Salah", + "Goulmima", "Guelmim", "Guelta_Zemmur", "Guercif", "Guerguerat", "Ifrane", "Imzouren", + "Inezgane", "Jerada", "Jorf_El_Melha", "Kalaat_MGouna", "Kenitra", "Khemisset", "Khenifra", + "Khouribga", "Ksar_El_Kebir", "Ksar_es_Seghir", "Laayoune", "Larache", "Layoune", "Laâyoune", + "Marrakech", "Meknes", "Midar", "Midelt", "Mohammedia", "Moulay_Bousselham", "Nador", + "Ouarzazate", "Ouazzane", "Oujda", "Oujda_Angad", "Oulad_Teima", "Rabat", "Safi", "Saidia", + "Sale", "Sefrou", "Settat", "Sidi_Bennour", "Sidi_Bouzid", "Sidi_Ifni", "Sidi_Kacem", + "Sidi_Slimane", "Skhirate", "Smara", "Souk_Larbaa", "Tafraout", "Tan-Tan", "Tangier", + "Taourirt", "Tarfaya", "Taroudant", "Taza", "Temara", "Tetouan", "Tichka", "Tichla", "Tiflet", + "Tinghir", "Tiznit", "Youssoufia", "Zagora", "Zemamra", "had_soualem").map(City::new).toArray(City[]::new)); + + public static void main(String[] args) throws IOException, InterruptedException { + + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("/Users/mohammedlamzira/geeksblabla/input.1b.txt"))); + + int capacity = 1024; + int elementsCapacity = 2048; + List jobs = new ArrayList<>(); + ChunkProvider chunkProvider = new ChunkProvider(capacity, elementsCapacity); + + Chunk chunk = chunkProvider.rent(); + String line; + while ((line = bufferedReader.readLine()) != null) { + if (chunk.hasCapacity()) { + chunk.add(line); + } else { + jobs.add(chunk.proccesInVThread(sortedCities, chunkProvider)); + chunk = chunkProvider.rent(); + chunk.add(line); + } + } + if (chunk.size() > 0) { + Thread lastChunk = chunk.proccesInVThread(sortedCities, chunkProvider); + lastChunk.join(); + } + + for (Thread vThread : jobs) { + if (vThread.isAlive()) { + vThread.join(); + } + } + + City cheapestCity = sortedCities.getCheapestCity(); + FileOutputStream out = new FileOutputStream("./output.txt"); + PrintStream printStream = new PrintStream(out); + printStream.print(cheapestCity.toString()); + printStream.close(); + out.flush(); + out.close(); + } + + public static int fastCompare(String a, String b) { + int len1 = a.length(); + int len2 = b.length(); + int len = Math.min(Math.min(len1, len2), 7); + + int i = 0; + while (i < len - 3) { + if (a.charAt(i) != b.charAt(i)) { + return a.charAt(i) - b.charAt(i); + } + if (a.charAt(i + 1) != b.charAt(i + 1)) { + return a.charAt(i + 1) - b.charAt(i + 1); + } + if (a.charAt(i + 2) != b.charAt(i + 2)) { + return a.charAt(i + 2) - b.charAt(i + 2); + } + i += 3; + } + for (; i < len; i++) { + if (a.charAt(i) != b.charAt(i)) { + return a.charAt(i) - b.charAt(i); + } + } + + return Integer.compare(len1, len2); + } + + public static class Chunk implements Comparable { + private final List elements; + private final int initialCapacity; + + public Chunk(int initialCapacity) { + elements = new ArrayList<>(initialCapacity); + this.initialCapacity = initialCapacity; + } + + public void add(String line) { + elements.add(new ChunkElement(line)); + } + + public void add(ChunkElement chunkElement) { + elements.add(chunkElement); + } + + public boolean hasCapacity() { + return elements.size() < initialCapacity; + } + + public int size() { + return elements.size(); + } + + public Thread proccesInVThread(SortedCities sortedCities, ChunkProvider chunkProvider) { + return Thread.ofVirtual().start(() -> { + elements.forEach(chunkElement -> chunkElement.processChunkElement(sortedCities)); + elements.clear(); + chunkProvider.back(this); + }); + } + + @Override + public int compareTo(Chunk o) { + return elements.size() - o.elements.size(); + } + } + + public record ChunkElement(String line) { + public static final double[] COEFFICIENT = new double[]{100, 10, 1, 0.1f, 0.01f}; + + public void processChunkElement(SortedCities sortedCities) { + String[] parts = splitLine(line); + double price = parse(parts[2]); + City city = sortedCities.search(parts[0]); + synchronized (city) { + city.addProduct(new Product(parts[1], price)); + } + } + + private static double parse(String s) { + double result = 0; + int doubleingNumber = s.indexOf('.'); + int highestNumber = 0; + if (doubleingNumber == 1) { + highestNumber = 2; + } else if (doubleingNumber == 2) { + highestNumber = 1; + } else if (doubleingNumber == 3) { + return 100; + } + + int j = highestNumber; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c != '.') { + result += Character.getNumericValue(c) * COEFFICIENT[j]; + j++; + } + } + return result; + } + + private static String[] splitLine(String line) { + int firstComma = line.indexOf(','); + int secondComma = line.indexOf(',', firstComma + 1); + + return new String[]{ + line.substring(0, firstComma), + line.substring(firstComma + 1, secondComma), + line.substring(secondComma + 1) + }; + } + } + + public static class ChunkProvider { + private final LinkedList chunks = new LinkedList<>(); + private final int chunksCapacity; + private final int individualCapacity; + + public ChunkProvider(int chunksCapacity, int individualCapacity) { + this.chunksCapacity = chunksCapacity; + this.individualCapacity = individualCapacity; + for (int i = 0; i < chunksCapacity; i++) { + chunks.add(new Chunk(individualCapacity)); + } + } + + public Chunk rent() { + try { + return chunks.removeLast(); + } catch (Exception e) { + for (int i = 0; i < chunksCapacity; i++) { + chunks.addFirst(new Chunk(individualCapacity)); + } + return chunks.removeLast(); + } + } + + public void back(Chunk chunk) { + chunks.addFirst(chunk); + } + } + + public static class City { + public final String name; + public double sumPrice = 0; + private final TreeSet cheapestProducts = new TreeSet<>(); + + public City(String name) { + this.name = name; + } + + public void addProduct(Product product) { + sumPrice += product.price; + cheapestProducts.add(product); + if (cheapestProducts.size() == 6) { + cheapestProducts.removeLast(); + } + } + + @Override + public String toString() { + List array = cheapestProducts.stream().toList(); + Product product1 = array.get(0); + Product product2 = array.get(1); + Product product3 = array.get(2); + Product product4 = array.get(3); + Product product5 = array.get(4); + return String.format(""" + %s %.2f + %s %.2f + %s %.2f + %s %.2f + %s %.2f + %s %.2f""", name, sumPrice, + product1.name, product1.price, + product2.name, product2.price, + product3.name, product3.price, + product4.name, product4.price, + product5.name, product5.price + ); + } + } + + public record Product(String name, double price) implements Comparable { + + @Override + public int compareTo(Product o) { + if (price == o.price) { + return fastCompare(name, o.name); + } + return (int) (price * 1000 - o.price * 1000); + } + } + + public static class SortedCities { + public final City[] cities; + public final List list; + private final Map map; + + public SortedCities(City[] cities) { + this.cities = cities; + list = Stream.of(cities).toList(); + map = Stream.of(cities).collect(Collectors.toMap(it -> it.name, it -> it)); + } + + public City search(String cityName) { + return map.get(cityName); + } + + City getCheapestCity() { + City cheapestCity = null; + for (City city : cities) { + if (cheapestCity == null || cheapestCity.sumPrice > city.sumPrice) { + cheapestCity = city; + } + } + return cheapestCity; + } + } +}