2D Array in Kotlin - arrays

How do you make a 2D Int array in Kotlin? I'm trying to convert this code to Kotlin:
int[][] states = new int[][] {
new int[]{-android.R.attr.state_pressed}, // not pressed
new int[] { android.R.attr.state_pressed} // pressed
};
int[] colors = new int[] {
foregroundColor,
accentColor,
accentColor
};
ColorStateList myList = new ColorStateList(states, colors);
Here is one attempt I tried, where the first 2D array didn't work, but I got the 1D array to work:
//This doesn't work:
var states: IntArray = intArrayOf(
intArrayOf(-android.R.attr.state_pressed), // not pressed
intArrayOf(android.R.attr.state_pressed) // pressed
);
//This array works:
var colors: IntArray = intArrayOf(
foregroundColor,
accentColor,
accentColor
);
val myList: ColorStateList = ColorStateList(states, colors);

You may use this line of code for an Integer array.
val array = Array(row) { IntArray(column) }
This line of code is pretty simple and works like 1D array and also can be accessible like java 2D array.

You are trying to put your IntArrays inside another array to make it 2-dimensional.
The type of that array cannot be intArray, which is why this fails.
Wrap your initial arrays with arrayOf instead of intArrayOf.
val even: IntArray = intArrayOf(2, 4, 6)
val odd: IntArray = intArrayOf(1, 3, 5)
val lala: Array<IntArray> = arrayOf(even, odd)

Short Answer:
// A 6x5 array of Int, all set to 0.
var m = Array(6) {Array(5) {0} }
Here is another example with more details on what is going on:
// a 6x5 Int array initialise all to 0
var m = Array(6, {i -> Array(5, {j -> 0})})
The first parameter is the size, the second lambda method is for initialisation.

I have been using this one-liner when creating matrix
var matrix: Array<IntArray> = Array(height) { IntArray(width) }

1. Nested arrayOf calls
You can nest calls of arrayOf, e.g., to create an Array of IntArray, do the following:
val first: Array<IntArray> = arrayOf(
intArrayOf(2, 4, 6),
intArrayOf(1, 3, 5)
)
Note that the IntArray itself only takes arguments of type Int as arguments, so you cannot have an IntArray<IntArray> which obviously does not make much sense anyway.
2. Use Array::constructor(size: Int, init: (Int) -> T) for repeated logic
If you want to create your inner arrays with some logical behaviour based on the index, you can make use of the Array constructor taking a size and an init block:
val second: Array<IntArray> = Array(3) {
intArrayOf(it * 1, it * 2, it * 3, it * 4)
}
//[[0, 0, 0, 0], [1, 2, 3, 4], [2, 4, 6, 8]]

It seems that you are trying to create a ColorStateList in Kotlin. The code for that is a bit messy, i'll try to keep it readable:
val resolvedColor = Color.rgb(214, 0, 0)
val states = arrayOf(
intArrayOf(-android.R.attr.state_pressed),
intArrayOf(android.R.attr.state_pressed)
)
val csl = ColorStateList(
states,
intArrayOf(resolvedColor, Color.WHITE)
)

You can use a simple 1D (linear) array for this purpose. For example, this is my class for a rectangle array of Double values:
/**
* Rect array of Double values
*/
class DoubleRectArray(private val rows: Int, private val cols: Int) {
private val innerArray: DoubleArray
init {
if(rows < 1) {
throw IllegalArgumentException("Rows value is invalid. It must be greater than 0")
}
if(cols < 1) {
throw IllegalArgumentException("Cols value is invalid. It must be greater than 0")
}
innerArray = DoubleArray(rows*cols)
}
/**
*
*/
fun get(row: Int, col: Int): Double {
checkRowAndCol(row, col)
return innerArray[row*cols + col]
}
/**
*
*/
fun set(row: Int, col: Int, value: Double) {
checkRowAndCol(row, col)
innerArray[row*cols + col] = value
}
/**
*
*/
private fun checkRowAndCol(row: Int, col: Int) {
if(row !in 0 until rows) {
throw ArrayIndexOutOfBoundsException("Row value is invalid. It must be in a 0..${rows-1} interval (inclusive)")
}
if(col !in 0 until cols) {
throw ArrayIndexOutOfBoundsException("Col value is invalid. It must be in a 0..${cols-1} interval (inclusive)")
}
}
}

package helloWorld
import java.util.Scanner
fun main(){
val sc = Scanner(System.`in`)
print("ENTER THE SIZE OF THE ROW: ")
var row = sc.nextInt()
println()
print("ENTER THE SIZE OF COLUMN: ")
val column = sc.nextInt()
println()
var a = Array(row){IntArray(column)}
for(i in 0 until row){
when (i) {
0 -> {
println("----------${i+1} st ROW'S DATA----------")
}
1 -> {
println("----------${i+1} nd ROW'S DATA----------")
}
2 -> {
println("----------${i+1} rd ROW'S DATA----------")
}
else -> {
println("----------${i+1} th ROW'S DATA----------")
}
}
for(j in 0 until column)
{
print("ENTER ${j+1} COLUMN'S DATA: ")
var data:Int = sc.nextInt()
a[i][j]=data;
}
println()
}
println("COLLECTION OF DATA IS COMPLETED")
for(i in 0 until row){
for(j in 0 until column){
print(a[i][j])
print(" ")
}
println()
}
}
It works like this:

You can create 2D array in kotlin.
var twoDarray = Array(8) { IntArray(8) }
this is a example of int 2D array

Using an inline function and a Pair:
inline fun<reified T> Pair<Int,Int>.createArray(initialValue:T) = Array(this.first){ Array(this.second){initialValue}}
// Create m*n Array of Ints filled with 0
val twoDimArray = Pair(10,20).createArray(0)
// Create m*n Array of Doubles filled with 0.0
val twoDimArray = Pair(10,20).createArray(0.0)
// Create m*n Array of Strings filled with "Value"
val twoDimArray = Pair(10,20).createArray("Value")
...

You can create two one dimensional array and add them in new array.
val unChecked = intArrayOf(-android.R.attr.state_checked)
val checked = intArrayOf(android.R.attr.state_checked)
val states = arrayOf(unChecked, checked)
val thumbColors = intArrayOf(Color.WHITE, Color.parseColor("#55FFD4"))
val stateList = ColorStateList(states, thumbColors)

Related

How can I find min or max valued item index for one of struct array items with Swift 5

Lets say we have a struct and an array made of that struct.
struct MyStruct {
item1: Int = 0
item2: Int = 0
}
var myStruct: [MyStruct] = []
Consider that we filled myStruct array with some data with append like that.
myStruct.append(MyStruct(item1: 12, item2:123) )
Think that we have 10 value in myStruct array like [ (item1: 12, item2: 123),... ,() ]
And we want to find index number of myStruct according to item1 max value.
I can do it with a loop but there might be a ready way maybe which I can not find.
This is my in 1 min found solution;
func findMaxIndexForItem1() -> Int {
var maxIndex = 0
var max = 0
for k in 0..<myStruct.count {
if myStruct[k].item1 > max {
max = myStruct[k].item1
index = k
}
}
return max
}
You can use max(by:) and pass in a closure that returns whether one index of the array is "smaller" than another. The method will use this to determine the index that is not smaller than any other index.
let index = myStruct.indices.max(by:
{ myStruct[$0].item1 < myStruct[$1].item1 }
)
You can do this by making MyStruct conform to Comparable protocol.
To conform to Comparable you need to specify what makes two instances of of your instance < or == each to each.
Once you have define that, you get a lot of functionality for free. For eg: You can check if two instances are equal (by your definition), find the max, min etc.
struct MyStruct : Comparable {
var item1: Int = 0
var item2: Int = 0
static func < (lhs : MyStruct, rhs : MyStruct) -> Bool {
return lhs.item1 < rhs.item1
}
static func == (lhs : MyStruct, rhs : MyStruct) -> Bool {
return lhs.item1 == rhs.item1
}
}
let arr = [MyStruct(item1: 20, item2: 0), MyStruct(item1: 10, item2: 0), MyStruct(item1: 5, item2: 0)]
let maxObj = arr.max()
maxObj?.item1

