How to index 2-dimensional values like x,y position in map - kotlin

I'm developing a map in Kotlin.
When I zoom in, I need to know what place in my screen (ex: Places in 123.45<x<124.57, 63.2<y<64.5)
When I used MySql, it calculated very fast.
But I have to develop data structure myself.
For this I used 2 TreeMap each index x, y and intersect them. But it has awful performance.
What Can I do to index 2-dimensional index. And get values between each value.
Add ===========================================================
// method 1: without treemap
for (point in points){
if(point.x in startX..finishX && point.y in startY..finishY){
satisfiedPoints.add(point)
}
}
// method 2: with treemap
val satisfiedXPoints = xIndex.subMap(startX, true, finishX, true).values
for(point in satisfiedXPoints){
if(point.y in startY..finishY){
satisfiedPoints.add(point)
}
}
I used TreeMap like this. But method 2 takes more time than 1. Is there something wrong with iterate map?

Related

What is the most efficient way to join one list to another in kotlin?

I start with a list of integers from 1 to 1000 in listOfRandoms.
I would like to left join on random from the createDatabase list.
I am currently using a find{} statement within a loop to do this but feel like this is too heavy. Is there not a better (quicker) way to achieve same result?
Psuedo Code
data class DatabaseRow(
val refKey: Int,
val random: Int
)
fun main() {
val createDatabase = (1..1000).map { i -> DatabaseRow(i, Random()) }
val listOfRandoms = (1..1000).map { j ->
val lookup = createDatabase.find { it.refKey == j }
lookup.random
}
}
As mentioned in comments, the question seems to be mixing up database and programming ideas, which isn't helping.
And it's not entirely clear which parts of the code are needed, and which can be replaced. I'm assuming that you already have the createDatabase list, but that listOfRandoms is open to improvement.
The ‘pseudo’ code compiles fine except that:
You don't give an import for Random(), but none of the likely ones return an Int. I'm going to assume that should be kotlin.random.Random.nextInt().
And because lookup is nullable, you can't simply call lookup.random; a quick fix is lookup!!.random, but it would be safer to handle the null case properly with e.g. lookup?.random ?: -1. (That's irrelevant, though, given the assumption above.)
I think the general solution is to create a Map. This can be done very easily from createDatabase, by calling associate():
val map = createDatabase.associate{ it.refKey to it.random }
That should take time roughly proportional to the size of the list. Looking up values in the map is then very efficient (approx. constant time):
map[someKey]
In this case, that takes rather more memory than needed, because both keys and values are integers and will be boxed (stored as separate objects on the heap). Also, most maps use a hash table, which takes some memory.
Since the key is (according to comments) “an ascending list starting from a random number, like 18123..19123”, in this particular case it can instead be stored in an IntArray without any boxing. As you say, array indexes start from 0, so using the key directly would need a huge array and use only the last few cells — but if you know the start key, you could simply subtract that from the array index each time.
Creating such an array would be a bit more complex, for example:
val minKey = createDatabase.minOf{ it.refKey }
val maxKey = createDatabase.maxOf{ it.refKey }
val array = IntArray(maxKey - minKey + 1)
for (row in createDatabase)
array[row.refKey - minKey] = row.random
You'd then access values with:
array[someKey - minKey]
…which is also constant-time.
Some caveats with this approach:
If createDatabase is empty, then minOf() will throw a NoSuchElementException.
If it has ‘holes’, omitting some keys inside that range, then the array will hold its default value of 0 — you can change that by using the alternative IntArray constructor which also takes a lambda giving the initial value.)
Trying to look up a value outside that range will give an ArrayIndexOutOfBoundsException.
Whether it's worth the extra complexity to save a bit of memory will depend on things like the size of the ‘database’, and how long it's in memory for; I wouldn't add that complexity unless you have good reason to think memory usage will be an issue.

Efficient way of Square of a Sorted Array

