Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/main/kotlin/exercise2/task1/FindPairOfHighestSum.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import org.jetbrains.exercise2.task3.findPairWithBiggestDifference
*/

internal fun List<Int>.findHighestSumPair(): Pair<Int, Int> {
TODO("Implement me!!")
val prvi = this.sorted().get(this.lastIndex)
val drugi = this.sorted().get(this.lastIndex-1)
Comment on lines +21 to +22
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to sort the array twice. Please name the variables in English, as that is a widely accepted convention.


return Pair(prvi, drugi)
}

fun main() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import org.jetbrains.exercise2.task3.findPairWithBiggestDifference
*/

internal fun List<Int>.findHighestSumPairFunctional(): Pair<Int, Int> {
TODO("Implement me!!")
return Pair(
this.sorted().get(this.lastIndex), this.sorted().get(this.lastIndex-1)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a functional approach :)

The idea of the functional approach is that you compose function calls that operate on data to get the desired result.

Functional approach would be following:

Suggested change
this.sorted().get(this.lastIndex), this.sorted().get(this.lastIndex-1)
return this.sorted().let { sortedList -> Pair(this.lastIndex, this.lastIndex-1) }

In this case, we are using the result of the sorted function invocation, and we are providing it as an input of the let function invocation. Hence, we are composing function calls to get the result.

)
}

fun main() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,29 @@ import kotlin.math.abs
*/

internal fun List<Int>.findPairWithBiggestDifference(): Pair<Int, Int> {
// TODO refactor me to functional approach and make tests pass!!!
var resultPair: Pair<Int, Int>? = null
var biggestDifference = Int.MIN_VALUE

for (i in this.indices) {
for (j in (i + 1) until this.size) {
val first = this[i]
val second = this[j]
val absDifference = abs(first - second)

if (absDifference >= biggestDifference) {
biggestDifference = absDifference
resultPair = Pair(first, second)
}
}
}

return resultPair!!
return Pair(
this.sorted().get(this.size-1), this.sorted().get(0)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solution is correct, but it is written in Java-style code. Please consider my suggestion above to implement it in a Kotlin, functional style. :)

Also, this.size - 1 has a Kotlin equivalent in this.lastIndex, and get(0) has an equivalent in a first() function.

)


// var resultPair: Pair<Int, Int>? = null
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clean up the code before pushing the changes.

// var biggestDifference = Int.MIN_VALUE
//
// for (i in this.indices) {
// for (j in (i + 1) until this.size) {
// val first = this[i]
// val second = this[j]
// val absDifference = abs(first - second)
//
// if (absDifference >= biggestDifference) {
// biggestDifference = absDifference
// resultPair = Pair(first, second)
// }
// }
// }
//
// return resultPair!!
}

fun main() {
Expand Down
18 changes: 11 additions & 7 deletions src/main/kotlin/exercise2/task4/ProcessCountriesData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,27 +59,31 @@ internal val countries = listOf(
*/

internal fun List<Country>.findCountryWithBiggestTotalArea(): Country {
TODO("Implement me!!!")
return countries.maxBy { it.totalAreaInSquareKilometers }
}

internal fun List<Country>.findCountryWithBiggestPopulation(): Country {
TODO("Implement me!!!")
return countries.maxBy { it.population }
}

internal fun List<Country>.findCountryWithHighestPopulationDensity(): Country {
TODO("Implement me!!!")
return countries.maxBy { it.population/it.totalAreaInSquareKilometers }
}

internal fun List<Country>.findCountryWithLowestPopulationDensity(): Country {
TODO("Implement me!!!")
return countries.minBy { it.population/it.totalAreaInSquareKilometers }
}

internal fun List<Country>.findLanguageSpokenInMostCountries(): String {
TODO("Implement me!!!")
return countries.flatMap { it.languages }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice solution!

.groupingBy { it }
.eachCount()
.maxBy { it.value }
.key
}

internal fun List<Country>.filterCountriesThatSpeakLanguage(language: String): List<Country> {
TODO("Implement me!!!")
return countries.filter { country -> country.languages.contains(language) }
}


Expand All @@ -88,7 +92,7 @@ fun main() {
println("Country with a biggest population is a ${countries.findCountryWithBiggestPopulation().name}")
println("Country with a biggest population density is a ${countries.findCountryWithHighestPopulationDensity().name}")
println("Country with a lowest population density is a ${countries.findCountryWithLowestPopulationDensity().name}")
println("Language spoken in most countries is a ${countries.findLanguageSpokenInMostCountries()}")
println("Language spoken in most countries is ${countries.findLanguageSpokenInMostCountries()}")
val countriesThatSpeakEnglish = countries.filterCountriesThatSpeakLanguage("English")
println("Countries that speak English language are ${countriesThatSpeakEnglish.joinToString { it.name }}")
}
10 changes: 7 additions & 3 deletions src/main/kotlin/exercise2/task5/CreateUserDSL.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,15 @@ internal data class Address(
*/

internal fun user(initUser: User.() -> Unit): User {
TODO("Implement me!!!")
val user = User()
return user.apply(initUser)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this can be a one-line expression :)

}

internal fun User.address(initAddress: Address.() -> Unit): User {
TODO("Implement me!!!")
internal fun User.address (initAddress: Address.() -> Unit): User {
val adr = Address()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's it! Why not using apply scoped function here as well?

adr.initAddress()
this.address = adr
return this
}

fun main() {
Expand Down
26 changes: 25 additions & 1 deletion src/main/kotlin/exercise3/task1/BalancedBrackets.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package exercise3.task1
import java.util.Stack

/**
* Task1: Balanced Brackets (Parentheses) Problem
Expand Down Expand Up @@ -26,9 +27,32 @@ package exercise3.task1


internal fun isExpressionBalanced(expression: String): Boolean {
TODO("Implement me!!!")
val chars = Stack<Char>()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solution is correct. 👏🏻
Please now try solving it in the functional way. :)

val opening = "({["
val closing = ")}]"

for(char in expression) {
when {
char in opening -> chars.add(char)
char in closing -> {
if(chars.isEmpty() || !valid(chars.lastElement(), char)) {
return false
}
chars.removeLast()
}
}
}
return chars.isEmpty()
}

fun valid(opening: Char, closing: Char): Boolean {
return (opening == '(' && closing == ')') ||
(opening == '[' && closing == ']') ||
(opening == '{' && closing == '}')
}



fun main() {
val expressions = listOf(
"{[()]}" to true,
Expand Down
40 changes: 39 additions & 1 deletion src/main/kotlin/exercise3/task2/ParenthesesClusters.kt
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solution is correct! It's written in Java imperative way so it's a bit hard to follow the execution flow, and it took me some to understand what it does.

Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,45 @@ package exercise3.task2
*/

internal fun String.splitToBracketsClusters(): List<String> {
TODO("Implement me!!!")
val opening = "({["
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opening and closing variables aren't used

val closing = ")}]"
val clusterList = ArrayList<String>()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: don't forget that we have mutableListOf top-level function to create list

val emptyList = ArrayList<String>()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only used as a return value at the end of the function.
It's better to move it's declaration closer to the places where it's used.


var start = 0
var counter = 0
var balanced = true

for(i in this.indices) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use for ((index, char) in this.withIndex()) to make for loop more readable

when (this[i]) {
'(' -> {
counter++
if (counter == 1) {
start = i
}
}

')' -> {
counter--
if (counter == 0) {
clusterList.add(this.substring(start, i + 1))
} else if (counter < 0) {
balanced = false
}
}
}
}

if(counter != 0) {
balanced = false
}

if(balanced) {
return clusterList
}
else {
return emptyList
}
}

fun main() {
Expand Down
19 changes: 18 additions & 1 deletion src/main/kotlin/exercise3/task3/SherlockValidatesString.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,24 @@ package exercise3.task3
*/

internal fun isSherlockValid(s: String): String {
TODO("Implement me!!!")
val charCounts = s.groupBy { it }.values.map { it.size }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same can be achieved with s.groupingBy { it }.eachCount()


if (charCounts.toSet().size == 1) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

charCounts.toSet() could have be done in the line above where we define charCounts so that we avoid using toSet multiple times.

return "YES"
}

if (charCounts.toSet().size == 2) {
val minFreq = charCounts.minOrNull() ?: return "NO"
val maxFreq = charCounts.maxOrNull() ?: return "NO"
val minFreqCounter = charCounts.count { it == minFreq }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we know that we have two different numbers and get their min and max values, why is it necessary to use a counter here?
Isn't it enough to check if both values are the same, or that maxFreq - minFreq is equal to 1?

val maxFreqCounter = charCounts.count { it == maxFreq }

if ((minFreq == 1 && minFreqCounter == 1) || (maxFreq - minFreq == 1 && maxFreqCounter == 1)) {
return "YES"
}
}

return "NO"
}

fun main() {
Expand Down
25 changes: 20 additions & 5 deletions src/main/kotlin/exercise3/task4/TaxiParkTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,44 @@ package exercise3.task4
* Find all the drivers who performed no trips.
*/
internal fun TaxiPark.findFakeDrivers(): Set<Driver> {
TODO("Implement me!!!")
return allDrivers.minus(this.trips.map { it.driver }.toSet())
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well done! 👏🏻

}

/**
/**
* Subtask 2:
* Find all the clients who completed at least the given number of trips.
*/
internal fun TaxiPark.findFaithfulPassengers(minTrips: Int): Set<Passenger> {
TODO("Implement me!!!")
return this.trips
.flatMap { it.passengers }
.groupingBy { it }
.eachCount()
.filter { it.value >= minTrips }
.keys
}

/**
* Subtask 3:
* Find all the passengers, who were taken by a given driver more than once.
*/
internal fun TaxiPark.findFrequentPassengers(driver: Driver): Set<Passenger> {
TODO("Implement me!!!")
return this.trips
.filter { it.driver == driver }
.flatMap { it.passengers }
.groupingBy { it }
.eachCount()
.filter { it.value > 1}
.keys
}

/**
* Subtask 4:
* Find the passengers who had a discount for the majority of their trips.
*/
internal fun TaxiPark.findSmartPassengers(): Set<Passenger> {
TODO("Implement me!!!")
return allPassengers.filter { passenger ->
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well done! 👏🏻

val eachPassengerTrips = trips.filter { it.passengers.contains(passenger) }
val discountedTripsCount = eachPassengerTrips.count { it.discount != null }
discountedTripsCount > eachPassengerTrips.size / 2
}.toSet()
}