Regex and .contains - kotlin

I am recognizing words from an Imageview using FirbaseVisionImage class. I want to determined a substring which has a regex pattern of ( "^\\d{6}-\\d{2}-\\d{4}\$") from the whole string from an Imageview, and then show the substring which has the regex pattern of ( "^\\d{6}-\\d{2}-\\d{4}\$") at a textview, however it won't work
val rotatedBitmap = rotateBitmap(bitmap, 270f)
val firebaseVisionImage = FirebaseVisionImage.fromBitmap(rotatedBitmap)
val firebaseVision = FirebaseVision.getInstance()
val firebaseVisionTextRecognizer = firebaseVision.onDeviceTextRecognizer
val task: Task<FirebaseVisionText> =
firebaseVisionTextRecognizer.processImage(firebaseVisionImage)
task.addOnSuccessListener { p0 ->
var s = p0?.text
val regex = Regex( "^\\d{6}-\\d{2}-\\d{4}\$")
var icFormat = ""
var subString = regex.matches(icFormat)
if(s!!.contains(subString.toString())){
binding.tvDemo.text = subString.toString()
}else{
binding.tvDemo.text = "Cannot Detect Regex"
}
}

Related

How to do calculations with numbers separated with commas?

I want to do calculations with numbers separated by thousands (comma), and the result will be formatted in thousands separated (comma) as well. Example:
var editText1 = **12,520.00**
var editText2 = **52,345.00**
var result = **64,825.00**
//
var editText1 = **12,520**
var editText2 = **52,345**
var result = **64,825.00**
=====================================
I just tried to format the result according to the separation in thousands (comma) of the values that I would receive.
//formats
decimalSymbols = DecimalFormatSymbols(Locale.US)
format="##,###.##"
decimal = DecimalFormat(format, decimalSymbols)
decimal.roundingMode = RoundingMode.CEILING
//Variables that will receive the values
val prov = profit.text.toString().toDouble()
val cust = costs.text.toString().toDouble()
val amort = amortizacoes.text.toString().toDouble()
val jur = interest.text.toString().toDouble()
//Formatting the result in BigDecimal
result val = (prov - cost - amort - jur) * 0.32
val parsed = BigDecimal(result)
val formatResult = decimal.format(parsed)
tax.setText(formatResult.toString())
Simply remove all commas from the string value:
value= value.replace(",", "")
Do your calculations
And finally, you can use format to decorate and show them with commas, with:
"%,d".format(value)
Tested with JVM and Kotlin v1.8.0.
Here is the playground link: https://pl.kotl.in/pXpev-dei
Code snippet, pasted here:
fun main() {
var editText1 = "12,520.00";
var editText2 = "52,345.00";
// var result = **64,825.00**
editText1 = editText1.replace(",","");
editText2 = editText2.replace(",","");
var resDouble = editText1.toDouble() * editText2.toDouble();
val res = "%,f".format(resDouble)
println(res)
}

Merge properties of a list to another based on properties objects

I got 2 lists with x objects inside , for example:
data class Model(
var token: String = "",
var id: String = "",
var name: String = "",
var image: Int = 0,
)
array is initialized and filled, the other list has x objects also that contains the objects of the first list but with different values in their properties!
what I want to do is to change the properties of the first array by the second one if they got the same object.name
var arr1 = ArrayList<Model>() // locale
var arr2 = ArrayList<Model>() // from db
the first array I got for example
[Model(name = "David", token = "" , image = 0)]
the second array I got
[Model(name = "David", token = "1asd5asdd851", image = 1)]
How do I make the first array take the missing token?
I tried with .filter{} and with .map{}. groupBy {} for hours because Name is the only properties that are the same but I'm more and more confused.
We can first group the second array by name using associateBy() and then iterate over first array and reassign properties:
val arr2ByName = arr2.associateBy { it.name }
arr1.forEach { item1 ->
arr2ByName[item1.name]?.let { item2 ->
item1.token = item2.token
item1.image = item2.image
}
}
Alternatively, if you don't need to modify items in arr1, but create another array and you can use items from both arr1 and arr2, then it will be much easier:
val arr3 = arr1.map { arr2ByName[it.name] ?: it }
One possible way would be to use fold() as follows:
fun main(args: Array<String>) {
val arr1 = listOf(Model(name = "David", token = "" , image = 0))
val arr2 = listOf(Model(name = "David", token = "1asd5asdd851", image = 1))
val mergedModels = arr2.fold(arr1) { localModels, dbModel ->
localModels.map { localModel ->
if (localModel.name == dbModel.name) localModel.copy(token = dbModel.token, image = dbModel.image)
else localModel
}
}
println(mergedModels)
}
If you want to reuse arr1 variable then you can do the following (but I would still use the previous option):
fun main(args: Array<String>) {
var arr1 = listOf(Model(name = "David", token = "" , image = 0))
val arr2 = listOf(Model(name = "David", token = "1asd5asdd851", image = 1))
arr1 = arr2.fold(arr1) { localModels, dbModel ->
localModels.map { localModel ->
if (localModel.name == dbModel.name) localModel.copy(token = dbModel.token, image = dbModel.image)
else localModel
}
}
println(arr1)
}

