Obtain the length of the selected string in kotlin - kotlin

I want to obtain the index chars or words in a string
for example
tv.text=" hey how are you, are you okay"
val res=tv.text.indexOf('h')
(have any way for put string instead of char?
output res=0
index of return only first char with h but in my tv text I have more h chars
can we return all h chars indexs

You can use filter function to get all the string indices with the required character.
val text = " hey how are you, are you okay"
val charToSearch = 'h'
val occurrences = text.indices.filter { text[it] == charToSearch }
println(occurences)
Try it yourself
And, if you want to search for strings instead of a single character, you can do this:
text.indices.filter { text.startsWith(stringToSearch, it) }

The following should work (you try to find an index if you found one in the previous iteration and you begin the folloing iteration from the previously found character instance plus 1, so that you don't find the same again and again):
fun main() {
val word = " hey how are you, are you okay"
val character = 'h'
var index: Int = word.indexOf(character)
while (index >= 0) {
println(index)
index = word.indexOf(character, index + 1)
}
}
If you want to store the indexes for later usage you can also do the following:
fun main() {
val word = " hey how are you, are you okay"
val character = 'h'
val indexes = mutableListOf<Int>()
var index: Int = word.indexOf(character)
while (index >= 0) {
index = word.indexOf(character, index + 1)
indexes.add(index)
}
println(indexes)
}

If you just want all the indices matching a char you can do this:
text.indices.filter { text[it] == 'h' }
Finding string matches is trickier, you could use Kotlin's regionMatches function to check if the part of the string starting at index matches what you're looking for:
val findMe = "you"
text.indices.filter { i ->
text.regionMatches(i, findMe, 0, findMe.length)
}
You could use a regular expression too, so long as you're careful about validating the search pattern:
Regex(findMe).findAll(text)
.map { it.range.first() } // getting the first index of each matching range
.toList()

Related

Removing a loop to make code run faster (Kotlin) (Big O)

I'm trying a leetcode challenge and am struggling to pass the challenge due to the speed of my code:
class Solution {
fun longestPalindrome(s: String): String {
var longestPal = ""
var substring = ""
for (i in 0..s.length) {
for (j in i + 1..s.length) {
substring = s.substring(i, j)
if (substring == substring.reversed() && substring.length > longestPal.length) {
longestPal = substring
}
}
}
return longestPal
}
}
I'm a newb and not familiar with Big O notation.
I imagine if I could use just one loop I would be able to speed this code up significantly but am not sure how I would go about this.
(Not saying this is the best approach, but that is a start)
Palindromes can only be found between two same letters. So one idea is to go through the string once, and keep track of letter indexes. When you encounter a letter you already saw before, and the difference in indexes is longer than the current longest palindrome, you check for a palindrome:
fun longestPal(s: String): String {
val letters = mutableMapOf<Char, MutableList<Int>>()
var longest = ""
s.indices.forEach { index ->
val indicesForCurrentChar = letters[s[index]] ?: mutableListOf()
for (i in indicesForCurrentChar) {
if ((index - i) < longest.length) break // (1) won't be the longest anyway
val sub = s.substring(i, index + 1)
if (sub == sub.reversed()) longest = sub
}
indicesForCurrentChar.add(index)
letters[s[index]] = indicesForCurrentChar
}
return longest
}
What is costly here is the palindrome check itself (sub == sub.reversed). But the check in (1) should contain it (think of a string which is the repetition of the same letter).
I would be curious to know what other suggest online.
Your code runs in O(n^3) time, a loop within a loop within a loop, because that reversed() call iterates up to the size of the input string. You can look up Manacher's algorithm for an explanation of how to do it in linear time (O(n)), no nested iteration at all.

Write a kotlin program that prints the number that is repeated the most in a consecutive way

I'm kind of stuck, I don't know how to make the second loop to start 1 position above the first loop in Kotlin.
I have an array (named myArray) with 10 elements, I need to Write a Kotlin program that prints the number that has the most consecutive repeated number in the array and also prints the number of times it appears in the sequence.
The program must parse the array from left to right so that if two numbers meet the condition, the one that appears first from left to right will be printed.
Longest: 3
Number: 8
fun main() {
val myArray: IntArray = intArrayOf(1,2,2,4,5,6,7,8,8,8)
for((index , value) in myArray.withIndex()){
var inx = index + 1
var count = 0
var longest = 0
var number = 0
for((inx,element) in myArray.withIndex()) {
if(value == element ){
count+=
}
}
if(longest < count){
longest = count
number = value
}
}
}
I'm against just dropping answers, but it is quite late for me, so I'll leave this answer here and edit it tomorrow with more info on how each part works. I hope that maybe in the meanwhile it will help you to gain some idea to where you might be going wrong.
val results = mutableMapOf<Int, Int>()
(0..myArray.size - 2).forEach { index ->
val current = myArray[index]
if (current == myArray[index + 1]) {
results[current] = (results[current] ?: 1) + 1
}
}
val (max, occurrences) = results.maxByOrNull { it.value } ?: run { println("No multiple occurrences"); return }
println("Most common consecutive number $max, with $occurrences occurrences")
Alternatively if the intArray would be a list, or if we allowed to change it to a list myArray.toList(), you could replace the whole forEach loop with a zipWithNext. But I'm pretty sure that this is a HW question, so I doubt this is the expected way of solving it.
myList.zipWithNext { a, b ->
if (a == b) results[a] = (results[a] ?: 1) + 1
}

can't get Kotlin to check if variable in listOf

I've tried this 10 different ways and i can't get this to work.
I want this Kotlin code to take in a string, check each character of that string against a listOf characters, and, if it is in that list, increase a counting variable by 1, so then at the end it can check if that counting variable is high enough to pass a test. this is taken straight from Sololearn: Code Coach - Password Validator. I have completed this code successfully already in Python (https://code.sololearn.com/c0fl17IMHPfC), but in trying to convert it over to Kotlin, it doesn't seem to work. The variables don't seem to register as true when compared to the elements in the listOf.
fun main() {
var password: String = readLine()!!
var numberCount: Int = 0
var numbers: List<String> = listOf("0","1","2","3","4","5","6","7","8","9")
var specialCount: Int = 0
var specialCharacters: List<String> = listOf("!","#","#","$","%","&","*")
if (password.length < 7) {
println("Weak")
} else {
for (character in password) {
println(character)
var numberCheck = numbers.contains(character)
println(numberCheck)
if (numberCheck == true) {
numberCount += 1
}
var specialCharactersCheck = specialCharacters.contains(character)
println(specialCharactersCheck)
if (specialCharactersCheck == true) {
specialCount += 1
}
}
println(numberCount)
println(specialCount)
if (numberCount < 2) {
println("Weak")
} else if (specialCount < 2) {
println("Weak")
} else {
println("Strong")
}
}
}
When I enter an input of "letssee43$#", the result of this code is:
l
false
false
e
false
false
t
false
false
s
false
false
s
false
false
e
false
false
e
false
false
4
false
false
3
false
false
$
false
false
false
false
0
0
Weak
Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
Your list is a list of Strings, but for (character in password) loops over the Chars in password. So you're trying to see if one of the Strings in your list is a specific Char, which it isn't, because they're two different types - a string with a single character in it is still a String, not a Char (that's why you're getting that type error)
There are lots of ways to do it (and there's nothing wrong with your code besides the Char/String thing!), personally I'd just do this:
var numbers = "0123456789"
var specialCharacters = "!##$%&*"
val password = "letssee43$#"
val nums = password.count { it in numbers }
val specials = password.count { it in specialCharacters }
println("nums: $nums, specials: $specials")
> nums: 2, specials: 2
count is iterating over the Chars in password and counting how many of them each character string contains. A String is treated like an array of Chars, so you can check it that way. (You could also add .toList() after the string declaration if you really want your characters stored in a list - that way it'll be a List<Char> so the lookup will still work.)
Or you could do things the way you are, and explicitly write out the listOf elements - but make them Chars instead, e.g. listOf('1') (single quotes) instead of listOf("1") (double quotes).
If you do want to search a list of strings for a match, you need to provide a String, so you need to convert your Char to one, e.g. by calling toString() on it, using a literal like "$character", etc.
edit like gidds points out below, sets are way more efficient for lookups like in or contains, so toSet() is a better idea than toList() unless you really need that ordered list for some reason. If you don't care about efficiency (like if you're not doing a lot of lookups) I'd personally just leave it as a string like in the code block up there - it's nice and simple. But if you do want to be more efficient, or if you do need a collection (like if you're matching against Strings) then a Set is ideal
I will give you another way to get the same result as you by using Extensions
fun main() {
var password: String = readln()
println("Password contain numbers amount: " + password.containNumbersAmount())
println("Password contain special characters amount: "+ password.containSpecialCharactersAmount())
println("Password Status : "+ password.validationResult())
}
fun String.containNumbersAmount() = count { it.isDigit() }
fun String.containSpecialCharactersAmount(): Int {
val specialCharacters = "!##$%&*"
return count { it in specialCharacters } }
fun String.validationResult() : String {
return when {
length < 7 -> "Weak"
containNumbersAmount() < 2 -> "Weak"
containSpecialCharactersAmount() < 2 -> "Weak"
else -> "Strong"
}
}
The problem is that your Lists contain Strings, so every time you call contains on them and pass a Char, it will always be false because a Char is not a String.
Probably, the best way to fix it is to declare Iterables of Chars to check them. Lists are Iterables, but so are ranges.
val password: String = readln()
var numberCount: Int = 0
val numbers: Iterable<Char> = '0'..'9'
var specialCount: Int = 0
val specialCharacters: List<Char> = listOf('!','#','#','$','%','&','*')
And just for your learning, there's a count function that takes a lambda argument that can make this kind of task much easier:
fun main() {
val password: String = readln()
val numbers = '0'..'9'
val specialCharacters = listOf('!','#','#','$','%','&','*')
val numberCount: Int = password.count { numbers.contains(it) }
val specialCount: Int = password.count { specialCharacters.contains(it) }
val result = when {
password.length < 7 || numberCount < 2 || specialCount < 2 -> "Weak"
else -> "Strong"
}
println(result)
}

Koltin - print 5(or specific Number) random CharRange '0'..'z' and using + Operator to creat one new String

I've been doing this Challage and stuck so hard.
Yes, I did find a more easy way but it doesn't fulfill the Challange condition.
Condition:
Create(Print) one String that has 5 or a specific size of Character from a CharRange using + Operator.
little example
fun main() {
val cRange: CharRange = '0'..'z'
cRange.random()
}
Functional way to generate string out of random characters
val range = 'a'..'z'
val out = generateSequence { range.random() }
.take(5)
.fold("") { acc, c -> acc + c }
This solution does not need any mutable variable

Kotlin For loop start from a given index

I want to start a For loop from a given index
in Java you can easily write
for (int i = startingIndex; i < items.size(); i++)
how to to do that in Kotlin?
I know how to write a for loop in Kotlin
my example
I want to iterate over an array of strings but the start position is 3, not iterating over a Range the iteration will be over a collection of items
For iterating from the start item till the last, you can use something like this:
for (i in startingIndex until items.size) {
//apply your logic
}
Another option is to drop first n elements and use forEach from there:
val l = listOf(1, 2, 3, 4)
l.drop(1).forEach { println(it) } // prints "2, 3, 4"
Instead of iterating over the items in your array, you can iterate over the indices and access the array by index. Here's a simple example.
val otherStrings = arrayOf("a", "b", "c", "d", "e")
for (i in 3..otherStrings.size-1)
println(otherStrings[i])
This iterates from starting index 3 to the last index (which is size - 1)
If the function is repeated several times you could do this:
Create an extension function
List<String>.startByIndex(startingIndex : Int){
for(index in startingIndex until this.size){
//apply common logic
}
}
call the extension function from your string list
var startIndex : Int = 3 // example
items.startByIndex(startIndex)
P.S. : If, for example, the extension function must always return a string as output, you have to change everything like this:
List<String>.startByIndex(startingIndex : Int) : String {
for(index in startingIndex until this.size){
var result : String
//apply common logic and instantiate var result
return result
}
}
var startIndex : Int = 3 // example
var result : String = items.startByIndex(startIndex)