Created
May 13, 2020 14:26
-
-
Save ygrenzinger/ef2b4dd27b022fbe7f6ab9c3a9e848ee to your computer and use it in GitHub Desktop.
Jetbrains academy SimpleSearchEngine
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package search | |
import java.io.File | |
import java.util.* | |
typealias InvertedSearchData = MutableMap<String, Set<Int>> | |
enum class MatchingStrategy() { | |
ALL { | |
override fun execQuery(invertedSearch: InvertedSearchData, words: List<String>): Set<Int> { | |
val results = words.mapNotNull { invertedSearch[it] } | |
return if (results.isEmpty()) setOf() else results.reduce {acc, set -> acc.intersect(set) } | |
} | |
}, NONE { | |
override fun execQuery(invertedSearch: InvertedSearchData, words: List<String>): Set<Int> { | |
val allIndices = invertedSearch.values.flatten().toSet() | |
return allIndices.subtract(ANY.execQuery(invertedSearch, words)) | |
} | |
}, ANY { | |
override fun execQuery(invertedSearch: InvertedSearchData, words: List<String>): Set<Int> { | |
val results = words.mapNotNull { invertedSearch[it] } | |
return if (results.isEmpty()) setOf() else results.reduce {acc, set -> acc + set } | |
} | |
}; | |
abstract fun execQuery(invertedSearch: InvertedSearchData, words: List<String>) : Set<Int> | |
fun execQuery(invertedSearch: InvertedSearchData, query: String) : Set<Int> { | |
return execQuery(invertedSearch, query.split(" ").map { it.toLowerCase() }).toSet() | |
} | |
} | |
class SearchProgram(private val scanner: Scanner, private val peoples: List<String>) { | |
private val invertedSearch: InvertedSearchData | |
init { | |
invertedSearch = buildInvertedSearch() | |
} | |
private fun buildInvertedSearch(): InvertedSearchData { | |
return peoples.foldRight(mutableMapOf()) { input, m -> | |
val words = input.split(" ").map { it.toLowerCase() } | |
addElement(words, m) | |
} | |
} | |
private fun addElement(words: List<String>, m: InvertedSearchData) = | |
words.foldRight(m) { word, acc -> | |
val indices = peoples.withIndex().filter { | |
it.value.toLowerCase().contains(word) | |
}.map { it.index } | |
val v = acc.getOrDefault(word, setOf()) + indices | |
acc[word] = v | |
acc | |
} | |
fun run() { | |
var choice = menu() | |
while (choice != 0) { | |
when (choice) { | |
1 -> findPerson() | |
2 -> printAllPeople() | |
else -> println("Incorrect option! Try again.") | |
} | |
choice = menu() | |
} | |
} | |
private fun printAllPeople() { | |
println("=== List of people ===") | |
peoples.forEach { | |
println(it) | |
} | |
} | |
private fun findPerson() { | |
println("Select a matching strategy: ALL, ANY, NONE") | |
val matchingStrategy = MatchingStrategy.valueOf(scanner.nextLine()) | |
println("Enter a name or email to search all suitable people.") | |
val query = scanner.nextLine() | |
val found = matchingStrategy.execQuery(invertedSearch, query) | |
if (found.isEmpty()) { | |
println("No matching people found.") | |
} else { | |
println("${found.size} persons found:") | |
found.forEach { println(peoples[it]) } | |
} | |
} | |
private fun menu(): Int { | |
println(""" | |
=== Menu === | |
1. Find a person | |
2. Print all people | |
0. Exit | |
""".trimIndent()) | |
return scanner.nextLine().toInt() | |
} | |
companion object { | |
fun input(scanner: Scanner): SearchProgram { | |
println("Enter the number of people:") | |
val n = scanner.nextLine().toInt() | |
println("Enter all people:") | |
val peoples = (1..n).map { scanner.nextLine() } | |
return SearchProgram(scanner, peoples) | |
} | |
fun input(scanner: Scanner, file:File): SearchProgram { | |
val peoples = file.readLines() | |
return SearchProgram(scanner, peoples) | |
} | |
} | |
} | |
fun main(args: Array<String>) { | |
if(args.isEmpty()){ | |
print("Please add some command line arguments") | |
return | |
} | |
if (args[0] != "--data" || args.size < 2) { | |
print("Wrong command line arguments") | |
return | |
} | |
val scanner = Scanner(System.`in`) | |
val program = SearchProgram.input(scanner, File(args[1])) | |
program.run() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment