Is there any way to generate random numbers without duplication?
For instance I want to generate 50 random numbers from 1 to 100 no duplication, any way to do this or do I have to check every time incoming number is already created or not?
you can use shuffle as following code.
import 'dart:math';
var list = new List<int>.generate(10, (int index) => index); // [0, 1, 4]
list.shuffle();
print(list);
You can use Set. Each object can occur only once when using it. Just try this:
Set<int> setOfInts = Set();
while (setOfInts.length < 50) {
setOfInts.add(Random().nextInt(range) + 1);
}
You can read the documentation here: Set Doc
Here is an alternative that avoids creating an array of all the possible values, and avoids repeatedly looping until no collision occurs. It may be useful when there is a large range to select from.
import 'dart:math';
class RandomList {
static final _random = new Random();
static List<int> uniqueSample({int limit, int n}) {
final List<int> sortedResult = [];
final List<int> result = [];
for (int i = 0; i < n; i++) {
int rn = _random.nextInt(limit - i); // We select from a smaller list of available numbers each time
// Increment the number so that it picks from the remaining list of available numbers
int j = 0;
for (; j < sortedResult.length && sortedResult[j] <= rn; j++) rn++;
sortedResult.insert(j, rn);
result.add(rn);
}
return result;
}
}
I haven't tested it exhaustively but it seems to work.
Related
Why does the first code generate a list of random numbers with repetition and the second code a list of numbers without repetition? The difference is only a list declared with int[] in (1) and int{} in(2).
1.)
final generatedRandoms = <int>[];
final rng = Random();
while (generatedRandoms.length < 100) {
final gr = rng.nextInt(100) + 1;
generatedRandoms.add(gr);
}
2.)
final generatedRandoms = <int>{};
final rng = Random();
while (generatedRandoms.length < 100) {
final gr = rng.nextInt(100) + 1;
generatedRandoms.add(gr);
}
Because of this declaration:
final generatedRandoms = <int>[];
versus
final generatedRandoms = <int>{};
The first declares a list, the second declares a set.
Lists can hold multiple values, even duplicates, while sets cannot have duplicates. Since both loops run until there are 100 items in the container, you might get duplicates in the first example and you will not have duplicates in the second.
If you time them, you will notice the second one takes longer on average, because it will geenerate a lot more than 100 random numbers to get to 100 unique numbers.
I'm experiencing a ClassCastException with the following piece of code.
var temp = set.stream().flatMap(Arrays::stream).toArray(Token[]::new);
I also tried collecting into a set, but I got the same error.
var temp = set.stream().flatMap(Arrays::stream).collect(Collectors.toSet());
set is declared as a Set<Token[]>, but when debugging it says Set<Object[]>.
Edit:
I've narrowed down the issue to the method subsetsWithMinSize. Eventhough I call it with:
new Sets<Token>().subsetsWithMinSize(value, x);
it seems to return a Set<Object[]>. Can someone tell me why that is and how to fix it?
Here is the method subsetsWithMinSize:
public Set<T[]> subsetsWithMinSize(List<T> list, int min) {
Set<T[]> res = new HashSet<>();
for (int i = 0; i <= list.size() - min; i++)
for (int j = 0; list.size() - j >= i + min; j++) {
List<T> temp = new ArrayList<>();
for (int k = i; k < list.size() - j; k++) temp.add(list.get(k));
res.add((T[]) temp.toArray());
}
return res;
}
So after you guys helped me to minimise the search scope I found the issue.
When I was using (T[]) to cast it wouldn't work, because after type erasure T would just be cast to an Object. Here's the thread I found the answer on: How to properly return generic array in Java generic method?.
So to finally correct the code I had to change the method a little by using Array.newInstance() and put in Class<T> to make it work:
public Set<T[]> subsetsWithMinSize(Class<T> clazz, List<T> list, int min) {
Set<T[]> res = new HashSet<>();
for (int i = 0; i <= list.size() - min; i++)
for (int j = 0; list.size() - j >= i + min; j++) {
List<T> temp = new ArrayList<>();
for (int k = i; k < list.size() - j; k++)
temp.add(list.get(k));
var arr = (T[]) Array.newInstance(clazz, temp.size());
IntStream.range(0, temp.size()).forEach(k -> arr[k] = temp.get(k));
res.add(arr);
}
return res;
}
It uses Array.newInstance() to make T[] (cast is still necessary for the compiler) and then just copies temp into that array.
Another option would be to use lists instead of arrays, which is the better way.
Reference from Effective Java:
In Summary, arrays and generics have very different type rules. Arrays are covariant and reified; generics are invariant and erased. As a consequcne, arrays provide runtime type safety but not compile-time type safety and vice versa for generics. Generally speaking, arrays and generics don’t mix well. If you find yourself mixing them and getting compile-time error or warnings, your first impulse should be to replace the arrays with lists.
The issue with that is that, for my use at least, lists use an unnecessarily big amount of space. Combined with the fact that I am making a powerset of the results later everything would just run super slow.
I have a List of the type Model. when I loop all its elements and loop the next one except for the last one, then change the last one manually, the one before changes.
here is a little code to reproduce the problem (also you can run it directly in dartpad from here)
void main() {
List<Model> s = [];
for (int i = 0; i < 5; i++) {
s.add(Model(i));
}
for (int i = 0; i < s.length - 1; i++) {
s[i] = s[i + 1];
}
print(s);
s[s.length-1].x = 100;
print(s);
}
class Model {
int x;
Model(this.x);
#override
String toString() => 'x: ' + this.x.toString();
}
notice that this problem does not happen when you comment out the for loop or the manual change, or instead of changing the last one's property, you reassign a new value to it, like s[s.length - 1] = Model(100);. seems like dart for some reason is re-running the loop.
When you run the second for loop, you assign the i + 1th Model to the ith position in the list:
// initialise list
for (int i = 0; i < s.length; i++) {
s[i] = s[i + 1]
}
If you unwrap the loop, it looks roughly like this:
s[0] = s[1];
s[1] = s[2];
s[2] = s[3];
s[3] = s[4];
Notice that this leaves s[4] unchanged, but also assigns it to s[3].
In Dart, variables contain references to objects. This means that when your list runs s[3] = s[4];, both s[3] and s[4] point to the same object.
Now, if you modify s[4] you, are actually modifying the objects that s[4] refers to, which happens to also be the object that s[3] refers to, so they both appear to change in your list.
In a list of sequential integers, is there a simple way to locate where another integer would be placed (between two of the list members)?
main() {
var myList = new List();
myList.addAll([0, 4, 10, 20, 33, 45, 55, 64]);
int setStart;
int currentPosition;
currentPosition = 12;
// if currentPosition is greater than or equal to myList[fooPosition]
// but less than myList[barPosition]
// setStart = myList[foo]
}
So since the currentPosition is 12, the correct answer for setStart would be 10.
Try checking out package:collection's binarySearch.
Ok, figured it out myself. Pretty simple really. I just needed to add another variable (x) to indicate the list position of the upper number:
for (var i = 0; i < myList.length; i++) {
var x = i + 1;
if (currentPosition >= myList[i] && currentPosition < myList [x]) {
setStart = myList[i];
};
};
local function fShallowCopy(tData)
local tOutput = {}
for k,v in ipairs(tData) do
tOutput[k] = v
end
return tOutput
end
local function fLexTblSort(tA,tB) --sorter for tables
for i=1,#tA do
if tA[i]~=tB[i] then
return tA[i]<tB[i]
end
end
return false
end
function fBWT(tData)
--setup--
local iSize = #tData
local tSolution = {}
local tSolved = {}
--key table--
for n=1,iSize do
tData[iSize] = fRemove(tData,1)
tSolution[n] = fShallowCopy(tData)
end
table.sort(tSolution,fLexTblSort)
--encode output--
for i=1,iSize do
tSolved[i] = tSolution[i][iSize]
end
--finalize--
for i=1,iSize do
if fIsEqual(tSolution[i],tData) then
return i,tSolved
end
end
return false
end
Above is my current code for achieving BWT encoding in Lua. The issue is because of the size of the tables and lengths of loops it takes a long time to run. For a 1000 character input the average encoding time is about 1.15 seconds. Does anyone have suggestions for making a faster BWT encoding function?
the biggest slowdowns appear to be in fLexTblSort and fShallowCopy. I have included both above the BWT function as well.
If I see right, your algorithm has complexity O(n^2 log n), if the sort is quicksort. The comparator function fLexTblSort takes O(n) itself for each pair of values you compare.
As I checked with my implementation from few years back, I see possible space to improve. You create all the possible rotations of the tData, which takes also a lot of time. I used only single data block and I stored only starting positions of particular rotations. You also use a lot of loops which can shrink into less.
Mine implementation was in C, but the concept can be used also in Lua. The idea in some hybrid pseudocode between your Lua and C.
function fBWT(tData)
local n = #tData
local tSolution = {}
for(i = 0; i < n; i++)
tSolution[i] = i;
--table.sort(tSolution, fLexTblSort)
quicksort(tData, n, tSolution, 0, n)
for(i = 0; i < n; i++){
tSolved[i] = tData[(tSolution[i]+n-1)%n];
if( tSolution[i] == 0 )
I = i;
}
return I, tSolved
end
You will also need your own sort function, because the standard does not offer enough flexibility for this magic. Quicksort is a good idea (you might avoid some of the arguments, but I pasted just the C version I was using):
void swap(int array[], int left, int right){
int tmp = array[right];
array[right] = array[left];
array[left] = tmp;
}
void quicksort(uint8_t data[], int length, int array[], int left, int right){
if(left < right){
int boundary = left;
for(int i = left + 1; i < right; i++){
if( offset_compare(data, length, array, i, left) < 0 ){
swap(array, i, ++boundary);
}
}
swap(array, left, boundary);
quicksort(data, length, array, left, boundary);
quicksort(data, length, array, boundary + 1, right);
}
}
The last step is your own comparator function (similar to your original, but working on the rotations, again in C):
/**
* compare one string (fixed length) with different rotations.
*/
int offset_compare(uint8_t *data, int length, int *array, int first, int second){
int res;
for(int i = 0; i < length; i++){
res = data[(array[first]+i)%length] - data[(array[second]+i)%length];
if( res != 0 ){
return res;
}
}
return 0;
}
This is the basic idea I came up with few years ago and which worked for me. Let me know if there is something not clear or some mistake.