Advertisement
vkazar

Untitled

Nov 16th, 2023
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 3.79 KB | None | 0 0
  1. import java.io.BufferedReader
  2. import java.io.InputStreamReader
  3.  
  4. const val RESULT_COUNT = 5
  5.  
  6. class SearchSystem(private val index: Map<String, List<DocumentRelevance>>) {
  7.     companion object {
  8.         fun getSearchSystem(documents: Collection<String>) =
  9.             SearchSystem(
  10.                 buildMap<String, MutableList<DocumentRelevance>> { updateIndex(documents) }
  11.             )
  12.  
  13.         private fun MutableMap<String, MutableList<DocumentRelevance>>.updateIndex(documents: Collection<String>) =
  14.             documents.forEachIndexed { docId, document ->
  15.                 addDoc(document, docId)
  16.             }
  17.  
  18.         private fun MutableMap<String, MutableList<DocumentRelevance>>.addDoc(document: String, docId: Int) =
  19.             document.split(" ")
  20.                 .groupBy { it }
  21.                 .map { it.key to (docId + 1 to it.value.count()) }
  22.                 .forEach {
  23.                     compute(it.first) { _, v ->
  24.                         (v ?: mutableListOf())
  25.                             .apply {
  26.                                 add(it.second)
  27.                             }
  28.                     }
  29.                 }
  30.  
  31.         private infix fun Int.to(relevance: Int) = DocumentRelevance(this, relevance)
  32.     }
  33.  
  34.     /**
  35.      * Возвращает словарь, в котором ключ -- id документа, а значение релевантность документа по запросу
  36.      */
  37.     fun getDocRelevance(query: Set<String>): List<DocumentRelevance> =
  38.         buildMap {
  39.             query.forEach { addWordRelevanceDocuments(it) }
  40.         }
  41.             .map { it.key to it.value }
  42.  
  43.     /**
  44.      * В словаре-ресивере обновляет информацию о релевантности документа по конкретному слову
  45.      */
  46.     private fun MutableMap<Int, Int>.addWordRelevanceDocuments(word: String) =
  47.         index[word]?.let { docs ->
  48.             docs.forEach { (t, u) ->
  49.                 compute(t) { _, v -> (v ?: 0) + u }
  50.             }
  51.         }
  52.  
  53.     data class DocumentRelevance(val docId: Int, val relevance: Int) {
  54.         override fun toString() = "($docId, $relevance)"
  55.     }
  56. }
  57.  
  58. private fun <T> MutableList<T>.take(count: Int, comparator: Comparator<T>):List<T> {
  59.     val right = minOf(count, this.size)
  60.     for (i in 0 until right) {
  61.         var indexOfMin = i
  62.         for (j in i + 1 until right)
  63.             if (comparator.compare(this[j], this[indexOfMin]) < 0)
  64.                 indexOfMin = j
  65.         if (i != indexOfMin) {
  66.             val tmp = this[i]
  67.             this[i] = this[indexOfMin]
  68.             this[indexOfMin] = tmp
  69.         }
  70.     }
  71.     return take(count)
  72. }
  73.  
  74. fun main() {
  75.     val buffer = BufferedReader(InputStreamReader(System.`in`))
  76.     val docCount = buffer.readLine().toInt()
  77.     // Составляем словарь, в котором ключ -- слово, значение -- мапа, у которой ключ -- id документа, а значение -- кол-во вхождений этого слова
  78.     val documents = List(docCount) { buffer.readLine() }
  79.     val index = SearchSystem.getSearchSystem(documents)
  80.  
  81.     // Составляем список запросов, разбивая запрос на сет слов для исключения дубликатов
  82.     val queries: List<Set<String>> = List(buffer.readLine().toInt()) {
  83.         buildSet {
  84.             addAll(buffer.readLine().split(" "))
  85.         }
  86.     }
  87.  
  88.     queries.joinToString("\n") { query: Set<String> ->
  89.         index.getDocRelevance(query)
  90.             .toMutableList()
  91.             .take(RESULT_COUNT, compareByDescending <SearchSystem.DocumentRelevance> { it.relevance }.thenBy { it.docId })
  92.             .joinToString(" ") { it.docId.toString()}
  93.     }.let(::println)
  94. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement