Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.io.BufferedReader
- import java.io.InputStreamReader
- const val RESULT_COUNT = 5
- class SearchSystem(private val index: Map<String, List<DocumentRelevance>>) {
- companion object {
- fun getSearchSystem(documents: Collection<String>) =
- SearchSystem(
- buildMap<String, MutableList<DocumentRelevance>> { updateIndex(documents) }
- )
- private fun MutableMap<String, MutableList<DocumentRelevance>>.updateIndex(documents: Collection<String>) =
- documents.forEachIndexed { docId, document ->
- addDoc(document, docId)
- }
- private fun MutableMap<String, MutableList<DocumentRelevance>>.addDoc(document: String, docId: Int) =
- document.split(" ")
- .groupBy { it }
- .map { it.key to (docId + 1 to it.value.count()) }
- .forEach {
- compute(it.first) { _, v ->
- (v ?: mutableListOf())
- .apply {
- add(it.second)
- }
- }
- }
- private infix fun Int.to(relevance: Int) = DocumentRelevance(this, relevance)
- }
- /**
- * Возвращает словарь, в котором ключ -- id документа, а значение релевантность документа по запросу
- */
- fun getDocRelevance(query: Set<String>): List<DocumentRelevance> =
- buildMap {
- query.forEach { addWordRelevanceDocuments(it) }
- }
- .map { it.key to it.value }
- /**
- * В словаре-ресивере обновляет информацию о релевантности документа по конкретному слову
- */
- private fun MutableMap<Int, Int>.addWordRelevanceDocuments(word: String) =
- index[word]?.let { docs ->
- docs.forEach { (t, u) ->
- compute(t) { _, v -> (v ?: 0) + u }
- }
- }
- data class DocumentRelevance(val docId: Int, val relevance: Int) {
- override fun toString() = "($docId, $relevance)"
- }
- }
- private fun <T> MutableList<T>.take(count: Int, comparator: Comparator<T>):List<T> {
- val right = minOf(count, this.size)
- for (i in 0 until right) {
- var indexOfMin = i
- for (j in i + 1 until right)
- if (comparator.compare(this[j], this[indexOfMin]) < 0)
- indexOfMin = j
- if (i != indexOfMin) {
- val tmp = this[i]
- this[i] = this[indexOfMin]
- this[indexOfMin] = tmp
- }
- }
- return take(count)
- }
- fun main() {
- val buffer = BufferedReader(InputStreamReader(System.`in`))
- val docCount = buffer.readLine().toInt()
- // Составляем словарь, в котором ключ -- слово, значение -- мапа, у которой ключ -- id документа, а значение -- кол-во вхождений этого слова
- val documents = List(docCount) { buffer.readLine() }
- val index = SearchSystem.getSearchSystem(documents)
- // Составляем список запросов, разбивая запрос на сет слов для исключения дубликатов
- val queries: List<Set<String>> = List(buffer.readLine().toInt()) {
- buildSet {
- addAll(buffer.readLine().split(" "))
- }
- }
- queries.joinToString("\n") { query: Set<String> ->
- index.getDocRelevance(query)
- .toMutableList()
- .take(RESULT_COUNT, compareByDescending <SearchSystem.DocumentRelevance> { it.relevance }.thenBy { it.docId })
- .joinToString(" ") { it.docId.toString()}
- }.let(::println)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement