Compare commits
10 Commits
e56169441b
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c02a943a29 | ||
|
|
79249027cb | ||
|
|
946006096b | ||
|
|
964e001dd5 | ||
|
|
03ba2096c1 | ||
|
|
e3863557f5 | ||
|
|
8ee90f0d06 | ||
|
|
449d15c1c7 | ||
|
|
8dbedb691d | ||
|
|
c1355e3003 |
5
.dir-locals.el
Normal file
5
.dir-locals.el
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
;;; Directory Local Variables -*- no-byte-compile: t; -*-
|
||||||
|
;;; For more information see (info "(emacs) Directory Variables")
|
||||||
|
|
||||||
|
((c-mode . ((mode . clang-format)))
|
||||||
|
(c++-mode . ((mode . clang-format))))
|
||||||
3
Makefile
3
Makefile
@@ -15,6 +15,9 @@ list.out: impls/list.cpp
|
|||||||
bsearch.out: impls/bsearch.cpp
|
bsearch.out: impls/bsearch.cpp
|
||||||
$(CC) $(CFLAGS) $^ -o $@
|
$(CC) $(CFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
qsort.out: impls/qsort.cpp
|
||||||
|
$(CC) $(CFLAGS) $^ -o $@
|
||||||
|
|
||||||
vec.out: impls/vec.c
|
vec.out: impls/vec.c
|
||||||
$(CC) $(CFLAGS) $^ -o $@
|
$(CC) $(CFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
(defconst *LIST-SIZE* 128)
|
|
||||||
(defconst *UPPER-BOUND* 1024)
|
|
||||||
(with-current-buffer (find-file "bsearch.txt")
|
|
||||||
(mapcar
|
|
||||||
#'(lambda (res) (insert (format "%s\n" res)))
|
|
||||||
(cl-loop
|
|
||||||
for i from 0 to *LIST-SIZE*
|
|
||||||
collect
|
|
||||||
(random *UPPER-BOUND*))))
|
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -17,9 +18,7 @@ using std::ostream;
|
|||||||
using std::string;
|
using std::string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
vector<int> arr;
|
ostream &print_arr(ostream &os, std::vector<int> &arr)
|
||||||
|
|
||||||
ostream &print_arr(ostream &os)
|
|
||||||
{
|
{
|
||||||
os << "[";
|
os << "[";
|
||||||
for (size_t i = 0; i < arr.size(); ++i)
|
for (size_t i = 0; i < arr.size(); ++i)
|
||||||
@@ -27,31 +26,46 @@ ostream &print_arr(ostream &os)
|
|||||||
return os << "]";
|
return os << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
int bsearch(int n, int l = 0, int u = arr.size() - 1)
|
int bsearch(int n, std::vector<int> arr)
|
||||||
{
|
{
|
||||||
int midpoint = ((u + l) / 2);
|
int l = 0;
|
||||||
if (l >= u || u <= 0)
|
int u = arr.size() - 1;
|
||||||
return -1;
|
while (l <= u)
|
||||||
|
{
|
||||||
|
int midpoint = l + ((u - l) / 2);
|
||||||
int val = arr[midpoint];
|
int val = arr[midpoint];
|
||||||
|
|
||||||
if (val == n)
|
if (val == n)
|
||||||
|
{
|
||||||
return midpoint;
|
return midpoint;
|
||||||
|
}
|
||||||
else if (val > n)
|
else if (val > n)
|
||||||
return bsearch(n, l, midpoint - 1);
|
{
|
||||||
|
u = midpoint - 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return bsearch(n, midpoint + 1, u);
|
{
|
||||||
|
l = midpoint + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
std::ifstream input("bsearch.txt");
|
std::ifstream input(argc > 1 ? argv[1] : "bsearch.txt");
|
||||||
string line;
|
std::vector<int> arr;
|
||||||
while (std::getline(input, line))
|
|
||||||
arr.push_back(std::stoi(line));
|
for (std::string line; std::getline(input, line);
|
||||||
|
arr.push_back(std::stoi(line)))
|
||||||
|
continue;
|
||||||
|
|
||||||
std::sort(std::begin(arr), std::end(arr));
|
std::sort(std::begin(arr), std::end(arr));
|
||||||
string inp;
|
|
||||||
cout << "Enter number to search: ";
|
for (size_t i = 0; i < arr.size(); ++i)
|
||||||
cin >> inp;
|
{
|
||||||
int to_search = std::stoi(inp);
|
int index = bsearch(arr[i], arr);
|
||||||
cout << bsearch(to_search) << endl;
|
assert(index == (int)i);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
10
impls/num-gen.el
Normal file
10
impls/num-gen.el
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
(defconst *LIST-SIZE* 128)
|
||||||
|
(defconst *UPPER-BOUND* 1024)
|
||||||
|
(with-current-buffer (find-file "nums.txt")
|
||||||
|
(mapcar
|
||||||
|
#'(lambda (res) (insert (format "%s\n" res)))
|
||||||
|
(cl-remove-duplicates
|
||||||
|
(cl-loop
|
||||||
|
for i from 0 to *LIST-SIZE*
|
||||||
|
collect
|
||||||
|
(random *UPPER-BOUND*)))))
|
||||||
@@ -4,38 +4,39 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
void padding(size_t n, size_t depth)
|
std::vector<std::string> generate_triangle(const size_t depth)
|
||||||
{
|
|
||||||
for (size_t i = 0; i < ((depth - n) / 2); ++i)
|
|
||||||
printf("\t");
|
|
||||||
}
|
|
||||||
|
|
||||||
void generate_triangle(const size_t depth)
|
|
||||||
{
|
{
|
||||||
|
std::vector<std::string> levels;
|
||||||
std::vector<size_t> items;
|
std::vector<size_t> items;
|
||||||
items.reserve(depth * depth);
|
std::stringstream ss;
|
||||||
|
levels.reserve(depth);
|
||||||
|
items.resize(depth * depth);
|
||||||
|
|
||||||
#define AT(i, j) items[((i) * depth) + (j)]
|
#define AT(i, j) items[((i) * depth) + (j)]
|
||||||
AT(0, 0) = 1;
|
AT(0, 0) = 1;
|
||||||
padding(0, depth);
|
levels.push_back("1");
|
||||||
printf("%lu\n", items[0]);
|
|
||||||
for (size_t i = 1; i < depth; ++i)
|
for (size_t i = 1; i < depth; ++i)
|
||||||
{
|
{
|
||||||
AT(i, 0) = 1;
|
AT(i, 0) = 1;
|
||||||
padding(i, depth);
|
ss << "1 ";
|
||||||
printf("%lu,\t", AT(i, 0));
|
|
||||||
for (size_t j = 1; j < i; ++j)
|
for (size_t j = 1; j < i; ++j)
|
||||||
{
|
{
|
||||||
// Recurrence relation
|
|
||||||
AT(i, j) = AT(i - 1, j - 1) + AT(i - 1, j);
|
AT(i, j) = AT(i - 1, j - 1) + AT(i - 1, j);
|
||||||
printf("%lu,\t", AT(i, j));
|
ss << AT(i, j) << " ";
|
||||||
}
|
}
|
||||||
AT(i, i) = 1;
|
AT(i, i) = 1;
|
||||||
printf("%lu\n", AT(i, i));
|
ss << "1";
|
||||||
|
levels.push_back(ss.str());
|
||||||
|
ss.str(std::string{});
|
||||||
}
|
}
|
||||||
#undef AT
|
#undef AT
|
||||||
|
|
||||||
|
return levels;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usage(FILE *fp)
|
void usage(FILE *fp)
|
||||||
@@ -46,18 +47,29 @@ void usage(FILE *fp)
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc < 2)
|
// Variable declarations
|
||||||
{
|
std::vector<std::string> levels;
|
||||||
usage(stderr);
|
int depth = 0;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int arg = std::stoi(argv[1]);
|
|
||||||
if (arg <= 0)
|
|
||||||
{
|
|
||||||
usage(stderr);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_triangle(arg);
|
if (argc < 2)
|
||||||
|
goto error;
|
||||||
|
depth = std::stoi(argv[1]);
|
||||||
|
if (depth <= 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
levels = generate_triangle(depth);
|
||||||
|
|
||||||
|
for (const auto &level : levels)
|
||||||
|
{
|
||||||
|
for (size_t i = 0;
|
||||||
|
i < (levels[levels.size() - 1].size() - level.size()) / 2; ++i)
|
||||||
|
{
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
printf("%s\n", level.c_str());
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
error:
|
||||||
|
usage(stderr);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
128
impls/qsort.cpp
128
impls/qsort.cpp
@@ -4,8 +4,15 @@
|
|||||||
* Commentary: The inplace O(nlog(n)) sortitng algorithm. Originally designed
|
* Commentary: The inplace O(nlog(n)) sortitng algorithm. Originally designed
|
||||||
* in C, hence the lack of iostream.
|
* in C, hence the lack of iostream.
|
||||||
*/
|
*/
|
||||||
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stack>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using u64 = uint64_t;
|
||||||
|
|
||||||
#define ARR_SIZE(XS) (sizeof(XS) / sizeof((XS)[0]))
|
#define ARR_SIZE(XS) (sizeof(XS) / sizeof((XS)[0]))
|
||||||
#define SWAP(A, B) \
|
#define SWAP(A, B) \
|
||||||
@@ -16,85 +23,90 @@
|
|||||||
(A) ^= (B); \
|
(A) ^= (B); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define TEST_SIZE 20
|
void print_arr(u64 *arr, u64 size)
|
||||||
|
|
||||||
void print_arr(int *arr, int size)
|
|
||||||
{
|
{
|
||||||
printf("{");
|
printf("{\n");
|
||||||
for (int i = 0; i < size - 1; ++i)
|
for (u64 i = 0; i < size; ++i)
|
||||||
printf("%d, ", arr[i]);
|
printf(" %lu,\n", arr[i]);
|
||||||
printf("%d}", arr[size - 1]);
|
printf("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void quicksort(int *arr, int arr_size)
|
struct Partition
|
||||||
{
|
{
|
||||||
#ifdef TRACE
|
u64 *arr;
|
||||||
printf("before, arr=");
|
u64 arr_size;
|
||||||
print_arr(arr, arr_size);
|
};
|
||||||
printf("\n");
|
|
||||||
#endif
|
void quicksort(u64 *arr, u64 arr_size)
|
||||||
// Optimisation: for small arr_size, a different sort like the
|
{
|
||||||
// bubble sort may be better, instead of initialising new stack
|
std::stack<Partition> partitions;
|
||||||
// frames.
|
partitions.push({arr, arr_size});
|
||||||
if (arr_size < 2)
|
|
||||||
return;
|
while (!partitions.empty())
|
||||||
// Optimisation: Use some heuristics to figure out a better pivot
|
|
||||||
// than some constant choice of element.
|
|
||||||
int pivot = 0;
|
|
||||||
int pivot_value = arr[0];
|
|
||||||
for (int i = 1; i < arr_size; ++i)
|
|
||||||
{
|
{
|
||||||
if (arr[i] <= pivot_value)
|
const auto partition = partitions.top();
|
||||||
|
arr = partition.arr;
|
||||||
|
arr_size = partition.arr_size;
|
||||||
|
partitions.pop();
|
||||||
|
|
||||||
|
// TODO: Use a different sort for small enough sizes?
|
||||||
|
if (arr_size > 1)
|
||||||
{
|
{
|
||||||
if (i != pivot)
|
// TODO: Choose a better pivot maybe?
|
||||||
SWAP(arr[i], arr[pivot]);
|
u64 pivot = arr[arr_size - 1]; // Choose the last element as pivot
|
||||||
++pivot;
|
u64 pivot_index = -1;
|
||||||
|
|
||||||
|
for (u64 j = 0; j < arr_size; ++j)
|
||||||
|
{
|
||||||
|
if (arr[j] < pivot)
|
||||||
|
{
|
||||||
|
++pivot_index;
|
||||||
|
std::swap(arr[pivot_index], arr[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TRACE
|
std::swap(arr[pivot_index + 1], arr[arr_size - 1]);
|
||||||
printf("after, arr=");
|
|
||||||
print_arr(arr, arr_size);
|
partitions.push({arr, pivot_index + 1});
|
||||||
printf("\n");
|
partitions.push({arr + pivot_index + 1, arr_size - pivot_index - 1});
|
||||||
#endif
|
}
|
||||||
// Optimisation: Use a stack to do this instead of recursion.
|
}
|
||||||
//
|
|
||||||
// This algorithm is similar to a pre order traversal/dfs, in this
|
|
||||||
// case on an array where left and right partition are children
|
|
||||||
// nodes to the original array node. Also with recursion there's a
|
|
||||||
// real risk for very large ARR_SIZE of running out of space in the
|
|
||||||
// call stack.
|
|
||||||
if (pivot != 0)
|
|
||||||
quicksort(arr, pivot);
|
|
||||||
if (pivot < arr_size - 1)
|
|
||||||
quicksort(arr + pivot + 1, arr_size - pivot - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int arr[TEST_SIZE] = {0};
|
(void)argc;
|
||||||
const int size = TEST_SIZE;
|
(void)argv;
|
||||||
|
|
||||||
// Generate a completely reverse ordered list
|
#define TEST_SIZE 10
|
||||||
/*for (size_t i = 0; i < size; ++i) */
|
// randomly generate some numbers
|
||||||
/* arr[TEST_SIZE - i - 1] = i;*/
|
// u64 *arr = new u64[TEST_SIZE];
|
||||||
|
// u64 arr_size = TEST_SIZE;
|
||||||
|
|
||||||
// Generate a list where the first half is completely sorted and the
|
// for (size_t i = 0; i < TEST_SIZE; ++i)
|
||||||
// other half is in reverse order.
|
// arr[i] = rand() % (2L << 30);
|
||||||
for (size_t i = 0; i < size / 2; ++i)
|
|
||||||
arr[i] = i;
|
// Use nums.txt
|
||||||
for (size_t i = size / 2; i < size; ++i)
|
std::ifstream input(argc > 1 ? argv[1] : "nums.txt");
|
||||||
arr[TEST_SIZE - (i - size / 2) - 1] = i;
|
std::vector<u64> num_vec;
|
||||||
|
|
||||||
|
for (std::string line; std::getline(input, line);
|
||||||
|
num_vec.push_back(std::stoi(line)))
|
||||||
|
continue;
|
||||||
|
u64 *arr = &num_vec[0];
|
||||||
|
u64 arr_size = num_vec.size();
|
||||||
|
|
||||||
printf("Before: ");
|
printf("Before: ");
|
||||||
print_arr(arr, size);
|
print_arr(arr, arr_size);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
quicksort(arr, size);
|
quicksort(arr, arr_size);
|
||||||
|
|
||||||
printf("After: ");
|
printf("After: ");
|
||||||
print_arr(arr, size);
|
print_arr(arr, arr_size);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
// delete[] arr;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
@brief A vector, consisting of a header and some payload (data).
|
@brief A vector, consisting of a header and some payload (data).
|
||||||
@details The idea is that the user must never actually interact with this
|
@details The idea is that the user must never actually interact with this
|
||||||
structure directly, only the data involved. Any vector related functions
|
structure directly, only the data involved. Any vector related functions
|
||||||
deal with
|
will take the pointer to the data and look behind it to get the header.
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user