commit ea5a29c918839741e6640f801477c16756e92159 Author: Zev Averbach Date: Sun Jul 27 19:34:54 2025 +0200 first diff --git a/2023/Makefile b/2023/Makefile new file mode 100644 index 0000000..246a361 --- /dev/null +++ b/2023/Makefile @@ -0,0 +1,2 @@ +yep: + clang arrays_of_structs.c -o arrays_of_structs && ./arrays_of_structs diff --git a/2023/a.out b/2023/a.out new file mode 100755 index 0000000..4dd1196 Binary files /dev/null and b/2023/a.out differ diff --git a/2023/algorithmic_thinking/README.md b/2023/algorithmic_thinking/README.md new file mode 100644 index 0000000..ad16203 --- /dev/null +++ b/2023/algorithmic_thinking/README.md @@ -0,0 +1 @@ +This repo is to document my progress working through the book "Algorithmic Thinking". diff --git a/2023/algorithmic_thinking/food_line b/2023/algorithmic_thinking/food_line new file mode 100755 index 0000000..87fdbb8 Binary files /dev/null and b/2023/algorithmic_thinking/food_line differ diff --git a/2023/algorithmic_thinking/food_line.c b/2023/algorithmic_thinking/food_line.c new file mode 100644 index 0000000..f4b43c0 --- /dev/null +++ b/2023/algorithmic_thinking/food_line.c @@ -0,0 +1,30 @@ +#include + +#define MAX_LINES 100 + +int main() +{ + int i, j, num_lines, num_new_people; + int lines[MAX_LINES]; + scanf("%d%d", &num_lines, &num_new_people); + for (i = 0; i < num_lines; i++) + { + scanf("%d", &lines[i]); + } + int smallest; + int smallest_index = -1; + for (i = 0; i < num_new_people; i++) + { + smallest = 101; + for (j = 0; j < num_lines; j++) + { + if (lines[j] < smallest) { + smallest = lines[j]; + smallest_index = j; + } + } + printf("%d\n", smallest); + lines[smallest_index] += 1; + } + return 0; +} diff --git a/2023/algorithmic_thinking/snowflakes/Makefile b/2023/algorithmic_thinking/snowflakes/Makefile new file mode 100644 index 0000000..3c2f31b --- /dev/null +++ b/2023/algorithmic_thinking/snowflakes/Makefile @@ -0,0 +1,6 @@ +build: + clang snowflakes.c -o snowflakes +run: + ./snowflakes < snowflakes.txt +go: + clang snowflakes.c -o snowflakes && ./snowflakes < snowflakes.txt diff --git a/2023/algorithmic_thinking/snowflakes/TODO.md b/2023/algorithmic_thinking/snowflakes/TODO.md new file mode 100644 index 0000000..0d2be6b --- /dev/null +++ b/2023/algorithmic_thinking/snowflakes/TODO.md @@ -0,0 +1,11 @@ +- demonstrate segfault when you iterate beyond the end of an array +- make sure `num_snowflakes` is on the stack, and that it goes out of scope after you return from get_num_snowflakes_from_stdin + - print the memory address, for example +- is snowflakes really empty after declaration? +- why do we have to create `snowflake` using malloc? its size is predictable at compile time, so why can't we use the stack? + +# Later +- how does `bool` work in C? The definitions are simple enough but what about the type? +- does clang put "0"s in a declared array? +- make the Snowflakes linked list, but putting the latest Entry at the end instead of the beginning +- make the Snowflakes linked list, but putting the latest Entry in the middle (?) diff --git a/2023/algorithmic_thinking/snowflakes/array_of_structs_trying_to_understand_snowflakes_optimized_solution.c b/2023/algorithmic_thinking/snowflakes/array_of_structs_trying_to_understand_snowflakes_optimized_solution.c new file mode 100644 index 0000000..427899f --- /dev/null +++ b/2023/algorithmic_thinking/snowflakes/array_of_structs_trying_to_understand_snowflakes_optimized_solution.c @@ -0,0 +1,33 @@ +#include + +typedef struct Node +{ + int value; + struct Node * next; +} Node; + +int main() +{ + Node nodes[5]; + for (int i = 0; i < 5; i++) + { + nodes[i].value = i + 42; + if (i > 0) + { + nodes[i - 1].next = &nodes[i]; + } + } + for (int i = 0; i < 5; i++) + { + printf("node at %d has value %d\n", i, nodes[i].value); + if (i > 0) + { + printf("node at %d has value %d\n", i - 1, nodes[i - 1].value); + printf( + "that node's 'next' is %p and, as expected, its 'next' has value %d\n", + nodes[i - 1].next, nodes[i - 1].next->value + ); + } + } + return 0; +} diff --git a/2023/algorithmic_thinking/snowflakes/array_of_structs_trying_to_understand_snowflakes_optimized_solution_WRONG.c b/2023/algorithmic_thinking/snowflakes/array_of_structs_trying_to_understand_snowflakes_optimized_solution_WRONG.c new file mode 100644 index 0000000..583ad63 --- /dev/null +++ b/2023/algorithmic_thinking/snowflakes/array_of_structs_trying_to_understand_snowflakes_optimized_solution_WRONG.c @@ -0,0 +1,28 @@ +#include +#include + +typedef struct Node +{ + int value; + struct Node * next; +} Node; + +int main(void) +{ + Node nodes[5]; + + for (int i = 0; i < 5; i++) + { + Node curr_node = { i }; + nodes[i] = curr_node; + printf("Node in ARR current after insertion: %d\n", nodes[i].value); + printf("Node _address_ in ARR current after insertion: %p\n", &nodes[i]); + } + + for (int i = 0; i < 5; i++) + { + printf("Node in ARR: %d\n", nodes[i].value); + } + + return 0; +} diff --git a/2023/algorithmic_thinking/snowflakes/array_of_structs_trying_to_understand_snowflakes_optimized_solution_WRONG2.c b/2023/algorithmic_thinking/snowflakes/array_of_structs_trying_to_understand_snowflakes_optimized_solution_WRONG2.c new file mode 100644 index 0000000..fe7e857 --- /dev/null +++ b/2023/algorithmic_thinking/snowflakes/array_of_structs_trying_to_understand_snowflakes_optimized_solution_WRONG2.c @@ -0,0 +1,29 @@ +#include +#include + +typedef struct Node +{ + int value; + struct Node * next; +} Node; + +int main(void) +{ + Node *nodes[5]; + + for (int i = 0; i < 5; i++) + { + Node * curr_node = malloc(sizeof(Node)); + curr_node->value = i; + nodes[i] = curr_node; + printf("Node in ARR current after insertion: %d\n", nodes[i]->value); + printf("Node _address_ in ARR current after insertion: %p\n", &nodes[i]); + } + + for (int i = 0; i < 5; i++) + { + printf("Node in ARR: %d\n", nodes[i]->value); + } + + return 0; +} diff --git a/2023/algorithmic_thinking/snowflakes/array_of_structs_trying_to_understand_snowflakes_optimized_solution_WRONG3.c b/2023/algorithmic_thinking/snowflakes/array_of_structs_trying_to_understand_snowflakes_optimized_solution_WRONG3.c new file mode 100644 index 0000000..78f1912 --- /dev/null +++ b/2023/algorithmic_thinking/snowflakes/array_of_structs_trying_to_understand_snowflakes_optimized_solution_WRONG3.c @@ -0,0 +1,31 @@ +#include +#include + +#define ARRAY_LEN 1047505 + +typedef struct Node +{ + int value; + struct Node * next; +} Node; + +Node * make_node(int value) +{ + Node * node = malloc(sizeof(Node)); + node->value = value; + return node; +} + +int main() +{ + Node * nodes[ARRAY_LEN]; + for (int i = 0; i < ARRAY_LEN; i++) + { + nodes[i] = make_node(i); + } + for (int i = 0; i < ARRAY_LEN; i++) + { + printf("Node in ARR: %d\n", nodes[i]->value); + } + return 0; +} diff --git a/2023/algorithmic_thinking/snowflakes/snowflakes b/2023/algorithmic_thinking/snowflakes/snowflakes new file mode 100755 index 0000000..40804d7 Binary files /dev/null and b/2023/algorithmic_thinking/snowflakes/snowflakes differ diff --git a/2023/algorithmic_thinking/snowflakes/snowflakes.c b/2023/algorithmic_thinking/snowflakes/snowflakes.c new file mode 100644 index 0000000..e5ae8cc --- /dev/null +++ b/2023/algorithmic_thinking/snowflakes/snowflakes.c @@ -0,0 +1,147 @@ +#include +#include +#include + +#define STRING_THERE_ARE_DUPLICATE_SNOWFLAKES "Twin snowflakes found.\n" +#define STRING_SNOWFLAKES_ARE_UNIQUE "No two snowflakes are alike.\n" +#define LEN_SNOWFLAKE 6 +#define LARGEST_POSSIBLE_SUM 6000 + +int get_num_snowflakes_from_stdin(void) +{ + int num_snowflakes; // this is allocated on the stack + scanf("%d", &num_snowflakes); + return num_snowflakes; +} + +bool they_are_equal_right(int sf1[LEN_SNOWFLAKE], int sf2[LEN_SNOWFLAKE], int sf2_offset) +{ + int sf1_tip, sf2_tip, sf2_index; + for (int i = 0; i < LEN_SNOWFLAKE; i++) + { + sf1_tip = sf1[i]; + + sf2_index = (i + sf2_offset) % LEN_SNOWFLAKE; + sf2_tip = sf2[sf2_index]; + + if (sf1_tip != sf2_tip) + return false; + } + return true; +} + +bool they_are_equal_left(int sf1[LEN_SNOWFLAKE], int sf2[LEN_SNOWFLAKE], int sf2_offset) +{ + int sf1_tip, sf2_tip, sf2_index; + for (int i = 0; i < LEN_SNOWFLAKE; i++) + { + sf1_tip = sf1[i]; + + sf2_index = sf2_offset - i; + if (sf2_index < 0) + sf2_index = sf2_index + LEN_SNOWFLAKE; + sf2_tip = sf2[sf2_index]; + + if (sf1_tip != sf2_tip) + return false; + } + return true; +} + +bool they_are_equal(int sf1[LEN_SNOWFLAKE], int sf2[LEN_SNOWFLAKE]) +{ + for (int o = 0; o < LEN_SNOWFLAKE; o++) + { + if (they_are_equal_right(sf1, sf2, o)) + return true; + if (they_are_equal_left(sf1, sf2, o)) + return true; + } + return false; +} + +int get_hash(int snowflake[LEN_SNOWFLAKE]) +{ + int sum = 0; + for (int i = 0; i < LEN_SNOWFLAKE; i++) + { + sum += snowflake[i]; + } + return sum; +} + +typedef struct Entry { + int snowflake[LEN_SNOWFLAKE]; + struct Entry * next; +} Entry; + +void populate_snowflakes_from_stdin(Entry * snowflakes[LARGEST_POSSIBLE_SUM], int indices_to_check[LARGEST_POSSIBLE_SUM], int num_snowflakes) +{ + int hash; + Entry * snowflake; + int indices_index = 0; + for (int _ = 0; _ < num_snowflakes; _++) + { + snowflake = malloc(sizeof(Entry)); + for (int j = 0; j < LEN_SNOWFLAKE; j++) + { + scanf("%d", &snowflake->snowflake[j]); + } + hash = get_hash(snowflake->snowflake); + if (snowflakes[hash] != 0) + { + indices_to_check[indices_index] = hash; + indices_index++; + } + // snowflakes[hash] is 0 at the terminus + snowflake->next = snowflakes[hash]; + snowflakes[hash] = snowflake; + } +} + +int main(void) +{ + int num_snowflakes = get_num_snowflakes_from_stdin(); + + Entry * snowflakes[LARGEST_POSSIBLE_SUM]; // 48MB of memory, 6 million slots + int indices_to_check[LARGEST_POSSIBLE_SUM]; + + populate_snowflakes_from_stdin(snowflakes, indices_to_check, num_snowflakes); + + int prev_idx; + int idx_to_check; + + for (int i = 0; i < LARGEST_POSSIBLE_SUM; i++) + { + idx_to_check = indices_to_check[i]; + if (idx_to_check == 0) + break; + if (idx_to_check == prev_idx) + continue; + + printf("at index %d of indices_to_check => %d\n", i, indices_to_check[i]); + Entry * sf = snowflakes[idx_to_check]; + Entry * next; + while (sf->next) + { + next = sf->next; + if (they_are_equal(sf->snowflake, next->snowflake)) + { + printf(STRING_THERE_ARE_DUPLICATE_SNOWFLAKES); + return 0; + } + } + prev_idx = idx_to_check; + } + + // for (int i = 0; i < num_snowflakes; i++) + // for (int j = i + 1; j < num_snowflakes; j++) + // if (they_are_equal(snowflakes[i], snowflakes[j])) + // { + // printf(STRING_THERE_ARE_DUPLICATE_SNOWFLAKES); + // return 0; + // } + + // printf(STRING_SNOWFLAKES_ARE_UNIQUE); + return 0; +} diff --git a/2023/algorithmic_thinking/snowflakes/snowflakes.md b/2023/algorithmic_thinking/snowflakes/snowflakes.md new file mode 100644 index 0000000..11b2f65 --- /dev/null +++ b/2023/algorithmic_thinking/snowflakes/snowflakes.md @@ -0,0 +1,25 @@ +Two snowflakes are identical if they are the same, +if we can make them the same by moving rightward +through one of the snowflakes (moving clockwise), +or if we can make them the same by moving leftward +through one of the snowflakes (moving counterclockwise). + +# Input + +The first line of input is an integer n, +the number of snowflakes that weโ€™ll be processing. +The value n will be between 1 and 100,000. + +Each of the following n lines represents one snowflake: + each line has six integers, where each integer is + at least 0 and at most 10,000,000. + +# Output +Our output will be a single line of text: + +If there are no identical snowflakes, output exactly + "No two snowflakes are alike." +If there are at least two identical snowflakes, output exactly + "Twin snowflakes found." + +The time limit for solving the test cases is one second. diff --git a/2023/algorithmic_thinking/snowflakes/snowflakes.txt b/2023/algorithmic_thinking/snowflakes/snowflakes.txt new file mode 100644 index 0000000..b361343 --- /dev/null +++ b/2023/algorithmic_thinking/snowflakes/snowflakes.txt @@ -0,0 +1,8 @@ +4 +6 5 4 3 2 1 +4 6 5 1 2 3 +1 2 10 2 1 5 +15 12 12 12 12 12 +4 5 6 1 2 3 +1 1 1 1 1 1 + diff --git a/2023/arrays_of_structs b/2023/arrays_of_structs new file mode 100755 index 0000000..3af52f7 Binary files /dev/null and b/2023/arrays_of_structs differ diff --git a/2023/arrays_of_structs.c b/2023/arrays_of_structs.c new file mode 100644 index 0000000..ef22992 --- /dev/null +++ b/2023/arrays_of_structs.c @@ -0,0 +1,16 @@ +#include +#include + +typedef struct MyStruct { + char name[10]; +} MyStruct; + + +int main() +{ + MyStruct * structs_p = malloc(5 * sizeof(MyStruct)); + MyStruct &structs_p[0] = { "Sylvia" }; + printf("structs[4] = '%s'\n", structs[4].name); + printf("pointer for structs[4] = '%p'\n", &structs[4].name); + return 0; +} diff --git a/2023/assert.c b/2023/assert.c new file mode 100644 index 0000000..a9ede9b --- /dev/null +++ b/2023/assert.c @@ -0,0 +1,8 @@ +#include + +int main() +{ + int age = 43; + assert(age == 44); + return 0; +} diff --git a/2023/beginning_c__from_beginner_to_pro/a.out b/2023/beginning_c__from_beginner_to_pro/a.out new file mode 100755 index 0000000..4eba9a4 Binary files /dev/null and b/2023/beginning_c__from_beginner_to_pro/a.out differ diff --git a/2023/beginning_c__from_beginner_to_pro/hello_world.c b/2023/beginning_c__from_beginner_to_pro/hello_world.c new file mode 100644 index 0000000..fc29a5b --- /dev/null +++ b/2023/beginning_c__from_beginner_to_pro/hello_world.c @@ -0,0 +1,10 @@ +#include +#define MESSAGE_WITH_A_LENGTH_GREATER_THAN_31_HOPEFULLY "Hi Mom!\n" + +int main(void) +{ + int a_number_whose_var_name_has_quite_a_long_length_wouldnt_you_say = 42; + printf(MESSAGE_WITH_A_LENGTH_GREATER_THAN_31_HOPEFULLY); + printf("%d\n", a_number_whose_var_name_has_quite_a_long_length_wouldnt_you_say); + return 0; +} diff --git a/2023/beginning_c__from_beginner_to_pro/hello_world.o b/2023/beginning_c__from_beginner_to_pro/hello_world.o new file mode 100644 index 0000000..230aafe Binary files /dev/null and b/2023/beginning_c__from_beginner_to_pro/hello_world.o differ diff --git a/2023/beginning_c__from_beginner_to_pro/limits.c b/2023/beginning_c__from_beginner_to_pro/limits.c new file mode 100644 index 0000000..ee9240e --- /dev/null +++ b/2023/beginning_c__from_beginner_to_pro/limits.c @@ -0,0 +1,17 @@ +#include +#include +#include + +int main(void) { + printf("variables of type char store values from %d to %d\n", CHAR_MIN, CHAR_MAX); + printf("variables of type unsigned char store values from 0 to %d\n", UCHAR_MAX); + printf("variables of type short store values from %d to %d\n", SHRT_MIN, SHRT_MAX); + printf("variables of type unsigned short store values from 0 to %d\n", USHRT_MAX); + printf("variables of type int store values from %d to %d\n", INT_MIN, INT_MAX); + printf("variables of type unsigned int store values from 0 to %d\n", UINT_MAX); + printf("variables of type long store values from %ld to %ld\n", LONG_MIN, LONG_MAX); + printf("variables of type unsigned long store values from 0 to %lu\n", ULONG_MAX); + printf("variables of type long long store values from %lld to %lld\n", LLONG_MIN, LLONG_MAX); + printf("variables of type unsigned long long store values from 0 to %llu\n", ULLONG_MAX); + printf("\nthe size of the smallest positive non-zero value of type float is %.3e\n", FLT_MIN); +} diff --git a/2023/beginning_c__from_beginner_to_pro/mult_table.c b/2023/beginning_c__from_beginner_to_pro/mult_table.c new file mode 100644 index 0000000..c42bb68 --- /dev/null +++ b/2023/beginning_c__from_beginner_to_pro/mult_table.c @@ -0,0 +1,46 @@ +#include +#include + +/* Write a program that will generate a multiplication table of a size entered by the user. +A table of size 4, for instance, would have four rows and four columns. +The rows and columns would be labeled from 1 to 4. +Each cell in the table will contain the product of the corresponding row and column numbers, +so the value in the position corresponding to the third row and the fourth column would contain 12.*/ + +void print_column_labels(int size_of_table) { + printf(" "); + for (int i=0; i 99) { + printf("%d"); + } else if (prev_prod > 9) { + printf(" %d", prod); + } else { + printf(" %d", prod); + } + prev_prod = prod; + } + printf("\n"); + prev_prod = 0; + } + return 0; +} + diff --git a/2023/beginning_c__from_beginner_to_pro/printable_chars.c b/2023/beginning_c__from_beginner_to_pro/printable_chars.c new file mode 100644 index 0000000..5c4b6a8 --- /dev/null +++ b/2023/beginning_c__from_beginner_to_pro/printable_chars.c @@ -0,0 +1,20 @@ +/* +Write a program that will output the printable characters for character code values from 0 to 127. +Output each character code along with its symbol with two characters to a line. +Make sure the columns are aligned. +(Hint: You can use the isgraph() function thatโ€™s declared in ctype.h to determine when a character is printable.)โ€ +*/ + +#include +#include + +int main(void) { + for (int i=0; i<128; i++) { + if (isgraph(i)) { + printf("%d: %c\n", i, i); + } else { + printf("%d: %c\n", i, toascii(i)); + } + } + return 0; +} diff --git a/2023/get_index_of_letter b/2023/get_index_of_letter new file mode 100755 index 0000000..f352a84 Binary files /dev/null and b/2023/get_index_of_letter differ diff --git a/2023/get_index_of_letter.c b/2023/get_index_of_letter.c new file mode 100644 index 0000000..b058644 --- /dev/null +++ b/2023/get_index_of_letter.c @@ -0,0 +1,9 @@ +#include + +int main() +{ + char a = 'a'; + int char_code = a - 'a'; + printf("the letter '%c' has char code %d\n", a, char_code); + return 1; +} diff --git a/2023/get_largest_number_for_x_bits.c b/2023/get_largest_number_for_x_bits.c new file mode 100644 index 0000000..32b2ffa --- /dev/null +++ b/2023/get_largest_number_for_x_bits.c @@ -0,0 +1,10 @@ +#include +#include + +int main() +{ + uint64_t zero = 0; + uint64_t minus_one = zero - 1; + printf("%llu", minus_one); + return 0; +} diff --git a/2023/get_num_digits_of_integer b/2023/get_num_digits_of_integer new file mode 100755 index 0000000..4686513 Binary files /dev/null and b/2023/get_num_digits_of_integer differ diff --git a/2023/get_num_digits_of_integer.c b/2023/get_num_digits_of_integer.c new file mode 100644 index 0000000..2b83949 --- /dev/null +++ b/2023/get_num_digits_of_integer.c @@ -0,0 +1,18 @@ +#include +#include + +int get_num_digits(int num) +{ + int the_log_10 = log10(num); + printf("\nlog10 of %d is %d\n", num, the_log_10); + int num_digits = floor(the_log_10 + 1); + return num_digits; +} + +int main() +{ + int the_num = 42000; + int num_digits = get_num_digits(the_num); + printf("%d has %d digits\n\n", the_num, num_digits); + return 0; +} diff --git a/2023/leetcode/maximum_subarray_53 b/2023/leetcode/maximum_subarray_53 new file mode 100755 index 0000000..bef777c Binary files /dev/null and b/2023/leetcode/maximum_subarray_53 differ diff --git a/2023/leetcode/maximum_subarray_53.c b/2023/leetcode/maximum_subarray_53.c new file mode 100644 index 0000000..e04b5a9 --- /dev/null +++ b/2023/leetcode/maximum_subarray_53.c @@ -0,0 +1,21 @@ +#include + +int find_largest_subarray_sum(int * nums, int size) +{ + // find the subarray with the largest sum and return that sum + int largest_sum = 10 << 4; + printf("sizeof(int) = %lu\n", sizeof(int)); + printf("largest_sum is starting out as %d\n", largest_sum); + +} + +int main() +{ + int result; + int input1_size = 9; + int input1[9] = {-2, 1, -3, 4, -1, 2, 1, -5, 4}; + result = find_largest_subarray_sum(input1, input1_size); + printf("result for input1 = %d\n", result); + printf("was hoping for 6 (the sum of {4, -1, 2, 1})\n"); + +} diff --git a/2023/muratori/add/.gitignore b/2023/muratori/add/.gitignore new file mode 100644 index 0000000..92275db --- /dev/null +++ b/2023/muratori/add/.gitignore @@ -0,0 +1,405 @@ +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/main/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/main/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# content below from: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ \ No newline at end of file diff --git a/2023/muratori/add/a.out b/2023/muratori/add/a.out new file mode 100755 index 0000000..f730034 Binary files /dev/null and b/2023/muratori/add/a.out differ diff --git a/2023/muratori/add/add.cpp b/2023/muratori/add/add.cpp new file mode 100644 index 0000000..7614c1f --- /dev/null +++ b/2023/muratori/add/add.cpp @@ -0,0 +1,10 @@ +int __declspec(noinline) add(int A, int B) +{ + return A + B; +} + +#pragma optimize("", off) +int main(int ArgCount, char **Args) +{ + return add(1234, 5678); +} diff --git a/2023/muratori/add/how_many_instructions.s b/2023/muratori/add/how_many_instructions.s new file mode 100644 index 0000000..9dc9074 --- /dev/null +++ b/2023/muratori/add/how_many_instructions.s @@ -0,0 +1,44 @@ + .section __TEXT,__text,regular,pure_instructions + .build_version macos, 14, 0 sdk_version 14, 0 + .intel_syntax noprefix + .globl __Z3addii ## -- Begin function _Z3addii + .p2align 4, 0x90 +__Z3addii: ## @_Z3addii + .cfi_startproc +## %bb.0: + push rbp + .cfi_def_cfa_offset 16 + .cfi_offset rbp, -16 + mov rbp, rsp + .cfi_def_cfa_register rbp + mov dword ptr [rbp - 4], edi + mov dword ptr [rbp - 8], esi + mov eax, dword ptr [rbp - 4] + add eax, dword ptr [rbp - 8] + pop rbp + ret + .cfi_endproc + ## -- End function + .globl _main ## -- Begin function main + .p2align 4, 0x90 +_main: ## @main + .cfi_startproc +## %bb.0: + push rbp + .cfi_def_cfa_offset 16 + .cfi_offset rbp, -16 + mov rbp, rsp + .cfi_def_cfa_register rbp + sub rsp, 16 + mov dword ptr [rbp - 4], 0 + mov dword ptr [rbp - 8], edi + mov qword ptr [rbp - 16], rsi + mov edi, 1234 + mov esi, 5678 + call __Z3addii + add rsp, 16 + pop rbp + ret + .cfi_endproc + ## -- End function +.subsections_via_symbols diff --git a/2023/pointers b/2023/pointers new file mode 100755 index 0000000..4ed7377 Binary files /dev/null and b/2023/pointers differ diff --git a/2023/pointers.c b/2023/pointers.c new file mode 100644 index 0000000..dbd3b77 --- /dev/null +++ b/2023/pointers.c @@ -0,0 +1,23 @@ +#include +#include + +int main() +{ + int x; + int *px; + x = 42; + px = &x; + long px_copy; + px_copy = px; + printf("x = %d\n", x); + printf("px = %p\n", px); + printf("px_copy = %ld\n", px_copy); + printf("*px = %d\n", *px); + printf("incremented"); + x++; + printf("x = %d\n", x); + printf("px = %p\n", px); + printf("*px = %d\n", *px); + return 0; +} + diff --git a/2023/shifting b/2023/shifting new file mode 100755 index 0000000..4da2b49 Binary files /dev/null and b/2023/shifting differ diff --git a/2023/shifting.c b/2023/shifting.c new file mode 100644 index 0000000..4d4d713 --- /dev/null +++ b/2023/shifting.c @@ -0,0 +1,11 @@ +#include +#include + +int main() +{ + uint64_t one = 1; + uint64_t sixteen_times = one << 16; // this is hopefully 65_536 or so + uint64_t thirty_two_times = one << 32; // this is hopefully 65_536 or so + printf("\n%llu", sixteen_times); + printf("\n%llu\n", thirty_two_times); +} diff --git a/2023/tiny_c_projects/greetings b/2023/tiny_c_projects/greetings new file mode 100755 index 0000000..9a68976 Binary files /dev/null and b/2023/tiny_c_projects/greetings differ diff --git a/2023/tiny_c_projects/greetings.c b/2023/tiny_c_projects/greetings.c new file mode 100644 index 0000000..2609584 --- /dev/null +++ b/2023/tiny_c_projects/greetings.c @@ -0,0 +1,30 @@ +#include +#include + +int main(int num_args, char *args[]) +{ + time_t now; + int hour; + + struct tm * clock = localtime(&now); + time(&now); + hour = clock->tm_hour; + + printf("Good "); + if (hour < 12) + { + printf("morning"); + } else if (hour < 17) + { + printf("afternoon"); + } else { + printf("evening"); + } + if (num_args < 2) + { + puts(", dude.\n"); + } else { + printf(", %s\n", args[1]); + } + return 0; +} diff --git a/2023/tiny_c_projects/pithy b/2023/tiny_c_projects/pithy new file mode 100755 index 0000000..0316927 Binary files /dev/null and b/2023/tiny_c_projects/pithy differ diff --git a/2023/tiny_c_projects/pithy.c b/2023/tiny_c_projects/pithy.c new file mode 100644 index 0000000..92d796e --- /dev/null +++ b/2023/tiny_c_projects/pithy.c @@ -0,0 +1,41 @@ +#include +#include +#include + +#define BSIZE 512 + +int main() +{ + const char filename[] = "pithy.txt"; + FILE *fp; + char buffer[BSIZE]; + char *line_of_text, *entry; + int items; + + fp = fopen(filename, "r"); + if (fp == NULL) + { + fprintf(stderr, "Unable to open file %s\n", filename); + exit(1); + } + + while (!feof(fp)) + { + entry = (char *)malloc(sizeof(char) * strlen(buffer) + 1); + if (entry == NULL) + { + fprintf(stderr, "Unable to allocate memory\n"); + exit(1); + } + line_of_text = fgets(buffer, BSIZE, fp); + if (line_of_text == NULL) + break; + strlcpy(entry, buffer, BSIZE); + printf("%d: %s", items, entry); + items++; + } + + fclose(fp); + + return 0; +} diff --git a/2023/tiny_c_projects/pithy.txt b/2023/tiny_c_projects/pithy.txt new file mode 100644 index 0000000..09df6e8 --- /dev/null +++ b/2023/tiny_c_projects/pithy.txt @@ -0,0 +1,5 @@ +Once upon a time, there was a text file. + +It was not a long text file, and it contained very little of any value. + +One day there was a very long line and it exceeded 256 characters. That is a super long line! Oh well, maybe there will be something of value in this text file after all: A segfault-causing line of text which is greater than 256 chars long. Amazing! Oh well, I guess this wasn't quite long enough, so here's a longer line. Are we at 256 chars? My vim is configured to be so minimal that I can't even find this info out at a glance. ๐Ÿ˜ diff --git a/2023/tsoding/music_visualizer/music_visualizer b/2023/tsoding/music_visualizer/music_visualizer new file mode 160000 index 0000000..80c8257 --- /dev/null +++ b/2023/tsoding/music_visualizer/music_visualizer @@ -0,0 +1 @@ +Subproject commit 80c8257e7c20ae6eb0b1968bb40360704dde37bb diff --git a/2025/a.out b/2025/a.out new file mode 100755 index 0000000..2997bcf Binary files /dev/null and b/2025/a.out differ diff --git a/2025/c_programming_a_modern_approach/ch_4/division_and_signs b/2025/c_programming_a_modern_approach/ch_4/division_and_signs new file mode 100755 index 0000000..aba21bb Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_4/division_and_signs differ diff --git a/2025/c_programming_a_modern_approach/ch_4/division_and_signs.c b/2025/c_programming_a_modern_approach/ch_4/division_and_signs.c new file mode 100644 index 0000000..5dc2a75 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_4/division_and_signs.c @@ -0,0 +1,14 @@ +#include + +int main(void) { + printf("8 / 5 -> %d\n", 8 / 5); + printf("-8 / 5 -> %d\n", -8 / 5); + printf("8 / -5 -> %d\n", 8 / -5); + printf("-8 / -5 -> %d\n", -8 / -5); + + printf("8 %% 5 -> %d\n", 8 % 5); + printf("-8 %% 5 -> %d\n", -8 % 5); + printf("8 %% -5 -> %d\n", 8 % -5); + printf("-8 %% -5 -> %d\n", -8 % -5); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_4/increment_a_float b/2025/c_programming_a_modern_approach/ch_4/increment_a_float new file mode 100755 index 0000000..19be1dd Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_4/increment_a_float differ diff --git a/2025/c_programming_a_modern_approach/ch_4/increment_a_float.c b/2025/c_programming_a_modern_approach/ch_4/increment_a_float.c new file mode 100644 index 0000000..1f87ab1 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_4/increment_a_float.c @@ -0,0 +1,8 @@ +#include + +int main(void) { + float a = 1.235230f; + a++; + printf("a is %f\n", a); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_4/reverse_digits b/2025/c_programming_a_modern_approach/ch_4/reverse_digits new file mode 100755 index 0000000..c1599c3 Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_4/reverse_digits differ diff --git a/2025/c_programming_a_modern_approach/ch_4/reverse_digits.c b/2025/c_programming_a_modern_approach/ch_4/reverse_digits.c new file mode 100644 index 0000000..b2fe2b0 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_4/reverse_digits.c @@ -0,0 +1,31 @@ +/* + write a program which asks the user to enter a two-digit number, + then prints the number with its digits reversed. +*/ + +#include + +int using_math(void) { + printf("enter a three digit number: "); + int entry; + scanf("%d", &entry); + int first_digit = entry / 100; + int last_digits = entry % 100; + int second_digit = last_digits / 10; + int third_digit = last_digits % 10; + printf("reversed: %d%d%d\n", third_digit, second_digit, first_digit); + return 0; +} + +int using_scanf(void) { + printf("enter a nine digit number: "); + int first, second, third; + scanf("%1d%1d%1d", &first, &second, &third); + printf("reversed: %d%d%d\n", third, second, first); + return 0; +} + +int main(void) { + using_scanf(); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_5/calc_num_digits b/2025/c_programming_a_modern_approach/ch_5/calc_num_digits new file mode 100755 index 0000000..b45c3cb Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_5/calc_num_digits differ diff --git a/2025/c_programming_a_modern_approach/ch_5/calc_num_digits.c b/2025/c_programming_a_modern_approach/ch_5/calc_num_digits.c new file mode 100644 index 0000000..3e4182c --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_5/calc_num_digits.c @@ -0,0 +1,17 @@ +#include + +/* + Write a program which calculates how many digits a number contains. +*/ +int main(void) { + int num; + int num_digits = 1; + printf("enter a number: "); + scanf("%d", &num); + while (num > 9) { + num /= 10; + num_digits++; + } + printf("number of digits: %d\n", num_digits); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_5/find_closest_flight b/2025/c_programming_a_modern_approach/ch_5/find_closest_flight new file mode 100755 index 0000000..91c6338 Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_5/find_closest_flight differ diff --git a/2025/c_programming_a_modern_approach/ch_5/find_closest_flight.c b/2025/c_programming_a_modern_approach/ch_5/find_closest_flight.c new file mode 100644 index 0000000..e176c62 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_5/find_closest_flight.c @@ -0,0 +1,101 @@ +#include + +/* + find the closest flight + + Departure Time Arrival Time + 8:00am 10:16am + 9:43am 11:52am + 11:19am 1:31pm + 12:47pm 3:00pm + 2:00pm 4:08pm + 3:45pm 5:55pm + 7:00pm 9:20pm + 9:45pm 11:58pm +*/ + +int min(int num1, int num2) { + return num1 < num2 ? num1 : num2; +} + +int get_diff(int flight_time, int current_time) { + int diff = flight_time - current_time; + if (diff < 0) { + diff = -diff; + } + int flight_time_to_midnight = (24 * 60) - flight_time; + int mid_diff = flight_time_to_midnight + current_time; + return min(mid_diff, diff); +} + +int main(void) { + printf("Enter a 24-hour time: "); + int hours, minutes; + scanf("%2d:%2d", &hours, &minutes); + + int minutes_since_midnight = minutes + (hours * 60); + int smallest_diff = 60 * 24; + int diff; + + char *departure_time; + char *arrival_time; + + diff = get_diff(8 * 60, minutes_since_midnight); + if (diff < smallest_diff) { + smallest_diff = diff; + departure_time = "8:00am"; + arrival_time = "10:16am"; + } + + diff = get_diff((9 * 60) + 43, minutes_since_midnight); + if (diff < smallest_diff) { + smallest_diff = diff; + departure_time = "9:43am"; + arrival_time = "11:52am"; + } + + diff = get_diff((11 * 60) + 19, minutes_since_midnight); + if (diff < smallest_diff) { + smallest_diff = diff; + departure_time = "11:19am"; + arrival_time = "1:31pm"; + } + + diff = get_diff((12 * 60) + 47, minutes_since_midnight); + if (diff < smallest_diff) { + smallest_diff = diff; + departure_time = "12:47pm"; + arrival_time = "3:00pm"; + } + + diff = get_diff((14 * 60), minutes_since_midnight); + if (diff < smallest_diff) { + smallest_diff = diff; + departure_time = "2:00pm"; + arrival_time = "4:08pm"; + } + + diff = get_diff((15 * 60) + 45, minutes_since_midnight); + if (diff < smallest_diff) { + smallest_diff = diff; + departure_time = "3:45pm"; + arrival_time = "5:55pm"; + } + + diff = get_diff((19 * 60), minutes_since_midnight); + if (diff < smallest_diff) { + smallest_diff = diff; + departure_time = "7:00pm"; + arrival_time = "9:20pm"; + } + + diff = get_diff((21 * 60) + 45, minutes_since_midnight); + if (diff < smallest_diff) { + smallest_diff = diff; + departure_time = "9:45pm"; + arrival_time = "11:58pm"; + } + + printf("Closest departure time is %s, arriving at %s\n", departure_time, arrival_time); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_5/find_closest_flight.md b/2025/c_programming_a_modern_approach/ch_5/find_closest_flight.md new file mode 100644 index 0000000..3daf631 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_5/find_closest_flight.md @@ -0,0 +1,15 @@ +If it's 2am then the closest flight is 9:45pm, not 8:00am because +it's 4.25 hours between 9:45pm and 2am, versus six hours for the latter. + +With the following implementation, + +```c +int get_diff(int flight_time, int current_time) { + int diff = flight_time - current_time; + return diff < 0 ? -diff : diff; +} +``` + +When `current_time` is 120 and `flight_time` is 8:00am -> 480, the difference is 360. + +When `current_time` is 120 and `flight_time` is 9:45pm -> 1_305, the difference is 1_185, but what we'd like it to show is 255. diff --git a/2025/c_programming_a_modern_approach/ch_5/find_smallest_and_largest b/2025/c_programming_a_modern_approach/ch_5/find_smallest_and_largest new file mode 100755 index 0000000..01437ba Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_5/find_smallest_and_largest differ diff --git a/2025/c_programming_a_modern_approach/ch_5/find_smallest_and_largest.c b/2025/c_programming_a_modern_approach/ch_5/find_smallest_and_largest.c new file mode 100644 index 0000000..ea2507b --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_5/find_smallest_and_largest.c @@ -0,0 +1,33 @@ +#include + +int main(void) { + // find the largest and smallest numbers; use no more than four "if"s + + int one, two, three, four; + printf("please enter four integers: "); + scanf("%d %d %d %d", &one, &two, &three, &four); + + int smallest = one; + int largest = two; + if (one > two) { + smallest = two; + largest = one; + } + + int smallest2 = three; + int largest2 = four; + if (three > four) { + smallest2 = four; + largest2 = three; + } + + if (smallest2 < smallest) { + smallest = smallest2; + } + + if (largest2 > largest) { + largest = largest2; + } + + printf("the smallest is %d and the largest is %d\n", smallest, largest); +} diff --git a/2025/c_programming_a_modern_approach/ch_6/all_even_squares b/2025/c_programming_a_modern_approach/ch_6/all_even_squares new file mode 100755 index 0000000..0312099 Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_6/all_even_squares differ diff --git a/2025/c_programming_a_modern_approach/ch_6/all_even_squares.c b/2025/c_programming_a_modern_approach/ch_6/all_even_squares.c new file mode 100644 index 0000000..e8e162e --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_6/all_even_squares.c @@ -0,0 +1,12 @@ +#include + +int main(void) { + int n; + printf("enter an integer and I'll print all the even squares between zero and it: "); + scanf("%d", &n); + int i, product; + for (i = 1, product = i * i; i <= n / 10, product % 2 == 0; i++, product = i * i) { + printf("%d\n", i * i); + } + return 0; + } diff --git a/2025/c_programming_a_modern_approach/ch_6/approximate_e b/2025/c_programming_a_modern_approach/ch_6/approximate_e new file mode 100755 index 0000000..90cf07b Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_6/approximate_e differ diff --git a/2025/c_programming_a_modern_approach/ch_6/approximate_e.c b/2025/c_programming_a_modern_approach/ch_6/approximate_e.c new file mode 100644 index 0000000..0939e81 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_6/approximate_e.c @@ -0,0 +1,17 @@ +#include + +int main(void) { + printf("to what precision shall we calculate 'e'? " ); + int n; + scanf("%d", &n); + float e = 1; + for (int i = 1; i < n; i++) { + float prod = 1; + for (int j = i; j > 1; j--) { + prod *= j; + } + e += 1 / prod; + } + printf("e is approximately %.22f\n", e); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_6/do_while b/2025/c_programming_a_modern_approach/ch_6/do_while new file mode 100755 index 0000000..5201ccd Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_6/do_while differ diff --git a/2025/c_programming_a_modern_approach/ch_6/do_while.c b/2025/c_programming_a_modern_approach/ch_6/do_while.c new file mode 100644 index 0000000..e61e60a --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_6/do_while.c @@ -0,0 +1,10 @@ +#include + +int main(void) { + int i = 9384; + do { + printf("%d ", i); + i /= 10; + } while (i > 0); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_6/largest_num b/2025/c_programming_a_modern_approach/ch_6/largest_num new file mode 100755 index 0000000..08ca03d Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_6/largest_num differ diff --git a/2025/c_programming_a_modern_approach/ch_6/largest_num.c b/2025/c_programming_a_modern_approach/ch_6/largest_num.c new file mode 100644 index 0000000..43272a4 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_6/largest_num.c @@ -0,0 +1,16 @@ +#include + +#define PROMPT "Enter a number: " + +int main(void) { + float num = 0; + float largest_num = num; + do { + printf(PROMPT); + scanf("%f", &num); + if (num > largest_num) { + largest_num = num; + } + } while (num > 0); + printf("The largest number entered was %f\n", largest_num); +} diff --git a/2025/c_programming_a_modern_approach/ch_6/reverse_digits b/2025/c_programming_a_modern_approach/ch_6/reverse_digits new file mode 100755 index 0000000..53f8a33 Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_6/reverse_digits differ diff --git a/2025/c_programming_a_modern_approach/ch_6/reverse_digits.c b/2025/c_programming_a_modern_approach/ch_6/reverse_digits.c new file mode 100644 index 0000000..6b7565a --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_6/reverse_digits.c @@ -0,0 +1,17 @@ +// we did this in an earlier chapter but now want to do it for arbitrary numbers of digits + +#include + +int main(void) { + int num; + printf("enter an integer of any length and I'll reverse the digits: "); + scanf("%d", &num); + int next_digit; + while (num > 0) { + next_digit = num - (num / 10 * 10); + printf("%d", next_digit); + num /= 10; + } + printf("\n"); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_6/sum_for b/2025/c_programming_a_modern_approach/ch_6/sum_for new file mode 100755 index 0000000..ed8c9de Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_6/sum_for differ diff --git a/2025/c_programming_a_modern_approach/ch_6/sum_for.c b/2025/c_programming_a_modern_approach/ch_6/sum_for.c new file mode 100644 index 0000000..19e547b --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_6/sum_for.c @@ -0,0 +1,14 @@ +#include + +int main(void) { + int sum = 0; + for (int i = 0; i < 10; i++) { + if (i % 2) { + continue; + } + sum += i; + printf("%d\n", sum); + } + printf("%d\n", sum); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_7/a.out b/2025/c_programming_a_modern_approach/ch_7/a.out new file mode 100755 index 0000000..18dc27d Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_7/a.out differ diff --git a/2025/c_programming_a_modern_approach/ch_7/abbrev_name b/2025/c_programming_a_modern_approach/ch_7/abbrev_name new file mode 100755 index 0000000..22600fd Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_7/abbrev_name differ diff --git a/2025/c_programming_a_modern_approach/ch_7/abbrev_name.c b/2025/c_programming_a_modern_approach/ch_7/abbrev_name.c new file mode 100644 index 0000000..dffb32c --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_7/abbrev_name.c @@ -0,0 +1,19 @@ +/* + Write a program which takes a first and last name entered by the user and displays the last name, first initial like "Smith, J." +*/ + +#include + +int main(void) { + char first_char, last_entered_char; + // skip leading spaces + while ((first_char = getchar()) == ' '); + // skip first word after the first letter + while ((last_entered_char = getchar()) != ' '); + + while ((last_entered_char = getchar()) != '\n') { + printf("%c", last_entered_char); + } + printf(", %c.\n", first_char); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_7/char_nums b/2025/c_programming_a_modern_approach/ch_7/char_nums new file mode 100755 index 0000000..20f735d Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_7/char_nums differ diff --git a/2025/c_programming_a_modern_approach/ch_7/char_nums.c b/2025/c_programming_a_modern_approach/ch_7/char_nums.c new file mode 100644 index 0000000..3c53470 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_7/char_nums.c @@ -0,0 +1,12 @@ +#include +#include + +#define ENTER_KEY_NUM 10; + +int main(void) { + while (true) { + char c = getchar(); + printf("you typed '%d'\n", c); + } + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_7/enter_to_continue b/2025/c_programming_a_modern_approach/ch_7/enter_to_continue new file mode 100755 index 0000000..28eafc1 Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_7/enter_to_continue differ diff --git a/2025/c_programming_a_modern_approach/ch_7/enter_to_continue.c b/2025/c_programming_a_modern_approach/ch_7/enter_to_continue.c new file mode 100644 index 0000000..75c4a3c --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_7/enter_to_continue.c @@ -0,0 +1,19 @@ +#include +#include + +#define ENTER_KEY_NUM 10; + +int main(void) { + int i = 1; + while (true) { + if (i % 1000000 == 0) { + printf("press ENTER to continue..."); + while (getchar() != 10) { + continue; + } + } + printf("%d\n", i); + i++; + } + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_7/enter_to_continue.py b/2025/c_programming_a_modern_approach/ch_7/enter_to_continue.py new file mode 100644 index 0000000..b5c552a --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_7/enter_to_continue.py @@ -0,0 +1,8 @@ +i = 1 +while True: + if i % 1_000_000 == 0: + print("press ENTER to continue...") + while input() != "": + continue + print(i) + i += 1 diff --git a/2025/c_programming_a_modern_approach/ch_7/eval_math b/2025/c_programming_a_modern_approach/ch_7/eval_math new file mode 100755 index 0000000..d70ed49 Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_7/eval_math differ diff --git a/2025/c_programming_a_modern_approach/ch_7/eval_math.c b/2025/c_programming_a_modern_approach/ch_7/eval_math.c new file mode 100644 index 0000000..ae6e3ff --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_7/eval_math.c @@ -0,0 +1,36 @@ +#include +#include + +/* + Write a program that evaluates an expression e.g. + + Enter an expression: 1+2.5*3 + Value of expression: 10.5 + +*/ + +int main(void) { + float total, rhs; + char operator; + printf("Enter an expression: "); + scanf("%f", &total); + while (true) { + scanf("%c", &operator); + if (operator == '\n') { + break; + } + scanf("%f", &rhs); + + if (operator == '+') { + total += rhs; + } else if (operator == '-') { + total -= rhs; + } else if (operator == '*') { + total *= rhs; + } else { + total /= rhs; + } + } + printf("Value of expression: %.1f\n", total); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_7/frac_part b/2025/c_programming_a_modern_approach/ch_7/frac_part new file mode 100755 index 0000000..2b1684f Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_7/frac_part differ diff --git a/2025/c_programming_a_modern_approach/ch_7/frac_part.c b/2025/c_programming_a_modern_approach/ch_7/frac_part.c new file mode 100644 index 0000000..0a8eaa0 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_7/frac_part.c @@ -0,0 +1,10 @@ +#include + +int main(void) { + float f, frac_part; + printf("enter a fraction: "); + scanf("%f", &f); + frac_part = f - (int) f; + printf("frac_part: %f\n", frac_part); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_7/math_with_different_types b/2025/c_programming_a_modern_approach/ch_7/math_with_different_types new file mode 100755 index 0000000..a274d4b Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_7/math_with_different_types differ diff --git a/2025/c_programming_a_modern_approach/ch_7/math_with_different_types.c b/2025/c_programming_a_modern_approach/ch_7/math_with_different_types.c new file mode 100644 index 0000000..65481cc --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_7/math_with_different_types.c @@ -0,0 +1,35 @@ +#include + +int main(void) { + char c = '\1'; + short s = 2; + int i = -3; + long m = 5; + float f = 6.5f; + double d = 7.5; + + printf("c is %d\n", c); + printf("i is %d\n", i); + printf("c * i = %d\n", c * i); + + printf("s is %d\n", c); + printf("m is %d\n", i); + printf("s + m = %d\n", c + i); + + printf("f is %f\n", f); + printf("c is %d\n", c); + printf("f / c = %f\n", f / c); + + printf("d is %f\n", d); + printf("s is %d\n", s); + printf("d / s = %lf\n", d / s); + + printf("f is %f\n", f); + printf("d is %lf\n", d); + printf("f - d = %lf\n", f - d); + + printf("f is %f\n", f); + printf("(int) f = %d\n", (int) f); + + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_7/sizeof b/2025/c_programming_a_modern_approach/ch_7/sizeof new file mode 100755 index 0000000..a942166 Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_7/sizeof differ diff --git a/2025/c_programming_a_modern_approach/ch_7/sizeof.c b/2025/c_programming_a_modern_approach/ch_7/sizeof.c new file mode 100644 index 0000000..dddd8e2 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_7/sizeof.c @@ -0,0 +1,11 @@ +#include + +int main(void) { + printf("sizeof(short): %zu\n", sizeof(short)); + printf("sizeof(int): %zu\n", sizeof(int)); + printf("sizeof(long): %zu\n", sizeof(long)); + printf("sizeof(float): %zu\n", sizeof(float)); + printf("sizeof(double): %zu\n", sizeof(double)); + printf("sizeof(long double): %zu\n", sizeof(long double)); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_7/squares_types b/2025/c_programming_a_modern_approach/ch_7/squares_types new file mode 100755 index 0000000..935f9a3 Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_7/squares_types differ diff --git a/2025/c_programming_a_modern_approach/ch_7/squares_types.c b/2025/c_programming_a_modern_approach/ch_7/squares_types.c new file mode 100644 index 0000000..20b6aa6 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_7/squares_types.c @@ -0,0 +1,36 @@ +#include +/* + This is interesting. The compiler and linter give me warnings about implicit conversion to `long` when I assign a value to `n` above ~2_147_400_000. Meanwhile, if I stay at or below that value the results are as expected. However, somewhere above 2146923072 the sign flips: + + i (46340) * i (46340) = 2147395600 + breaking becauses we're about to overflow + + This happens because, indeed, `i * i` _is_ less than `n`, but only because there's been an overflow. + + The exact highest number for `short` is 2_147_483_647 + + What's also interesting is that I get a compilation warning if I assign a value one larger than the largest int, even if I use the type `long` or `long long` for `n`. + + I conclude that the number of bits my machine uses to store an `int` is 32 bits: one bit for the sign, and 31 bits for the number: + + 2^31 = 2_147_483_648 + +*/ + +#define LARGEST_INT 2147483647 +#define LARGEST_SHORT 32767 + +int main(void) { + long long n = LARGEST_INT + 1; + for (int i = 1; (i * i) < n; i++) { + if (i * i < 0) { + printf("breaking becauses we're about to overflow\n"); + printf("the next product is %d x %d = %d\n", i, i, i * i); + break; + } + if (i * i <= n) { + printf("i (%d) * i (%d) = %d\n", i, i, i * i); + } + } + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_7/typedefs b/2025/c_programming_a_modern_approach/ch_7/typedefs new file mode 100755 index 0000000..8237d9a Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_7/typedefs differ diff --git a/2025/c_programming_a_modern_approach/ch_7/typedefs.c b/2025/c_programming_a_modern_approach/ch_7/typedefs.c new file mode 100644 index 0000000..2a396cb --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_7/typedefs.c @@ -0,0 +1,12 @@ +#include + +typedef short Int8; +typedef int Int16; +typedef long Int32; + +int main(void) { + Int32 a = 32000000000; + Int16 b = 5; + printf("a - b -> %ld\n", a - b); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_7/upper b/2025/c_programming_a_modern_approach/ch_7/upper new file mode 100755 index 0000000..c5087dd Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_7/upper differ diff --git a/2025/c_programming_a_modern_approach/ch_7/upper.c b/2025/c_programming_a_modern_approach/ch_7/upper.c new file mode 100644 index 0000000..84d36bd --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_7/upper.c @@ -0,0 +1,17 @@ +#include + +char to_upper(char a_char) { + if (a_char >= 97 && a_char <= 97 + 26) { + return a_char - 32; + } + return a_char; +} + +int main(void) { + printf("give me a letter and I'll uppercase it: "); + char letter; + scanf("%c", &letter); + letter = to_upper(letter); + printf("here it is! %c\n", letter); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_7/word_length b/2025/c_programming_a_modern_approach/ch_7/word_length new file mode 100755 index 0000000..7099b2a Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_7/word_length differ diff --git a/2025/c_programming_a_modern_approach/ch_7/word_length.c b/2025/c_programming_a_modern_approach/ch_7/word_length.c new file mode 100644 index 0000000..96973fa --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_7/word_length.c @@ -0,0 +1,25 @@ +#include +#include +/* + Write a program that calculates the average word length for a sentence: + + Enter a sentence: It was deja vu all over again. + Average word length: 3.4 +*/ + +int main(void) { + printf("Enter a sentence: "); + float num_words = 0; + float num_chars = 0; + char next_char; + while ((next_char = getchar()) != '\n') { + if (next_char == ' ') { + num_words++; + } else { + num_chars++; + } + } + num_words++; // when the next char is '\n' we've finished one more word + printf("Average word length: %.1f\n", num_chars / num_words); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_8/array_of_bool b/2025/c_programming_a_modern_approach/ch_8/array_of_bool new file mode 100755 index 0000000..0ebe754 Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_8/array_of_bool differ diff --git a/2025/c_programming_a_modern_approach/ch_8/array_of_bool.c b/2025/c_programming_a_modern_approach/ch_8/array_of_bool.c new file mode 100644 index 0000000..eec431c --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_8/array_of_bool.c @@ -0,0 +1,17 @@ +#include +#include + +int main(void) { + bool bools[100] = {false}; + bool multi_dimensional_bools[3][5] = {false}; + for (size_t i = 0; i < 100; i++) { + printf("bools[%zu] => %b\n", i, bools[i]); + } + for (size_t i = 0; i < 3; i++) { + for (size_t j = 0; j < 5; j++) { + printf("multi_dimensional_bools[%zu][%zu] => %b\n", i, j, multi_dimensional_bools[i][j]); + } + } + + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_8/cards.c b/2025/c_programming_a_modern_approach/ch_8/cards.c new file mode 100644 index 0000000..5f21a27 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_8/cards.c @@ -0,0 +1,9 @@ +#include +#include +#include + +int main(void) { + rand() + + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_8/designated_initializer b/2025/c_programming_a_modern_approach/ch_8/designated_initializer new file mode 100755 index 0000000..57561af Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_8/designated_initializer differ diff --git a/2025/c_programming_a_modern_approach/ch_8/designated_initializer.c b/2025/c_programming_a_modern_approach/ch_8/designated_initializer.c new file mode 100644 index 0000000..feeaea8 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_8/designated_initializer.c @@ -0,0 +1,9 @@ +#include + +int main(void) { + int a[] = {[100] = 42}; + printf("a[0] = %d\n", a[0]); + printf("a[99] = %d\n", a[99]); + printf("a[100] = %d\n", a[100]); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_8/fib_seq b/2025/c_programming_a_modern_approach/ch_8/fib_seq new file mode 100755 index 0000000..8d0cdb0 Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_8/fib_seq differ diff --git a/2025/c_programming_a_modern_approach/ch_8/fib_seq.c b/2025/c_programming_a_modern_approach/ch_8/fib_seq.c new file mode 100644 index 0000000..b558409 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_8/fib_seq.c @@ -0,0 +1,14 @@ +#include + +int main(void) { + // fill an array with the first 40 numbers in the Fibonacci sequence + size_t fib_seq[40] = { 1, 1 }; + for (size_t i = 0; i < 39; i++) { + fib_seq[i + 2] = fib_seq[i] + fib_seq[i + 1]; + } + for (size_t i = 0; i <= 39; i++) { + printf("%zu (%zu) \n", fib_seq[i], i + 1); + } + + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_8/random_walk b/2025/c_programming_a_modern_approach/ch_8/random_walk new file mode 100755 index 0000000..5c2c8d2 Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_8/random_walk differ diff --git a/2025/c_programming_a_modern_approach/ch_8/random_walk.c b/2025/c_programming_a_modern_approach/ch_8/random_walk.c new file mode 100644 index 0000000..cd1679f --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_8/random_walk.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include + +#define LEFT 0 +#define RIGHT 1 +#define UP 2 +#define DOWN 3 +#define NUM_STEPS 26 +#define NUM_DIRECTIONS 4 + +int main(void) { + srand((unsigned) time(NULL)); + int x = 0; + int y = 0; + int arr[10][10] = { 0 }; + + size_t steps_taken = 1; + arr[0][0] = 1; + + int direction; + + for (size_t i = 0; i < NUM_STEPS; i++) { + while (true) { + direction = rand() % NUM_DIRECTIONS; + printf("%zu: direction: %d", steps_taken, direction); + if (direction == LEFT && x != 0 && !arr[--x][y]) { + x--; + arr[x][y] = steps_taken; + break; + } else if (direction == RIGHT && x != 9 && !arr[++x][y]) { + x++; + arr[x][y] = steps_taken; + break; + } else if (direction == UP && y != 0 && !arr[x][--y]) { + y--; + arr[x][y] = steps_taken; + break; + } else if (direction == DOWN && y != 9 && !arr[x][++y]) { + y++; + arr[x][y] = steps_taken; + break; + } + } + steps_taken++; + } + int val; + for (size_t i = 0; i < 10; i++) { + for (size_t j = 0; j < 10; j++) { + val = arr[i][j]; + if (val == 0) { + printf(". "); + } else { + printf("%d", val); + } + if (j == 9) { + printf("\n"); + } + } + } + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_8/repeated_digits b/2025/c_programming_a_modern_approach/ch_8/repeated_digits new file mode 100755 index 0000000..fd9f20b Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_8/repeated_digits differ diff --git a/2025/c_programming_a_modern_approach/ch_8/repeated_digits.c b/2025/c_programming_a_modern_approach/ch_8/repeated_digits.c new file mode 100644 index 0000000..d65115f --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_8/repeated_digits.c @@ -0,0 +1,34 @@ +#include +#include + +#define PROMPT "Enter a number: " +#define RESPONSE "Repeated digit(s): " + +int main(void) { + printf(PROMPT); + size_t number; + size_t digit; + scanf("%zu", &number); + bool digits_seen[10] = { false }; + bool digits_repeated[10] = { false }; + + do { + digit = number % 10; + // printf("digit: %zu\n", digit); + if (digits_seen[digit] == true && digits_repeated[digit] == false) { + digits_repeated[digit] = true; + } else { + digits_seen[digit] = true; + } + number /= 10; + // printf("%zu\n", number); + } while (number > 0); + printf(RESPONSE); + for (size_t i = 0; i < 10; i++) { + if (digits_repeated[i] == true) { + printf("%zu ", i); + } + } + + return 0; +} diff --git a/2025/c_programming_a_modern_approach/ch_8/sizeof_array b/2025/c_programming_a_modern_approach/ch_8/sizeof_array new file mode 100755 index 0000000..39dc2c1 Binary files /dev/null and b/2025/c_programming_a_modern_approach/ch_8/sizeof_array differ diff --git a/2025/c_programming_a_modern_approach/ch_8/sizeof_array.c b/2025/c_programming_a_modern_approach/ch_8/sizeof_array.c new file mode 100644 index 0000000..a7f9a34 --- /dev/null +++ b/2025/c_programming_a_modern_approach/ch_8/sizeof_array.c @@ -0,0 +1,11 @@ +#include + +int main(void) { + int a[] = {[100] = 42}; + size_t size_of_a = sizeof(a); + size_t size_of_item = sizeof(a[0]); + printf("size of a in bytes: %zu\n", size_of_a); + printf("size of a[0] in bytes: %zu\n", size_of_item); + printf("number of items in a: %zu\n", size_of_a / size_of_item); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/chapter_2/benchy.sh b/2025/c_programming_a_modern_approach/chapter_2/benchy.sh new file mode 100755 index 0000000..bd8982d --- /dev/null +++ b/2025/c_programming_a_modern_approach/chapter_2/benchy.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# save as memory_avg.sh + +runs=10 +cmd="$*" +total_memory=0 + +echo "Running '$cmd' $runs times..." + +for i in $(seq 1 $runs); do + output=$(/usr/bin/time -l bash -c "$cmd" 2>&1) + + # Extract the number after "maximum resident set size" + mem=$(echo "$output" | grep "maximum resident set size" | awk '{print $1}') + + if [[ -n "$mem" && "$mem" =~ ^[0-9]+$ ]]; then + total_memory=$((total_memory + mem)) + echo "Run $i: $mem bytes" + else + echo "Run $i: Failed to get memory usage" + echo "Debug: maximum resident set size line:" + echo "$output" | grep -A 1 "maximum resident set size" + runs=$((runs - 1)) + fi +done + +if [ $runs -gt 0 ]; then + avg=$((total_memory / runs)) + avg_kb=$(echo "scale=2; $avg/1024" | bc) + avg_mb=$(echo "scale=2; $avg/1024/1024" | bc) + + echo "----------------------------------------" + echo "Average memory usage over $runs runs:" + echo "$avg bytes ($avg_kb KB, $avg_mb MB)" +fi diff --git a/2025/c_programming_a_modern_approach/chapter_2/chapter_2.md b/2025/c_programming_a_modern_approach/chapter_2/chapter_2.md new file mode 100644 index 0000000..819dc6e --- /dev/null +++ b/2025/c_programming_a_modern_approach/chapter_2/chapter_2.md @@ -0,0 +1,39 @@ +# Floats + +It's recommended to append 'f' to the end of a float value: + +```c +float amount = 2.52f; +``` + +To print a float use the "%f" placeholder, and to specify the number of digits do +`.%f`: + +```c +printf("amount: %.2f", amount); +// amount: 2.52 +``` + +# Directives + +You don't need semicolons at the end of `#directive`s. + +To define a constant you do + +```c +#define CONSTANT_NAME 7 +``` + +You can assign expressions to constants but they must be wrapped in parentheses. + +You can use constants in the body of your C file; they'll be replaced by the values in the preprocessing step. + +# `main()` + +You can end this with `exit(0)` if you want, instead of `return 0`. + +# gcc flags + +```bash +> gcc -Wall -W -pedantic -std=c99 progname.c -o progname +``` diff --git a/2025/c_programming_a_modern_approach/chapter_2/fewest_bills b/2025/c_programming_a_modern_approach/chapter_2/fewest_bills new file mode 100755 index 0000000..a4da590 Binary files /dev/null and b/2025/c_programming_a_modern_approach/chapter_2/fewest_bills differ diff --git a/2025/c_programming_a_modern_approach/chapter_2/fewest_bills.c b/2025/c_programming_a_modern_approach/chapter_2/fewest_bills.c new file mode 100644 index 0000000..4c28a06 --- /dev/null +++ b/2025/c_programming_a_modern_approach/chapter_2/fewest_bills.c @@ -0,0 +1,32 @@ + +/* + Write a program that asks the user to enter a dollar amount + and then shows how to pay that amount using the smallest number of + 20, 10, 5 and 1-denominated bills. +*/ + +#include +#include + +int main(void) { + float amount = 1011; + // printf("Enter a dollar amount: "); + // scanf("%f", &amount); + + float num_20s = floor(amount / 20); + amount -= num_20s * 20; + + float num_10s = floor(amount / 10); + amount -= num_10s * 10; + + float num_5s = floor(amount / 5); + amount -= num_5s * 5; + + int num_1s = amount; + + printf("$20 bills: %.0f\n", num_20s); + printf("$10 bills: %.0f\n", num_10s); + printf("$5 bills: %.0f\n", num_5s); + printf("$1 bills: %d\n", num_1s); + +} diff --git a/2025/c_programming_a_modern_approach/chapter_2/fewest_bills.py b/2025/c_programming_a_modern_approach/chapter_2/fewest_bills.py new file mode 100644 index 0000000..291d84d --- /dev/null +++ b/2025/c_programming_a_modern_approach/chapter_2/fewest_bills.py @@ -0,0 +1,14 @@ +amount = 1011 + +num_20s = amount // 20 +amount -= num_20s * 20 +num_10s = amount // 10 +amount -= num_10s * 10 +num_5s = amount // 5 +amount -= num_5s * 5 +num_1s = amount + +print("$20 bills: %.0f" % num_20s) +print("$10 bills: %.0f" % num_10s) +print("$5 bills: %.0f" % num_5s) +print("$1 bills: %d" % num_1s) diff --git a/2025/c_programming_a_modern_approach/chapter_2/print_a_float b/2025/c_programming_a_modern_approach/chapter_2/print_a_float new file mode 100755 index 0000000..573f63f Binary files /dev/null and b/2025/c_programming_a_modern_approach/chapter_2/print_a_float differ diff --git a/2025/c_programming_a_modern_approach/chapter_2/print_a_float.c b/2025/c_programming_a_modern_approach/chapter_2/print_a_float.c new file mode 100644 index 0000000..3fcb93e --- /dev/null +++ b/2025/c_programming_a_modern_approach/chapter_2/print_a_float.c @@ -0,0 +1,7 @@ +#include + +int main(void) { + float amount = 2.52f; + printf("amount: %.3f\n", amount); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/chapter_2/vol b/2025/c_programming_a_modern_approach/chapter_2/vol new file mode 100755 index 0000000..407ffe6 Binary files /dev/null and b/2025/c_programming_a_modern_approach/chapter_2/vol differ diff --git a/2025/c_programming_a_modern_approach/chapter_2/volume_of_sphere.c b/2025/c_programming_a_modern_approach/chapter_2/volume_of_sphere.c new file mode 100644 index 0000000..7f68456 --- /dev/null +++ b/2025/c_programming_a_modern_approach/chapter_2/volume_of_sphere.c @@ -0,0 +1,16 @@ +#include + +/* + Write a program which computes the volume of a sphere with a 10-meter radius + using the formula + + v = 4/3 * ฯ€ * r^3 +*/ +int main(void) { + float r; + printf("what is the radius of your sphere?\n\n"); + scanf("%f", &r); + float pi = 3.14; + float v = pi * r * r * r * 4 / 3; + printf("\nthe volume of a sphere with radius %.2f is %.2f\n", r, v); +} diff --git a/2025/c_programming_a_modern_approach/chapter_3/date_input b/2025/c_programming_a_modern_approach/chapter_3/date_input new file mode 100755 index 0000000..9182939 Binary files /dev/null and b/2025/c_programming_a_modern_approach/chapter_3/date_input differ diff --git a/2025/c_programming_a_modern_approach/chapter_3/date_input.c b/2025/c_programming_a_modern_approach/chapter_3/date_input.c new file mode 100644 index 0000000..ed1bf34 --- /dev/null +++ b/2025/c_programming_a_modern_approach/chapter_3/date_input.c @@ -0,0 +1,14 @@ +#include + +/* + write a program which accepts a date from the user + in the form mm/dd/yyyy and then displays it in the form + yyyymmdd +*/ +int main(void) { + int month, day, year; + printf("month, day and year in the format mm/dd/yyyy please: "); + scanf("%d/%d/%d", &month, &day, &year); + printf("\n%d%02d%02d", year, month, day); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/chapter_3/printing_nums b/2025/c_programming_a_modern_approach/chapter_3/printing_nums new file mode 100755 index 0000000..00d0d07 Binary files /dev/null and b/2025/c_programming_a_modern_approach/chapter_3/printing_nums differ diff --git a/2025/c_programming_a_modern_approach/chapter_3/printing_nums.c b/2025/c_programming_a_modern_approach/chapter_3/printing_nums.c new file mode 100644 index 0000000..4248a37 --- /dev/null +++ b/2025/c_programming_a_modern_approach/chapter_3/printing_nums.c @@ -0,0 +1,13 @@ +#include + +int main(void) { + int i; + float x; + + i = 40; + x = 839.21f; + + printf("|%d|%5d|%-5d|%5.3d|\n", i, i, i, i); + printf("|%10.3f|%10.3e|%-10g\n", x, x, x); + return 0; +} diff --git a/2025/c_programming_a_modern_approach/chapter_3/scanf_mixed_types b/2025/c_programming_a_modern_approach/chapter_3/scanf_mixed_types new file mode 100755 index 0000000..cec053b Binary files /dev/null and b/2025/c_programming_a_modern_approach/chapter_3/scanf_mixed_types differ diff --git a/2025/c_programming_a_modern_approach/chapter_3/scanf_mixed_types.c b/2025/c_programming_a_modern_approach/chapter_3/scanf_mixed_types.c new file mode 100644 index 0000000..6c98912 --- /dev/null +++ b/2025/c_programming_a_modern_approach/chapter_3/scanf_mixed_types.c @@ -0,0 +1,8 @@ +#include + +int main(void) { + float a; int b; float c; + scanf("%f%d%f", &a, &b, &c); + printf("%f\n%d\n%f", a, b, c); + return 0; +} diff --git a/2025/checkmark/a.out b/2025/checkmark/a.out new file mode 100755 index 0000000..211cee3 Binary files /dev/null and b/2025/checkmark/a.out differ diff --git a/2025/checkmark/main.c b/2025/checkmark/main.c new file mode 100644 index 0000000..c5819df --- /dev/null +++ b/2025/checkmark/main.c @@ -0,0 +1,11 @@ +#include + +int main(void) { + printf(" *\n"); + printf(" * \n"); + printf(" * \n"); + printf("* * \n"); + printf(" * * \n"); + printf(" * \n"); + return 0; +} diff --git a/2025/main.c b/2025/main.c new file mode 100644 index 0000000..7edf22f --- /dev/null +++ b/2025/main.c @@ -0,0 +1,11 @@ +#include + +int main(void) { + /* write a program that computes + the volume of a sphere with a 10-meter radius + using the formula v = 4/3 * pi * r * r * r + */ + int r = 10; + float volume = 4 / 3 * 3.14 * r * r * r; + printf("volume: %.2f", volume); +} diff --git a/2025/making_a_c_compiler b/2025/making_a_c_compiler new file mode 160000 index 0000000..8eaddcc --- /dev/null +++ b/2025/making_a_c_compiler @@ -0,0 +1 @@ +Subproject commit 8eaddccf913f02b26586d6fd42fdbe527c719bc0 diff --git a/2025/notes_how_i_program_c.md b/2025/notes_how_i_program_c.md new file mode 100644 index 0000000..8eb1dd4 --- /dev/null +++ b/2025/notes_how_i_program_c.md @@ -0,0 +1,677 @@ +# from YouTube: Eskil Steenberg https://www.youtube.com/watch?v=443UNeGrFoM&pp=ygUNaG93IGkgd3JpdGUgYw%3D%3D + + +- uses C89 because C99 is "too new and too broken" +- doesn't use + - goto + - register + - do + - continue + - auto + - volatile +- 0 unwrapt dependencies + - this might mean that he doesn't use dependencies at all + - "i wrap everything so I have 100% control over my code" + +- his code is durable, "i want my code to last forever" + +- "really important to read your code and understand it" + - there can't be any misunderstanding between how the compiler views your code and how you do. -> no ambiguity + - therefore C++ is a terrible language + - tries to be clever, which is the root of all evil + - tries to hide things; but things should be explicit + - overloading is bad + +# Good Tooling + Simple Language = ๐Ÿ‘ + +- e.g. he generates documentation websites of his C projects using his own tool, which parses C +- it's harder to make cool tools in more complex, heavier languages + +# Naming + +- long names are good; it means you're being descriptive +- being descriptive is good! +- snake case > camel, but camel might be more differentiated from vars (if you use snake for vars) +- func() > func () + +# Functions + +- less flipping around +- write code that does something (no handlers, managers, controllers) + - ~ verbs +- WIDE and LONG == good + - you can track the state if it's all in one function +- _really_ long functions are great, you can follow it step by step + +## Function Names + +- module first, file second, object third, verb last + - `vast_db_session_get` + +# API Design + +- create the API you want, then fill in the implementation +- one "entrypoint" (?) "external" file e.g. `main.h` which contains everything from the library modules + - not `main.c` and `main.h` + - put internal things into something called `*_internal.h` + +## Object Orientation (!) + +- no such thing as object-oriented on the machine level + - data + code is impossible at the machine level + - stops malicious attacks + - all memory is write-protected + - "objects are fundamentally wrong" + +In C, + +```c + // can't and _shouldn't_ do + + object thing(); + thing.do_something(); + + // this is the way + + thing = object_create(); + object_do_something(thing); + +``` + +For internal functions being exposed externally, force their usage via void pointer, by exposing them as such. + +```c +// external module +typedef void RShader + +extern RShader *shader_shader_create(...) +extern int shader_shader_make_opaque(...) + +// internal +type def struct{ + ... +}RShader; + + +``` + +# Macros Are Mostly Bad and Dangerous + +Even the first example below has problems: The debugger won't be able to help you. + +## Except + +### Duplicative code for different types + +```c +func(float *array_a, float *array_b, uint count) { + uint i; + for (i = 0; i < count; i++) { + array_a[i] *= array_b[i]; + } +} + +// but you want a bunch of different versions of this with different types +// e.g. double *array_a, etc. +``` + +### __FILE__ and __LINE__ + +These interpolate as the filename and the line number. + +This allows _easy finding of memory leaks_!: + +```c +extern void *f_debug_mem_malloc(uint size, char *file, uint line); +extern void f_debug_mem_print(uint min_allocs); +// goes through the registry and makes sure the allocations are intact; if not, it gives an easy to read list of stomped memory +extern boolean f_debug_memory(); +// if you have an allocation that happens a lot of times, you can comment on each allocation so the registry entry has more detail. +extern boolean f_debug_mem_comment(void *buf, char *comment); + +#ifdef F_MEMORY_DEBUG +# define malloc(n) f_debug_mem_malloc(n, __FILE__, __LINE__) +# define realloc(n, m) f_debug_mem_malloc(n, m, __FILE__, __LINE__) +# define free(n) f_debug_mem_free(n, __FILE__, __LINE__) +``` + +Creates a registry of what _file_ and _line_no_ allocated or deallocated memory! (and other things, see comments) + +He turns it on ~ once a week for debugging. It slows the execution, so not for use all the time. + +### Debugging Data Packing/Unpacking + +In binary files/network protocol stuff. + +- add a `char *name` to your `pack` and `unpack` functions +- has a flag enabling a macro to actually use `name`, so it's only on when trying to debug packing/unpacking or callers thereof + +```c +#define testify_pack_uint8(n, m, l) testify_pack_uint8_internal(n, m, l, __FILE__, __LINE__) +#define testify_unpack_uint8 ... +``` +# Only Use Unsigned Integers + +- 'nuff said, use them by default + +# Memory + +Understanding and having control over memory is a good thing, even if you don't program C. + +## If Something Exists, It Exists _Somewhere_ + +A thing can be described by "what" as well as "_where_". _where_ is a pointer, which is a number. It's like a street address. + +### Pointers + +Why do pointers have types? + +Because you can't _use_ the pointer if you don't know what/how long the thing is it's pointing to. + +```c + +void *p; // untyped, this is fine as seen before (internal objects) +short *short_pointer; +int *int_pointer; + +a = *short_pointer; // reads 2 bytes as a short +b = *int_pointer; // reads 4 bytes as an int + +short_pointer++; // adds 2 bytes = sizeof(short) +int_pointer++; // adds 4 bytes = sizeof(int) + +if (short_pointer != int_pointer) + printf("Not the same!"); + +``` + +Pointers point to one thing, but they sort of also point to the _next_ thing. They's also _kind of arrays_, they're pointers to the starting point of a street/array of addresses (midpoint really, you can go forwards or backwards). + +## `malloc` + +```c +double *a; + +a = malloc(sizeof(float)); // looks like a function, but malloc is an operator in C. this is typically how malloc gets used, but below is better. + +// better to write it this way, because it's more of a _cast_ + +a = malloc((sizeof *a) * 10); // this respects what it _is_ and it also is dynamic, since if `a`'s type changes this will remain correct. + +sizeof (float)a; // this casts `a` as a float +``` + +## Arrays + +- taking a pointer, stepping forward, then reading what's there + +```c +a = x[3]; + +// equivalent to + +uint *p; +p = x; +x = p + (sizeof *x) * 3; +a = *x; +``` + +## Counters + +```c + +// these are equivalent, but the bottom one is faster +// because the first one requires multiplication +// (or not, because compilers are sophisticated) + +uint i; +for (i = 0; i < 10; i++) + // p + (sizeof *p) * i + p[i] = 0; + + +void *end; +for (end = &p[10]; p != end; p++) + *p = 0; +``` + +# Structs + +Don't fool yourself that the computer knows the names in a struct! It's just a bunch of offsets. + +```c +typedef struct{ + uint type; + char name[32]; + float size; +}MyStructType; + +// "scary code" to get the offset of size +offset = (uint)(&((MyStructType *)NULL)->size); +``` + +## Object-Oriented Inheritance + +```c +typedef enum{ + MST_INT, + MST_FLOAT, + MST_COUNT +}MyStructType; + +typedef struct{ + char name[32]; + MyStructType type; +}MyHeader; + +typedef struct{ + MyHeader head; + int value; +}MyStructInt; + +typedef struct{ + MyHeader head; + float value; +}MyStructFloat; + +void my_set_value(MyHeader *h, double value) { + if (h->type == MST_INT) + ((MyStructInt *)h)->value = (int)value; + else + ((MyStructFloat *)h)->value = (float)value; +} + +// a pointer to MyStructFloat _is_ a pointer to MyHeader, which is _also_ a pointer to MyHeader->name +``` + +## Alignment + +Computers like to store things on even byte addresses. + +```c +typedef struct{ + uint8 a; // 1 byte + uint32 b; // 4 byte +}MyStructType; + +sizeof(MyStructType) == 8 // we expected 5 +// the compiler (computer?) stores `a` with three bytes of padding +// this is true even if you reverse the order + +typedef struct{ + uint8 a; // 1 byte + uint8 a; // 1 byte + uint8 a; // 1 byte + uint8 a; // 1 byte + uint32 b; // 4 bytes +}MyStructType; + +// uses exactly the same amount of memory as the one above + +typedef struct{ + uint8 a; // 1 byte + uint32 b; // 4 bytes + uint8 x; // 1 byte +}MyStructType; + +// sizeof (MyStructType) == 12 + +``` + +The takeaway is that you should try to order your struct attributes to land on even/factors of 4 of memory. + + +### Manual Packing + +```c +uint8 *memory; +MyStructType *s; + +memory = malloc(5 * 10); + +for (i = 0; i < 10; i++) { + s = (MyStructType *)&memory[i * 5]; + s->b = i; + s->a = i; +} +// this may be slow or even cause a crash +``` + +## Memory Blocks + +Memory is one big array, BUT it's divided into blocks of 4k. + +Each block has read/write/execute flags. + +Each address isn't the *actual* address, they're virtualized. + +"This piece of memory is for this program; this piece is for that other program. If an application tries to write into memory allocated for another application, I will _crash_ it." + +Since memory addresses are virtualized, you can rearrange them. + +### `realloc` + +`realloc` takes a piece of memory and reallocates the _size_ of it; the contents remain the same. + +It's sometimes seen as bad because it may require copying of memory contents. However, since memory addresses are virtualized... + +#### `gflags.exe` + +If you allocate one byte of memory, the processor will assign you an entire block (4k bytes). Then if you ask for ten bytes more, it'll allocate from the original block. You allocate some more things, and the memory block looks like this: + +---------------------------- +1222222222222233333344444444 + +Then you allocate a fifth thing, and you are allocated a second block of 4k: + +--------------------------- +55555555555555555555555 + +Let's say `a1` is the first var, which only has one byte, then `b1` is the second one, and they're stored contiguously. + +Then you try to do + +```c +a1[1] = 0; +``` + +The computer isn't going to stop you because you're overwriting memory in _your_ application. + +```c +{ + uint a[10], i; + for (i = 0; i < 11; i++) + a[i] = 0; +} +``` + +This will become an infinite loop because `i` when initialized is probably going to be directly after `a` in memory. So when `a[11] = 0` happens, `i` is overwritten as `0`. + +For this reason "I'm always scared when I put an array on the stack." Just be aware this can happen, it's okay to actually do it. + +You can tell Gflags: "Every time I do a new allocation, give me a new block." It puts every item in its own block _separated by a 'kill block'_ which you may not touch. + +When you do that, your computer won't work very well BECAUSE THERE ARE MEMORY LEAKS EVERYWHERE. + +But turn it on every few weeks, run your application, and see if it crashes. + +### Memory is Slow + +Accessing data: + +- register: 0 cycles +- level 1 cache: 2-3 cycles +- level 2 cache: 10-15 +- main memory: 50 cycles + +It's gotten _worse_ over the last 30 years and will continue to do so. + +```c +// this might be faster +a = a * a * a * a * a * a * a * a * a * a * a * a * a * a * a * a * a; +b = b * b * b * b * b * b * b * b * b * b * b * b * b * b * b * b * b; +c = c * c * c * c * c * c * c * c * c * c * c * c * c * c * c * c * c; +d = d * d * d * d * d * d * d * d * d * d * d * d * d * d * d * d * d; + +// than this + +b = *a; // memory access +``` + +#### Linked List + +They're the worst thing you can do for memory coherence. You're jumping around in memory, so lots of cache misses. + +```c +typedef struct{ + void *data; + void *next; +}LinkedList; +// uses twice as much memory as the other options here because it needs +// -> next + +// not memory coherent +for (l = list; l != NULL; l = l->next) + do_something(l); + +// memory coherent (adjacency) +for (i = 0; i < array_length; i++) + do_something(&array[i]); + +// realloc rarely when adding +if (array_length == array_allocated) { + array_allocated += 16; // allocate 16 more values + // then reallocate (every 16 times) + array = realloc(array, (sizeof *array) * array_allocated); +} +// operting on this piece of memory is very fast, everything is adjacent +array[array_length] = value; +array_length++; + +// remove +array[i] = array[--array_length]; // fast + +// if you need to preserve the order, backwards remove is still faster than an LL + +for (i = array_length; i != 0;) { + i--; + if (array[i] == the_one_we_want_to_remove) + break; + last = save; + save = array[i]; + array[i] = last; +} + +// usually you don't need to preserve the order though + +``` + +# Don't Store Data Twice + +```c +typedef struct{ + float width; + float length; + float area; +}MyPlane; + +// a bug waiting to happen because one of the attributes could be updated without one of the others being updated +// ideally, just don't store `area` since math is "free" as we've seen + +// but if you must, + +typedef void MyPlane; + +void my_plain_width_set(MyPlane *plane, float width); +float my_plain_width_get(MyPlane *plane); +void my_plain_length_set(MyPlane *plane, float length); +float my_plain_length_get(MyPlane *plane); +float my_plain_area_get(MyPlane *plane); + +// this is safe because the only public interface is this set of functions +``` + +# Smart Allocations + +## Array with Length + +```c +// typical way of storing an array with length + +typedef struct{ + uint length; + uint8 *data; +}MyArrayOfBytes; + +MyArrayOfBytes *array; +array = malloc(sizeof *array); +array->length = length; +array->data = malloc((sizeof *array->data) * array->length); + +// the flaw is that the struct and its instance may not be contiguous +// therefore slow + +// ๐Ÿš€ better: + +typedef struct{ + uint length; + uint8 data[1]; // in c99: data[]; + // if you add any additional members don't put them here! put them before `data[1]` +}MyArrayOfBytes; + +MyArrayOfBytes *array; +array = malloc((sizeof *array) + sizeof(uint8) * (length - 1)); // because there's already one in `data`; in c99 no need for ' - 1' +array->length = length; + +for (i = 0; i < length; i++) + array->data[i] = 0; + +// only one allocation! it's faster + +``` + +## Instantiate Two Structs + +Only one allocation! + +```c +typedef struct{ + uint64 a; + float b; +}MyStructA; + +typedef struct{ + float x; + uint64 y; + double z; +}MyStructB; + +MyStructA *a; +MyStructB *b; + +a = malloc(sizeof(MyStructA) + sizeof(MyStructA)); +b = (MyStructB *)&a[1]; + +// this could be dangerous because the alignments might not be right, depending on the machine +// however, it can boost performance +``` + +## Stride + +```c +// requires rgb_pixels to be adjacent to each other +void rgb_color_correct(uint8 *rgb_pixels, uint pixel_count); +// more flexible +void rgb_color_correct(uint8 *rgb_pixels, uint pixel_count, uint stride); +// how to call +rgb_color_correct(rgba, pixel_count, sizeof(uint8) * 4); + +typedef struct{ + float size; + uint8 color[3]; + char name[16]; +}Thing; + +Thing t[10]; + +rgb_color_correct(t[0].color, 10, sizeof *t); +``` + +# Don't Be Afraid to Write Code: Build a Mountain + +"Don't implement anything, everything is hard." == conventional wisdom + +aliases: "Don't write your drivers, don't write an operating system." + +Better: "This is something I don't know how to do; therefore I should be doing it." You learn by implementing things. + +When you wrote the code, you can fix it/change it, you have an _expert_ == YOU. Super valuable in the long run. + +## Concrete Advice + +- build huge technology, small applications + E.g. if you build a music player, + - build an interface library (tech) + - build a sound library (tech) + - then build the music player (app) + +## Example: Apple + +They built the mountain: + +- QuickTime -> iTunes + -> webobject -> iTunes Store + +- OS X -> OpenGL + -> iOS + -> App Store + +- Safari -> iPhone + +# Fix Your Code NOW + +- don't fix it later; it snowballs and will be harder later +- have zero technical debt +- if you deliver things quickly at work because you hacked something together, it will create an expectation + - give them very little at the beginning + - only show your manager what's finished, debugged, ready + - then they'll have a realistic idea of what you can build + - (don't spend forever, but write it right from the beginning) +- really important, will always pay off + +# How To Do UIs, Applications, etc. + +Widgets can either 1) draw 2) have an event or 3) update itself, which all happens inside `input`. + +So you can have a button which can be called many times for different reasons. + +```c +void my_widget(BInputState *input) { + if (input->mode == BAM_DRAW) { // draw widget } + else if (input->mode == BAM_EVENT) { // deal with events } + else if (input->mode == BAM_MAIN) { // advance time } +} + +// most UI libs work like this, it's annoying and object-oriented +// lots of ids to keep track of etc +void button_func(void *user) { printf("button press"); } +void init_ui() { + element = element_create; + id = element_button_add(element, x, y, "hello", button_func, NULL); + element_surface_add(element, x, y, size); +} +main_loop() { + element_move(element, id, sin(time), cos(time)); + element_run(element); +}; + + +// nice to have +// problem: this looks nice, but it can't be done +// I don't know if I'm going to draw a surface after the button press +// can't switch the order either +main_loop() { + if (draw_button(sin(time), cos(time), "hello")) + printf("button press"); + draw_surface(x, y, size); +} + +// Better: +main_loop() { + if(draw_button_add(id1, sin(time), cos(time), "hello")) + printf("button press); + draw_surface(id2, x, y, size); + + // the `id`s are pointers and can be to ANYTHING. + // turns out you usually have a pointer: + + slider(&value, &value, x, y, size); + + // if you need an id: + + malloc() + + // the id could even be a string, because everything has an address, and therefore pointers can be `id`s + +} +``` diff --git a/2025/number_guess/a.out b/2025/number_guess/a.out new file mode 100755 index 0000000..6f6cb63 Binary files /dev/null and b/2025/number_guess/a.out differ diff --git a/2025/number_guess/guess b/2025/number_guess/guess new file mode 100755 index 0000000..08ce5c9 Binary files /dev/null and b/2025/number_guess/guess differ diff --git a/2025/number_guess/guess.c b/2025/number_guess/guess.c new file mode 100644 index 0000000..83a6152 --- /dev/null +++ b/2025/number_guess/guess.c @@ -0,0 +1,35 @@ +#include +#include +#include + +#define MAX_NUM 100 + +int generate_random_num(void) { + srand(time(NULL)); // seed rand + return rand() % MAX_NUM + 1; +} + +int main(void) +{ + int random_num = generate_random_num(); + int guess = 0; + char* high_or_low = ""; + printf("randomNum: %d\n", random_num); + while (guess != random_num) { + printf("guess?\n> "); + scanf("%d", &guess); + + /* TODO: an interesting bug is that if I hit at this moment it goes + into an infinite loop of printing this prompt over and over without taking + any input. The same thing happens if you give it a float as the input + instead of an int! These loops are only terminated with */ + if (guess > random_num) { + high_or_low = "high"; + } else { + high_or_low = "low"; + } + printf("guess is %s\n", high_or_low); + } + printf("you got it!\n"); + exit(0); +} diff --git a/2025/uninitialized_vars/a.out b/2025/uninitialized_vars/a.out new file mode 100755 index 0000000..d4b98ca Binary files /dev/null and b/2025/uninitialized_vars/a.out differ diff --git a/2025/uninitialized_vars/main.c b/2025/uninitialized_vars/main.c new file mode 100644 index 0000000..84ca42c --- /dev/null +++ b/2025/uninitialized_vars/main.c @@ -0,0 +1,13 @@ +#include + +int main(void) { + int a; + int b; + float d; + float e; + printf("a: %d\n", a); + printf("b: %d\n", b); + printf("d: %f\n", d); + printf("e: %f\n", e); + return 0; +}