kotlin: extracting from list - list

I have a list of Int items say
Now I want to call a function process(item1, item2, item3, item4)
How can I do this in kotlin.
I want to pass how much ever items are present in the list to the method. The method accepts variable number of arguments
I want to call this method from firbase mlk library
public FirebaseVisionBarcodeDetectorOptions.Builder
setBarcodeFormats(#BarcodeFormat int var1, #BarcodeFormat int... var2) {
}
So I need to call setBarcodeFormats(is there a way in kotlin to pass each element of list as an arg here)

Based on the description of your problem I assume you have one method that takes a variable number of integers – let's call it fun foo(vararg n: Int).
If that's the case, than the bytecode that gets generated is the following:
public final static varargs foo([I)V
This means the method takes an array of int, which is an IntArray in Kotlin world.
In order to call that method with an IntArray you need to do:
fun foo(vararg n: Int) {
n.forEach(::println) // do something with n
}
fun main() {
val numbers = intArrayOf(1, 2, 3, 4)
foo(*numbers) // prints 1; 2; 3; 4
}
In that snippet of code, * is the spread operator and is briefly described here.
Also note that the spread operator can only be applied to arrays, so if you have a list of Int you need to convert it to an IntArray first an then apply the spread operator, like this:
fun foo(vararg n: Int) {
n.forEach(::println) // do something with n
}
fun main() {
val numbers = listOf(1, 2, 3, 4)
foo(*numbers.toIntArray()) // prints 1; 2; 3; 4
}
EDIT
Following the update to your question, you can call that method from your Kotlin code like this:
val builder = ... // obtain a Builder instance
val args = intArrayOf(1, 2, 4, 10)
builder.setBarcodeFormats(1, *args) // or any other meaningful value

You have two ways. First is pass a List of Int to the method. second is using varargs. For example a function which takes n number as inputs and returns the average of all the inputs. If we want to use List it will be like so:
fun getAverage(numbersList: List<Int>): Float {
var sum = 0.0f
for (item in numbersList) {
sum += item
}
return (sum / numbersList.size)
}
val arrayList = arrayListOf(1, 2, 3, 4)
val result = getAverage(arrayList)
And if we want to pass numbers as infinite function parameters we could do it with varargs like this:
fun getAverage(vararg input: Int): Float {
var sum = 0.0f
for (item in input) {
sum += item
}
return (sum / input.size)
}
val result1 = getAverage(1, 2, 3)
val result2 = getAverage(1, 2, 3, 4, 5)

Related

How to implement shouldRepaint when the object being compared is a List?

Lets say in Flutter we have a Custom Painter like this that takes a List as an argument:
class StackPainter02 extends CustomPainter {
final List<double> brightnessValues;
late final int numberOfBulbs;
StackPainter02(
{required this.brightnessValues}) {
numberOfBulbs = brightnessValues.length;
}
#override
void paint(Canvas canvas, Size size) {
// ...
}
#override
bool shouldRepaint(covariant StackPainter02 oldDelegate) {
return (oldDelegate.brightnessValues != brightnessValues); // ??? does not seem to work
//return true;
}
}
In the shouldRepaint(), I suspect the reason this isn't working has to do with how comparing lists works in Dart and that comparing two lists will always return false even if their contents are the same.
... and that we have to use some type of special comparison like in this answer?
However, I don't want the performance hit of having to iterate through an entire list like that to compare every value.
Assuming it could ever be the same object in memory, is there some way to compare the "two" lists by asking "is it the same actual object in memory"?
That's exactly what == does. Take this example:
final l1 = <int>[1, 2, 3];
final l2 = <int>[1, 2, 3];
final l3 = l1;
print(l1 == l2); // prints false
print(l1 == l3); // prints true
l1[2] = 4;
print(l3); // prints [1, 2, 4];
Two different lists, albeit with the same contents, are not ==, but can be compared by exhaustively checking their contents.
But in this example l3 is the same list as l1 - so == is true. (Note how modifying l1 also modifies l3.

Create a list from another

Let say I have some values in a List. I would like to return another list with a new element
fun newList():List<Int>{
val values =listOf<Int>(1,2,3,4,5,6);
return 7::values; // something like that
}
The Kotlin lists have the plus operator overloaded in kotlin-stdlib, so you can add an item to a list:
val values = listOf(1, 2, 3, 4, 5, 6)
return values + 7
There's also an overload that adds another list:
val values = listOf(1, 2, 3, 4, 5, 6)
return listOf(-1, 0) + values + listOf(7, 8)
Note that in both cases a new list is created, and the elements are copied into it.
For MutableList<T> (which has mutating functions, in contrast with List<T>), there is a plusAssign operator implementation, that can be used as follows:
fun newList(): List<Int> {
val values = mutableListOf(1, 2, 3, 4, 5, 6)
values += 7
values += listOf(8, 9)
return values
}
A different approach by using spread operator. Maybe in some case would be simpler than using + sign or mutableListOf
fun newList(): List<Int>{
val values = listOf(1,2,3,4,5,6)
return listOf(7, *values.toTypedArray(), 8, 9)
}
You can do it like this
fun newList():List<Int>{
val values =listOf(1,2,3,4,5,6) //Type can be inferred
return values.plus(7)
}
I wanted a Scala-like with for and yield. It's pretty good in - currently experimental - coroutines :
fun testYield(max:Int): List<Int> {
val values = buildSequence{
for (i in 1..max){
yield(i)
}
}
return values.toList();
}
Or in shorter way:
fun testYieldFast(max: Int) = buildSequence {
for (i in 1..max)
yield(i)
}.toList();
It allows fast immutable lazy construction, where frequent concatenation are usually slow with immutable lists.

Factorial in D Language

I have just started with D and was trying to write a simple factorial program in D. Is there anything like vectors of C++ in D? I wanted to use vectors to create a dynamic function to compute factorial.
In D, dynamic arrays are resizable and can be concatenated, just like vectors in C++.
Here is an example with such array which reads from stdin and writes to stdout:
import std.stdio; // for readf and writeln
void main () // void for main means "int with return 0 at exit" to OS
{
int n;
readf (" %s", &n); // skip whitespace, then read int in default format
auto f = [1]; // a dynamic array of int containing a 1
foreach (i; 1..n + 1) // for i = 1, 2, 3, ..., n - 1, n
{
f ~= f[$ - 1] * i; // append to f its last element multiplied by i
}
writeln (f); // print the dynamic array in default format
}
For input
10
the output is:
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
As mentioned in the comments, refer to the documentation for more information on built-in dynamic arrays.
However, it is not clear what is a dynamic function you mention.
And, generally, we don't need an array or vector to calculate factorial.
Check RosettaCode for a few other approaches to calculating factorial in D.
Why don't you use std.bigint? - it's optimized for arbitrary-precision numerics. Even with ulong (2^64) you can only compute factorial until 20 and for this use-case an inline-table might make more sense. Here's an example with BigInt:
import std.bigint : BigInt;
BigInt factorial(int n)
{
auto b = BigInt(1);
foreach (i; 1..n + 1)
b *= i;
return b;
}
void main ()
{
import std.stdio : writeln;
factorial(10).writeln; // 3628800
factorial(100).writeln; // 9.33 * 10^157
}
If you want to learn more about dynamic arrays, maybe the DLang Tour pages for Arrays or Slices might help you?

How to remove similar elements from a Dart list?

I'd like to remove similar elements from a dart list, where similarity is given by some boolean function.
For example in Mathematica I would achieve that as follows:
Union[{2, -2, 1, 3, 1}, SameTest -> (Abs[#1] == Abs[#2] &)]
This statement yields the following list - {-2, 1, 3}. Effectively I'd like to keep one element from each equivalence class.
I know there is a function list.retainWhere( (e) => bool test(e) ), unfortunately this test can only operate on one value at a time. Another option, of course, I could do something like this (just writing from my head)
i=0;
for(final E in list) {
i++;
for(j=i; j<list.skip(i).length; j++) {
if sameTest(e, E) then list.removeAt(i+j);
}
}
but i find this bit ugly.
Any advice?
UPDATE
I will clarify my problem in more details and then show how to solve it using advice given below.
class Pair<T> {
final T left;
final T right;
Pair(this.left, this.right);
}
Now I want to have a structure holding such pair or points, and i don't want to hold point which are sufficiently close to each other. To do so I adopt solution of Alexandre Ardhuin and his comment too, which actually makes a difference for more complicated cases: Considering 2 elements e1 and e2 you have to define hashCode to ensure that e1.hashCode == e2.hashCode if e1 == e2
so here it goes:
int N=1000;
LinkedHashSet<Pair<double>> myset =
new LinkedHashSet<Pair<double>>(
equals: (Pair<double> e1, Pair<double> e2) =>
(e1.left - e2.left)*(e1.left - e2.left) + (e1.right - e2.right)*(e1.right - e2.right) < 1/N,
hashCode: (Pair<double> e){
int ex = (e.left*N).round();
int ey = (e.right*N).round();
return (ex+ey).hashCode;
}
);
List<Pair<double>> list = [new Pair<double>(0.1,0.2), new Pair<double>(0.1,0.2001)];
myset.addAll( list );
the result will be {0.1,0.2}. If the second element of list is altered to {0.1, 0.201} I predictably get a set with two elements.
Hope this was useful.
You can use a LinkedHashSet and define the equals and hashcode to use.
import 'dart:collection';
main() {
final result = new LinkedHashSet<int>(
equals: (int e1, int e2) => e1.abs() == e2.abs(),
hashCode: (int e) => e.abs().hashCode);
result.addAll([2, -2, 1, 3, 1]);
print(result); // {2, 1, 3}
}

How to produce a random number sequence that doesn't produce more than X consecutive elements

Ok, I really don't know how to frame the question properly because I barely have any idea how to describe what I want in one sentence and I apologize.
Let me get straight to the point and you can just skip the rest cause I just want to show that I've tried something and not coming here to ask a question on a whim.
I need an algorithm that produces 6 random numbers where it may not produce more than 2 consecutive numbers in that sequence.
example: 3 3 4 4 2 1
^FINE.
example: 3 3 3 4 4 2
^NO! NO! WRONG!
Obviously, I have no idea how to do this without tripping over myself constantly.
Is there a STL or Boost feature that can do this? Or maybe someone here knows how to concoct an algorithm for it. That would be awesome.
What I'm trying to do and what I've tried.(the part you can skip)
This is in C++. I'm trying to make a Panel de Pon/Tetris Attack/Puzzle League whatever clone for practice. The game has a 6 block row and 3 or more matching blocks will destroy the blocks. Here's a video in case you're not familiar.
When a new row comes from the bottom it must not come out with 3 horizontal matching blocks or else it will automatically disappear. Something I do not want for horizontal. Vertical is fine though.
I've tried to accomplish just that and it appears I can't get it right. When I start the game chunks of blocks are missing because it detects a match when it shouldn't. My method is more than likely heavy handed and too convoluted as you'll see.
enum BlockType {EMPTY, STAR, UP_TRIANGLE, DOWN_TRIANGLE, CIRCLE, HEART, DIAMOND};
vector<Block> BlockField::ConstructRow()
{
vector<Block> row;
int type = (rand() % 6)+1;
for (int i=0;i<6;i++)
{
row.push_back(Block(type));
type = (rand() % 6) +1;
}
// must be in order from last to first of the enumeration
RowCheck(row, diamond_match);
RowCheck(row, heart_match);
RowCheck(row, circle_match);
RowCheck(row, downtriangle_match);
RowCheck(row, uptriangle_match);
RowCheck(row, star_match);
return row;
}
void BlockField::RowCheck(vector<Block> &row, Block blockCheckArray[3])
{
vector<Block>::iterator block1 = row.begin();
vector<Block>::iterator block2 = row.begin()+1;
vector<Block>::iterator block3 = row.begin()+2;
vector<Block>::iterator block4 = row.begin()+3;
vector<Block>::iterator block5 = row.begin()+4;
vector<Block>::iterator block6 = row.begin()+5;
int bt1 = (*block1).BlockType();
int bt2 = (*block2).BlockType();
int bt3 = (*block3).BlockType();
int bt4 = (*block4).BlockType();
int type = 0;
if (equal(block1, block4, blockCheckArray))
{
type = bt1 - 1;
if (type <= 0) type = 6;
(*block1).AssignBlockType(type);
}
else if (equal(block2, block5, blockCheckArray))
{
type = bt2 - 1;
if (type <= 0) type = 6;
(*block2).AssignBlockType(type);
}
else if (equal(block3, block6, blockCheckArray))
{
type = bt3 - 1;
if (type == bt3) type--;
if (type <= 0) type = 6;
(*block3).AssignBlockType(type);
}
else if (equal(block4, row.end(), blockCheckArray))
{
type = bt4 - 1;
if (type == bt3) type--;
if (type <= 0) type = 6;
(*block4).AssignBlockType(type);
}
}
Sigh, I'm not sure if it helps to show this...At least it shows that I've tried something.
Basically, I construct the row by assigning random block types, described by the BlockType enum, to a Block object's constructor(a Block object has blockType and a position).
Then I use a RowCheck function to see if there's 3 consecutive blockTypes in one row and I have do this for all block types. The *_match variables are arrays of 3 Block objects with the same block type. If I do find that there are 3 consecutive block types then, I just simply subtract the first value by one. However if I do that I might end up inadvertently producing another 3 match so I just make sure the block types are going in order from greatest to least.
Ok, it's crappy, it's convoluted and it doesn't work! That's why I need your help.
It should suffice to keep record of the previous two values, and loop when the newly generated one matches both of the previous values.
For an arbitrary run length, it would make sense to size a history buffer on the fly and do the comparisons in a loop as well. But this should be close to matching your requirements.
int type, type_old, type_older;
type_older = (rand() % 6)+1;
row.push_back(Block(type_older));
type_old = (rand() % 6)+1;
row.push_back(Block(type_old));
for (int i=2; i<6; i++)
{
type = (rand() % 6) +1;
while ((type == type_old) && (type == type_older)) {
type = (rand() % 6) +1;
}
row.push_back(Block(type));
type_older = type_old;
type_old = type;
}
Idea no 1.
while(sequence doesn't satisfy you)
generate a new sequence
Idea no 2.
Precalculate all allowable sequences (there are about ~250K of them)
randomly choose an index and take that element.
The second idea requires much memory, but is fast. The first one isn't slow either because there is a veeery little probability that your while loop will iterate more than once or twice. HTH
Most solutions seen so far involve a potentially infinite loop. May I suggest a different approch?
// generates a random number between 1 and 6
// but never the same number three times in a row
int dice()
{
static int a = -2;
static int b = -1;
int c;
if (a != b)
{
// last two were different, pick any of the 6 numbers
c = rand() % 6 + 1;
}
else
{
// last two were equal, so we need to choose from 5 numbers only
c = rand() % 5;
// prevent the same number from being generated again
if (c == b) c = 6;
}
a = b;
b = c;
return c;
}
The interesting part is the else block. If the last two numbers were equal, there is only 5 different numbers to choose from, so I use rand() % 5 instead of rand() % 6. This call could still produce the same number, and it also cannot produce the 6, so I simply map that number to 6.
Solution with simple do-while loop (good enough for most cases):
vector<Block> row;
int type = (rand() % 6) + 1, new_type;
int repetition = 0;
for (int i = 0; i < 6; i++)
{
row.push_back(Block(type));
do {
new_type = (rand() % 6) + 1;
} while (repetition == MAX_REPETITION && new_type == type);
repetition = new_type == type ? repetition + 1 : 0;
type = new_type;
}
Solution without loop (for those who dislike non-deterministic nature of previous solution):
vector<Block> row;
int type = (rand() % 6) + 1, new_type;
int repetition = 0;
for (int i = 0; i < 6; i++)
{
row.push_back(Block(type));
if (repetition != MAX_REPETITION)
new_type = (rand() % 6) + 1;
else
{
new_type = (rand() % 5) + 1;
if (new_type >= type)
new_type++;
}
repetition = new_type == type ? repetition + 1 : 0;
type = new_type;
}
In both solutions MAX_REPETITION is equal to 1 for your case.
How about initializing a six element array to [1, 2, 3, 4, 5, 6] and randomly interchanging them for awhile? That is guaranteed to have no duplicates.
Lots of answers say "once you detect Xs in a row, recalculate the last one until you don't get an X".... In practice for a game like this, that approach is millions of times faster than you need for "real-time" human interaction, so just do it!
But, you're obviously uncomfortable with it and looking for something more inherently "bounded" and elegant. So, given you're generating numbers from 1..6, when you detect 2 Xs you already know the next one could be a duplicate, so there are only 5 valid values: generate a random number from 1 to 5, and if it's >= X, increment it by one more.
That works a bit like this:
1..6 -> 3
1..6 -> 3
"oh no, we've got two 3s in a row"
1..5 -> ?
< "X"/3 i.e. 1, 2 use as is
>= "X" 3, 4, 5, add 1 to produce 4, 5 or 6.
Then you know the last two elements differ... the latter would take up the first spot when you resume checking for 2 elements in a row....
vector<BlockType> constructRow()
{
vector<BlockType> row;
row.push_back(STAR); row.push_back(STAR);
row.push_back(UP_TRIANGLE); row.push_back(UP_TRIANGLE);
row.push_back(DOWN_TRIANGLE); row.push_back(DOWN_TRIANGLE);
row.push_back(CIRCLE); row.push_back(CIRCLE);
row.push_back(HEART); row.push_back(HEART);
row.push_back(DIAMOND); row.push_back(DIAMOND);
do
{
random_shuffle(row.begin(), row.end());
}while(rowCheckFails(row));
return row;
}
The idea is to use random_shuffle() here. You need to implement rowCheckFails() that satisfies the requirement.
EDIT
I may not understand your requirement properly. That's why I've put 2 of each block type in the row. You may need to put more.
I think you would be better served to hide your random number generation behind a method or function. It could be a method or function that returns three random numbers at once, making sure that there are at least two distinct numbers in your output. It could also be a stream generator that makes sure that it never outputs three identical numbers in a row.
int[] get_random() {
int[] ret;
ret[0] = rand() % 6 + 1;
ret[1] = rand() % 6 + 1;
ret[2] = rand() % 6 + 1;
if (ret[0] == ret[1] && ret[1] == ret[2]) {
int replacement;
do {
replacement = rand() % 6 + 1;
} while (replacement == ret[0]);
ret[rand() % 3] = replacement;
}
return ret;
}
If you wanted six random numbers (it's a little difficult for me to tell, and the video was just baffling :) then it'll be a little more effort to generate the if condition:
for (int i=0; i<4; i++) {
if (ret[i] == ret[i+1] && ret[i+1] == ret[i+2])
/* three in a row */
If you always change ret[1] (the middle of the three) you'll never have three-in-a-row as a result of the change, but the output won't be random either: X Y X will happen more often than X X Y because it can happen by random chance and by being forced in the event of X X X.
First some comments on the above solutions.
There is nothing wrong with the techniques that involve rejecting a random value if it isn't satisfactory. This is an example of rejection sampling, a widely used technique. For example, several algorithms for generating a random gaussian involve rejection sampling. One, the polar rejection method, involves repeatedly drawing a pair of numbers from U(-1,1) until both are non-zero and do not lie outside the unit circle. This throws out over 21% of the pairs. After finding a satisfactory pair, a simple transformation yields a pair of gaussian deviates. (The polar rejection method is now falling out of favor, being replaced by the ziggurat algorithm. That too uses a rejection sampling.)
There is something very much wrong with rand() % 6. Don't do this. Ever. The low order bits from a random number generator, even a good random number generator, are not quite as "random" as are the high order bits.
There is something very much wrong with rand(), period. Most compiler writers apparently don't know beans about producing random numbers. Don't use rand().
Now a solution that uses the Boost random number library:
vector<Block> BlockField::ConstructRow(
unsigned int max_run) // Maximum number of consecutive duplicates allowed
{
// The Mersenne Twister produces high quality random numbers ...
boost::mt19937 rng;
// ... but we want numbers between 1 and 6 ...
boost::uniform_int<> six(1,6);
// ... so we need to glue the rng to our desired output.
boost::variate_generator<boost::mt19937&, boost::uniform_int<> >
roll_die(rng, six);
vector<Block> row;
int prev = 0;
int run_length = 0;
for (int ii=0; ii<6; ++ii) {
int next;
do {
next = roll_die();
run_length = (next == prev) ? run_length+1 : 0;
} while (run_length > max_run);
row.push_back(Block(next));
prev = next;
}
return row;
}
I know that this already has many answers, but a thought just occurred to me. You could have 7 arrays, one with all 6 digits, and one for each missing a given digit. Like this:
int v[7][6] = {
{1, 2, 3, 4, 5, 6 },
{2, 3, 4, 5, 6, 0 }, // zeros in here to make the code simpler,
{1, 3, 4, 5, 6, 0 }, // they are never used
{1, 2, 4, 5, 6, 0 },
{1, 2, 3, 5, 6, 0 },
{1, 2, 3, 4, 6, 0 },
{1, 2, 3, 4, 5, 0 }
};
Then you can have a 2 level history. Finally to generate a number, if your match history is less than the max, shuffle v[0] and take v[0][0]. Otherwise, shuffle the first 5 values from v[n] and take v[n][0]. Something like this:
#include <algorithm>
int generate() {
static int prev = -1;
static int repeat_count = 1;
static int v[7][6] = {
{1, 2, 3, 4, 5, 6 },
{2, 3, 4, 5, 6, 0 }, // zeros in here to make the code simpler,
{1, 3, 4, 5, 6, 0 }, // they are never used
{1, 2, 4, 5, 6, 0 },
{1, 2, 3, 5, 6, 0 },
{1, 2, 3, 4, 6, 0 },
{1, 2, 3, 4, 5, 0 }
};
int r;
if(repeat_count < 2) {
std::random_shuffle(v[0], v[0] + 6);
r = v[0][0];
} else {
std::random_shuffle(v[prev], v[prev] + 5);
r = v[prev][0];
}
if(r == prev) {
++repeat_count;
} else {
repeat_count = 1;
}
prev = r;
return r;
}
This should result in good randomness (not reliant of rand() % N), no infinite loops, and should be fairly efficient given the small amount of numbers that we are shuffling each time.
Note, due to the use of statics, this is not thread safe, that may be fine for your usages, if it is not, then you probably want to wrap this up in an object, each with its own state.