Refactor assignment 3 and implement alternative Pareto Principle

This commit is contained in:
Martin Berg Alstad
2025-08-01 09:24:57 +02:00
parent 6ef68a5e05
commit 7233593860
4 changed files with 97 additions and 32 deletions

View File

@ -1,25 +1,22 @@
package nicestring
package assignment.week3.nicestring
fun String.isNice(): Boolean {
return listOf(
::containsNotNiceSubstring,
::containsAtLeastThreeVowels,
::containsDoubleLetter
)
.count { it() } >= 2
}
const val VOWELS = "aeiou"
fun String.containsNotNiceSubstring(): Boolean {
fun String.isNice(): Boolean = listOf(
::containsNotNiceSubstring,
::containsAtLeastThreeVowels,
::containsDoubleLetter
).count { it() } >= 2
private fun String.containsNotNiceSubstring(): Boolean {
val illegalSubStrings = listOf("bu", "ba", "be")
return this.zipWithNext()
.map { (first, second) -> "$first$second" }
.none { it in illegalSubStrings }
}
fun String.containsAtLeastThreeVowels(): Boolean {
val vovels = "aeiou".toCharArray()
return this.count { char -> char in vovels } >= 3
}
private fun String.containsAtLeastThreeVowels(): Boolean =
this.count { char -> char in VOWELS.toCharArray() } >= 3
fun String.containsDoubleLetter(): Boolean = this.zipWithNext()
private fun String.containsDoubleLetter(): Boolean = this.zipWithNext()
.any { (first, second) -> first == second }

View File

@ -1,22 +1,23 @@
package taxipark
package assignment.week3.taxipark
data class TaxiPark(
val allDrivers: Set<Driver>,
val allPassengers: Set<Passenger>,
val trips: List<Trip>)
val allDrivers: Set<Driver>,
val allPassengers: Set<Passenger>,
val trips: List<Trip>
)
data class Driver(val name: String)
data class Passenger(val name: String)
data class Trip(
val driver: Driver,
val passengers: Set<Passenger>,
// the trip duration in minutes
val duration: Int,
// the trip distance in km
val distance: Double,
// the percentage of discount (in 0.0..1.0 if not null)
val discount: Double? = null
val driver: Driver,
val passengers: Set<Passenger>,
// the trip duration in minutes
val duration: Int,
// the trip distance in km
val distance: Double,
// the percentage of discount (in 0.0..1.0 if not null)
val discount: Double? = null
) {
// the total cost of the trip
val cost: Double

View File

@ -0,0 +1,67 @@
package assignment.week3.taxipark
fun TaxiPark.checkParetoPrinciple2(): Boolean {
if (trips.isEmpty()) return false
val totalIncome = trips.sumOf { trip -> trip.cost }
val sortedDriversIncome: List<Double> = trips
.groupBy { it.driver }
.map { (_, tripsByDriver) -> tripsByDriver.sumOf { trip -> trip.cost } }
.sortedDescending()
val numberOfTopDrivers = (0.2 * allDrivers.size).toInt()
val incomeByTopDrivers = sortedDriversIncome
.take(numberOfTopDrivers)
.sum()
return incomeByTopDrivers >= 0.8 * totalIncome
}
fun main() {
taxiPark(
1..5, 1..4,
trip(1, 1, 20, 20.0),
trip(1, 2, 20, 20.0),
trip(1, 3, 20, 20.0),
trip(1, 4, 20, 20.0),
trip(2, 1, 20, 19.0)
)
.checkParetoPrinciple() eq true
taxiPark(
1..5, 1..4,
trip(1, 1, 20, 20.0),
trip(1, 2, 20, 20.0),
trip(1, 3, 20, 20.0),
trip(1, 4, 20, 20.0),
trip(2, 1, 20, 21.0)
)
.checkParetoPrinciple2() eq false
}
private infix fun <T> T.eq(other: T) {
if (this != other) throw AssertionError("Expected $this to equal $other")
println("OK")
}
private fun taxiPark(
allDrivers: IntProgression,
allPassengers: IntProgression,
vararg trips: Trip
) = TaxiPark(
allDrivers = allDrivers.map { Driver(it.toString()) }.toSet(),
allPassengers = allPassengers.map { Passenger(it.toString()) }.toSet(),
trips = trips.toList()
)
private fun trip(
driver: Int,
passenger: Int,
duration: Int,
distance: Double
) = Trip(
driver = Driver(driver.toString()),
passengers = setOf(Passenger(passenger.toString())),
duration = duration,
distance = distance
)

View File

@ -1,4 +1,4 @@
package taxipark
package assignment.week3.taxipark
/*
* Task #1. Find all the drivers who performed no trips.
@ -49,13 +49,13 @@ fun TaxiPark.findSmartPassengers(): Set<Passenger> = this.allPassengers
* Return any period if many are the most frequent, return `null` if there're no trips.
*/
fun TaxiPark.findTheMostFrequentTripDurationPeriod(): IntRange? {
val maxDuration = this.trips
val (maxDuration, _) = this.trips
.map { trip -> trip.duration / 10 }
.groupBy { it }
.maxByOrNull { it.value.size }
.maxByOrNull { it.value.size } ?: return null
val startRange = maxDuration?.let { it.key * 10 }
return startRange?.let { it.rangeTo(it + 9) }
val startRange = maxDuration * 10
return startRange.rangeTo(startRange + 9)
}
/*