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
|
||||
}
|
||||
|
||||
#let embedClass(name: str, label: none) = {
|
||||
#let embedClass(name: str, label: none, ..arguments) = {
|
||||
show figure: set block(width: 100%)
|
||||
show figure: set align(left)
|
||||
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
|
||||
]
|
||||
}
|
||||
|
|
|
|||
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) {
|
||||
let a = "./week" + str(week) + "/doc.typ"
|
||||
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.Pattern;
|
||||
|
||||
import common.In;
|
||||
|
||||
public class UglierSoup {
|
||||
public static void main(String[] args) {
|
||||
// var in = new In("./test.html");
|
||||
|
|
|
|||
Loading…
Reference in a new issue