How to try every possible permutation in Kotlin

fun main () {
var integers = mutableListOf(0)
for (x in 1..9) {
integers.add(x)
}
//for or while could be used in this instance
var lowerCase = listOf("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z")
var upperCase = listOf('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z')
println(integers)
println(lowerCase)
println(upperCase)
//Note that for the actual program, it is also vital that I use potential punctuation
val passwordGeneratorKey1 = Math.random()*999
val passwordGeneratorKey2 = passwordGeneratorKey1.toInt()
var passwordGeneratorL1 = lowerCase[(Math.random()*lowerCase.size).toInt()]
var passwordGeneratorL2 = lowerCase[(Math.random()*lowerCase.size).toInt()]
var passwordGeneratorL3 = lowerCase[(Math.random()*lowerCase.size).toInt()]
var passwordGeneratorU1 = upperCase[(Math.random()*upperCase.size).toInt()]
var passwordGeneratorU2 = upperCase[(Math.random()*upperCase.size).toInt()]
var passwordGeneratorU3 = upperCase[(Math.random()*upperCase.size).toInt()]
val password = passwordGeneratorKey2.toString()+passwordGeneratorL1+passwordGeneratorL2+passwordGeneratorL3+passwordGeneratorU1+passwordGeneratorU2+passwordGeneratorU3
println(password)
//No, this isn't random, but it's pretty close to it
//How do I now run through every possible combination of the lists //lowerCase, integers, and upperCase?
}
How do I run through every possible permutation to eventually solve for the randomly generated password? This is in Kotlin.
I think you should append all the lists together and then draw from it by random index, this way you ensure that position of numbers, lower cases and uppercases is random too. Also you don't need to write all the characters, you can use Range which generates them for you.
fun main() {
val allChars = mutableListOf<Any>().apply {
addAll(0..9) // creates range from 0 to 9 and adds it to a list
addAll('a'..'z') // creates range from a to z and adds it to a list
addAll('A'..'Z') // creates range from A to Z and adds it to a list
}
val passwordLength = 9
val password = StringBuilder().apply {
for (i in 0 until passwordLength) {
val randomCharIndex =
Random.nextInt(allChars.lastIndex) // generate random index from 0 to lastIndex of list
val randomChar = allChars[randomCharIndex] // select character from list
append(randomChar) // append char to password string builder
}
}.toString()
println(password)
}
Even shorter solution can be achieved using list methods
fun main() {
val password = mutableListOf<Any>()
.apply {
addAll(0..9) // creates range from 0 to 9 and adds it to a list
addAll('a'..'z') // creates range from a to z and adds it to a list
addAll('A'..'Z') // creates range from A to Z and adds it to a list
}
.shuffled() // shuffle the list
.take(9) // take first 9 elements from list
.joinToString("") // join them to string
println(password)
}
As others pointed out there are less painful ways to generate the initial password in the format of: 1 to 3 digits followed by 3 lowercase characters followed by 3 uppercase characters.
To brute force this password, you will need to consider all 3-permutations of "a..z" and all 3-permitations of "A..Z". In both cases the number of such 3-permutations is 15600 = 26! / (26-3)!. In worst case you will have to examine 1000 * 15600 * 15600 combination, half of this on the average.
Probably doable in a few hours with the code below:
import kotlin.random.Random
import kotlin.system.exitProcess
val lowercaseList = ('a'..'z').toList()
val uppercaseList = ('A'..'Z').toList()
val lowercase = lowercaseList.joinToString(separator = "")
val uppercase = uppercaseList.joinToString(separator = "")
fun genPassword(): String {
val lowercase = lowercaseList.shuffled().take(3)
val uppercase = uppercaseList.shuffled().take(3)
return (listOf(Random.nextInt(0, 1000)) + lowercase + uppercase).joinToString(separator = "")
}
/**
* Generate all K-sized permutations of str of length N. The number of such permutations is:
* N! / (N-K)!
*
* For example: perm(2, "abc") = [ab, ac, ba, bc, ca, cb]
*/
fun perm(k: Int, str: String): List<String> {
val nk = str.length - k
fun perm(str: String, accumulate: String): List<String> {
return when (str.length == nk) {
true -> listOf(accumulate)
false -> {
str.flatMapIndexed { i, c ->
perm(str.removeRange(i, i + 1), accumulate + c)
}
}
}
}
return perm(str, "")
}
fun main() {
val password = genPassword().also { println(it) }
val all3LowercasePermutations = perm(3, lowercase).also { println(it) }.also { println(it.size) }
val all3UppercasePermutations = perm(3, uppercase).also { println(it) }.also { println(it.size) }
for (i in 0..999) {
println("trying $i")
for (l in all3LowercasePermutations) {
for (u in all3UppercasePermutations) {
if ("$i$l$u" == password) {
println("found: $i$l$u")
exitProcess(0)
}
}
}
}
}

