mirror of
https://github.com/peter-tanner/Systems-programming-labs.git
synced 2024-11-30 10:50:19 +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