mirror of
https://github.com/danbulant/introductionToProgramming
synced 2026-05-19 04:18:32 +00:00
week 10
This commit is contained in:
parent
ba56e467f0
commit
c91fd07e47
16 changed files with 345 additions and 5 deletions
|
|
@ -7,12 +7,16 @@
|
||||||
doc
|
doc
|
||||||
}
|
}
|
||||||
|
|
||||||
#let embedClass(name: str, label: none) = {
|
#let embedClass(name: str, label: none, ..arguments) = {
|
||||||
show figure: set block(width: 100%)
|
show figure: set block(width: 100%)
|
||||||
show figure: set align(left)
|
show figure: set align(left)
|
||||||
show figure.caption: set align(center)
|
show figure.caption: set align(center)
|
||||||
|
let directory = arguments.named().at("directory", default: "")
|
||||||
|
let directory = if directory.len() == 0 { "" } else { directory + "/" }
|
||||||
|
let path = arguments.named().at("path", default: "../" + directory + name + ".java")
|
||||||
|
let kind = arguments.named().at("kind", default: "Class")
|
||||||
[
|
[
|
||||||
#figure(caption: name, kind: "Class", supplement: [Class], raw(read("../" + name + ".java"), lang:"java", block: true))
|
#figure(caption: name, kind: kind, supplement: [#kind], raw(read(path), lang:"java", block: true))
|
||||||
#label
|
#label
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
main.typ
2
main.typ
|
|
@ -15,7 +15,7 @@ Collection of solutions to programming exercises as part of Introduction to Prog
|
||||||
)
|
)
|
||||||
|
|
||||||
#{
|
#{
|
||||||
let count = 9;
|
let count = 10;
|
||||||
for week in range(1, count + 1).filter(it => it != 8) {
|
for week in range(1, count + 1).filter(it => it != 8) {
|
||||||
let a = "./week" + str(week) + "/doc.typ"
|
let a = "./week" + str(week) + "/doc.typ"
|
||||||
include a
|
include a
|
||||||
|
|
|
||||||
29
week10/cars/GasolineCar.java
Normal file
29
week10/cars/GasolineCar.java
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
public class GasolineCar implements Vehicle {
|
||||||
|
/** liters */
|
||||||
|
double fuel;
|
||||||
|
/** km per liter */
|
||||||
|
final double mileage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mileage km per liter
|
||||||
|
*/
|
||||||
|
GasolineCar(double mileage) {
|
||||||
|
this.mileage = mileage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRemainingRange() {
|
||||||
|
return (int)Math.floor(fuel * mileage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int drive(int kms) {
|
||||||
|
var range = getRemainingRange();
|
||||||
|
var toDrive = Math.min(range, kms);
|
||||||
|
// l = 1/(km/l) * km
|
||||||
|
var consumption = 1./mileage * toDrive;
|
||||||
|
fuel -= consumption;
|
||||||
|
|
||||||
|
return toDrive;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
week10/cars/HybridCar.java
Normal file
39
week10/cars/HybridCar.java
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
public class HybridCar implements Vehicle {
|
||||||
|
/** liters */
|
||||||
|
double fuel;
|
||||||
|
/** km per liter */
|
||||||
|
final double fuelMileage;
|
||||||
|
double electricalEnergy;
|
||||||
|
/** km per el energy point */
|
||||||
|
final double electricityMileage;
|
||||||
|
|
||||||
|
HybridCar(double fuelMileage, double electricityMileage) {
|
||||||
|
this.fuelMileage = fuelMileage;
|
||||||
|
this.electricityMileage = electricityMileage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRemainingRange() {
|
||||||
|
return (int)(fuel * fuelMileage + electricalEnergy * electricityMileage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int drive(int kms) {
|
||||||
|
// km
|
||||||
|
var range = getRemainingRange();
|
||||||
|
// km
|
||||||
|
var toDrive = Math.min(kms, range);
|
||||||
|
// km
|
||||||
|
var rangeEl = (int)(electricalEnergy * electricityMileage);
|
||||||
|
// km
|
||||||
|
var toDriveEl = Math.min(toDrive, rangeEl);
|
||||||
|
// km
|
||||||
|
var toDriveGas = toDrive - toDriveEl;
|
||||||
|
// l = 1/(km/l) * km
|
||||||
|
var consumptionGas = 1./fuelMileage * toDriveGas;
|
||||||
|
var consumptionEl = 1./electricityMileage * toDriveEl;
|
||||||
|
fuel -= consumptionGas;
|
||||||
|
electricalEnergy -= consumptionEl;
|
||||||
|
return toDrive;
|
||||||
|
}
|
||||||
|
}
|
||||||
27
week10/cars/Vehicle.java
Normal file
27
week10/cars/Vehicle.java
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
interface Vehicle {
|
||||||
|
int getRemainingRange();
|
||||||
|
int drive(int kms);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// 100km / 5l
|
||||||
|
var gasCar = new GasolineCar(100. / 5.);
|
||||||
|
gasCar.fuel = 10; // 200km fuel
|
||||||
|
// 100km / 5l; 10 km / "energy unit"
|
||||||
|
var hybridCar = new HybridCar(100. / 5., 10.);
|
||||||
|
hybridCar.fuel = 5; // 100km fuel
|
||||||
|
hybridCar.electricalEnergy = 5; // 50km eletricity
|
||||||
|
|
||||||
|
assert gasCar.getRemainingRange() == 200;
|
||||||
|
assert gasCar.drive(100) == 100;
|
||||||
|
assert gasCar.getRemainingRange() == 100;
|
||||||
|
assert gasCar.drive(200) == 100;
|
||||||
|
assert gasCar.getRemainingRange() == 0;
|
||||||
|
|
||||||
|
assert hybridCar.getRemainingRange() == 150;
|
||||||
|
assert hybridCar.drive(50) == 50;
|
||||||
|
assert hybridCar.electricalEnergy == 0;
|
||||||
|
assert hybridCar.fuel == 5;
|
||||||
|
assert hybridCar.drive(200) == 100;
|
||||||
|
assert hybridCar.getRemainingRange() == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
1
week10/common
Symbolic link
1
week10/common
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../common
|
||||||
22
week10/company/Employee.java
Normal file
22
week10/company/Employee.java
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
public class Employee extends Person {
|
||||||
|
String jobTitle;
|
||||||
|
int salary;
|
||||||
|
|
||||||
|
public Employee(String name, int age, String jobTitle, int salary) {
|
||||||
|
super(name, age);
|
||||||
|
this.jobTitle = jobTitle;
|
||||||
|
this.salary = salary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJobTitle() {
|
||||||
|
return jobTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSalary() {
|
||||||
|
return salary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBaseSalary() {
|
||||||
|
return salary;
|
||||||
|
}
|
||||||
|
}
|
||||||
16
week10/company/Manager.java
Normal file
16
week10/company/Manager.java
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
public class Manager extends Employee {
|
||||||
|
int monthlyBonus;
|
||||||
|
|
||||||
|
public Manager(String name, int age, String jobTitle, int salary, int monthlyBonus) {
|
||||||
|
super(name, age, jobTitle, salary);
|
||||||
|
this.monthlyBonus = monthlyBonus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMonthlyBonus() {
|
||||||
|
return monthlyBonus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSalary() {
|
||||||
|
return salary + monthlyBonus;
|
||||||
|
}
|
||||||
|
}
|
||||||
30
week10/company/Person.java
Normal file
30
week10/company/Person.java
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
public class Person {
|
||||||
|
String name;
|
||||||
|
int age;
|
||||||
|
|
||||||
|
Person(String name, int age) {
|
||||||
|
this.name = name;
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
var person = new Person("P1", 20);
|
||||||
|
var employee = new Employee("P2", 40, "Senior OOP Architect", 100_000);
|
||||||
|
var manager = new Manager("P3", 40, "Product Manager", 130_000, 20_000);
|
||||||
|
|
||||||
|
assert person.getAge() == person.age;
|
||||||
|
assert employee.getAge() == employee.age;
|
||||||
|
assert manager.getBaseSalary() == manager.salary;
|
||||||
|
assert manager.getSalary() > manager.getBaseSalary();
|
||||||
|
assert employee.getBaseSalary() == employee.getSalary();
|
||||||
|
assert manager.getJobTitle().equals("Product Manager");
|
||||||
|
}
|
||||||
|
}
|
||||||
48
week10/doc.typ
Normal file
48
week10/doc.typ
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
#import "./common/common.typ" : *
|
||||||
|
|
||||||
|
#show: template
|
||||||
|
|
||||||
|
= Week 10
|
||||||
|
|
||||||
|
== Exercise 10.5
|
||||||
|
|
||||||
|
Write an interface to represent a spellchecker with a method `boolean isWord(String word)` that returns `true` if the given word is spelled correctly. Implement three classes for three different languages.
|
||||||
|
|
||||||
|
- Each language implementation should recognize at least three words.
|
||||||
|
- The spellchecker must correctly handle both uppercase and lowercase letters.
|
||||||
|
- Add a `main` method that takes two command-line arguments: a language name and a string. The program should split the string into words and print any misspelled words.
|
||||||
|
|
||||||
|
#embedClass(name: "Spellchecker", directory: "spellcheck", kind: "Interface")
|
||||||
|
#embedClass(name: "EnglishSpellchecker", directory: "spellcheck")
|
||||||
|
#embedClass(name: "CzechSpellchecker", directory: "spellcheck")
|
||||||
|
#embedClass(name: "JavaSpellchecker", directory: "spellcheck")
|
||||||
|
#embedClass(name: "SpellcheckerProgram", directory: "spellcheck")
|
||||||
|
|
||||||
|
== Exercise 10.6
|
||||||
|
|
||||||
|
Write an interface to represent a vehicle with a method `int getRemainingRange()` that returns the number of kilometers the vehicle can drive with its current fuel. Implement two classes: a gasoline car and a hybrid car.
|
||||||
|
|
||||||
|
- The gasoline car should store the amount of fuel left and its mileage (km per liter).
|
||||||
|
- The hybrid car should store both the amount of gasoline and electric energy left, along with the mileage for running on gasoline and electricity.
|
||||||
|
- The hybrid car's `getRemainingRange()` method should compute the total range by considering both gasoline and energy.
|
||||||
|
- Add an `int drive(int kms)` method that simulates driving the specified distance, depletes the fuel accordingly, and returns the actual number of kilometers driven. For the hybrid car, electricity is used before gasoline.
|
||||||
|
- Write a `main` method to test both vehicle implementations.
|
||||||
|
|
||||||
|
#embedClass(name: "Vehicle", directory: "cars", kind: "Interface")
|
||||||
|
#embedClass(name: "GasolineCar", directory: "cars")
|
||||||
|
#embedClass(name: "HybridCar", directory: "cars")
|
||||||
|
|
||||||
|
== Exercise 10.7
|
||||||
|
|
||||||
|
Write a class `Person` to represent a person with a name and an age. Create two subclasses: `Employee` (which extends `Person`) and `Manager` (which extends `Employee`).
|
||||||
|
|
||||||
|
- The `Person` class should have a constructor that takes a name and an age.
|
||||||
|
- The `Employee` class should add a job title and a salary, with an appropriate constructor.
|
||||||
|
- The `Manager` class should add a monthly bonus field, with an appropriate constructor.
|
||||||
|
- Add appropriate getter methods for all fields in each class.
|
||||||
|
- Add a `getSalary()` method. Make sure `Manager` class takes the manager's monthly bonus into account.
|
||||||
|
- Write a `main` method to test the inheritance hierarchy by creating instances of each class.
|
||||||
|
|
||||||
|
#embedClass(name: "Person", directory: "company")
|
||||||
|
#embedClass(name: "Employee", directory: "company")
|
||||||
|
#embedClass(name: "Manager", directory: "company")
|
||||||
16
week10/spellcheck/CzechSpellchecker.java
Normal file
16
week10/spellcheck/CzechSpellchecker.java
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
class CzechSpellchecker implements Spellchecker {
|
||||||
|
public HashSet<String> words = new HashSet<String>(
|
||||||
|
Arrays.asList("tři", "tisíce", "sta", "třicet", "stříbrných", "stříkaček", "stříkalo", "přes", "střech"));
|
||||||
|
|
||||||
|
public boolean isWord(String word) {
|
||||||
|
if (words.contains(word))
|
||||||
|
return true;
|
||||||
|
var lowercasedFirst = Character.toLowerCase(word.charAt(0)) + word.substring(1);
|
||||||
|
if (words.contains(lowercasedFirst))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
16
week10/spellcheck/EnglishSpellchecker.java
Normal file
16
week10/spellcheck/EnglishSpellchecker.java
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
class EnglishSpellchecker implements Spellchecker {
|
||||||
|
public HashSet<String> words = new HashSet<String>(
|
||||||
|
Arrays.asList("buffalo", "I", "the", "a", "old", "young", "man", "woman", "boat"));
|
||||||
|
|
||||||
|
public boolean isWord(String word) {
|
||||||
|
if (words.contains(word))
|
||||||
|
return true;
|
||||||
|
var lowercasedFirst = Character.toLowerCase(word.charAt(0)) + word.substring(1);
|
||||||
|
if (words.contains(lowercasedFirst))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
week10/spellcheck/JavaSpellchecker.java
Normal file
23
week10/spellcheck/JavaSpellchecker.java
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
class JavaSpellchecker implements Spellchecker {
|
||||||
|
public HashSet<String> words = new HashSet<String>(Arrays.asList("I", "Java", "Factory", "Extended"));
|
||||||
|
|
||||||
|
public boolean isWord(String word) {
|
||||||
|
// we could use slices but they copy it char for char anyway
|
||||||
|
var buf = "";
|
||||||
|
for (var i = 0; i < word.length(); i++) {
|
||||||
|
var ch = word.charAt(i);
|
||||||
|
if (Character.isUpperCase(ch)) {
|
||||||
|
if (!buf.isEmpty() && !words.contains(buf))
|
||||||
|
return false;
|
||||||
|
buf = "";
|
||||||
|
}
|
||||||
|
buf += ch;
|
||||||
|
}
|
||||||
|
if (!buf.isEmpty() && !words.contains(buf))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
3
week10/spellcheck/Spellchecker.java
Normal file
3
week10/spellcheck/Spellchecker.java
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
interface Spellchecker {
|
||||||
|
boolean isWord(String word);
|
||||||
|
}
|
||||||
68
week10/spellcheck/SpellcheckerProgram.java
Normal file
68
week10/spellcheck/SpellcheckerProgram.java
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class SpellcheckerProgram {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
if (args.length < 2) {
|
||||||
|
assertTests();
|
||||||
|
System.out.println("SpellcheckerProgram <lang> <...words>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var lang = args[0];
|
||||||
|
var otherArgs = Arrays.copyOfRange(args, 1, args.length);
|
||||||
|
var text = String.join(" ", otherArgs);
|
||||||
|
// in real / more advanced spell checker, this would be done per language
|
||||||
|
// capital letters aren't checked properly as the implementations don't know if
|
||||||
|
// the word starts a sentence or not
|
||||||
|
var words = splitWords(text);
|
||||||
|
|
||||||
|
var spellchecker = getSpellchecker(lang);
|
||||||
|
|
||||||
|
var failed = false;
|
||||||
|
for (var word : words) {
|
||||||
|
if (!spellchecker.isWord(word)) {
|
||||||
|
failed = true;
|
||||||
|
System.out.println(word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failed) {
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static String[] splitWords(String text) {
|
||||||
|
return text.split("[\\s.!?'\"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
static Spellchecker getSpellchecker(String lang) {
|
||||||
|
return switch (lang) {
|
||||||
|
case "cs" -> new CzechSpellchecker();
|
||||||
|
case "en" -> new EnglishSpellchecker();
|
||||||
|
case "java" -> new JavaSpellchecker();
|
||||||
|
default -> throw new Error("Unknown language");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean checkAllWords(Spellchecker spellchecker, String text) {
|
||||||
|
for (var word : splitWords(text)) {
|
||||||
|
if (!spellchecker.isWord(word)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assertTests() {
|
||||||
|
var cs = getSpellchecker("cs");
|
||||||
|
var en = getSpellchecker("en");
|
||||||
|
var java = getSpellchecker("java");
|
||||||
|
|
||||||
|
assert checkAllWords(cs,
|
||||||
|
"tři tisíce tři třicet tři stříbrných stříkaček stříkalo přes tři tisíce tři třicet tři stříbrných střech.");
|
||||||
|
assert !checkAllWords(cs, "třitisíce");
|
||||||
|
assert checkAllWords(en, "Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo");
|
||||||
|
assert !checkAllWords(en, "Buffal buffal Buffal buffal buffal buffal Buffal buffal");
|
||||||
|
assert checkAllWords(java, "IExtendedJavaFactoryFactory FactoryJavaFactoryExtended");
|
||||||
|
assert !checkAllWords(java, "IExtendedJavaFactoryFactor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,8 +4,6 @@ import java.util.HashMap;
|
||||||
import java.util.regex.MatchResult;
|
import java.util.regex.MatchResult;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import common.In;
|
|
||||||
|
|
||||||
public class UglierSoup {
|
public class UglierSoup {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// var in = new In("./test.html");
|
// var in = new In("./test.html");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue