in kotlin how to get the object's size - kotlin

Is it possible to get the object's memory consumption, like in c++ with sizeOf()?
for object is Parcelable, seems this one could get the raw bytes, not sure if it is accurate for the size of that parcelable objec:
fun marshall(parceable: Parcelable): ByteArray {
val parcel = Parcel.obtain()
parceable.writeToParcel(parcel, 0)
val bytes = parcel.marshall()
parcel.recycle()
return bytes
}
Any suggestion?
Update:
Thanks #Gustavo Passini pints to a link with a lot approaches. Someone needs java.lang.instrument package and not able to use on Android, and found one but needs api level 26 above, converted into koltin and copied it here as ref (thanks Agnius Vasiliauskas ), is it accurate?:
import java.io.ByteArrayOutputStream
import java.io.ObjectOutputStream
import java.io.Serializable
#TargetApi (26)
object ObjectSizeCalculator {
private fun getFirstObjectReference(o: Any): Any? {
val objectType = o.javaClass.typeName
if (objectType.substring(objectType.length - 2) == "[]") {
try {
return if (objectType == "java.lang.Object[]")
(o as Array<Any>)[0]
else if (objectType == "int[]")
(o as IntArray)[0]
else
throw RuntimeException("Not Implemented !")
} catch (e: IndexOutOfBoundsException) {
return null
}
}
return o
}
fun getObjectSizeInBytes(o: Any?): Int {
val STRING_JAVA_TYPE_NAME = "java.lang.String"
if (o == null)
return 0
val objectType = o.javaClass.typeName
val isArray = objectType.substring(objectType.length - 2) == "[]"
val objRef = getFirstObjectReference(o)
if (objRef != null && objRef !is Serializable)
throw RuntimeException("Object must be serializable for measuring it's memory footprint using this method !")
try {
val baos = ByteArrayOutputStream()
val oos = ObjectOutputStream(baos)
oos.writeObject(o)
oos.close()
val bytes = baos.toByteArray()
var i = bytes.size - 1
var j = 0
while (i != 0) {
if (objectType !== STRING_JAVA_TYPE_NAME) {
if (bytes[i].toInt() == 112)
return if (isArray)
j - 4
else
j
} else {
if (bytes[i].toInt() == 0)
return j - 1
}
i--
j++
}
} catch (e: Exception) {
return -1
}
return -1
}
}

Related

Using abstract with Binary Search in Kotlin

I have a task in kotlin to use an abstract class, and the example was about binary search
so it shows an error message in the run.
first class is non
first class there's a non abstract class but it a parent class
second an abstract class the inherite the parent classes
third a class that display the operation
and that's my code:
open class BinarySearch() {
fun BinarySearchFunction(arr: Array<Int>, l: Int, r: Int, x: Int): Int {
if(r >= 1) {
var mid:Int=1+(r-1)/2
if (arr[mid] == x) {
return mid
}
if(arr[mid] > x){
return BinarySearchFunction(arr,l,mid-1,x)
}
return BinarySearchFunction(arr,mid+1,r,x)
}
return -1
}
open fun displayMassage(Massage:String){}
}
abstract class print(): BinarySearch() {
fun Function() {
var obj = BinarySearch()
var a = arrayOf<Int>(2, 3, 4, 10, 40)
var n = a.size
var x = 10
var result = obj.BinarySearchFunction(a, 0, n - 1, x)
if(result == -1)
println("Element not present")
else
println("Element found at index $result")
}
}
class display():print(){
override fun displayMassage(massage:String){
println(massage)
}
}
fun main() {
var dis=display()
dis.displayMassage("The Binary Search : ")
dis.Function()
}
You have an error in the implementation of the algorithm causing it to do infinite recursion.
I believe
var mid: Int = 1 + (r - 1) / 2
actually needs to be
var mid: Int = l + (r - 1) / 2

Parking lot project error: when using a scanner. NoSuchElementException

