Problems with mutable sets in Kotlin - for-loop

I've recently started learning to program in Kotlin. As I tried to add a sequence of numbers to a mutable set using the for loop, the corresponding ASCII value was being added instead.
fun main(args: Array<String>) {
var userInput = readLine() //The input was 12345
var set = mutableSetOf<Int>()
for(n in userInput.orEmpty()){
var numN = n.toInt()
set.add(numN)
}
println(set)
}
// The output is [49, 50, 51, 52, 53], whereas I expected [1, 2, 3, 4, 5]
At first I speculated the problem to be with the .toInt() function, so I tried this:
fun main(args: Array<String>) {
var x = "2"
println(x.toInt())
}
//The output is 2
But the output came as expected, the number itself, not the corresponding ASCII version.
Now how am I supposed to fix this, so that I get my expected result in the first code?
I'm yet a novice in this programming language, so there could be any hilarious mistakes in my code as well.
Thanks in advance!

This happens because n is a Char and the method Char.toInt() returns its ASCII value.
To avoid that, you should convert the Char into a String and then use String.toInt() (like you have done in the sample with the value "2").
fun main(args: Array<String>) {
var userInput = readLine() //The input was 12345
var set = mutableSetOf<Int>()
for(n in userInput.orEmpty()){
var numN = n.toString().toInt()
set.add(numN)
}
println(set)
}
By the way, you obtain the same result with way less code:
fun main(args: Array<String>) {
var userInput = readLine() //The input was 12345
// 1. Converts the string to an array of char
// 2. Transforms each char into its number value
// 3. Converts the result list in a set
val set = userInput.orEmpty().toCharArray().map(Character::getNumericValue).toSet()
println(set)
}

Related

How can I get a random number in Kotlin?