I am solving leetcode solution. The question is
Given an integer array nums sorted in non-decreasing order, return an array of the squares of each number sorted in non-decreasing order.
Example 1:
Input: nums = [-4,-1,0,3,10]
Output: [0,1,9,16,100]
Explanation: After squaring, the array becomes [16,1,0,9,100].
After sorting, it becomes [0,1,9,16,100].
Example 2:
Input: nums = [-7,-3,2,3,11]
Output: [4,9,9,49,121]
I solved this through map and then use sorted() for sorting purpose and lastly converted in toIntArray().
My solution
class Solution {
fun sortedSquares(nums: IntArray): IntArray {
return nums.map { it * it }.sorted().toIntArray()
}
}
After all I am taking a look in the discuss success, I found this solution
class Solution {
fun sortedSquares(A: IntArray): IntArray {
// Create markers to use to navigate inward since we know that
// the polar ends are (possibly, but not always) the largest
var leftMarker = 0
var rightMarker = A.size - 1
// Create a marker to track insertions into the new array
var resultIndex = A.size - 1
val result = IntArray(A.size)
// Iterate over the items until the markers reach each other.
// Its likely a little faster to consider the case where the left
// marker is no longer producing elements that are less than zero.
while (leftMarker <= rightMarker) {
// Grab the absolute values of the elements at the respective
// markers so they can be compared and inserted into the right
// index.
val left = Math.abs(A[leftMarker])
val right = Math.abs(A[rightMarker])
// Do checks to decide which item to insert next.
result[resultIndex] = if (right > left) {
rightMarker--
right * right
} else {
leftMarker++
left * left
}
// Once the item is inserted we can update the index we want
// to insert at next.
resultIndex--
}
return result
}
}
The guy also mention in the title Kotlin -- O(n), 95% time, 100% space
So my solution is equal in time and space complexity with other solution with efficient time and space? Or Is there any better solution?
So my solution is equal in time and space complexity with other solution with efficient time and space?
No, your solution runs in O(n log n) time, as it relies on sorted(), which likely runs in O(n log n). Since the alternative solution does not sort the items, it indeed runs on O(n) time. Both solutions use O(n) space, although your solution uses three times as much space (each of map, sorted and toIntArray create a copy of the input).

why are objects clipping behind each other?

