mirror of
https://github.com/peter-tanner/Systems-programming-labs.git
synced 2024-11-30 17:10:30 +08:00
Week 3 lab content (Exclude roman numerals and impossible problem)
This commit is contained in:
parent
b372fafd93
commit
e33e588cc0
3
Week 3-workshop/README.md
Normal file
3
Week 3-workshop/README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
## Worshop 2 content
|
||||||
|
|
||||||
|
Workshop content: https://teaching.csse.uwa.edu.au/units/CITS2002/workshops/workshop3.php
|
29
Week 3-workshop/haversine.c
Normal file
29
Week 3-workshop/haversine.c
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
4
Week 3/README.md
Normal file
4
Week 3/README.md
Normal file
|
@ -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
|
73
Week 3/ackermann/ackermann.c
Normal file
73
Week 3/ackermann/ackermann.c
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
*/
|
53
Week 3/byte_size/bytesize.c
Normal file
53
Week 3/byte_size/bytesize.c
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
85
Week 3/christmas_trees/tree.c
Normal file
85
Week 3/christmas_trees/tree.c
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
36
Week 3/leapyear/leapyear.c
Normal file
36
Week 3/leapyear/leapyear.c
Normal file
|
@ -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 <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
72
Week 3/luhn/lunh.c
Normal file
72
Week 3/luhn/lunh.c
Normal file
|
@ -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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
32
Week 3/max/max.c
Normal file
32
Week 3/max/max.c
Normal file
|
@ -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 <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
57
Week 3/ordinal/ordinal.c
Normal file
57
Week 3/ordinal/ordinal.c
Normal file
|
@ -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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user