Second array will not increment after repeating for loop

I am new to Kotlin and am trying to compare the elements of two arrays by seeing which array has the greater element. The arrays are created via user input. The error that I am having is that when I repeat the second for loop (inner loop), which contains the contents of the second array, it will not increment to the next element of the second array unlike the first for loop. So if a = {1,2} and b = {2,1}, a would increment through both 1 and 2, but b would stay at 2 through both iterations of the loop. Here is my function that is giving me a problem:
fun practiceCompareArray(a: Array<Int>, b: Array<Int>): Array<Int> {
var j: Array<Int>
var aPoints = 0
var bPoints = 0
for (x:Int in a) {
---------> for (y: Int in b) {
if (x > y) {
aPoints++
} else if (x < y) {
bPoints++
break
}
}
j = arrayOf(aPoints, bPoints)
return j
}
The for loop with the arrow is giving me the problem. I think it is because of the break statement at the end of the inner loop. Do I even need the inner loop to compare each array? Any help or documentation would be helpful.
If you know that both array have the same length and you want to compare them elementwise you could do something like:
fun practiceCompareArray(a: Array<Int>, b: Array<Int>): Array<Int> {
var aPoints = 0
var bPoints = 0
for ((x,y) in a.zip(b)) {
if (x>y) {
aPoints ++
} else {
bPoints ++
}
}
return arrayOf(aPoints, bPoints)
}
or in a more functional style
fun practiceCompareArray(a: Array<Int>, b: Array<Int>): Array<Int> {
val (aPoints, bPoints) = a.zip(b)
.fold(Pair(0,0), {(aScore, bScore), (x,y) ->
if (x > y) Pair(aScore + 1, bScore) else Pair(aScore, bScore + 1)})
return arrayOf(aPoints, bPoints)
}

Take input in array with loop

developers, i am new in Kotlin I am trying to take input in Array by using loop and after that, i print the all values of array by using loop but t get only input and not show the other chunk and through the error which is shiwn on attach image
fun main(args: Array<String>) {
var arrayint = Array<Int>(5){0}
var x = 1
val abc:Int = arrayint.size
while( x <= abc)
{
arrayint[x] = readLine()!!.toInt()
x++
}
for(index in 0..4)
{
println(arrayint[index])
}
}
The following is a little more succinct
var arrayint = Array<Int>(5) { readLine()!!.toInt() }
for(x in arrayint)
println(x)
On the first line, instead of using the initializer lambda { 0 }, I use a lambda that call readLine.
On line 2, instead of having to know my range (0..4), I let the language do it for me (an Array is iterable).
Try this:
fun main (args:Array<String>){
var arrayint = Array<Int>(5){0}
var x:Int = 0
val abc:Int = arrayint.size
while( x < abc)
{
arrayint[x] = readLine()!!.toInt()
x++
}
for(index in 0..4)
{
println(arrayint[index])
}
}
You should change x <= abc to x < abc and x = 1 to x = 0. It doesn't work now because if abc = 5 and you loop 4 times then x = 5 but arrays in Kotlin (and Java) start at index 0 which means that array of size 5 has the following indexes: 0, 1, 2, 3, 4 which means that arrayint[5] doesn't exist as 5 is out of bounds (> 4)
One of the shorthand for taking n data elements of data input in an array of predefined size is as follow.
Here the user is going to input a integer
n = number of elements then then the array elements
import java.util.*
fun main(){
val read = Scanner(System.`in`)
val n = read.nextInt()
var arr = Array(n) {i-> read.nextInt()} // taking input
arr.forEach{
println(it) // this loop prints the array
}
}
Following code is taking input in array using loop
import java.util.*
fun main(args: Array<String>) {
var num = arrayOfNulls<Int>(5)
var read= Scanner(System.`in`)
println("Enter array values")
for(i in 0..4)
{
num[i] = read.nextInt()
}
println("The array is")
for(x in num){
println(x)}
}
Following code is taking input of array size and then it's elements
fun main() {
print("Enter Array size: ")
val arraySize = readLine()!!.toInt()
println("Enter Array Elements")
val arr = Array<Int>(arraySize) { readLine()!!.toInt() }
for (x in arr)
println(x)
}

Inserting integer into array in swift

I'm not really on point with Swift yet and there is a problem that is starting to be a tad annoying.
I just want to add integer in a double dimensional array but it is always returning the same error code : "fatal error : Array index out of range"
var arrayVolley = [[Int]]()
init(){
self.arrayVolley = [[]]
}
Here is where I try to insert :
func addPoints(score : Int, x : Int, y : Int){
if (score > 11 || score < 0){ //11 will be translated as 10x
println("Error on score value")
}
else {
if (x>6 || y>6){
println("Out of array")
}
else{
arrayVolley[x][y]=score
}
}
}
And this is my main :
var i=0
var j=0
for i in 0...6 {
for j in 0...6{
println("Entrez le score")
var scoreinput=input()
var score = scoreinput.toInt()
distance.addPoints(score!, x: i, y: j)
}
}
Thanks a lot for your help in advance
Try to use append to add the integer to the array it is automatically the next idex. It think if the index was never used it gives an error e.g.
var test = [Int]()
test.append(2) // array is empty so 0 is added as index
test.append(4)
test.append(5) // 2 is added as max index array is not [2,4,5]
test[0] = 3 // works because the index 0 exist cause the where more then 1 element in array -> [3,4,5]
test[4] = 5 // does not work cause index for never added with append
or you intialize the array in the correct size, but it's need a size:
var test = [Int](count: 5, repeatedValue: 0) // [0,0,0,0,0]
test[0] = 3 //[3,0,0,0,0]
test[4] = 5 [3,0,0,0,5]
It hope this helps you if not please feel free to comment.

as3 random array - randomize array - actionscript 3

How do you randomize an array using actionscript 3?
There is a short version using Array.sort() function:
var arr : Array = [0,1,2,3,4,5,6,7,8,9];
function randomize ( a : *, b : * ) : int {
return ( Math.random() > .5 ) ? 1 : -1;
}
trace( arr.sort( randomize ) );
If you don't get "enough" randomness you can sort twice :)
EDIT - explanation line by line:
For Array class method sort() you can pass not only sort options like Array.CASEINSENSITIVE, Array.DESCENDING and so on but also your own custom compare function reference (a callback) that accepts two parameters (two elements from array to compare). From AS3 documentation:
A comparison function should take two arguments to compare. Given the elements A and B, the result of compareFunction can have a negative, 0, or positive value:
A negative return value specifies that A appears before B in the sorted sequence.
A return value of 0 specifies that A and B have the same sort order.
A positive return value specifies that A appears after B in the sorted sequence.
Note: compare function parameters might be typed (if your array is typed) and have any name you want eg.:
function compareElements ( elementA : SomeClass, elementB : SomeClass ) : int;
This method is very useful when you need to sort array elements by their special properties. In randomization case compareFunction randomly returns -1, 0 or 1 and makes array elements to switch their places (indices). I have found that better randomization (in my subjective and mathematically untested opinion) is when method returns only -1 and 1. Also have in mind that sorting function with custom compare function doesn't compare elements sequentially so in some special cases randomization results may differ from what you might expect.
There's a better way that will also allow you to randomize the array in place, if you need that, and it will not make you create more then a single copy of your original array.
package
{
import flash.display.Sprite;
public class RandomizeArrayExample extends Sprite
{
public function RandomizeArrayExample()
{
super();
testDistribution();
}
private function testDistribution():void
{
var hash:Object = { };
var tester:Array = [1, 2, 3, 4];
var key:String;
for (var i:int; i < 1e5; i++)
{
randomize(tester);
key = tester.join("");
if (key in hash) hash[key]++;
else hash[key] = 1;
}
for (var p:String in hash) trace(p, "=>", hash[p]);
}
private function randomize(array:Array):Array
{
var temp:Object;
var tempOffset:int;
for (var i:int = array.length - 1; i >= 0; i--)
{
tempOffset = Math.random() * i;
temp = array[i];
array[i] = array[tempOffset];
array[tempOffset] = temp;
}
return array;
}
}
}
I had an alternative requirement where i wanted to randomly insert lots of source arrays into a target array randomly. Like Rytis i'm a big fan of the forEach, map and sort functions on Arrays.
var randomInsert:Function = function callback(item:*, index:int, array:Vector.<MyItem>):void
{
var j:Number = Math.floor(Math.random() * targetArray.length);
targetArray.splice(j,0,item);
}
targetArray = new Vector.<MyItem>();
sourceArray1.forEach(randomInsert, this);
sourceArray2.forEach(randomInsert, this);
here's an easier function. Works also on multidimensional arrays
function randomizeArray(array:Array):Array
{
var newArray:Array = new Array();
while (array.length > 0)
{
var mn=Math.floor(Math.random()*array.length)
newArray[newArray.length]=array[mn]
array.splice(mn,1)
}
return newArray;
}
I found this very helpful. I hope it can help you too.
// Array to Randomize
var firstArray:Array = ["One","Two","Three","Four","Five","six","seven","eight","nine","ten"];
trace(firstArray); // Prints in order
var newArray:Array = new Array();
function randomizeArray(array:Array):Array
{
var newArray:Array = new Array();
while (array.length > 0)
{
newArray.push(array.splice(Math.floor(Math.random()*array.length), 1));
}
return newArray;
}
var randomArray:Array = randomizeArray(firstArray);
trace(randomArray); // Prints out randomized :)
If you need your array to be shuffled (your elements can not repeat). You could use this function:
/**
* Shuffles array into new array with no repeating elements. Simple swap algorithm is used.
*/
public function shuffleArray(original:Array):Array
{
// How many swaps we will do
// Increase this number for better results (more shuffled array, but slower performance)
const runs:int = original.length * 3;
var shuffled:Array = new Array(original.length);
var i:int;
var a:int;
var b:int;
var temp:Object;
// Copy original array to shuffled
for(i=0; i<shuffled.length; i++){
shuffled[i] = original[i];
}
// Run random swap cycle 'runs' times
for(i=0; i<runs; i++){
// There is a chance that array element will swap with itself,
// and there is always small probability it will make your shuffle
// results not that good, hence try to experiment with
// different runs count as stated above
a = Math.floor(Math.random() * original.length);
b = Math.floor(Math.random() * original.length);
// Swap messages
temp = shuffled[a];
shuffled[a] = shuffled[b];
shuffled[b] = temp;
}
return shuffled;
}
Usage:
var testArray:Array = ["Water", "Fire", "Air", "Earth"];
trace(shuffleArray(testArray).concat());
this is how I randomize my array of 36 cards for a memory game
const QUANT_CARTAS: int = 36;
//get the 36 numbers into the array
for (var i: int = 0; i < QUANT_CARTAS; i++)
{
cartas.push(i);
}
//shuffles them =)
for (var moeda: int = QUANT_CARTAS - 1; moeda > 0; moeda--)
{
var pos: int = Math.floor(Math.random() * moeda);
var carta: int = cartas[moeda];
cartas[moeda] = cartas[pos];
cartas[pos] = carta;
}
// and add them using the random order...
for (i = 0; i < QUANT_CARTAS; i++)
{
var novaCarta: Carta = new Carta();
novaCarta.tipoCarta = cartas[i];
etcetcetc.............
}
choose random string from array
function keyGenerator(len:Number):String
{
function randomRange(minNum:Number, maxNum:Number):Number
{
return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);
}
var hexArray = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'];
var key = "";
for (var i=0; i<len; i++)
{
key += hexArray[randomRange(0,hexArray.length-1)];
}
return key;
}
usage:
trace(keyGenerator(16));

Resources