diff --git a/Week 3-workshop/README.md b/Week 3-workshop/README.md new file mode 100644 index 0000000..a16cd65 --- /dev/null +++ b/Week 3-workshop/README.md @@ -0,0 +1,3 @@ +## Worshop 2 content + +Workshop content: https://teaching.csse.uwa.edu.au/units/CITS2002/workshops/workshop3.php diff --git a/Week 3-workshop/haversine.c b/Week 3-workshop/haversine.c new file mode 100644 index 0000000..c5c10c2 --- /dev/null +++ b/Week 3-workshop/haversine.c @@ -0,0 +1,29 @@ + +#include +#include + +#define TWO_PI (2*M_PI) +#define EARTH_RADIUS 6300000 + +double degrees_to_radians(double degrees) { + return degrees/360*TWO_PI; +} + +double radians_to_degrees(double radians) { + return radians/TWO_PI*360; +} + +bool valid_location(double latitude, double longitude) { + return latitude > -90 && latitude <= 90 + && longitude > 0 && longitude <= 360; +} + +double __sin_sqr_delta(double x1, double x2) { + double x = sin( (x2-x1)/2 ); + return x*x; +} + +double haversine(double latitude1, double longitude1, double latitude2, double longitude2) { + double d = sqrt(__sin_sqr_delta(longitude1,longitude2) + cos(latitude1)*cos(latitude2)*__sin_sqr_delta(longitude1,longitude2)); + return 2*EARTH_RADIUS*asin(d); +} \ No newline at end of file diff --git a/Week 3/README.md b/Week 3/README.md new file mode 100644 index 0000000..7f5edd1 --- /dev/null +++ b/Week 3/README.md @@ -0,0 +1,4 @@ +# Week 3 + +Lab sheet: https://teaching.csse.uwa.edu.au/units/CITS2002/labsheets/labsheet2.php\ +Sample `square.c`: https://teaching.csse.uwa.edu.au/units/CITS2002/labsheets/labsheet2.php diff --git a/Week 3/ackermann/ackermann.c b/Week 3/ackermann/ackermann.c new file mode 100644 index 0000000..df1bc2b --- /dev/null +++ b/Week 3/ackermann/ackermann.c @@ -0,0 +1,73 @@ +/* +* Trivially implement Ackermann's function. +* Extend your implementation to count the number of recursive calls and the + maximum recursive depth required for, say, A(1, 2) and A(3, 3). +* 🌶 🌶 Redesign your implementation so that it doesn't require any global + variables to maintain the counts of recursive calls and maximum recursive + depth. +*/ + +#include +#include + +// This is for the challenge (🌶 🌶). Trivial solution below. +struct ack_state { + int value; + int max_depth; + int current_depth; + int call_count; +}; + +/* +note about max depth: +https://courses.cs.cornell.edu/cs412/2001SP/hw/bench/ack.html +max depth of \(A(3,k)\) is \(2^{k+3}-1\) +*/ +void ackermann(int m, int n, struct ack_state *state) { + state->call_count++; + state->current_depth++; + if (m == 0) { + if (state->current_depth > state->max_depth) + { + state->max_depth = state->current_depth; + } + state->value = n+1; + } else if (n == 0) { + ackermann(m-1, 1, state); + } else { + ackermann(m, n-1, state); + ackermann(m-1, state->value, state); + } + state->current_depth--; + // return state; +} + +int main(int argc, char const *argv[]) +{ + if (argc != 3) { + printf("Only two integer inputs allowed for ackermann function\n"); + exit(EXIT_FAILURE); + } + int m = atoi(argv[1]); + int n = atoi(argv[2]); + struct ack_state *state; + state = malloc(sizeof(struct ack_state)); + ackermann(m, n, state); + printf("ackermann(%d,%d) = %d\n", m, n, state->value); + printf("ackermann calls: %d\n", state->call_count); + printf("maximum call depth: %d\n", state->max_depth); + exit(EXIT_SUCCESS); + return 0; +} + +// Trivial ackermann +/* +int ackermann(int m, int n) { + if (m == 0) { + return n+1; + } else if (n == 0) { + return ackermann(m-1, 1); + } + return ackermann(m-1, ackermann(m, n-1)); +} +*/ \ No newline at end of file diff --git a/Week 3/byte_size/bytesize.c b/Week 3/byte_size/bytesize.c new file mode 100644 index 0000000..fbed6cb --- /dev/null +++ b/Week 3/byte_size/bytesize.c @@ -0,0 +1,53 @@ +/* +* 🌶 Write a program that prints out the "byte size" description of the (assumed + to be numerical) arguments supplied to the program. For example: + +prompt> ./bytesize 1 1200 2444555 5666777888 +1Byte +1KByte +2MByte +5GByte (this one may be a challenge!) +*/ + +#include +#include + +#define UNIT "Byte" + +static char *METRIC_PREFIX[] = {"K", "M", "G", "T", "P", "E", "Z", "Y"}; + +/* +* Let's use the old standard which defines the size of 1kb to be 1024b, rather + than 1000b (SI/IEC definition). Allows us to use bitshifts. +* https://en.wikipedia.org/wiki/Kilobyte +*/ +char byteSize(unsigned long long size) { + int level = 0; + while ((size >> 10) > 0) { + size >>= 10; + level++; + } + + if (level > 0) { + printf("%llu%s%s\n", size, METRIC_PREFIX[level-1], UNIT); + } else { + printf("%llu%s\n", size, UNIT); + } + +} + +int main(int argc, char const *argv[]) +{ + if (argc == 1) + { + printf("Must pass at least one size as a parameter\n"); + exit(EXIT_FAILURE); + } + + for (int i = 1; i < argc; i++) + { + byteSize(atoll(argv[i])); + } + exit(EXIT_SUCCESS); + return 0; +} diff --git a/Week 3/christmas_trees/tree.c b/Week 3/christmas_trees/tree.c new file mode 100644 index 0000000..3459616 --- /dev/null +++ b/Week 3/christmas_trees/tree.c @@ -0,0 +1,85 @@ +/* +Write programs to print each of the following shapes. Use C's for loops to +control your printing, rather than just 'fixed' calls to printf (imagine +if a command-line argument indicated how big the Christmas tree should be!): +a. * b. * c. ***** d. * + ** ** **** *** + *** *** *** ***** + **** **** ** ******* + ***** ***** * ********* +*/ + +#include +#include +#include +#include + +#define DEFAULT_HEIGHT 5 + +void repeatChar(char c, int pad, int n) { + printf("%*s", pad, ""); + for (int i = 0; i < n; i++) + { + printf("%c",c); + } +} + + +void drawTree(int n, bool reverse, bool pad, bool cone) { + int incr = 1; + if (cone) { + incr = 2; + n++; + } + for (int i = 1; i <= n; i+=incr) + { + if (reverse) { + if (pad) { + repeatChar('*',i/incr,n-i); + } else { + repeatChar('*',0,n-i); + } + } else { + if (pad) { + repeatChar('*',(n-i)/incr,i); + } else { + repeatChar('*',0,i); + } + } + printf("\n"); + } +} + +void drawTreeOption(int argc, char const *argv[], int n) { + bool cone = false; + bool right = false; + bool inverted = false; + for (int i = 0; i < argc; i++) + { + if (strcmp(argv[i], "--cone") == 0) { + cone = true; + right = true; + } else if (strcmp(argv[i], "--right") == 0) { + right = true; + } else if (strcmp(argv[i], "--inverted") == 0) { + inverted = true; + } + } + + if (n <= 0) { + n = DEFAULT_HEIGHT; + } + + drawTree(n, inverted, right, cone); +} + +int main(int argc, char const *argv[]) +{ + if (argc > 1) { + drawTreeOption(argc, argv, atoi(argv[1])); + } else { + drawTreeOption(0, NULL, 0); + } + exit(EXIT_SUCCESS); + return 0; +} diff --git a/Week 3/leapyear/leapyear.c b/Week 3/leapyear/leapyear.c new file mode 100644 index 0000000..ec58df0 --- /dev/null +++ b/Week 3/leapyear/leapyear.c @@ -0,0 +1,36 @@ +/* +* A year is a leap year if it is divisible by 400, or if it is divisible by 4 + and not divisible by 100. For example - 1996, 2000, and 2012 were leap years, + while 1899, 1900, and 2013 were not. Write a program that prints whether a + year, supplied as a command-line argument, is a leap year or not. +*/ + +#include +#include +#include + +bool isLeapYear(int year) { + return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); +} + +int main(int argc, char const *argv[]) +{ + if (argc == 1) + { + printf("No input provided! Provide one or more years to check\n"); + exit(EXIT_FAILURE); + } + + for (int i = 1; i < argc; i++) + { + int year = atoi(argv[i]); + char *value = "No"; + if (isLeapYear(year)) + { + value = "Yes"; + } + printf("%d => %s\n",year,value); + } + exit(EXIT_SUCCESS); + return 0; +} diff --git a/Week 3/luhn/lunh.c b/Week 3/luhn/lunh.c new file mode 100644 index 0000000..c4a26ed --- /dev/null +++ b/Week 3/luhn/lunh.c @@ -0,0 +1,72 @@ +/* +The Luhn algorithm was developed by German computer scientist Hans Peter Luhn in +1954, and is used by many credit card companies to distinguish valid credit card +numbers from random sequences of digits. To determine if a given credit card +number passes the Luhn test: +* Consider the card's digits from right-to-left. +* Taking the first, third, ... and every odd digit (from right-to-left), sum + them to form the sum s1 +* Taking the second, fourth ... and every even digit (from right-to-left): + * Multiply each even digit by two, sum that product's digits, and add + together all those sums to form the sum s2 +* If (s1 + s2) ends in zero, then the original number was a valid credit card + number! +* Encourage everyone in the Lab to give you their credit card number (so you can + test your code, of course). +*/ + +#include +#include +#include +#include + +bool number(char c) { + int n = c - '0'; + return n >= 0 && n <= 9; +} + +bool checkCreditCard(char const *cc) { + int start = strlen(cc)-1; + int s1 = 0; + int s2 = 0; + bool odd = true; + bool success = true; + for (int i = start; i >= 0; i--) + { + if (!number(cc[i])) + { + success = false; + return false; + break; + } + + if (odd) { + s1 += (cc[i] - '0'); + } else { + s2 += (cc[i] - '0'); + } + odd = !odd; + } + s2 *= 2; + return success && (s1+s2) % 10 == 0; +} + +int main(int argc, char const *argv[]) +{ + if (argc < 2) + { + printf("Expected one or more CC numbers\n"); + exit(EXIT_FAILURE); + } + + for (int i = 1; i < argc; i++) + { + if (checkCreditCard(argv[i])) { + printf("Valid credit card number %s\n",argv[i]); + } else { + printf("Invalid credit card number %s\n",argv[i]); + } + } + exit(EXIT_SUCCESS); + return 0; +} diff --git a/Week 3/max/max.c b/Week 3/max/max.c new file mode 100644 index 0000000..8946ea8 --- /dev/null +++ b/Week 3/max/max.c @@ -0,0 +1,32 @@ +/* +* Write a program which accepts exactly 3 command-line arguments (other than the + program's name in argvalue[0]), converts each to an integer value, and prints + the maximum of the 3 values. +* Rewrite your solution to the previous task so that it now prints the maximum + of an arbitrary number of command-line arguments, perhaps 3, or 10, or 20.... +*/ + +#include +#include + + +int main(int argc, char const *argv[]) +{ + if (argc == 1) + { + printf("No input provided!\n"); + exit(EXIT_FAILURE); + } + + int max = -__INT32_MAX__; + for (int i = 0; i < argc; i++) + { + if (atoi(argv[i]) > max) + { + max = atoi(argv[i]); + } + } + printf("Maximum value: %d\n",max); + exit(EXIT_SUCCESS); + return 0; +} diff --git a/Week 3/ordinal/ordinal.c b/Week 3/ordinal/ordinal.c new file mode 100644 index 0000000..831053e --- /dev/null +++ b/Week 3/ordinal/ordinal.c @@ -0,0 +1,57 @@ +/* +* Write a program that prints out the ordinal description of the (assumed to be + numerical) arguments supplied to the program. For example: + +prompt> ./ordinal 1 6 11 12 21 22 23 +1st +6th +11th +12th +21st +22nd +23rd +*/ + +#include +#include +#include +#include + +void ordinal(int n) { + char *suffix; + switch (n % 10) + { + case 1: + suffix = "st"; + break; + case 2: + suffix = "nd"; + break; + case 3: + suffix = "rd"; + break; + default: + suffix = "th"; + break; + } + if (n % 100 > 10 && n % 100 < 20) { + suffix = "th"; + } + printf("%d%s\n", n, suffix); +} + +int main(int argc, char const *argv[]) +{ + if (argc < 2) + { + printf("Need one or more numbers to convert\n"); + exit(EXIT_FAILURE); + } + + for (int i = 1; i < argc; i++) + { + ordinal(atoi(argv[i])); + } + + return 0; +}