Is there any way duplicated sequential string delete in kotlin - kotlin

I got strings like
String1=277473—-2627272———-273-3838383-/./--asdfg-----123:12:2---
I cant take length of function because I have multiple strings with different lenghts.
I wanted to use split function to take them as a variable but I need this format
String1=277473-2627272—273-3838383-/./-asdfg-123:12:2
Is there any way to do that easily?

You are using 2 different kind of '-' characters, use this instead:
fun formatString(string: String): String {
return string.mapNotNull { char -> if (char == '—' || char == '-') '-' else char }
.joinToString(separator = "")
.replace("""-+""".toRegex(), "-")
.trimDashes()
}
fun String.trimDashes(): String = dropWhile { it == '-' }
.dropLastWhile { !it.isDigit() }

you can do something like this:
fun formatString(string: String): String {
return string.trimDashes()
.split("-")
.joinToString(separator = "-", transform = String::trimDashes)
}
fun String.trimDashes(): String = dropWhile { it == '-' }
.dropLastWhile { !it.isDigit() }

Related

kotlin product of odd or even integers

The problem I'm working on accepts a number string and will output the product of the odd or even numbers in the string. While the product of purely number string is working fine, my code should also accept strings that is alphanumeric (ex: 67shdg8092) and output the product. I'm quite confused on how I should code the alphanumeric strings, because the code I have done uses toInt().
Here's my code:
fun myProd(Odd: Boolean, vararg data: Char): Int {
var bool = isOdd
var EvenProd = 1
var OddProd = 1
for (a in data)
{
val intVal = a.toString().toInt()
if (intVal == 0)
{
continue
}
if (intVal % 2 == 0)
{
EvenProd *= intVal
}
else
{
OddProd *= intVal
}
}
if(bool == true) return OddProd
else return EvenProd
}
Use toIntOrNull instead of toInt. It only converts numeric string
val intVal = a.toString().toIntOrNull()
if (intVal == null || intVal == 0) {
continue
}
Starting from Kotlin 1.6 you can also use a.digitToIntOrNull().
P.S. Your method could be also rewritten in functional style
fun myProd(isOdd: Boolean, input: String): Int {
return input.asSequence()
.mapNotNull { it.toString().toIntOrNull() } // parse to numeric, ignore non-numeric
.filter { it > 0 } // avoid multiplying by zero
.filter { if (isOdd) it % 2 != 0 else it % 2 == 0 } // pick either odd or even numbers
.fold(1) { prod, i -> prod * i } // accumulate with initial 1
}

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)
}
}
}
}
}

How to solve PW Generator can´t handle specific Chars?

I´m new to Kotlin so first I start with a Password Generator. I do use IntelliJIDea
fun main() {
var helper = Int
var counter = 0
val counterOfPwCha = 10
var pwString = ""
val opportunityArray = arrayOf('A','C','a','c','B','b','D','d','E','e','F','f','#','+','*','$','%','&','§','G','g','H','h','I','i','J','j','k','K','1','2','3','4','5','6','7','8','9',
'l','L','M','m','N','n','O','o','P','p','Q','q','R','r','S','s','T','t','U','u','V','v','W','w','Y','y','X','x','Z','z','<','>','|','?','!',)
while (counter <= counterOfPwCha)
{
helper = (0..73).random()
pwString += opportunityArray[helper]
counter++
}
println(pwString)
}
it workes fine, but the output isn´t what I expected.
Example: +3�2L%II>J�
So it cant handle some of my Chars, I can debug it until I know what kind of Char he can´t handle with and delete them from the Array, but they are all some typical PW Chars, so my question is:
How can I let Kotlin know, how to Handle these ASCI2 chars?
Or is it because of the $?
Avoid hardcoded numbers like the "73" in your range, it's way too error prone!
If you still get funny characters, put in some println that shows each character's numeric value so that you can lookup it using "man ascii".
A more Kotlin-like code would be:
fun pwgen() {
val counterOfPwCha = 10
val charset = ('A'..'Z') + ('a'..'z') + ('0'..'9') + listOf('#', '+', '*', '$', '%', '&', '§', '<', '>', '|', '?', '!')
val pwString = (1..counterOfPwCha)
.map {
val randomArrayIndex = charset.indices.random()
charset[randomArrayIndex]
}
.onEach { c -> println("Character $c = " + c.toInt()) }
.joinToString("")
println(pwString)
}
fun main() {
var helper = Int
var counter = 0
val counterOfPwCha = 10
var pwString = ""
val opportunityArray = arrayOf('A','C','a','c','B','b','D','d','E','e','F','f','#','+','*','$','%','&','§','G','g','H','h','I','i','J','j','k','K','1','2','3','4','5','6','7','8','9',
'l','L','M','m','N','n','O','o','P','p','Q','q','R','r','S','s','T','t','U','u','V','v','W','w','Y','y','X','x','Z','z','<','>','|','?','!',)
while (counter <= counterOfPwCha)
{
helper = (0..73).random()
pwString += opportunityArray[helper]
counter++
}
println(pwString)
}

`string index out of range 0` how to resolve it?

The toCamelCase function takes in any kind of string and converts it into camelCase or Pascal case;
fun toCamelCase(str:String): String {
var ans: String = str[0].toString()
for(i in 1..str.length - 1) {
if(str[i] != '-' && str[i] != '_' ) {
ans += str[i]
}
}
return ans
}
But the code above produces the following error
String index out of range: 0
I am a novice so please help me understand.
Edit: This piece of code worked out without any error in Kotlin playground( online kotlin editor)
but is not working in codewars website
I think your code may provide that kind of error if you call your function with an empty string: e.g. toCamelCase(""). This is because you try to access index 0 regardless of the input string (in str[0].toString()).
To avoid that, you should build your ans from an empty string and append characters starting from index 0, for example changing your for(i in 1..str.length - 1) to for(i in 0..str.length - 1).
An example fix can be as follows:
fun toCamelCase(str:String): String {
var ans: String = ""
for(i in 0..str.length - 1) {
if(str[i] != '-' && str[i] != '_' ) {
ans += str[i]
}
}
return ans
}

Swift equivalent to Objective-C FourCharCode single quote literals (e.g. 'TEXT')

I am trying replicate some Objective C cocoa in Swift. All is good until I come across the following:
// Set a new type and creator:
unsigned long type = 'TEXT';
unsigned long creator = 'pdos';
How can I create Int64s (or the correct Swift equivalent) from single quote character literals like this?
Types:
public typealias AEKeyword = FourCharCode
public typealias OSType = FourCharCode
public typealias FourCharCode = UInt32
I'm using this in my Cocoa Scripting apps, it considers characters > 0x80 correctly
func OSTypeFrom(string : String) -> UInt {
var result : UInt = 0
if let data = string.dataUsingEncoding(NSMacOSRomanStringEncoding) {
let bytes = UnsafePointer<UInt8>(data.bytes)
for i in 0..<data.length {
result = result << 8 + UInt(bytes[i])
}
}
return result
}
Edit:
Alternatively
func fourCharCodeFrom(string : String) -> FourCharCode
{
assert(string.count == 4, "String length must be 4")
var result : FourCharCode = 0
for char in string.utf16 {
result = (result << 8) + FourCharCode(char)
}
return result
}
or still swiftier
func fourCharCode(from string : String) -> FourCharCode
{
return string.utf16.reduce(0, {$0 << 8 + FourCharCode($1)})
}
I found the following typealiases from the Swift API:
typealias FourCharCode = UInt32
typealias OSType = FourCharCode
And the following functions:
func NSFileTypeForHFSTypeCode(hfsFileTypeCode: OSType) -> String!
func NSHFSTypeCodeFromFileType(fileTypeString: String!) -> OSType
This should allow me to create the equivalent code:
let type : UInt32 = UInt32(NSHFSTypeCodeFromFileType("TEXT"))
let creator : UInt32 = UInt32(NSHFSTypeCodeFromFileType("pdos"))
But those 4-character strings doesn't work and return 0.
If you wrap each string in ' single quotes ' and call the same functions, you will get the correct return values:
let type : UInt32 = UInt32(NSHFSTypeCodeFromFileType("'TEXT'"))
let creator : UInt32 = UInt32(NSHFSTypeCodeFromFileType("'pdos'"))
Adopt the ExpressibleByStringLiteral protocol to use four-character string literals directly:
extension FourCharCode: ExpressibleByStringLiteral {
public init(stringLiteral value: StringLiteralType) {
if let data = value.data(using: .macOSRoman), data.count == 4 {
self = data.reduce(0, {$0 << 8 + Self($1)})
} else {
self = 0
}
}
}
Now you can just pass a string literal as the FourCharCode / OSType / UInt32 parameter:
let record = NSAppleEventDescriptor.record()
record.setDescriptor(NSAppleEventDescriptor(boolean: true), forKeyword: "test")
In Swift 4 or later, I use this code - if the string is not 4 characters in size, it will return an OSType(0):
extension String {
public func osType() -> OSType {
var result:UInt = 0
if let data = self.data(using: .macOSRoman), data.count == 4
{
data.withUnsafeBytes { (ptr:UnsafePointer<UInt8>) in
for i in 0..<data.count {
result = result << 8 + UInt(ptr[i])
}
}
}
return OSType(result)
}
}
let type = "APPL".osType() // 1095782476
// check if this is OK in a playground
let hexStr = String(format: "0x%lx", type) // 0x4150504c -> "APPL" in ASCII
Swift 5 Update:
extension String {
func osType() -> OSType {
return OSType(
data(using: .macOSRoman)?
.withUnsafeBytes {
$0.reduce(into: UInt(0)) { $0 = $0 << 8 + UInt($1) }
} ?? 0
)
}
}
Here's a simple function
func mbcc(foo: String) -> Int
{
let chars = foo.utf8
var result: Int = 0
for aChar in chars
{
result = result << 8 + Int(aChar)
}
return result
}
let a = mbcc("TEXT")
print(String(format: "0x%lx", a)) // Prints 0x54455854
It will work for strings that will fit in an Int. Once they get longer it starts losing digits from the top.
If you use
result = result * 256 + Int(aChar)
you should get a crash when the string gets too big instead.
Using NSHFSTypeCodeFromFileType does work, but only for 4-character strings wrapped with single quotes, aka 6-character strings. It returns 0 for unquoted 4-character strings.
So wrap your 4-character string in ' ' before passing it to the function:
extension FourCharCode: ExpressibleByStringLiteral {
public init(stringLiteral value: StringLiteralType) {
switch (value.count, value.first, value.last) {
case (6, "'", "'"):
self = NSHFSTypeCodeFromFileType(value)
case (4, _, _):
self = NSHFSTypeCodeFromFileType("'\(value)'")
default:
self = 0
}
}
}
Using the above extension, you can use 4-character or single-quoted 6-character string literals:
let record = NSAppleEventDescriptor.record()
record.setDescriptor(NSAppleEventDescriptor(boolean: true), forKeyword: "4444")
record.setDescriptor(NSAppleEventDescriptor(boolean: true), forKeyword: "'6666'")
It would be even better to limit the string literal to 4-character strings at compile time. That does not seem to currently be possible, but is being discussed for Swift here:
Allow for Compile-Time Checked Intervals for Parameters Expecting Literal Values