diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 0c19cf9..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -benchmarks/** diff --git a/Lab1/.gitignore b/Lab1/.gitignore new file mode 100644 index 0000000..55576fd --- /dev/null +++ b/Lab1/.gitignore @@ -0,0 +1,3 @@ +benchmarks/** +dist/** +results.txt diff --git a/benchmark.py b/Lab1/benchmark.py similarity index 62% rename from benchmark.py rename to Lab1/benchmark.py index 4f6b9a7..7a5c8bb 100644 --- a/benchmark.py +++ b/Lab1/benchmark.py @@ -7,6 +7,8 @@ def run_benchmark(program_name, array): start = time() process = subprocess.Popen(program_name, stdin=subprocess.PIPE) process.communicate((f"{len(array)}\n" + "\n".join(map(str, array))).encode()) + if process.returncode == 1: + raise RuntimeError("Error while benchmarking") end = time() return end - start @@ -25,23 +27,38 @@ def generate_sequence(sequence_type, array_size): raise ValueError("Invalid sequence type") def plot(program_name, sequences, array_size): + sequence_names = { + "random": "Losowy", + "sorted": "Posortowany", + "reversed": "Odwrócony", + "constant": "Stały", + "v_shaped": "V-kształtny", + } plt.figure(figsize=(10, 6)) for sequence_type, timings in sequences.items(): - plt.plot(array_size, timings, label=sequence_type) - plt.xlabel("") + plt.plot(array_size, timings, label=sequence_names[sequence_type]) + plt.xlabel("Rozmiar tablicy") plt.ylabel("Czas (ms)") - plt.title(f"{program_name}") + plt.title(program_name.capitalize()) plt.legend() - plt.savefig(f"benchmarks/{program_name}.png") - # plt.show() + plt.savefig(f"./benchmarks/{program_name}.png") if __name__ == "__main__": - program_names = ["./insertion", "./selection"] + # program_names = ["insertion", "selection", "heapsort", "mergesort"] + program_names = ["heapsort"] sequence_types = ["random", "sorted", "reversed", "constant", "v_shaped"] array_sizes = [i for i in range(1000, 15001, 1000)] + tests = 10 with open("results.txt", "w") as f: for program_name in program_names: + if program_name == "heapsort" or program_name == "mergesort": + array_sizes = [i for i in range(15000, 40001, 1000)] + tests = 20 + else: + array_sizes = [i for i in range(1000, 15001, 1000)] + tests = 10 + sequenceTiming = { "random": [], "sorted": [], @@ -54,16 +71,18 @@ if __name__ == "__main__": print(f" - running {sequence_type}") for array_size in array_sizes: sequence = generate_sequence(sequence_type, array_size) - print(f" - running {sequence_type} with size {array_size}") durations = [] - for i in range(10): - duration = run_benchmark(program_name, sequence) + for i in range(tests): + print(f" - running {sequence_type} with size {array_size} {i+1}/{tests}", end="\r") + duration = run_benchmark(f"./dist/{program_name}", sequence) duration *= 1000 durations.append(duration) - sleep(0.1) + if program_name == "heapsort" or program_name == "mergesort": + sleep(0.1) + print() duration = sum(durations) / len(durations) - f.write(f"{program_name} {sequence_type} {array_size} {duration}\n") sequenceTiming[sequence_type].append(duration) - sleep(0.5) + if program_name == "heapsort" or program_name == "mergesort": + sleep(0.1) plot(program_name, sequenceTiming, array_sizes) print("Benchmark finished") diff --git a/heapsort.c b/Lab1/heapsort.c similarity index 100% rename from heapsort.c rename to Lab1/heapsort.c diff --git a/insertion.c b/Lab1/insertion.c similarity index 57% rename from insertion.c rename to Lab1/insertion.c index 95c834a..c4bb052 100644 --- a/insertion.c +++ b/Lab1/insertion.c @@ -4,13 +4,23 @@ // Capture the pipe of array contents, first number is the size int main() { int s; - scanf("%d", &s); - int *array = malloc(sizeof(int) * s); - for (int i = 0; i < s; i++) { - scanf("%d", &array[i]); + int res = scanf("%d", &s); + if (res != 1) { + fprintf(stderr, "Error reading size\n"); + return 1; } - for (int j = 1; j < s; j++) { + int *array = malloc(sizeof(int) * s); + for (int i = 0; i < s; i++) { + res = scanf("%d", &array[i]); + if (res != 1) { + fprintf(stderr, "Error reading array element\n"); + free(array); + return 1; + } + } + + for (int j = 0; j < s; j++) { int key = array[j]; int i = j - 1; while (i >= 0 && array[i] > key) { diff --git a/Lab1/mergesort.c b/Lab1/mergesort.c new file mode 100644 index 0000000..303785d --- /dev/null +++ b/Lab1/mergesort.c @@ -0,0 +1,53 @@ +#include +#include + +void MergeSort(int A[], int l, int r, int B[]) { + int m = (l + r) / 2; + if (m - l > 0) { + MergeSort(A, l, m, B); + } + + if (r - m > 0) { + MergeSort(A, m + 1, r, B); + } + + int i = l; + int j = m + 1; + for (int k = l; k <= r; k++) { + if ((i <= m && j > r) || ((i <= m && j <= r) && A[i] <= A[j])) { + B[k] = A[i]; + i++; + } else { + B[k] = A[j]; + j++; + } + } + + for (int k = l; k <= r; k++) { + A[k] = B[k]; + } +} + +int main() { + int size; + int res = scanf("%d", &size); + if (res != 1) { + fprintf(stderr, "Error reading size\n"); + return 1; + } + + int *arrayA = malloc(sizeof(int) * size); + for (int i = 0; i < size; i++) { + res = scanf("%d", &arrayA[i]); + if (res != 1) { + fprintf(stderr, "Error reading array element\n"); + free(arrayA); + return 1; + } + } + + int *arrayB = malloc(sizeof(int) * size); + MergeSort(arrayA, 0, size - 1, arrayB); + + return 0; +} diff --git a/Lab1/quicksort.c b/Lab1/quicksort.c new file mode 100644 index 0000000..f2e3687 --- /dev/null +++ b/Lab1/quicksort.c @@ -0,0 +1,80 @@ +#include +#include +#include + +enum PivotStrategy { RIGHTMOST = 0, MIDDLE = 1, RANDOM = 2 }; + +void swap(int *a, int *b) { + int temp = *a; + *a = *b; + *b = temp; +} + +int partition(int A[], int left, int right, int pivot_strategy, int length) { + int pivot_index; + if (pivot_strategy == RIGHTMOST) { + pivot_index = right; + } else if (pivot_strategy == MIDDLE) { + pivot_index = (left + right) / 2; + } else if (pivot_strategy == RANDOM) { + pivot_index = (rand() % (length + 1)); + } + + int pivot = A[pivot_index]; + swap(&A[pivot_index], &A[right]); + int i = left - 1; + + for (int j = left; j < right; j++) { + if (A[j] <= pivot) { + i++; + swap(&A[i], &A[j]); + } + } + swap(&A[i + 1], &A[right]); + return i + 1; +} + +void quicksort(int A[], int p, int r, int pivot_strategy, int length) { + if (p < r) { + int q = partition(A, p, r, pivot_strategy, length); + quicksort(A, p, q - 1, pivot_strategy, length); + quicksort(A, q + 1, r, pivot_strategy, length); + } +} + +int main() { + int size, pivot_strategy; + + if (scanf("%d", &size) != 1) { + fprintf(stderr, "Error reading size\n"); + return 1; + } + + if (scanf("%d", &pivot_strategy) != 1) { + fprintf(stderr, "Error reading pivot strategy\n"); + return 1; + } + // Init the random number generator when needed + if (pivot_strategy == RANDOM) { + srand(size); + } + + int *array = malloc(sizeof(int) * size); + if (array == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + return 1; + } + + for (int i = 0; i < size; i++) { + if (scanf("%d", &array[i]) != 1) { + fprintf(stderr, "Error reading array element\n"); + free(array); + return 1; + } + } + + quicksort(array, 0, size - 1, pivot_strategy, size); + + free(array); + return 0; +} diff --git a/Lab1/quicksort_bench.py b/Lab1/quicksort_bench.py new file mode 100644 index 0000000..7bdc945 --- /dev/null +++ b/Lab1/quicksort_bench.py @@ -0,0 +1,66 @@ +import subprocess +from time import time, sleep +import matplotlib.pyplot as plt + +pivot_strategies = { + "rightmost": 0, + "middle": 1, + "random": 2 +} + +def run_benchmark(array, pivot_strategy): + input_data = f"{len(array)}\n{pivot_strategies[pivot_strategy]}\n" + "\n".join(map(str, array)) + "\n" + + start = time() + process = subprocess.Popen("./dist/quicksort", stdin=subprocess.PIPE) + process.communicate(input_data.encode()) + if process.returncode != 0: + raise RuntimeError("Error while benchmarking") + end = time() + + return end - start + +def generate_v_shaped(array_size): + return [i for i in range(array_size // 2, 0, -1)] + [i for i in range(array_size // 2)] + +def plot(sequences, array_size): + pivot_names = { + "rightmost": "Pivot prawy", + "middle": "Pivot środkowy", + "random": "Pivot losowy" + } + plt.figure(figsize=(10, 6)) + for pivot_type, timings in sequences.items(): + plt.plot(array_size, timings, label=pivot_names[pivot_type]) + plt.xlabel("Rozmiar tablicy") + plt.ylabel("Czas (ms)") + plt.title("Quicksort") + plt.legend() + plt.savefig("./benchmarks/quicksort.png") + +if __name__ == "__main__": + array_sizes = [i for i in range(1000, 15001, 1000)] + + with open("results.txt", "w") as f: + sequenceTiming = { + "rightmost": [], + "middle": [], + "random": [], + } + for pivot_strategy in pivot_strategies: + print(f"Running with pivot strategy {pivot_strategy}") + for array_size in array_sizes: + sequence = generate_v_shaped(array_size) + durations = [] + for i in range(10): + print(f" - with size of {array_size} {i+1}/10", end="\r") + duration = run_benchmark(sequence, pivot_strategy) + duration *= 1000 + durations.append(duration) + sleep(0.1) + print() + duration = sum(durations) / len(durations) + sequenceTiming[pivot_strategy].append(duration) + sleep(0.1) + plot(sequenceTiming, array_sizes) + print("Benchmark finished") diff --git a/selection.c b/Lab1/selection.c similarity index 99% rename from selection.c rename to Lab1/selection.c index 1499d9b..7ba936e 100644 --- a/selection.c +++ b/Lab1/selection.c @@ -8,6 +8,7 @@ int main() { fprintf(stderr, "Error reading size\n"); return 1; } + int *array = malloc(sizeof(int) * s); for (int i = 0; i < s; i++) { res = scanf("%d", &array[i]); diff --git a/Lab1/test_data.txt b/Lab1/test_data.txt new file mode 100644 index 0000000..37bb752 --- /dev/null +++ b/Lab1/test_data.txt @@ -0,0 +1,6 @@ +5 +12 +65 +233 +87 +23 diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..1d0fc86 --- /dev/null +++ b/flake.lock @@ -0,0 +1,25 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1739736696, + "narHash": "sha256-zON2GNBkzsIyALlOCFiEBcIjI4w38GYOb+P+R4S8Jsw=", + "rev": "d74a2335ac9c133d6bbec9fc98d91a77f1604c1f", + "revCount": 754461, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.754461%2Brev-d74a2335ac9c133d6bbec9fc98d91a77f1604c1f/01951426-5a87-7b75-8413-1a0d9ec5ff04/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/NixOS/nixpkgs/0.1.%2A.tar.gz" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..2a1088b --- /dev/null +++ b/flake.nix @@ -0,0 +1,35 @@ +{ + description = "A Nix-flake-based C/C++ development environment"; + + inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1.*.tar.gz"; + + outputs = { self, nixpkgs }: + let + supportedSystems = [ "x86_64-linux" ]; + forEachSupportedSystem = f: + nixpkgs.lib.genAttrs supportedSystems + (system: f { pkgs = import nixpkgs { inherit system; }; }); + in { + devShells = forEachSupportedSystem ({ pkgs }: { + default = pkgs.mkShell.override { + # Override stdenv in order to change compiler: + # stdenv = pkgs.clangStdenv; + } { + packages = with pkgs; + [ + clang-tools + cmake + codespell + conan + cppcheck + doxygen + gtest + lcov + vcpkg + vcpkg-tool + python312Packages.matplotlib + ] ++ (if system == "aarch64-darwin" then [ ] else [ gdb ]); + }; + }); + }; +} diff --git a/heapsort b/heapsort deleted file mode 100755 index 6258740..0000000 Binary files a/heapsort and /dev/null differ diff --git a/insertion b/insertion deleted file mode 100755 index 6135dce..0000000 Binary files a/insertion and /dev/null differ diff --git a/insertion_benchmark.png b/insertion_benchmark.png deleted file mode 100644 index 3d99f95..0000000 Binary files a/insertion_benchmark.png and /dev/null differ diff --git a/results.txt b/results.txt deleted file mode 100644 index 50d2643..0000000 --- a/results.txt +++ /dev/null @@ -1,150 +0,0 @@ -./insertion random 1000 1.0615110397338867 -./insertion random 2000 1.5358448028564453 -./insertion random 3000 2.274918556213379 -./insertion random 4000 3.3971309661865234 -./insertion random 5000 4.603886604309082 -./insertion random 6000 6.020760536193848 -./insertion random 7000 7.8598737716674805 -./insertion random 8000 9.824132919311523 -./insertion random 9000 12.162041664123535 -./insertion random 10000 14.610838890075684 -./insertion random 11000 17.46840476989746 -./insertion random 12000 20.206165313720703 -./insertion random 13000 23.66960048675537 -./insertion random 14000 27.488040924072266 -./insertion random 15000 30.75859546661377 -./insertion sorted 1000 0.8951187133789062 -./insertion sorted 2000 0.9664773941040039 -./insertion sorted 3000 1.1182308197021484 -./insertion sorted 4000 1.237630844116211 -./insertion sorted 5000 1.397252082824707 -./insertion sorted 6000 1.5844106674194336 -./insertion sorted 7000 1.7046451568603516 -./insertion sorted 8000 1.8734216690063477 -./insertion sorted 9000 2.349853515625 -./insertion sorted 10000 2.4387359619140625 -./insertion sorted 11000 2.462148666381836 -./insertion sorted 12000 2.5963783264160156 -./insertion sorted 13000 3.156876564025879 -./insertion sorted 14000 3.132033348083496 -./insertion sorted 15000 3.238677978515625 -./insertion reversed 1000 1.2768268585205078 -./insertion reversed 2000 2.137279510498047 -./insertion reversed 3000 3.491377830505371 -./insertion reversed 4000 5.584287643432617 -./insertion reversed 5000 7.988524436950684 -./insertion reversed 6000 10.77868938446045 -./insertion reversed 7000 14.134597778320312 -./insertion reversed 8000 18.278932571411133 -./insertion reversed 9000 22.71718978881836 -./insertion reversed 10000 27.739286422729492 -./insertion reversed 11000 33.2233190536499 -./insertion reversed 12000 39.423227310180664 -./insertion reversed 13000 45.474839210510254 -./insertion reversed 14000 52.727437019348145 -./insertion reversed 15000 60.09998321533203 -./insertion constant 1000 0.9403467178344727 -./insertion constant 2000 0.9927988052368164 -./insertion constant 3000 1.1275291442871094 -./insertion constant 4000 1.2822389602661133 -./insertion constant 5000 1.5305280685424805 -./insertion constant 6000 1.5430212020874023 -./insertion constant 7000 1.8325090408325195 -./insertion constant 8000 1.804804801940918 -./insertion constant 9000 2.2058486938476562 -./insertion constant 10000 2.1335840225219727 -./insertion constant 11000 2.322697639465332 -./insertion constant 12000 2.5031328201293945 -./insertion constant 13000 2.8443336486816406 -./insertion constant 14000 2.675914764404297 -./insertion constant 15000 2.9070377349853516 -./insertion v_shaped 1000 1.075124740600586 -./insertion v_shaped 2000 1.6106843948364258 -./insertion v_shaped 3000 2.419257164001465 -./insertion v_shaped 4000 3.438878059387207 -./insertion v_shaped 5000 4.725170135498047 -./insertion v_shaped 6000 6.513190269470215 -./insertion v_shaped 7000 7.992100715637207 -./insertion v_shaped 8000 10.184979438781738 -./insertion v_shaped 9000 12.364602088928223 -./insertion v_shaped 10000 15.029740333557129 -./insertion v_shaped 11000 18.083977699279785 -./insertion v_shaped 12000 21.661686897277832 -./insertion v_shaped 13000 24.31178092956543 -./insertion v_shaped 14000 27.93755531311035 -./insertion v_shaped 15000 32.60822296142578 -./selection random 1000 1.4104366302490234 -./selection random 2000 2.2107839584350586 -./selection random 3000 3.5886764526367188 -./selection random 4000 5.592441558837891 -./selection random 5000 7.922983169555664 -./selection random 6000 11.436033248901367 -./selection random 7000 14.230155944824219 -./selection random 8000 18.193602561950684 -./selection random 9000 22.896504402160645 -./selection random 10000 29.131484031677246 -./selection random 11000 33.37256908416748 -./selection random 12000 39.19968605041504 -./selection random 13000 47.031211853027344 -./selection random 14000 53.545570373535156 -./selection random 15000 61.37092113494873 -./selection sorted 1000 1.2252330780029297 -./selection sorted 2000 2.236461639404297 -./selection sorted 3000 3.660869598388672 -./selection sorted 4000 5.638456344604492 -./selection sorted 5000 8.042407035827637 -./selection sorted 6000 11.208224296569824 -./selection sorted 7000 14.447546005249023 -./selection sorted 8000 18.74523162841797 -./selection sorted 9000 22.982478141784668 -./selection sorted 10000 28.246402740478516 -./selection sorted 11000 34.0437650680542 -./selection sorted 12000 39.82250690460205 -./selection sorted 13000 46.31156921386719 -./selection sorted 14000 53.86967658996582 -./selection sorted 15000 61.89534664154053 -./selection reversed 1000 1.210784912109375 -./selection reversed 2000 2.1828174591064453 -./selection reversed 3000 3.7517547607421875 -./selection reversed 4000 5.427956581115723 -./selection reversed 5000 8.042573928833008 -./selection reversed 6000 10.962772369384766 -./selection reversed 7000 14.444756507873535 -./selection reversed 8000 18.53172779083252 -./selection reversed 9000 22.98440933227539 -./selection reversed 10000 28.051161766052246 -./selection reversed 11000 33.19251537322998 -./selection reversed 12000 39.997243881225586 -./selection reversed 13000 45.667243003845215 -./selection reversed 14000 53.35855484008789 -./selection reversed 15000 60.373663902282715 -./selection constant 1000 1.2602806091308594 -./selection constant 2000 2.1334409713745117 -./selection constant 3000 3.5085439682006836 -./selection constant 4000 5.34212589263916 -./selection constant 5000 7.747673988342285 -./selection constant 6000 10.555744171142578 -./selection constant 7000 14.265799522399902 -./selection constant 8000 18.23742389678955 -./selection constant 9000 22.236275672912598 -./selection constant 10000 27.255654335021973 -./selection constant 11000 32.57889747619629 -./selection constant 12000 38.65196704864502 -./selection constant 13000 45.708537101745605 -./selection constant 14000 51.95658206939697 -./selection constant 15000 59.54868793487549 -./selection v_shaped 1000 1.179647445678711 -./selection v_shaped 2000 2.0728111267089844 -./selection v_shaped 3000 3.5805463790893555 -./selection v_shaped 4000 5.700540542602539 -./selection v_shaped 5000 8.303594589233398 -./selection v_shaped 6000 10.987281799316406 -./selection v_shaped 7000 14.623737335205078 -./selection v_shaped 8000 18.853092193603516 -./selection v_shaped 9000 22.894835472106934 -./selection v_shaped 10000 27.98130512237549 -./selection v_shaped 11000 33.84420871734619 -./selection v_shaped 12000 39.37234878540039 -./selection v_shaped 13000 46.07586860656738 -./selection v_shaped 14000 53.040337562561035 -./selection v_shaped 15000 60.929179191589355 diff --git a/selection b/selection deleted file mode 100755 index f3f1257..0000000 Binary files a/selection and /dev/null differ diff --git a/selection_benchmark.png b/selection_benchmark.png deleted file mode 100644 index e297dc0..0000000 Binary files a/selection_benchmark.png and /dev/null differ