I'll appreciate all your help.
I've been working on a course project where I have to make a parking lot that registers cars. When I use it in my IDE it works fine but when I run it through the platforms tests, in the first one, there's no problem but when the second iteration reaches the "when (val command = scanner.next())" in the createOrder fun, it crashes with the error:
java.lang.AssertionError: Exception in test #1
Probably your program run out of input (Scanner tried to read more than expected).
java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1371)
at parking.ParkingLot.createOrder(Main.kt:39)
at parking.ParkingLot.start(Main.kt:31)
at parking.MainKt.main(Main.kt:6)
at parking.MainKt.main(Main.kt)
Please find below the output of your program during this failed test.
Note that the '>' character indicates the beginning of the input line.
---
> park KA-01-HH-1234 White
White car parked in spot 1.
the idea is that the test inputs many cars but it crashes when trying to do the second input
this is my code (sorry if my code is messy, I'm still learning)
import java.util.*
fun main() {
ParkingLot.start()
}
class Car(val regNumber: String = "", val color: String = "") {
}
class Order(val command: String) {
lateinit var regNum: String
lateinit var color: String
lateinit var spot: String
lateinit var status: String
}
object ParkingLot {
val spaces: Array<Pair<String?, Car?>> = Array(20) { Pair(null, null) }
const val occupied = "occupied"
const val park = "park"
const val leave = "leave"
const val exit = "exit"
fun start() {
val scanner = Scanner(System.`in`)
do {
val order = createOrder(scanner)
interaction(order, scanner)
} while (order.command != exit)
}
fun createOrder(scanner: Scanner): Order {
when (val command = scanner.next()) {
park -> {
val parkOrder = Order(command)
parkOrder.regNum = scanner.next()
parkOrder.color = scanner.next()
parkOrder.status = "valid"
return parkOrder
}
leave -> {
val retrieveOrder = Order(command)
retrieveOrder.spot = scanner.next()
retrieveOrder.status = "valid"
return retrieveOrder
}
exit -> {
val exitOrder = Order(command)
exitOrder.status = "valid"
return exitOrder
}
else -> {
val incorrectOrder = Order(command)
incorrectOrder.status = "invalid"
return incorrectOrder
}
}
}
fun interaction(order: Order, scanner: Scanner) {
if (order.command == park) {
// val toParkCar = Car(order.regNum, order.color)
park(Car(order.regNum, order.color))
}
if (order.command == leave) {
leave(order)
}
if (order.command == exit) return
//TODO update the error msg to include exit command
if (order.status == "invalid") println("\"${order.command}\" isn't a valid , either use \"park\" or \"leave\"")
// scanner.close()
}
fun park(car: Car) {
for ((index, item) in spaces.withIndex()) {
if (item.first == null) {
spaces[index] = Pair(occupied, car)
println("${car.color} car parked in spot ${index + 1}.")
return
}
}
println("Sorry, the parking lot is full.")
}
fun leave(order: Order) {
if (spaces[order.spot.toInt() - 1].first == occupied) {
spaces[order.spot.toInt() - 1] = Pair(null, null)
println("Spot ${order.spot} is free.")
} else {
println("There is no car in spot ${order.spot}.")
}
}
}
Ok so I noticed this is a problem for the JetBrains plugin. I don't know why but the solution was taking the scanner out of the function and directly in the main loop.

Convert collection of numbers to range formatted string with Kotlin

I have a very large list of numbers. I need to pass this list of numbers as a URL query parameter. Since these lists can get so large, it could potentially cause the request URL to exceed the allowed length of a URL; also, it's a bit difficult to debug a string of sequential numbers (E.G. 1,2,3,..,500,782). To remedy these issues, I would like to convert the sequential number list string to one that is formatted using a range notation (E.G. -5..-3,1..500,782). How do I create this range notation string using Kotlin and how do I parse the string back to a collection of numbers also using Kotlin?
This will convert a Collection<Int> to a string that uses the "range notation" specified:
fun Collection<Int>.toRangesString(): String {
if (this.isEmpty()) {
return ""
}
if (this.size <= 2) {
return this.toSortedSet().joinToString(",")
}
val rangeStrings = mutableListOf<String>()
var start: Int? = null
var prev: Int? = null
for (num in this.toSortedSet()) {
if (prev == null) {
start = num
prev = num
continue
}
if (num != (prev + 1)) {
_addRangeString(rangeStrings, start!!, prev)
start = num
prev = num
continue
}
prev = num
}
if (start != null) {
_addRangeString(rangeStrings, start, prev!!)
}
return rangeStrings.joinToString(",")
}
private fun _addRangeString(rangeStrings: MutableList<String>, start: Int, prev: Int) {
rangeStrings.add(
when {
(start == prev) -> start.toString()
((start + 1) == prev) -> "${start},${prev}"
else -> "${start}..${prev}"
}
)
}
...and this will parse those range notated strings into a Set<Int>:
fun parseRangesString(str: String): Set<Int> {
if (str.isBlank()) {
return setOf()
}
val ranges = str.trim().split(",")
val numbers = mutableListOf<Int>()
for (range in ranges) {
if (range.contains("..")) {
val (start, end) = range.split("..")
numbers.addAll(start.toInt()..end.toInt())
continue
}
numbers.add(range.toInt())
}
return numbers.toSet()
}
...and, finally, even better than using a huge collection of numbers, you can use Kotlin's IntRange (or LongRange) class:
fun toIntRanges(str: String): Collection<IntRange> = _toRanges(str, ::_createIntRange)
fun toLongRanges(str: String): Collection<LongRange> = _toRanges(str, ::_createLongRange)
private fun <T : ClosedRange<*>> _toRanges(str: String, createRange: (start: String, end: String) -> T): Collection<T> {
if (str.isBlank()) {
return listOf()
}
val rangeStrs = str.trim().split(",")
val ranges = mutableListOf<T>()
for (rangeStr in rangeStrs) {
if (rangeStr.contains("..")) {
val (start, end) = rangeStr.split("..")
ranges.add(createRange(start, end))
continue
}
ranges.add(createRange(rangeStr, rangeStr))
}
return ranges.toList()
}
private fun _createIntRange(start: String, end: String) = IntRange(start.toInt(), end.toInt())
private fun _createLongRange(start: String, end: String) = LongRange(start.toLong(), end.toLong())

Error 10001st prime number in Kotlin

My code:
import java.util.*
fun checkPrime(n : Int): Boolean{
val z = n/2
var stop = false
if(n == 0 || n == 1){
stop = true
return false
}
for(i in 2..z){
if(n % i == 0){
stop = true
return false
break
}
}
return !stop
}
fun main(args : Array<String>){
var primes = ArrayList<Int>()
//The "500000" can be replaced with any number so you get at least 100001 primes
for(i in 2..500000){
if(checkPrime(i)){
primes.add(i)
}
}
println("Finished")
println("Size of Array: ${primes.size}")
println("10001st Prime: ${primes.get(index = 10001)}")
}
I'm new to Kotlin so this probably looks horrible to you. When I run it, I get 104759, which is wrong. Where is the error here? Is my prime checking function incorrect? Thanks.
Alternatively, you could use Java's built in Prime Number checker and Kotlin's infinite sequences generated by buildSequence.
Ensure that you use take() to select how many elements you want to extract.
import java.math.BigInteger
import kotlin.coroutines.experimental.buildSequence
fun primes() = buildSequence {
var n = 1
while (true){
if (BigInteger("$n").isProbablePrime(1)){
yield(n)
}
n++
}
}
fun main(args: Array<String>) {
println(primes().take(10001).last())
}
Prime numbers are of the form 6f ± 1, excluding 2 and 3 where f is any integer
fun isPrime(number: Int) : Boolean
{
if (number <= 1)
{
return false;
}
// The check for the number 2 and 3
if (number <= 3)
{
return true;
}
if (number%2 == 0 || number%3 == 0)
{
return false;
}
for (i in 5..number/2 step 6)
{
if (number%i == 0 || number%(i+2) == 0)
{
return false;
}
}
return true;
}
Time Complexity of the solution: O(sqrt(n))

Mutate string from an extension

I was trying to port a Swift script to Kotlin but it's not working as expected, what the code does is to consume a string while the condition is true (need it for a parser). In Swift it works as expected but in Kotlin it doesn't (I just started with Kotlin a month ago so maybe I'm missing something).
Swift
extension String {
#discardableResult public mutating func consumeWhile(test: (String) -> Bool) -> String {
var chars = [Character](self.characters)
var result = ""
while chars.count > 0 && test(String(chars[0])) {
result.append(chars.remove(at: 0))
}
self = String(chars)
return result
}
}
Kotlin
fun String.consumeWhile(test: (String) -> Boolean): String {
if (isEmpty()) return ""
val chars = toCharArray().toMutableList()
var result = ""
var i = -1
while (chars.isNotEmpty() && test(chars.first().toString())) {
result += chars.removeAt(0)
++i
}
removeRange(0..i)
return result
}
So the basic usage will look like
val myString = "--Test" // IntelliJ suggests change var to val
val consumedString = myString.consumeWhile{ it != "-" }
println("result: $myString consumedString: $consumedString")
// expected: "result: Test consumedString: --"
// but got: "result: --Test consumedString: --"
Edit: Thanks for all the answers, don't know if will be possible to do like I want because as mentioned string are immutable in Kotlin/Java (just using the same string).
I forgot to mention that I need the consumed string, basically b/c I'm doing a parser so I need to store the consumed chars and the mutated string. I will leave open this question but I ended up creating a class that implements only a few String class methods.
class Line(var string: String) {
val length: Int
get() = string.length
fun consumeWhile(test: (String) -> Boolean): String {
if (string.isEmpty()) return ""
val chars = string.toCharArray().toMutableList()
var result = ""
while (chars.isNotEmpty() && test(chars.first().toString())) {
result += chars.removeAt(0)
}
string = chars.joinToString("")
return result
}
fun isNullOrEmpty(): Boolean {
return string.isNullOrEmpty()
}
fun isNotEmpty(): Boolean {
return string.isNotEmpty()
}
private fun removeRange(range: IntRange) {
string = string.removeRange(range)
}
operator fun get(i: Int): Char {
return string[i]
}
}
Usage example
val line = Line(string)
if (line.isNotEmpty() && line[0].toString() == "(") {
line.consumeWhile { it == "(" }
while (line.isNotEmpty() && line[0].toString() != ")") {
line.consumeWhile { it == " " }
val key = line.consumeWhile { it != "=" }
line.consumeWhile { it == "\"" || it == "=" }
val value = line.consumeWhile { it != "\"" }
line.consumeWhile { it == "\"" }
attributes[key] = value
}
line.consumeWhile { it == ")" }
}
String is immutable in Kotlin & Java, so you can't modify its state anyway.
You should avoiding to makes the wheels repeatedly, there is an existing function String#dropWhile(Char) in Kotlin. one thing you need to do is invert the condition, for example:
val result = "--Test".dropWhile { it == '-' }
// ^--- "Test"
In both Java and Kotlin String is immutable and you cannot change it after it has been created.
In swift this presumably can be turned off through the mutating modifier. However in Kotlin removeRange(0..i) creates a new String object which you then discard.
To have it behave as you want you will need to either:
Create a wrapper object that contains a string that can be replaced.
Return both the split string and the rest as a Pair, you can then use the destructuring operators to assign it as [_, myString] = myString.consumeWhile {}
Kotlin Strings are immutable and cannot be modified in place. Instead you can create a new String and return it
fun String.consumeWhile(test: (String) -> Boolean): String {
if (isEmpty()) return ""
val chars = toCharArray().toMutableList()
while (chars.isNotEmpty() && test(chars.first().toString())) {
chars.removeAt(0)
// Do something with the char
}
return chars.joinToString(separator = "")
}
Additionally, unless I am misunderstanding, your test condition should be it == "-" to get the result you want:
val myString = "--Test"
val newString = myString.consumeWhile{ it == "-" }
println("result: $newString")
You use
myString.consumeWhile{ it != "-" }
which stops consuming as soon as it meets the first "-", and thus it's nothing more to do.
The code works as it should, if you use
myString.consumeWhile{ it == "-" }
you will get the expected output as is correct.
I ended up creating a class that implements only a few String class methods.
class Line(var string: String) {
val length: Int
get() = string.length
fun consumeWhile(test: (String) -> Boolean): String {
if (string.isEmpty()) return ""
val chars = string.toCharArray().toMutableList()
var result = ""
while (chars.isNotEmpty() && test(chars.first().toString())) {
result += chars.removeAt(0)
}
string = chars.joinToString("")
return result
}
fun isNullOrEmpty(): Boolean {
return string.isNullOrEmpty()
}
fun isNotEmpty(): Boolean {
return string.isNotEmpty()
}
private fun removeRange(range: IntRange) {
string = string.removeRange(range)
}
operator fun get(i: Int): Char {
return string[i]
}
}
Usage example
val line = Line(string)
if (line.isNotEmpty() && line[0].toString() == "(") {
line.consumeWhile { it == "(" }
while (line.isNotEmpty() && line[0].toString() != ")") {
line.consumeWhile { it == " " }
val key = line.consumeWhile { it != "=" }
line.consumeWhile { it == "\"" || it == "=" }
val value = line.consumeWhile { it != "\"" }
line.consumeWhile { it == "\"" }
attributes[key] = value
}
line.consumeWhile { it == ")" }
}
Obs: for now will mark as answered, till a better solution comes out