Compare multiple fields of Object to those in an ArrayList of Objects

I have created a 'SiteObject' which includes the following fields:
data class SiteObject(
//Site entry fields (10 fields)
var siteReference: String = "",
var siteAddress: String = "",
var sitePhoneNumber: String = "",
var siteEmail: String = "",
var invoiceAddress: String = "",
var invoicePhoneNumber: String = "",
var invoiceEmail: String = "",
var website: String = "",
var companyNumber: String = "",
var vatNumber: String = "",
)
I want to filter an ArrayList<SiteObject> (call it allSites) by checking if any of the fields of the objects within the list match those in a specific <SiteObject> (call it currentSite).
So for example, I know how to filter looking at one field:
fun checkIfExistingSite(currentSite: SiteObject) : ArrayList<SiteObject> {
var matchingSites = ArrayList<SiteObject>()
allSites.value?.filter { site ->
site.siteReference.contains(currentSite.siteReference)}?.let { matchingSites.addAll(it)
}
return matchingSites
}
But I am looking for an elegant way to create a list where I compare the matching fields in each of the objects in allSites with the corresponding fields in currentSite..
This will give me a list of sites that may be the same (allowing for differences in the way user inputs data) which I can present to the user to check.
Use equals property of Data Class:
val matchingSites: List<SiteObject> = allSites
.filterNotNull()
.filter { it.equals(currentSite) }
If you are looking for a more loose equlity criteria than the full match of all fields values, I would suggest usage of reflection (note that this approach could have performance penalties):
val memberProperties = SiteObject::class.memberProperties
val minMatchingProperties = 9 //or whatever number that makes sense in you case
val matchingItems = allSites.filter {
memberProperties.atLeast(minMatchingProperties) { property -> property.get(it) == property.get(currentSite) }
}
fun <E> Iterable<E>.atLeast(n: Int, predicate: (E) -> Boolean): Boolean {
val size = count()
return when {
n == 1 -> this.any(predicate)
n == size -> this.all(predicate)
n > size - n + 1 -> this.atLeast(size - n + 1) { !predicate.invoke(it) }
else -> {
var count = 0
for (element in this) {
if (predicate.invoke(element)) count++
if (count >= n) return true
}
return false
}
}
}
you could specify all the fields by which you want to match the currentSite inside the filter predicate:
fun checkIfExistingSite(currentSite: SiteObject) =
allSites.filter {
it.siteAddress == currentSite.siteAddress
|| it.sitePhoneNumber == currentSite.sitePhoneNumber
|| it.siteReference == currentSite.siteReference
}
Long but fast solution because of short circuiting.
If the list is nullable you can transform it to a non nullable list like:
allSites?filter{...}.orEmpty()
// or imho better
allSites.orEmpty().filter{...}

How to get length of a character array in kotlin?

I am trying to find the length of two different character array but I am only being allowed to use array.size only once.
How to bypass this problem?
fun chararraytostr(inp1: CharArray): String{
var arlen: Int = inp1.size //here lies the problem
var out1: String = ""
for(j in 0..arlen-1){
var str = inp1[j].toString()
out1+=str
}
return out1
}
fun uppercase(input: String): String{
var temp1: CharArray = input.toCharArray()
var len = input.size //here lies the problem
var temp3: Char
for(i in 0..len-1){
var temp2: Char = temp1[i]
var ascii: Int = temp2.toInt()
if(ascii<=122 && ascii>=97){
ascii-=32
temp3 = ascii.toChar()
temp1[i] = temp3
}else{}
}
var output = chararraytostr(temp1)
return output
}
fun main(arg: Array<String>){
var toupper = "Hi my friend!"
println(uppercase(toupper))
}
It is always showing Unresolved reference: size. I don't know why. Please help.
You're calling size on the String variable instead of the CharArray variable. Use temp1.size instead of input.size.