diff options
Diffstat (limited to 'misc/examples/mixed')
| -rw-r--r-- | misc/examples/mixed/astar.c | 173 | ||||
| -rw-r--r-- | misc/examples/mixed/complex.c | 48 | ||||
| -rw-r--r-- | misc/examples/mixed/convert.c | 57 | ||||
| -rw-r--r-- | misc/examples/mixed/demos.c | 195 | ||||
| -rw-r--r-- | misc/examples/mixed/inits.c | 108 | ||||
| -rw-r--r-- | misc/examples/mixed/read.c | 27 |
6 files changed, 608 insertions, 0 deletions
diff --git a/misc/examples/mixed/astar.c b/misc/examples/mixed/astar.c new file mode 100644 index 00000000..d15a9ed7 --- /dev/null +++ b/misc/examples/mixed/astar.c @@ -0,0 +1,173 @@ +// +// -- An A* pathfinder inspired by the excellent tutorial at Red Blob Games -- +// +// This is a reimplementation of the CTL example to STC: +// https://github.com/glouw/ctl/blob/master/examples/astar.c +// https://www.redblobgames.com/pathfinding/a-star/introduction.html +#define i_implement +#include <stc/cstr.h> +#include <stdio.h> + +typedef struct +{ + int x; + int y; + int priorty; + int width; +} +point; + +point +point_init(int x, int y, int width) +{ + return c_LITERAL(point){ x, y, 0, width }; +} + +int +point_cmp_priority(const point* a, const point* b) +{ + return c_default_cmp(&a->priorty, &b->priorty); +} + +int +point_equal(const point* a, const point* b) +{ + return a->x == b->x && a->y == b->y; +} + +point +point_from(const cstr* maze, const char* c, int width) +{ + int index = (int)cstr_find(maze, c); + return point_init(index % width, index / width, width); +} + +int +point_index(const point* p) +{ + return p->x + p->width * p->y; +} + +int +point_key_cmp(const point* a, const point* b) +{ + int i = point_index(a); + int j = point_index(b); + return (i == j) ? 0 : (i < j) ? -1 : 1; +} + +#define i_key point +#define i_cmp point_cmp_priority +#include <stc/cpque.h> + +#define i_key point +#include <stc/cdeq.h> + +#define i_key point +#define i_val int +#define i_cmp point_key_cmp +#define i_tag pcost +#include <stc/csmap.h> + +#define i_key point +#define i_val point +#define i_cmp point_key_cmp +#define i_tag pstep +#include <stc/csmap.h> + +cdeq_point +astar(cstr* maze, int width) +{ + cdeq_point ret_path = {0}; + + cpque_point front = {0}; + csmap_pstep from = {0}; + csmap_pcost costs = {0}; + c_defer( + cpque_point_drop(&front), + csmap_pstep_drop(&from), + csmap_pcost_drop(&costs) + ){ + point start = point_from(maze, "@", width); + point goal = point_from(maze, "!", width); + csmap_pcost_insert(&costs, start, 0); + cpque_point_push(&front, start); + while (!cpque_point_empty(&front)) + { + point current = *cpque_point_top(&front); + cpque_point_pop(&front); + if (point_equal(¤t, &goal)) + break; + point deltas[] = { + { -1, +1, 0, width }, { 0, +1, 0, width }, { 1, +1, 0, width }, + { -1, 0, 0, width }, /* ~ ~ ~ ~ ~ ~ ~ */ { 1, 0, 0, width }, + { -1, -1, 0, width }, { 0, -1, 0, width }, { 1, -1, 0, width }, + }; + for (size_t i = 0; i < c_arraylen(deltas); i++) + { + point delta = deltas[i]; + point next = point_init(current.x + delta.x, current.y + delta.y, width); + int new_cost = *csmap_pcost_at(&costs, current); + if (cstr_str(maze)[point_index(&next)] != '#') + { + const csmap_pcost_value *cost = csmap_pcost_get(&costs, next); + if (cost == NULL || new_cost < cost->second) + { + csmap_pcost_insert(&costs, next, new_cost); + next.priorty = new_cost + abs(goal.x - next.x) + abs(goal.y - next.y); + cpque_point_push(&front, next); + csmap_pstep_insert(&from, next, current); + } + } + } + } + point current = goal; + while (!point_equal(¤t, &start)) + { + cdeq_point_push_front(&ret_path, current); + current = *csmap_pstep_at(&from, current); + } + cdeq_point_push_front(&ret_path, start); + } + return ret_path; +} + +int +main(void) +{ + cstr maze = cstr_lit( + "#########################################################################\n" + "# # # # # # #\n" + "# # ######### # ##### ######### ##### ##### ##### # ! #\n" + "# # # # # # # # # #\n" + "######### # ######### ######### ##### # # # ######### #\n" + "# # # # # # # # # # #\n" + "# # ############# # # ######### ##### # ######### # #\n" + "# # # # # # # # # #\n" + "# ############# ##### ##### # ##### ######### # ##### #\n" + "# # # # # # # # # #\n" + "# ##### ##### # ##### # ######### # # # #############\n" + "# # # # # # # # # # # #\n" + "############# # # # ######### # ##### # ##### ##### #\n" + "# # # # # # # # # #\n" + "# ##### # ######### ##### # ##### ##### ############# #\n" + "# # # # # # # # # #\n" + "# # ######### # ##### ######### # # ############# # #\n" + "# # # # # # # # # # #\n" + "# ######### # # # ##### ######### ######### # #########\n" + "# # # # # # # # # #\n" + "# @ # ##### ##### ##### ######### ##### # ######### # #\n" + "# # # # # # #\n" + "#########################################################################\n" + ); + int width = (int)cstr_find(&maze, "\n") + 1; + cdeq_point ret_path = astar(&maze, width); + + c_foreach (it, cdeq_point, ret_path) + cstr_data(&maze)[point_index(it.ref)] = 'x'; + + printf("%s", cstr_str(&maze)); + + cdeq_point_drop(&ret_path); + cstr_drop(&maze); +} diff --git a/misc/examples/mixed/complex.c b/misc/examples/mixed/complex.c new file mode 100644 index 00000000..9fcbc417 --- /dev/null +++ b/misc/examples/mixed/complex.c @@ -0,0 +1,48 @@ + +// Define similar c++ data types: +// +// using FloatStack = std::stack<float>; +// using StackList = std::stack<FloatStack>; +// using ListMap = std::unordered_map<int, std::forward_list<StackList>>; +// using MapMap = std::unordered_map<std::string, ListMap>; +#define i_implement +#include <stc/cstr.h> + +#define i_type FloatStack +#define i_key float +#include <stc/cstack.h> + +#define i_type StackList +#define i_keyclass FloatStack // "class" picks up _clone, _drop, _cmp +#include <stc/clist.h> + +#define i_type ListMap +#define i_key int +#define i_valclass StackList // "class" picks up _clone, _drop +#include <stc/cmap.h> + +#define i_type MapMap +#define i_key_str +#define i_valclass ListMap +#include <stc/cmap.h> + + +int main(void) +{ + MapMap mmap = {0}; + + // Put in some data in the structures + ListMap* lmap = &MapMap_emplace(&mmap, "first", ListMap_init()).ref->second; + StackList* list = &ListMap_insert(lmap, 42, StackList_init()).ref->second; + FloatStack* stack = StackList_push_back(list, FloatStack_with_size(10, 0)); + stack->data[3] = 3.1415927f; + printf("stack size: %" c_ZI "\n", FloatStack_size(stack)); + + // Access the data entry + const ListMap* lmap_p = MapMap_at(&mmap, "first"); + const StackList* list_p = ListMap_at(lmap_p, 42); + const FloatStack* stack_p = StackList_back(list_p); + printf("value is: %f\n", (double)*FloatStack_at(stack_p, 3)); // pi + + MapMap_drop(&mmap); +} diff --git a/misc/examples/mixed/convert.c b/misc/examples/mixed/convert.c new file mode 100644 index 00000000..fa64560e --- /dev/null +++ b/misc/examples/mixed/convert.c @@ -0,0 +1,57 @@ +#define i_implement +#include <stc/cstr.h> + +#define i_key_str +#define i_val_str +#include <stc/cmap.h> + +#define i_key_str +#include <stc/cvec.h> + +#define i_key_str +#include <stc/clist.h> + +int main(void) +{ + cmap_str map, mclone; + cvec_str keys = {0}, values = {0}; + clist_str list = {0}; + + c_defer( + cmap_str_drop(&map), + cmap_str_drop(&mclone), + cvec_str_drop(&keys), + cvec_str_drop(&values), + clist_str_drop(&list) + ){ + map = c_init(cmap_str, { + {"green", "#00ff00"}, + {"blue", "#0000ff"}, + {"yellow", "#ffff00"}, + }); + + puts("MAP:"); + c_foreach (i, cmap_str, map) + printf(" %s: %s\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second)); + + puts("\nCLONE MAP:"); + mclone = cmap_str_clone(map); + c_foreach (i, cmap_str, mclone) + printf(" %s: %s\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second)); + + puts("\nCOPY MAP TO VECS:"); + c_foreach (i, cmap_str, mclone) { + cvec_str_emplace_back(&keys, cstr_str(&i.ref->first)); + cvec_str_emplace_back(&values, cstr_str(&i.ref->second)); + } + c_forrange (i, cvec_str_size(&keys)) + printf(" %s: %s\n", cstr_str(keys.data + i), cstr_str(values.data + i)); + + puts("\nCOPY VEC TO LIST:"); + c_foreach (i, cvec_str, keys) + clist_str_emplace_back(&list, cstr_str(i.ref)); + + c_foreach (i, clist_str, list) + printf(" %s\n", cstr_str(i.ref)); + } +} diff --git a/misc/examples/mixed/demos.c b/misc/examples/mixed/demos.c new file mode 100644 index 00000000..43c9a7ae --- /dev/null +++ b/misc/examples/mixed/demos.c @@ -0,0 +1,195 @@ +#define i_implement +#include <stc/cstr.h> + +void stringdemo1(void) +{ + cstr cs = cstr_lit("one-nine-three-seven-five"); + printf("%s.\n", cstr_str(&cs)); + + cstr_insert(&cs, 3, "-two"); + printf("%s.\n", cstr_str(&cs)); + + cstr_erase(&cs, 7, 5); // -nine + printf("%s.\n", cstr_str(&cs)); + + cstr_replace(&cs, "seven", "four", 1); + printf("%s.\n", cstr_str(&cs)); + + cstr_take(&cs, cstr_from_fmt("%s *** %s", cstr_str(&cs), cstr_str(&cs))); + printf("%s.\n", cstr_str(&cs)); + + printf("find \"four\": %s\n", cstr_str(&cs) + cstr_find(&cs, "four")); + + // reassign: + cstr_assign(&cs, "one two three four five six seven"); + cstr_append(&cs, " eight"); + printf("append: %s\n", cstr_str(&cs)); + + cstr_drop(&cs); +} + +#define i_key long long +#define i_tag ix +#include <stc/cvec.h> + +void vectordemo1(void) +{ + cvec_ix bignums = cvec_ix_with_capacity(100); + cvec_ix_reserve(&bignums, 100); + for (int i = 10; i <= 100; i += 10) + cvec_ix_push(&bignums, i * i); + + printf("erase - %d: %lld\n", 3, bignums.data[3]); + cvec_ix_erase_n(&bignums, 3, 1); // erase index 3 + + cvec_ix_pop(&bignums); // erase the last + cvec_ix_erase_n(&bignums, 0, 1); // erase the first + + for (int i = 0; i < cvec_ix_size(&bignums); ++i) { + printf("%d: %lld\n", i, bignums.data[i]); + } + + cvec_ix_drop(&bignums); +} + +#define i_key_str +#define i_use_cmp +#include <stc/cvec.h> + +void vectordemo2(void) +{ + cvec_str names = {0}; + cvec_str_emplace_back(&names, "Mary"); + cvec_str_emplace_back(&names, "Joe"); + cvec_str_emplace_back(&names, "Chris"); + cstr_assign(&names.data[1], "Jane"); // replace Joe + printf("names[1]: %s\n", cstr_str(&names.data[1])); + + cvec_str_sort(&names); // Sort the array + + c_foreach (i, cvec_str, names) + printf("sorted: %s\n", cstr_str(i.ref)); + + cvec_str_drop(&names); +} + +#define i_key int +#define i_tag ix +#define i_use_cmp +#include <stc/clist.h> + +void listdemo1(void) +{ + clist_ix nums = {0}, nums2 = {0}; + for (int i = 0; i < 10; ++i) + clist_ix_push_back(&nums, i); + for (int i = 100; i < 110; ++i) + clist_ix_push_back(&nums2, i); + + /* splice nums2 to front of nums */ + clist_ix_splice(&nums, clist_ix_begin(&nums), &nums2); + c_foreach (i, clist_ix, nums) + printf("spliced: %d\n", *i.ref); + puts(""); + + *clist_ix_find(&nums, 104).ref += 50; + clist_ix_remove(&nums, 103); + clist_ix_iter it = clist_ix_begin(&nums); + clist_ix_erase_range(&nums, clist_ix_advance(it, 5), clist_ix_advance(it, 15)); + clist_ix_pop_front(&nums); + clist_ix_push_back(&nums, -99); + clist_ix_sort(&nums); + + c_foreach (i, clist_ix, nums) + printf("sorted: %d\n", *i.ref); + + c_drop(clist_ix, &nums, &nums2); +} + +#define i_key int +#define i_tag i +#include <stc/cset.h> + +void setdemo1(void) +{ + cset_i nums = {0}; + cset_i_insert(&nums, 8); + cset_i_insert(&nums, 11); + + c_foreach (i, cset_i, nums) + printf("set: %d\n", *i.ref); + cset_i_drop(&nums); +} + +#define i_key int +#define i_val int +#define i_tag ii +#include <stc/cmap.h> + +void mapdemo1(void) +{ + cmap_ii nums = {0}; + cmap_ii_insert(&nums, 8, 64); + cmap_ii_insert(&nums, 11, 121); + printf("val 8: %d\n", *cmap_ii_at(&nums, 8)); + cmap_ii_drop(&nums); +} + +#define i_key_str +#define i_val int +#define i_tag si +#include <stc/cmap.h> + +void mapdemo2(void) +{ + cmap_si nums = {0}; + cmap_si_emplace_or_assign(&nums, "Hello", 64); + cmap_si_emplace_or_assign(&nums, "Groovy", 121); + cmap_si_emplace_or_assign(&nums, "Groovy", 200); // overwrite previous + + // iterate the map: + for (cmap_si_iter i = cmap_si_begin(&nums); i.ref; cmap_si_next(&i)) + printf("long: %s: %d\n", cstr_str(&i.ref->first), i.ref->second); + + // or rather use the short form: + c_foreach (i, cmap_si, nums) + printf("short: %s: %d\n", cstr_str(&i.ref->first), i.ref->second); + + cmap_si_drop(&nums); +} + +#define i_key_str +#define i_val_str +#include <stc/cmap.h> + +void mapdemo3(void) +{ + cmap_str table = {0}; + cmap_str_emplace(&table, "Map", "test"); + cmap_str_emplace(&table, "Make", "my"); + cmap_str_emplace(&table, "Sunny", "day"); + cmap_str_iter it = cmap_str_find(&table, "Make"); + c_foreach (i, cmap_str, table) + printf("entry: %s: %s\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second)); + printf("size %" c_ZI ": remove: Make: %s\n", cmap_str_size(&table), cstr_str(&it.ref->second)); + //cmap_str_erase(&table, "Make"); + cmap_str_erase_at(&table, it); + + printf("size %" c_ZI "\n", cmap_str_size(&table)); + c_foreach (i, cmap_str, table) + printf("entry: %s: %s\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second)); + + cmap_str_drop(&table); // frees key and value cstrs, and hash table. +} + +int main(void) +{ + printf("\nSTRINGDEMO1\n"); stringdemo1(); + printf("\nVECTORDEMO1\n"); vectordemo1(); + printf("\nVECTORDEMO2\n"); vectordemo2(); + printf("\nLISTDEMO1\n"); listdemo1(); + printf("\nSETDEMO1\n"); setdemo1(); + printf("\nMAPDEMO1\n"); mapdemo1(); + printf("\nMAPDEMO2\n"); mapdemo2(); + printf("\nMAPDEMO3\n"); mapdemo3(); +} diff --git a/misc/examples/mixed/inits.c b/misc/examples/mixed/inits.c new file mode 100644 index 00000000..53a49f1f --- /dev/null +++ b/misc/examples/mixed/inits.c @@ -0,0 +1,108 @@ +#define i_implement +#include <stc/cstr.h> + +#define i_key int +#define i_val_str +#define i_tag id // Map of int => cstr +#include <stc/cmap.h> + +#define i_key_str +#define i_val int +#define i_tag cnt // Map of cstr => int +#include <stc/cmap.h> + +typedef struct {int x, y;} ipair_t; +inline static int ipair_cmp(const ipair_t* a, const ipair_t* b) { + int c = c_default_cmp(&a->x, &b->x); + return c ? c : c_default_cmp(&a->y, &b->y); +} + + +#define i_key ipair_t +#define i_cmp ipair_cmp +#define i_tag ip +#include <stc/cvec.h> + +#define i_key ipair_t +#define i_cmp ipair_cmp +#define i_tag ip +#include <stc/clist.h> + +#define i_key float +#define i_tag f +#include <stc/cpque.h> + +int main(void) +{ + // CVEC FLOAT / PRIORITY QUEUE + + cpque_f floats = {0}; + const float nums[] = {4.0f, 2.0f, 5.0f, 3.0f, 1.0f}; + + // PRIORITY QUEUE + c_forrange (i, c_arraylen(nums)) + cpque_f_push(&floats, nums[i]); + + puts("\npop and show high priorites first:"); + while (! cpque_f_empty(&floats)) { + printf("%.1f ", (double)*cpque_f_top(&floats)); + cpque_f_pop(&floats); + } + puts("\n"); + cpque_f_drop(&floats); + + // CMAP ID + + int year = 2020; + cmap_id idnames = {0}; + cmap_id_emplace(&idnames, 100, "Hello"); + cmap_id_insert(&idnames, 110, cstr_lit("World")); + cmap_id_insert(&idnames, 120, cstr_from_fmt("Howdy, -%d-", year)); + + c_foreach (i, cmap_id, idnames) + printf("%d: %s\n", i.ref->first, cstr_str(&i.ref->second)); + puts(""); + cmap_id_drop(&idnames); + + // CMAP CNT + + cmap_cnt countries = c_init(cmap_cnt, { + {"Norway", 100}, + {"Denmark", 50}, + {"Iceland", 10}, + {"Belgium", 10}, + {"Italy", 10}, + {"Germany", 10}, + {"Spain", 10}, + {"France", 10}, + }); + cmap_cnt_emplace(&countries, "Greenland", 0).ref->second += 20; + cmap_cnt_emplace(&countries, "Sweden", 0).ref->second += 20; + cmap_cnt_emplace(&countries, "Norway", 0).ref->second += 20; + cmap_cnt_emplace(&countries, "Finland", 0).ref->second += 20; + + c_forpair (country, health, cmap_cnt, countries) + printf("%s: %d\n", cstr_str(_.country), *_.health); + puts(""); + cmap_cnt_drop(&countries); + + // CVEC PAIR + + cvec_ip pairs1 = c_init(cvec_ip, {{5, 6}, {3, 4}, {1, 2}, {7, 8}}); + cvec_ip_sort(&pairs1); + + c_foreach (i, cvec_ip, pairs1) + printf("(%d %d) ", i.ref->x, i.ref->y); + puts(""); + cvec_ip_drop(&pairs1); + + // CLIST PAIR + + clist_ip pairs2 = c_init(clist_ip, {{5, 6}, {3, 4}, {1, 2}, {7, 8}}); + clist_ip_sort(&pairs2); + + c_foreach (i, clist_ip, pairs2) + printf("(%d %d) ", i.ref->x, i.ref->y); + puts(""); + clist_ip_drop(&pairs2); +} diff --git a/misc/examples/mixed/read.c b/misc/examples/mixed/read.c new file mode 100644 index 00000000..de04fd31 --- /dev/null +++ b/misc/examples/mixed/read.c @@ -0,0 +1,27 @@ +#define i_implement +#include <stc/cstr.h> +#include <stc/algo/raii.h> +#define i_key_str +#include <stc/cvec.h> +#include <errno.h> + +cvec_str read_file(const char* name) +{ + cvec_str vec = {0}; + c_with (FILE* f = fopen(name, "r"), fclose(f)) + c_with (cstr line = {0}, cstr_drop(&line)) + while (cstr_getline(&line, f)) + cvec_str_push(&vec, cstr_clone(line)); + return vec; +} + +int main(void) +{ + int n = 0; + c_with (cvec_str vec = read_file(__FILE__), cvec_str_drop(&vec)) + c_foreach (i, cvec_str, vec) + printf("%5d: %s\n", ++n, cstr_str(i.ref)); + + if (errno) + printf("error: read_file(" __FILE__ "). errno: %d\n", errno); +} |