I'm making a script that sorts the depth for my objects by prioritizing the y variable, but then afterwards checks to see if the objects that are touching each other have a higher depth the further to the right they are, but for some reason the last part isn't working.
Here's the code:
ds_grid_sort(_dg,1,true);
_yy = 0;
repeat _inst_num
{
_inst = _dg[# 0, _yy];
with _inst
{
with other
{
if (x > _inst.x and y = _inst.y)
{
_inst.depth = depth + building_space;
}
}
}
_yy++;
}
I've identified that the problem is that nothing comes out as true when the game checks the y = _inst.y part of the _inst statement, but that doesn't make any sense seeing how they're all at the same y coordinate. Could someone please tell me what I'm doing wrong?
As Steven mentioned, it's good practice to use double equal signs for comparisons (y == _inst.y) and a single equals sign for assignments (_yy = 0;), but GML doesn't care if you use a single equals sign for comparison, so it won't be causing your issue. Though it does matter in pretty much every other language besides GML.
From what I understand, the issue seems to be your use of other. When you use the code with other, it doesn't iterate through all other objects, it only grabs one instance. You can test this by running this code and seeing how many debug messages it shows:
...
with other
{
show_debug_message("X: "+string(x)+"; Y: "+string(y));
...
You could use with all. That will iterate through all objects or with object, where object is either an object or parent object. That will iterate through all instances of that object. However, neither of these functions check whether the objects overlap (it's just going to iterate over all of them), so you'll have to check for collisions. You could do something like this:
...
with all
{
if place_meeting(x, y, other)
{
if (x > _inst.x and y = _inst.y)
{
_inst.depth = depth + building_space;
}
}
...
I don't know what the rest of your code looks like, but there might be an easier way to achieve your goal. Is it possible to initially set the depth based on both the x and y variables? Something such as depth = -x-y;? For people not as familiar with GameMaker, objects with a smaller depth value are drawn above objects with higher depth values; that is why I propose setting the depth to be -x-y. Below is what a view of that grid would look like (first row and column are x and y variables; the other numbers would be the depth of an object at that position):
Having one equation that everything operates on will also make it so that if you have anything moving (such as a player), you can easily and efficiently update their depth to be able to display them correctly relative to all the other objects.
I think it should be y == _inst.y.
But I'm not sure as GML tends to accept such formatting.
It's a better practise to use == to check if they're equal when using conditions.

Kotlin: Why is Sequence more performant in this example?

Currently, I am looking into Kotlin and have a question about Sequences vs. Collections.
I read a blog post about this topic and there you can find this code snippets:
List implementation:
val list = generateSequence(1) { it + 1 }
.take(50_000_000)
.toList()
measure {
list
.filter { it % 3 == 0 }
.average()
}
// 8644 ms
Sequence implementation:
val sequence = generateSequence(1) { it + 1 }
.take(50_000_000)
measure {
sequence
.filter { it % 3 == 0 }
.average()
}
// 822 ms
The point here is that the Sequence implementation is about 10x faster.
However, I do not really understand WHY that is. I know that with a Sequence, you do "lazy evaluation", but I cannot find any reason why that helps reducing the processing in this example.
However, here I know why a Sequence is generally faster:
val result = sequenceOf("a", "b", "c")
.map {
println("map: $it")
it.toUpperCase()
}
.any {
println("any: $it")
it.startsWith("B")
}
Because with a Sequence you process the data "vertically", when the first element starts with "B", you don't have to map for the rest of the elements. It makes sense here.
So, why is it also faster in the first example?
Let's look at what those two implementations are actually doing:
The List implementation first creates a List in memory with 50 million elements.  This will take a bare minimum of 200MB, since an integer takes 4 bytes.
(In fact, it's probably far more than that.  As Alexey Romanov pointed out, since it's a generic List implementation and not an IntList, it won't be storing the integers directly, but will be ‘boxing’ them — storing references to Int objects.  On the JVM, each reference could be 8 or 16 bytes, and each Int could take 16, giving 1–2GB.  Also, depending how the List gets created, it might start with a small array and keep creating larger and larger ones as the list grows, copying all the values across each time, using more memory still.)
Then it has to read all the values back from the list, filter them, and create another list in memory.
Finally, it has to read all those values back in again, to calculate the average.
The Sequence implementation, on the other hand, doesn't have to store anything!  It simply generates the values in order, and as it does each one it checks whether it's divisible by 3 and if so includes it in the average.
(That's pretty much how you'd do it if you were implementing it ‘by hand’.)
You can see that in addition to the divisibility checking and average calculation, the List implementation is doing a massive amount of memory access, which will take a lot of time.  That's the main reason it's far slower than the Sequence version, which doesn't!
Seeing this, you might ask why we don't use Sequences everywhere…  But this is a fairly extreme example.  Setting up and then iterating the Sequence has some overhead of its own, and for smallish lists that can outweigh the memory overhead.  So Sequences only have a clear advantage in cases when the lists are very large, are processed strictly in order, there are several intermediate steps, and/or many items are filtered out along the way (especially if the Sequence is infinite!).
In my experience, those conditions don't occur very often.  But this question shows how important it is to recognise them when they do!
Leveraging lazy-evaluation allows avoiding the creation of intermediate objects that are irrelevant from the point of the end goal.
Also, the benchmarking method used in the mentioned article is not super accurate. Try to repeat the experiment with JMH.
Initial code produces a list containing 50_000_000 objects:
val list = generateSequence(1) { it + 1 }
.take(50_000_000)
.toList()
then iterates through it and creates another list containing a subset of its elements:
.filter { it % 3 == 0 }
... and then proceeds with calculating the average:
.average()
Using sequences allows you to avoid doing all those intermediate steps. The below code doesn't produce 50_000_000 elements, it's just a representation of that 1...50_000_000 sequence:
val sequence = generateSequence(1) { it + 1 }
.take(50_000_000)
adding a filtering to it doesn't trigger the calculation itself as well but derives a new sequence from the existing one (3, 6, 9...):
.filter { it % 3 == 0 }
and eventually, a terminal operation is called that triggers the evaluation of the sequence and the actual calculation:
.average()
Some relevant reading:
Kotlin: Beware of Java Stream API Habits
Kotlin Collections API Performance Antipatterns

Linking Text to an Integer Objective C

The goal of this post is to find a more efficient way to create this method. Right now, as I start adding more and more values, I'm going to have a very messy and confusing app. Any help is appreciated!
I am making a workout app and assign an integer value to each workout. For example:
Where the number is exersiceInt:
01 is High Knees
02 is Jumping Jacks
03 is Jog in Place
etc.
I am making it so there is a feature to randomize the workout. To do this I am using this code:
-(IBAction) setWorkoutIntervals {
exerciseInt01 = 1 + (rand() %3);
exerciseInt02 = 1 + (rand() %3);
exerciseInt03 = 1 + (rand() %3);
}
So basically the workout intervals will first be a random workout (between high knees, jumping jacks, and jog in place). What I want to do is make a universal that defines the following so I don't have to continuously hard code everything.
Right now I have:
-(void) setLabelText {
if (exerciseInt01 == 1) {
exercise01Label.text = [NSString stringWithFormat:#"High Knees"];
}
if (exerciseInt01 == 2) {
exercise01Label.text = [NSString stringWithFormat:#"Jumping Jacks"];
}
if (exerciseInt01 == 3) {
exercise01Label.text = [NSString stringWithFormat:#"Jog in Place"];
}
}
I can already tell this about to get really messy once I start specifying images for each workout and start adding workouts. Additionally, my plan was to put the same code for exercise02Label, exercise03Label, etc. which would become extremely redundant and probably unnecessary.
What I'm thinking would be perfect if there would be someway to say
exercise01Label.text = exercise01Int; (I want to to say that the Label's text equals Jumping Jacks based on the current integer value)
How can I make it so I only have to state everything once and make the code less messy and less lengthy?
Three things for you to explore to make your code easier:
1. Count from zero
A number of things can be easier if you count from zero. A simple example is if your first exercise was numbered 0 then your random calculation would just be rand() % 3 (BTW look up uniform random number, there are much better ways to get a random number).
2. Learn about enumerations
An enumeration is a type with a set of named literal values. In (Objective-)C you can also think of them as just a collection of named integer values. For example you might declare:
typedef enum
{
HighKnees,
JumpingJacks,
JogInPlace,
ExerciseKindCount
} ExerciseCount;
Which declares ExerciseCount as a new type with 4 values. Each of these is equivalent to an integer, here HighKnees is equivalent to 0 and ExerciseKindCount to 3 - this should make you think of the first thing, count from zero...
3. Discover arrays
An array is an ordered collection of items where each item has an index - which is usually an integer or enumeration value. In (Objective-)C there are two basic kinds of arrays: C-style and object-style represented by NSArray and NSMutableArray. For example here is a simple C-style array:
NSString *gExerciseLabels[ExerciseKindCount] =
{ #"High Knees",
#"Jumping Jacks",
#"Jog in Place"
}
You've probably guessed by now, the first item of the above array has index 0, back to counting from zero...
Exploring these three things should quickly show you ways to simplify your code. Later you may wish to explore structures and objects.
HTH
A simple way to start is by putting the exercise names in an array. Then you can access the names by index. eg - exerciseNames[exerciseNumber]. You can also make the list of exercises in an array (of integers). So you would get; exerciseNames[exerciseTable[i]]; for example. Eventually you will want an object to define an exercise so that you can include images, videos, counts, durations etc.