Skip to content

Commit 33f01b0

Browse files
committed
Update kotlin
1 parent 5e390cc commit 33f01b0

31 files changed

+635
-27
lines changed

kotlin/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ plugins {
33
}
44

55
allprojects {
6-
version = "1.0.0-SNAPSHOT"
7-
group = "ac.obl.voidkt"
8-
96
repositories {
107
mavenCentral()
118
}
@@ -16,3 +13,6 @@ tasks.named('wrapper') {
1613
distributionType = Wrapper.DistributionType.ALL
1714
}
1815

16+
dependencies {
17+
implementation "org.jodd:jodd-util:6.0.0"
18+
}

kotlin/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
kotlin_version=1.7.20
1+
kotlin_version=1.9.10
22
gradle_version=7.4.2
33
kotlin.code.style=official
44

kotlin/src/main/kotlin/ac/obl/voidkt/terminal/Terminal.kt

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package challenge.height
2+
3+
/**
4+
You are given an array A representing heights of students. All the students are asked to stand in rows. The students arrive by one, sequentially (as their heights appear in A). For the i-th student, if there is a row in which all the students are taller than A[i], the student will stand in one of such rows. If there is no such row, the student will create a new row. Your task is to find the minimum number of rows created.
5+
Write a function that, given a non-empty array A containing N integers, denoting the heights of the students, returns the minimum number of rows created.
6+
7+
For example, given A = [5, 4, 3, 6, 1], the function should return 2.
8+
9+
Students will arrive in sequential order from A[0] to A[N−1]. So, the first student will have height = 5, the second student will have height = 4, and so on.
10+
For the first student, there is no row, so the student will create a new row.
11+
Row1 = [5]
12+
For the second student, all the students in Row1 have height greater than 4. So, the student will stand in Row1.
13+
Row1 = [5, 4]
14+
Similarly, for the third student, all the students in Row1 have height greater than 3. So, the student will stand in Row1.
15+
Row1 = [5, 4, 3]
16+
For the fourth student, there is no row in which all the students have height greater than 6. So, the student will create a new row.
17+
Row1 = [5, 4, 3]
18+
Row2 = [6]
19+
For the fifth student, all the students in Row1 and Row2 have height greater than 1. So, the student can stand in either of the two rows.
20+
Row1 = [5, 4, 3, 1]
21+
Row2 = [6]
22+
Since two rows are created, the function should return 2.
23+
24+
Assume that:
25+
N is an integer within the range [1..1,000]
26+
each element of array A is an integer within the range [1..10,000]
27+
*/
28+
class HeightRows {
29+
30+
data class Height(var value: Int)
31+
32+
fun calc(students: Array<Int>): Int {
33+
val rows: MutableList<Height> = mutableListOf()
34+
35+
students.forEach { studentHeight ->
36+
val minHeightFromAllMatchingRows: Height? =
37+
rows
38+
.filter {
39+
// student may join this row, everyone is high(er)
40+
studentHeight < it.value
41+
}
42+
.minWith(Comparator { p1, p2 -> p1.value.compareTo(p2.value) })
43+
?.let {
44+
it.value = studentHeight
45+
it
46+
}
47+
48+
if (minHeightFromAllMatchingRows == null) {
49+
rows.add(Height(studentHeight))
50+
}
51+
}
52+
return rows.size
53+
}
54+
}
55+
56+
fun main() {
57+
println(HeightRows().calc(arrayOf(9, 5, 2)));
58+
println(HeightRows().calc(arrayOf(9, 5, 10)));
59+
println(HeightRows().calc(arrayOf(9, 2, 7, 1, 6)));
60+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package challenge.tvsm
2+
3+
import challenge.tvsm.maze.*
4+
import challenge.tvsm.model.Candles
5+
import challenge.tvsm.model.HeroK
6+
import challenge.tvsm.model.HeroMinotaurK
7+
import challenge.tvsm.model.HeroTheseusK
8+
9+
class TwoHeroes(val theseus: HeroTheseusK, val minotaur: HeroMinotaurK)
10+
class HeroAndCandles(val hero: HeroK, val candles: Candles)
11+
12+
class MazeK(
13+
private var theseus: HeroTheseusK,
14+
private var minotaur: HeroMinotaurK,
15+
private var candles: Candles = Candles()
16+
) {
17+
18+
fun minotaur(fn: (HeroMinotaurK) -> Unit) {
19+
fn(minotaur)
20+
}
21+
22+
fun theseus(fn: (HeroK) -> Unit) {
23+
fn(theseus)
24+
}
25+
26+
private fun heroes(): TwoHeroes {
27+
return TwoHeroes(theseus, minotaur)
28+
}
29+
30+
fun solve() {
31+
while (true) {
32+
33+
HeroAndCandles(minotaur, candles).run {
34+
senseCandleInNextCavern(this)
35+
}.ifCandleSeen {
36+
turnBack(it)
37+
}
38+
39+
minotaur(enterCavern)
40+
enterCavern(theseus)
41+
42+
HeroAndCandles(theseus, candles).apply {
43+
putCandleInHeroesCavern(this)
44+
}
45+
46+
checkPlace(heroes())
47+
.inSamePlace {
48+
TheseusKillMinotaur(it)
49+
}
50+
.also { if (it) return@solve }
51+
52+
minotaur(enterLeftUnmarkedExit)
53+
theseus(enterRightUnmarkedExit)
54+
55+
checkPlace(heroes())
56+
.inSamePlace {
57+
MinotaurKillTheseus(it)
58+
}
59+
.also { if (it) return@solve }
60+
}
61+
}
62+
63+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package challenge.tvsm
2+
3+
import challenge.tvsm.model.*
4+
5+
fun createMazeK(cavernPairs: Iterable<Pair<String, String>>,
6+
theseusPair: Pair<String, String>,
7+
minotaurPair: Pair<String, String>): MazeK {
8+
9+
// collect caverns first (as passages uses caverns)
10+
val caverns: Set<MutableCavernK> = cavernPairs
11+
.map { it.first }
12+
.distinct()
13+
.map { MutableCavernK(it) }
14+
.toSet()
15+
16+
fun cavernOf(name: String): MutableCavernK {
17+
return caverns.find { it.name == name } ?: throw IllegalArgumentException("Non-existing cavern: $name")
18+
}
19+
20+
// then create _distinct_ passages
21+
val passages = cavernPairs
22+
.map { MutablePassageK(cavernOf(it.first), cavernOf(it.second)) }
23+
.toSet()
24+
25+
// then add passages to caverns
26+
fun passageOf(from: String, to: String) : MutablePassageK {
27+
return passages.find {
28+
(it.a.name == from && it.b.name == to) ||
29+
(it.a.name == to && it.b.name == from)
30+
} ?: throw IllegalArgumentException("Invalid passage $from - $to")
31+
}
32+
33+
fun passageOf(pair: Pair<String, String>) : MutablePassageK {
34+
return passageOf(pair.first, pair.second)
35+
}
36+
37+
cavernPairs
38+
.map { Pair(cavernOf(it.first), passageOf(it)) }
39+
.forEach { it.first.addPassage(it.second) }
40+
41+
42+
// finally put heroes in the maze
43+
44+
val theseus = HeroTheseusK(PositionInPassageK(passageOf(theseusPair), cavernOf(theseusPair.second), null))
45+
val minotaur = HeroMinotaurK(PositionInPassageK(passageOf(minotaurPair), cavernOf(minotaurPair.second), null))
46+
47+
// *** We don't need to store the passages and caverns!
48+
return MazeK(theseus, minotaur)
49+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package challenge.tvsm
2+
3+
import jodd.util.ResourcesUtil
4+
import jodd.util.StringPool
5+
6+
// *** just a quick-and-dirty text parser
7+
class MazeLoader {
8+
// utility class that controls the lifespan and usage of caverns set
9+
class Caverns {
10+
var caverns = new()
11+
12+
private fun new(): MutableList<Pair<String, String>> {
13+
return mutableListOf()
14+
}
15+
16+
fun add(pairs: Iterable<Pair<String, String>>) {
17+
caverns.addAll(pairs)
18+
}
19+
20+
fun get(): Iterable<Pair<String, String>> {
21+
val result = caverns;
22+
caverns = new()
23+
return result;
24+
}
25+
}
26+
27+
fun loadMazes(): List<MazeK> {
28+
val mazes = mutableListOf<MazeK>()
29+
val caverns = Caverns()
30+
val input = ResourcesUtil.getResourceAsString("challenge/theseusvsminotaur/in1.txt")
31+
32+
input
33+
.lines()
34+
.forEach { line ->
35+
println(line)
36+
37+
if (isEndOfFile(line)) {
38+
return@forEach
39+
}
40+
41+
if (isEndOfMaze(line)) {
42+
// positions of Theseus and Minotaur
43+
44+
val theseus = line[1].toString() to line[2].toString()
45+
val minotaur = line[3].toString() to line[4].toString()
46+
47+
mazes.add(createMazeK(caverns.get(), theseus, minotaur))
48+
} else {
49+
// caverns
50+
51+
val ndx = line.indexOf(':')
52+
val cavernName = line.substring(0, ndx)
53+
54+
line.substring(ndx + 1)
55+
.toCharArray()
56+
.map { it.toString() }
57+
.map { cavernName to it }
58+
.toList()
59+
.let {
60+
caverns.add(it)
61+
}
62+
}
63+
}
64+
65+
return mazes
66+
}
67+
68+
private fun isEndOfMaze(line: String): Boolean {
69+
return line.startsWith(StringPool.AT)
70+
}
71+
72+
private fun isEndOfFile(line: String): Boolean {
73+
return line == StringPool.HASH
74+
}
75+
76+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package challenge.tvsm
2+
3+
4+
fun main() {
5+
MazeLoader()
6+
.loadMazes()
7+
.stream()
8+
.forEach {
9+
println("---------------------------")
10+
it.solve()
11+
}
12+
13+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package challenge.tvsm.maze
2+
3+
import challenge.tvsm.model.HeroK
4+
5+
val enterCavern = fun(hero: HeroK) {
6+
return hero.doInPassage {
7+
it.stepIntoCavern()
8+
}.let {
9+
hero.move(it)
10+
}
11+
}
12+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package challenge.tvsm.maze
2+
3+
import challenge.tvsm.model.HeroK
4+
5+
val enterLeftUnmarkedExit = fun(hero: HeroK) {
6+
hero.doInCavern {
7+
var pp = it.previousPassage
8+
while (true) {
9+
val leftPassage = it.cavern.leftPassageOf(pp)
10+
val otherCave = leftPassage.otherEndOf(it.cavern)
11+
if (!hero.usedExitTo(otherCave)) {
12+
hero.move(it.enterPassage(leftPassage))
13+
break
14+
}
15+
pp = leftPassage
16+
}
17+
}
18+
}
19+
20+
val enterRightUnmarkedExit = fun(hero: HeroK) {
21+
hero.doInCavern {
22+
var pp = it.previousPassage
23+
while (true) {
24+
val rightPassage = it.cavern.rightPassageOf(pp)
25+
val otherCave = rightPassage.otherEndOf(it.cavern)
26+
if (!hero.usedExitTo(otherCave)) {
27+
hero.move(it.enterPassage(rightPassage))
28+
break
29+
}
30+
pp = rightPassage
31+
}
32+
}
33+
34+
}

0 commit comments

Comments
 (0)