Week 3 lab content (Exclude roman numerals and impossible problem)

This commit is contained in:
Peter 2021-08-10 23:20:26 +08:00
parent b372fafd93
commit e33e588cc0
10 changed files with 444 additions and 0 deletions

View File

@ -0,0 +1,3 @@
## Worshop 2 content
Workshop content: https://teaching.csse.uwa.edu.au/units/CITS2002/workshops/workshop3.php

View 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
View 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

View 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));
}
*/

View 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;
}

View 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;
}

View 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
View 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
View 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
View 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;
}