A generic method that can return a random integer between 2 parameters like ruby does with rand(0..n).
Any suggestion?
My suggestion would be an extension function on IntRange to create randoms like this: (0..10).random()
TL;DR Kotlin >= 1.3, one Random for all platforms
As of 1.3, Kotlin comes with its own multi-platform Random generator. It is described in this KEEP. The extension described below is now part of the Kotlin standard library, simply use it like this:
val rnds = (0..10).random() // generated random from 0 to 10 included
Kotlin < 1.3
Before 1.3, on the JVM we use Random or even ThreadLocalRandom if we're on JDK > 1.6.
fun IntRange.random() =
Random().nextInt((endInclusive + 1) - start) + start
Used like this:
// will return an `Int` between 0 and 10 (incl.)
(0..10).random()
If you wanted the function only to return 1, 2, ..., 9 (10 not included), use a range constructed with until:
(0 until 10).random()
If you're working with JDK > 1.6, use ThreadLocalRandom.current() instead of Random().
KotlinJs and other variations
For kotlinjs and other use cases which don't allow the usage of java.util.Random, see this alternative.
Also, see this answer for variations of my suggestion. It also includes an extension function for random Chars.
Generate a random integer between from(inclusive) and to(exclusive)
import java.util.Random
val random = Random()
fun rand(from: Int, to: Int) : Int {
return random.nextInt(to - from) + from
}
As of kotlin 1.2, you could write:
(1..3).shuffled().last()
Just be aware it's big O(n), but for a small list (especially of unique values) it's alright :D
In Kotlin SDK >=1.3 you can do it like
import kotlin.random.Random
val number = Random.nextInt(limit)
You can create an extension function similar to java.util.Random.nextInt(int) but one that takes an IntRange instead of an Int for its bound:
fun Random.nextInt(range: IntRange): Int {
return range.start + nextInt(range.last - range.start)
}
You can now use this with any Random instance:
val random = Random()
println(random.nextInt(5..9)) // prints 5, 6, 7, 8, or 9
If you don't want to have to manage your own Random instance then you can define a convenience method using, for example, ThreadLocalRandom.current():
fun rand(range: IntRange): Int {
return ThreadLocalRandom.current().nextInt(range)
}
Now you can get a random integer as you would in Ruby without having to first declare a Random instance yourself:
rand(5..9) // returns 5, 6, 7, 8, or 9
Possible Variation to my other answer for random chars
In order to get random Chars, you can define an extension function like this
fun ClosedRange<Char>.random(): Char =
(Random().nextInt(endInclusive.toInt() + 1 - start.toInt()) + start.toInt()).toChar()
// will return a `Char` between A and Z (incl.)
('A'..'Z').random()
If you're working with JDK > 1.6, use ThreadLocalRandom.current() instead of Random().
For kotlinjs and other use cases which don't allow the usage of java.util.Random, this answer will help.
Kotlin >= 1.3 multiplatform support for Random
As of 1.3, Kotlin comes with its own multiplatform Random generator. It is described in this KEEP. You can now directly use the extension as part of the Kotlin standard library without defining it:
('a'..'b').random()
Building off of #s1m0nw1 excellent answer I made the following changes.
(0..n) implies inclusive in Kotlin
(0 until n) implies exclusive in Kotlin
Use a singleton object for the Random instance (optional)
Code:
private object RandomRangeSingleton : Random()
fun ClosedRange<Int>.random() = RandomRangeSingleton.nextInt((endInclusive + 1) - start) + start
Test Case:
fun testRandom() {
Assert.assertTrue(
(0..1000).all {
(0..5).contains((0..5).random())
}
)
Assert.assertTrue(
(0..1000).all {
(0..4).contains((0 until 5).random())
}
)
Assert.assertFalse(
(0..1000).all {
(0..4).contains((0..5).random())
}
)
}
Examples random in the range [1, 10]
val random1 = (0..10).shuffled().last()
or utilizing Java Random
val random2 = Random().nextInt(10) + 1
No need to use custom extension functions anymore. IntRange has a random() extension function out-of-the-box now.
val randomNumber = (0..10).random()
Kotlin >= 1.3, multiplatform support for Random
As of 1.3, the standard library provided multi-platform support for randoms, see this answer.
Kotlin < 1.3 on JavaScript
If you are working with Kotlin JavaScript and don't have access to java.util.Random, the following will work:
fun IntRange.random() = (Math.random() * ((endInclusive + 1) - start) + start).toInt()
Used like this:
// will return an `Int` between 0 and 10 (incl.)
(0..10).random()
Another way of implementing s1m0nw1's answer would be to access it through a variable. Not that its any more efficient but it saves you from having to type ().
val ClosedRange<Int>.random: Int
get() = Random().nextInt((endInclusive + 1) - start) + start
And now it can be accessed as such
(1..10).random
If the numbers you want to choose from are not consecutive, you can use random().
Usage:
val list = listOf(3, 1, 4, 5)
val number = list.random()
Returns one of the numbers which are in the list.
Using a top-level function, you can achieve exactly the same call syntax as in Ruby (as you wish):
fun rand(s: Int, e: Int) = Random.nextInt(s, e + 1)
Usage:
rand(1, 3) // returns either 1, 2 or 3
There is no standard method that does this but you can easily create your own using either Math.random() or the class java.util.Random. Here is an example using the Math.random() method:
fun random(n: Int) = (Math.random() * n).toInt()
fun random(from: Int, to: Int) = (Math.random() * (to - from) + from).toInt()
fun random(pair: Pair<Int, Int>) = random(pair.first, pair.second)
fun main(args: Array<String>) {
val n = 10
val rand1 = random(n)
val rand2 = random(5, n)
val rand3 = random(5 to n)
println(List(10) { random(n) })
println(List(10) { random(5 to n) })
}
This is a sample output:
[9, 8, 1, 7, 5, 6, 9, 8, 1, 9]
[5, 8, 9, 7, 6, 6, 8, 6, 7, 9]
Kotlin standard lib doesn't provide Random Number Generator API. If you aren't in a multiplatform project, it's better to use the platform api (all the others answers of the question talk about this solution).
But if you are in a multiplatform context, the best solution is to implement random by yourself in pure kotlin for share the same random number generator between platforms. It's more simple for dev and testing.
To answer to this problem in my personal project, i implement a pure Kotlin Linear Congruential Generator. LCG is the algorithm used by java.util.Random. Follow this link if you want to use it :
https://gist.github.com/11e5ddb567786af0ed1ae4d7f57441d4
My implementation purpose nextInt(range: IntRange) for you ;).
Take care about my purpose, LCG is good for most of the use cases (simulation, games, etc...) but is not suitable for cryptographically usage because of the predictability of this method.
First, you need a RNG. In Kotlin you currently need to use the platform specific ones (there isn't a Kotlin built in one). For the JVM it's java.util.Random. You'll need to create an instance of it and then call random.nextInt(n).
To get a random Int number in Kotlin use the following method:
import java.util.concurrent.ThreadLocalRandom
fun randomInt(rangeFirstNum:Int, rangeLastNum:Int) {
val randomInteger = ThreadLocalRandom.current().nextInt(rangeFirstNum,rangeLastNum)
println(randomInteger)
}
fun main() {
randomInt(1,10)
}
// Result – random Int numbers from 1 to 9
Hope this helps.
Below in Kotlin worked well for me:
(fromNumber.rangeTo(toNumber)).random()
Range of the numbers starts with variable fromNumber and ends with variable toNumber. fromNumber and toNumber will also be included in the random numbers generated out of this.
You could create an extension function:
infix fun ClosedRange<Float>.step(step: Float): Iterable<Float> {
require(start.isFinite())
require(endInclusive.isFinite())
require(step.round() > 0.0) { "Step must be positive, was: $step." }
require(start != endInclusive) { "Start and endInclusive must not be the same"}
if (endInclusive > start) {
return generateSequence(start) { previous ->
if (previous == Float.POSITIVE_INFINITY) return#generateSequence null
val next = previous + step.round()
if (next > endInclusive) null else next.round()
}.asIterable()
}
return generateSequence(start) { previous ->
if (previous == Float.NEGATIVE_INFINITY) return#generateSequence null
val next = previous - step.round()
if (next < endInclusive) null else next.round()
}.asIterable()
}
Round Float value:
fun Float.round(decimals: Int = DIGITS): Float {
var multiplier = 1.0f
repeat(decimals) { multiplier *= 10 }
return round(this * multiplier) / multiplier
}
Method's usage:
(0.0f .. 1.0f).step(.1f).forEach { System.out.println("value: $it") }
Output:
value: 0.0 value: 0.1 value: 0.2 value: 0.3 value: 0.4 value: 0.5
value: 0.6 value: 0.7 value: 0.8 value: 0.9 value: 1.0
Full source code. Can control whether duplicates are allowed.
import kotlin.math.min
abstract class Random {
companion object {
fun string(length: Int, isUnique: Boolean = false): String {
if (0 == length) return ""
val alphabet: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9') // Add your set here.
if (isUnique) {
val limit = min(length, alphabet.count())
val set = mutableSetOf<Char>()
do { set.add(alphabet.random()) } while (set.count() != limit)
return set.joinToString("")
}
return List(length) { alphabet.random() }.joinToString("")
}
fun alphabet(length: Int, isUnique: Boolean = false): String {
if (0 == length) return ""
val alphabet = ('A'..'Z')
if (isUnique) {
val limit = min(length, alphabet.count())
val set = mutableSetOf<Char>()
do { set.add(alphabet.random()) } while (set.count() != limit)
return set.joinToString("")
}
return List(length) { alphabet.random() }.joinToString("")
}
}
}
Whenever there is a situation where you want to generate key or mac address which is hexadecimal number having digits based on user demand, and that too using android and kotlin, then you my below code helps you:
private fun getRandomHexString(random: SecureRandom, numOfCharsToBePresentInTheHexString: Int): String {
val sb = StringBuilder()
while (sb.length < numOfCharsToBePresentInTheHexString) {
val randomNumber = random.nextInt()
val number = String.format("%08X", randomNumber)
sb.append(number)
}
return sb.toString()
}
Here is a straightforward solution in Kotlin, which also works on KMM:
fun IntRange.rand(): Int =
Random(Clock.System.now().toEpochMilliseconds()).nextInt(first, last)
Seed is needed for the different random number on each run. You can also do the same for the LongRange.
Gets the next random Int from the random number generator.
Random.nextInt()
to be super duper ))
fun rnd_int(min: Int, max: Int): Int {
var max = max
max -= min
return (Math.random() * ++max).toInt() + min
}

Efficient Sequence conversion to String

I have a string sequence Seq[String] which represents stdin input lines.
Those lines map to a model entity, but it is not guaranteed that 1 line = 1 entity instance.
Each entity is delimited with a special string that will not occur anywhere else in the input.
My solution was something like:
val entities = lines.mkString.split(myDelimiter).map(parseEntity)
parseEntity implementation is not relevant, it gets a String and maps to a case class which represents the model entity
The problem is with a given input, I get an OutOfMemoryException on the lines.mkString. Would a fold/foldLeft/foldRight be more efficient? Or do you have any better alternative?
You can solve this using akka streams and delimiter framing. See this section of the documentation for the basic approach.
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Framing, Source}
import akka.util.ByteString
val example = (0 until 100).mkString("delimiter").grouped(8).toIndexedSeq
val framing = Framing.delimiter(ByteString("delimiter"), 1000)
implicit val system = ActorSystem()
implicit val mat = ActorMaterializer()
Source(example)
.map(ByteString.apply)
.via(framing)
.map(_.utf8String)
.runForeach(println)
The conversion to and from ByteString is a bit annoying, but Framing.delimiter is only defined for ByteString.
If you are fine with a more pure functional approach, fs2 will also offer primitives to solve this problem.
Something that worked for me if you are reading from a stream (your mileage may vary). Slightly modified version of Scala LineIterator:
class EntityIterator(val iter: BufferedIterator[Char]) extends AbstractIterator[String] with Iterator[String] {
private[this] val sb = new StringBuilder
def getc() = iter.hasNext && {
val ch = iter.next
if (ch == '\n') false // Replace with your delimiter here
else {
sb append ch
true
}
}
def hasNext = iter.hasNext
def next = {
sb.clear
while (getc()) { }
sb.toString
}
}
val entities =
new EnityIterator(scala.io.Source.fromInputStream(...).iter.buffered)
entities.map(...)

xcode: need to convert strings to double and back to string

this is my line of code.
budgetLabel.text = String((budgetLabel.text)!.toInt()! - (budgetItemTextBox.text)!.toInt()!)
the code works, but when I try to input a floating value into the textbox the program crashes. I am assuming the strings need to be converted to a float/double data type. I keep getting errors when i try to do that.
In Swift 2 there are new failable initializers that allow you to do this in more safe way, the Double("") returns an optional in cases like passing in "abc" string the failable initializer will return nil, so then you can use optional-binding to handle it like in the following way:
let s1 = "4.55"
let s2 = "3.15"
if let n1 = Double(s1), let n2 = Double(s2) {
let newString = String( n1 - n2)
print(newString)
}
else {
print("Some string is not a double value")
}
If you're using a version of Swift < 2, then old way was:
var n1 = ("9.99" as NSString).doubleValue // invalid returns 0, not an optional. (not recommended)
// invalid returns an optional value (recommended)
var pi = NSNumberFormatter().numberFromString("3.14")?.doubleValue
Fixed: Added Proper Handling for Optionals
let budgetLabel:UILabel = UILabel()
let budgetItemTextBox:UITextField = UITextField()
budgetLabel.text = ({
var value = ""
if let budgetString = budgetLabel.text, let budgetItemString = budgetItemTextBox.text
{
if let budgetValue = Float(budgetString), let budgetItemValue = Float(budgetItemString)
{
value = String(budgetValue - budgetItemValue)
}
}
return value
})()
You need to be using if let. In swift 2.0 it would look something like this:
if let
budgetString:String = budgetLabel.text,
budgetItemString:String = budgetItemTextBox.text,
budget:Double = Double(budgetString),
budgetItem:Double = Double(budgetItemString) {
budgetLabel.text = String(budget - budgetItem)
} else {
// If a number was not found, what should it do here?
}

How can I concatenate strings only if they have passed a logical statement in Swift?

My challenge is twofold:
To pick individual strings from an array of similar strings, but only if a boolean test has been passed first.
"Finally" I need to concatenate any/all of the strings generated into one complete text and the entire code must be in Swift.
Illustration: A back of the envelope code for illustration of logic:
generatedText.text =
case Int1 <= 50 && Int2 == 50
return generatedParagraph1 = pick one string at RANDOM from a an array1 of strings
case Int3 =< 100
return generatedParagraph2 = pick one string at RANDOM from a an array2 of strings
case Int4 == 100
return generatedParagraph3 = pick one string at RANDOM from a an array3 of strings
...etc
default
return "Nothing to report"
and concatenate the individual generatedParagraphs
Attempt: Code picks a random element within stringArray1, 2 and 3.
Example of what the code returns:
---> "Sentence1_c.Sentence2_a.Sentence3_b."
PROBLEM: I need the code to ONLY pick an element if it has first passed a boolean. It means that the final concatenated string (concastString) could be empty, just contain one element, or several depending on how many of the bools were True. Does anyone know how to do this?
import Foundation
var stringArray1 = ["","Sentence1_a.", "Sentence1_b.", "Sentence1_c."]
var stringArray2 = ["","Sentence2_a.", "Sentence2_b.", "Sentence2_c."]
var stringArray3 = ["","Sentence3_a.", "Sentence3_b.", "Sentence3_c."]
let count1 = UInt32(stringArray1.count)-1
let count2 = UInt32(stringArray2.count)-1
let count3 = UInt32(stringArray3.count)-1
var randomNumberOne = Int(arc4random_uniform(count1))+1
var randomNumberTwo = Int(arc4random_uniform(count2))+1
var randomNumberThree = Int(arc4random_uniform(count3))+1
let concatString = stringArray1[randomNumberOne] + stringArray2[randomNumberTwo] + stringArray3[randomNumberThree]
Okay, I didn't pass a Bool, but I show concatenating three random strings from a [String]. I ran this in a playground.
import Foundation
var stringArray = [String]()
for var i = 0; i < 100; i++ {
stringArray.append("text" + "\(i)")
}
func concat (array: [String]) -> String {
let count = UInt32(stringArray.count)
let randomNumberOne = Int(arc4random_uniform(count))
let randomNumberTwo = Int(arc4random_uniform(count))
let randomNumberThree = Int(arc4random_uniform(count))
let concatString = array[randomNumberOne] + array[randomNumberTwo] + array[randomNumberThree]
return concatString
}
let finalString = concat(stringArray)

Accessing position information in a scala combinatorparser kills performance

I wrote a new combinator for my parser in scala.
Its a variation of the ^^ combinator, which passes position information on.
But accessing the position information of the input element really cost performance.
In my case parsing a big example need around 3 seconds without position information, with it needs over 30 seconds.
I wrote a runnable example where the runtime is about 50% more when accessing the position.
Why is that? How can I get a better runtime?
Example:
import scala.util.parsing.combinator.RegexParsers
import scala.util.parsing.combinator.Parsers
import scala.util.matching.Regex
import scala.language.implicitConversions
object FooParser extends RegexParsers with Parsers {
var withPosInfo = false
def b: Parser[String] = regexB("""[a-z]+""".r) ^^# { case (b, x) => b + " ::" + x.toString }
def regexB(p: Regex): BParser[String] = new BParser(regex(p))
class BParser[T](p: Parser[T]) {
def ^^#[U](f: ((Int, Int), T) => U): Parser[U] = Parser { in =>
val source = in.source
val offset = in.offset
val start = handleWhiteSpace(source, offset)
val inwo = in.drop(start - offset)
p(inwo) match {
case Success(t, in1) =>
{
var a = 3
var b = 4
if(withPosInfo)
{ // takes a lot of time
a = inwo.pos.line
b = inwo.pos.column
}
Success(f((a, b), t), in1)
}
case ns: NoSuccess => ns
}
}
}
def main(args: Array[String]) = {
val r = "foo"*50000000
var now = System.nanoTime
parseAll(b, r)
var us = (System.nanoTime - now) / 1000
println("without: %d us".format(us))
withPosInfo = true
now = System.nanoTime
parseAll(b, r)
us = (System.nanoTime - now) / 1000
println("with : %d us".format(us))
}
}
Output:
without: 2952496 us
with : 4591070 us
Unfortunately, I don't think you can use the same approach. The problem is that line numbers end up implemented by scala.util.parsing.input.OffsetPosition which builds a list of every line break every time it is created. So if it ends up with string input it will parse the entire thing on every call to pos (twice in your example). See the code for CharSequenceReader and OffsetPosition for more details.
There is one quick thing you can do to speed this up:
val ip = inwo.pos
a = ip.line
b = ip.column
to at least avoid creating pos twice. But that still leaves you with a lot of redundant work. I'm afraid to really solve the problem you'll have to build the index as in OffsetPosition yourself, just once, and then keep referring to it.
You could also file a bug report / make an enhancement request. This is not a very good way to implement the feature.

Resources