mirror of
https://github.com/danbulant/introductionToProgramming
synced 2026-05-19 04:18:32 +00:00
partial week 9 solution
This commit is contained in:
parent
107999a98a
commit
90b439f5de
7 changed files with 266 additions and 3 deletions
4
main.typ
4
main.typ
|
|
@ -15,8 +15,8 @@ Collection of solutions to programming exercises as part of Introduction to Prog
|
|||
)
|
||||
|
||||
#{
|
||||
let count = 7;
|
||||
for week in range(1, count + 1) {
|
||||
let count = 9;
|
||||
for week in range(1, count + 1).filter(it => it != 8) {
|
||||
let a = "./week" + str(week) + "/doc.typ"
|
||||
include a
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ pkgs.mkShell rec {
|
|||
jdk
|
||||
typst
|
||||
tinymist
|
||||
nushell
|
||||
];
|
||||
nativeBuildInputs = with pkgs; [
|
||||
jre
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#show: template
|
||||
|
||||
= Week 6
|
||||
= Week 7
|
||||
|
||||
== Exercise 2.3.22
|
||||
|
||||
|
|
|
|||
79
week9/Person.java
Normal file
79
week9/Person.java
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
public class Person {
|
||||
final String firstName;
|
||||
String lastName;
|
||||
int age;
|
||||
Person spouse;
|
||||
|
||||
public Person(String first, String last) {
|
||||
this(first, last, 0);
|
||||
}
|
||||
public Person(String first, String last, int age) {
|
||||
this.firstName = first;
|
||||
this.lastName = last;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
public Person getSpouse() {
|
||||
return spouse;
|
||||
}
|
||||
public void setSpouse(Person spouse) {
|
||||
this.spouse = spouse;
|
||||
}
|
||||
|
||||
public void birthday() {
|
||||
this.age += 1;
|
||||
}
|
||||
|
||||
public boolean marry(Person that) {
|
||||
if(this.spouse != null || that.spouse != null) return false;
|
||||
if(this.age < 18 || that.age < 18) return false;
|
||||
if(this == that) return false;
|
||||
this.spouse = that;
|
||||
that.spouse = this;
|
||||
|
||||
var lastName = String.format("%s-%s", this.lastName, that.lastName);
|
||||
this.lastName = lastName;
|
||||
that.lastName = lastName;
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
var isMarried = this.spouse == null ? "unmarried" : "married";
|
||||
return String.format("%s %s, %s, %s", this.firstName, this.lastName, this.age, isMarried);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// check example toString
|
||||
assert (new Person("Lucky", "Luke", 23)).toString().equals("Lucky Luke, 23, unmarried");
|
||||
|
||||
var nathan = new Person("Nathan", "Cole", 17);
|
||||
var emily = new Person("Emily", "Parker", 18);
|
||||
|
||||
// not 18
|
||||
assert !nathan.marry(emily);
|
||||
assert !emily.marry(nathan);
|
||||
|
||||
// is 18
|
||||
nathan.birthday();
|
||||
|
||||
assert nathan.marry(emily);
|
||||
// marry must fail if married
|
||||
assert !nathan.marry(emily);
|
||||
assert !emily.marry(nathan);
|
||||
assert nathan.lastName.equals("Cole-Parker");
|
||||
assert emily.spouse == nathan;
|
||||
assert nathan.spouse == emily;
|
||||
}
|
||||
}
|
||||
61
week9/ShoppingCart.java
Normal file
61
week9/ShoppingCart.java
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
class ShoppingCart {
|
||||
public String ownerName;
|
||||
// assume maximum of 100 items in a cart.
|
||||
private String[] itemNames = new String[100];
|
||||
private double[] itemPrices = new double[100];
|
||||
private int itemCount = 0;
|
||||
public double discount = 0.;
|
||||
|
||||
ShoppingCart(String ownerName) {
|
||||
this.ownerName = ownerName;
|
||||
}
|
||||
|
||||
public double getTotal() {
|
||||
var price = 0.;
|
||||
for(int i = 0; i < this.itemCount; i++) {
|
||||
price += this.itemPrices[i];
|
||||
}
|
||||
return price * (1. - discount);
|
||||
}
|
||||
|
||||
public void add(String name, double price) {
|
||||
assert this.itemCount <= this.itemNames.length;
|
||||
this.itemNames[this.itemCount] = name;
|
||||
this.itemPrices[this.itemCount] = price;
|
||||
this.itemCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an item with a given name and price combination from the shopping cart.
|
||||
* Returns boolean of whether such item existed before (and was removed).
|
||||
*/
|
||||
public boolean remove(String name, double price) {
|
||||
for (int i = 0; i < this.itemCount; i++) {
|
||||
if (this.itemNames[i].equals(name)) {
|
||||
if(this.itemPrices[i] != price) continue;
|
||||
// overwrite the removed item by the next element
|
||||
// results in array with no gaps
|
||||
for (int j = i; j < this.itemCount - 1; j++) {
|
||||
this.itemNames[j] = this.itemNames[j + 1];
|
||||
this.itemPrices[j] = this.itemPrices[j + 1];
|
||||
}
|
||||
// deinitialize last value to prevent data corruption
|
||||
// in case of logic errors with e.g. not using itemCount later
|
||||
this.itemNames[this.itemCount - 1] = null;
|
||||
this.itemPrices[this.itemCount - 1] = 0.;
|
||||
this.itemCount -= 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a new discount, overwriting any previously set discount.
|
||||
* @param newDiscount as real value, for example '0.1' meaning a 10% discount
|
||||
*/
|
||||
public void setDiscount(double newDiscount) {
|
||||
assert newDiscount >= 0;
|
||||
this.discount = newDiscount;
|
||||
}
|
||||
}
|
||||
1
week9/common
Symbolic link
1
week9/common
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../common
|
||||
121
week9/doc.typ
Normal file
121
week9/doc.typ
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
#import "@preview/showybox:2.0.4": showybox
|
||||
#import "./common/common.typ" : *
|
||||
|
||||
#show: template
|
||||
|
||||
= Week 9
|
||||
|
||||
== Exercise 3.1.26
|
||||
|
||||
Find a website that publishes the current temperature in your area, and
|
||||
write a screen-scraper program Weather so that typing java Weather followed by
|
||||
your ZIP code will give you a weather forecast.
|
||||
|
||||
- You can use: https://www.flotvejr.dk/%C3%A5rhus/observations
|
||||
- You may use city names instead of zip code
|
||||
- Note: Do not overcommit; we are expecting something simple.
|
||||
|
||||
== Exercise 9.1
|
||||
|
||||
Write a class `Person` to represent a person. The class should have the following fields: `String firstName`, `String lastName`, `int age`, and `Person spouse`. The `spouse` field is initially `null`.
|
||||
|
||||
Add two constructors:
|
||||
|
||||
- `Person(String first, String last)`
|
||||
- `Person(String first, String last, int age)`
|
||||
|
||||
Add getters and setters:
|
||||
|
||||
- Add getters for all fields.
|
||||
- Add setters, but only for lastName and spouse.
|
||||
|
||||
Add a method `void birthday()` which increases the persons age by one year.
|
||||
|
||||
Add a method `boolean marry(Person that)` which marries this person to that person by updating the `spouse` fields and joining their last names. For example: If Nathan Cole and Emily Parker are married they become Nathan Cole-Parker and Emily Cole-Parker.
|
||||
|
||||
- A person cannot be married until they are 18 years old.
|
||||
- A person cannot be married if they are already married.
|
||||
|
||||
The method should return `true` if the marriage is successful.
|
||||
|
||||
Add a `toString` method that returns a `String` of the form `Lucky Luke, 23, unmarried`.
|
||||
|
||||
Add a `main` method to test your implementation.
|
||||
|
||||
#embedClass(name: "Person")
|
||||
|
||||
== Exercise 9.6
|
||||
|
||||
A student was asked to solve the following exercise:
|
||||
|
||||
#showybox([
|
||||
Write a class `ShoppingCart` to represent a shopping cart in an online store. The class should store the cart owner's name, an array of item names, an array of item prices, and track how many items are in the cart. Include a constructor, methods to add items, remove items, calculate the total price, and apply a discount.
|
||||
])
|
||||
|
||||
The student wrote the following code:
|
||||
|
||||
```java
|
||||
class cart {
|
||||
public String n; // name, maybe unused?
|
||||
protected double total; //total price of items
|
||||
public String[] items; // this is the items
|
||||
|
||||
public void add(String item, double p) {
|
||||
items[count] = item; prices[count] = p; count++;
|
||||
total = total + p;
|
||||
return;
|
||||
}
|
||||
|
||||
// count how many items are in the shopping cart
|
||||
int size;
|
||||
|
||||
cart(String n, int size) {
|
||||
n = n;
|
||||
this.size = this.size;
|
||||
//initialise the fields of the class.
|
||||
items = new String[100];
|
||||
prices = new double[100];
|
||||
items = new String[100];
|
||||
}
|
||||
|
||||
// Getter method
|
||||
public double getTotal() { return total; }
|
||||
|
||||
// count how many items are in the shopping bag
|
||||
public static int count = 0; // counter variable
|
||||
private double[] prices; //stores the cost
|
||||
|
||||
public void remove(String x) {
|
||||
for(int i=0;i<count;i++){
|
||||
if(items[i].equals(x)){
|
||||
total=total-prices[i];
|
||||
for(int j=i;j<count-1;j++){
|
||||
items[j]=items[j+1];
|
||||
prices[j]=prices[j+1];
|
||||
}
|
||||
count--;
|
||||
return;
|
||||
}}
|
||||
}
|
||||
|
||||
public String discount( double persent) {
|
||||
if (persent > 0) {
|
||||
total = (double) ((double) total - ((double) total * (double) persent));
|
||||
} else {
|
||||
total = total - (total * persent);
|
||||
} return null; }}
|
||||
```
|
||||
|
||||
- What do you think of the code style?
|
||||
|
||||
Meaningless indentation and (lack of) use of whitespace makes the code hard to follow. Indescriptive naming of variables (`n`, `total`) may be confusing to users of this class (and later to anyone reading it), especially since the comments aren't written in such a way to show on hover on relevant properties (Javadoc). Ordering of methods and properties hides their relationship and makes it harder to skim through the class. Total being calculated when items are added or when discount is applied makes operations order sensitive (applying discount before adding items results in no effect). Not using a subclass/object for linking names/prices of items makes cart manipulation prone to errors, but that's part of the exercise, similar to using arrays instead of vectors/arraylist.
|
||||
|
||||
Persent, if read as percent, may imply the function takes a percentage, but it expects a 'direct' value (90% = 0.90). Some fields being public may allow (accidental) logic errors from class users (e.g. desynchronized items and prices).
|
||||
|
||||
- Do you find the comments helpful?
|
||||
|
||||
Better naming of variables would result in less comments needed. Some are self describing and thus only add to the visual noise.
|
||||
|
||||
- Refactor the code such that it follows best practices.
|
||||
|
||||
#embedClass(name: "ShoppingCart")
|
||||
Loading…
Reference in a new issue