Need solution to rand_range providing only floats and not integers - GDScript - random

For a project, I need to make use of a random number generator to provide random numbers as part of a Fisher-Yates Shuffle. I am using both randomize() and randi()%1+50 methods to get my random numbers.
However doing it this way does not let my Fisher-Yates shuffler count down to n=0, because if it does, it kicks out an error:
Division By Zero in operator %
Pointing right at my generator range where the % resides. I can work around this by using rand_range(), however, because rand_range() returns a float and not an integer, I am forced to round the result, which sometimes results in duplicate numbers, which I cannot have.
ceil() and floor() are also out of the question for the same reason. This, of course, could all be solved if GDScript included something like randi_range() but I have seen on other forums that this has been a problem since 2014, and to which there still is no solution.
Q: Given that this is not an option, does anyone know a way to return a random number, within a range, that does not include 0 and is a positive integer that doesn't require the % operator to dictate the range?
Don't get me wrong, I love the Godot engine, and appreciate it for what it is, but sometimes the code requires a tad too much "wrestling" for my mental sanity to handle.
Any help would be greatly appreciated.
Thanks in advance...

Godot has a class RandomNumberGenerator that does implement randi_range().
Here's a FisherYates Shuffle to prove to myself that it should work:
extends Node2D
var deck = []
func init_deck():
var arr = []
for i in range(1,52):
arr.append(i)
return arr
# Called when the node enters the scene tree for the first time.
func _ready():
deck = init_deck()
var n = len(deck)
print(fy_shuffle(deck, n))
pass # Replace with function body.
#Fisher Yates Shuffle
func fy_shuffle (arr, n):
# Start from the last element and swap one by one.
var rng = RandomNumberGenerator.new()
for i in range(n-1,0,-1):
# Pick a random index from 0 to i
var j = rng.randi_range(0,i+1)
# Swap arr[i] with the element at random index
var t1 = arr[i]
var t2 = arr[j]
arr[i] = t2
arr[j] = t1
return arr

const START = 10
const STOP = 20
var random = RandomNumberGenerator.new()
random.randomize()
var n = random.randi_range(START, STOP)

Related

List comprehension that involves summing values

I was presented with a problem where I had to create an algorithm that takes any given input integer of even length and, based on the input, determines whether the sum of the first n digits is equal to the sum of the last n digits, where each n is the equal to the length of the number divided by two (e.g. 2130 returns True, 3304 returns False).
My solution, which works but is rather unwieldy, was as follows:
def ticket(num):
list_num = [int(x) for x in str(num)]
half_length = int(len(list_num)/2)
for i in range(half_length*2):
first_half = list_num[0:half_length]
second_half = list_num[half_length::]
if sum(first_half) == sum(second_half):
return True
else:
return False
In an effort to improve my understanding of list comprehensions, I've tried to look at ways that I can make this more efficient but am struggling to do so. Any guidance would be much appreciated.
EDIT:
Thank you to jarmod:
Reorganised as so:
def ticket(num):
list_num = [int(x) for x in str(num)]
half_length = int(len(list_num)/2)
return sum(list_num[0:half_length]) == sum(list_num[half_length::])
ticket(1230)
You can remove the unnecessary assignment and loops to create a shorter, more pythonic solution:
def ticket(num):
half_length = int(len(list_num)/2)
first_half = sum(list(num[:half_length]))
second_half = sum(list(num[half_length:]))
return first_half == second_half
It can be further shortened though, which isn't as readable:
def ticket(num):
return sum(list(num[:len(num)//2])) == sum(list(num[len(num)//2:]))

Converting Map[Int, Double] to breeze.linalg.SparseVector

I am new to the Breeze library and I would like to convert a Map[Int, Double] to breeze.linalg.SparseVector, and ideally without having to specify a fixed length of the SparseVector. I managed to achieve the goal with this clumsy code:
import breeze.linalg.{SparseVector => SBV}
val mySparseVector: SBV[Double] = new SBV[Double](Array.empty, Array.empty, 10000)
myMap foreach { e => mySparseVector(e._1) = e._2 }
Not only I have to specify a fixed length of 10,000, but the code runs in O(n), where n is the size of the map. Is there a better way?
You can use VectorBuilder. There's a (sadly) undocumented feature where if you tell it the length is -1, it will happily let you add things. You will have to (annoyingly) set the length before you construct the result...
val vb = new VectorBuilder(length = -1)
myMap foreach { e => vb.add(e._1, e._2) }
vb.length = myMap.keys.max + 1
vb.toSparseVector
(Your code is actually n^2 because SparseVector has to be sorted so you're repeatedly moving elements around in an array. VectorBuilder gives you n log n, which is the best you can do.)

Given a number, produce another random number that is the same every time and distinct from all other results

Basically, I would like help designing an algorithm that takes a given number, and returns a random number that is unrelated to the first number. The stipulations being that a) the given output number will always be the same for a similar input number, and b) within a certain range (ex. 1-100), all output numbers are distinct. ie., no two different input numbers under 100 will give the same output number.
I know it's easy to do by creating an ordered list of numbers, shuffling them randomly, and then returning the input's index. But I want to know if it can be done without any caching at all. Perhaps with some kind of hashing algorithm? Mostly the reason for this is that if the range of possible outputs were much larger, say 10000000000, then it would be ludicrous to generate an entire range of numbers and then shuffle them randomly, if you were only going to get a few results out of it.
Doesn't matter what language it's done in, I just want to know if it's possible. I've been thinking about this problem for a long time and I can't think of a solution besides the one I've already come up with.
Edit: I just had another idea; it would be interesting to have another algorithm that returned the reverse of the first one. Whether or not that's possible would be an interesting challenge to explore.
This sounds like a non-repeating random number generator. There are several possible approaches to this.
As described in this article, we can generate them by selecting a prime number p and satisfies p % 4 = 3 that is large enough (greater than the maximum value in the output range) and generate them this way:
int randomNumberUnique(int range_len , int p , int x)
if(x * 2 < p)
return (x * x) % p
else
return p - (x * x) % p
This algorithm will cover all values in [0 , p) for an input in range [0 , p).
Here's an example in C#:
private void DoIt()
{
const long m = 101;
const long x = 387420489; // must be coprime to m
var multInv = MultiplicativeInverse(x, m);
var nums = new HashSet<long>();
for (long i = 0; i < 100; ++i)
{
var encoded = i*x%m;
var decoded = encoded*multInv%m;
Console.WriteLine("{0} => {1} => {2}", i, encoded, decoded);
if (!nums.Add(encoded))
{
Console.WriteLine("Duplicate");
}
}
}
private long MultiplicativeInverse(long x, long modulus)
{
return ExtendedEuclideanDivision(x, modulus).Item1%modulus;
}
private static Tuple<long, long> ExtendedEuclideanDivision(long a, long b)
{
if (a < 0)
{
var result = ExtendedEuclideanDivision(-a, b);
return Tuple.Create(-result.Item1, result.Item2);
}
if (b < 0)
{
var result = ExtendedEuclideanDivision(a, -b);
return Tuple.Create(result.Item1, -result.Item2);
}
if (b == 0)
{
return Tuple.Create(1L, 0L);
}
var q = a/b;
var r = a%b;
var rslt = ExtendedEuclideanDivision(b, r);
var s = rslt.Item1;
var t = rslt.Item2;
return Tuple.Create(t, s - q*t);
}
That generates numbers in the range 0-100, from input in the range 0-100. Each input results in a unique output.
It also shows how to reverse the process, using the multiplicative inverse.
You can extend the range by increasing the value of m. x must be coprime with m.
Code cribbed from Eric Lippert's article, A practical use of multiplicative inverses, and a few of the previous articles in that series.
You can not have completely unrelated (particularly if you want the reverse as well).
There is a concept of modulo inverse of a number, but this would work only if the range number is a prime, eg. 100 will not work, you would need 101 (a prime). This can provide you a pseudo random number if you want.
Here is the concept of modulo inverse:
If there are two numbers a and b, such that
(a * b) % p = 1
where p is any number, then
a and b are modular inverses of each other.
For this to be true, if we have to find the modular inverse of a wrt a number p, then a and p must be co-prime, ie. gcd(a,p) = 1
So, for all numbers in a range to have modular inverses, the range bound must be a prime number.
A few outputs for range bound 101 will be:
1 == 1
2 == 51
3 == 34
4 == 76
etc.
EDIT:
Hey...actually you know, you can use the combined approach of modulo inverse and the method as defined by #Paul. Since every pair will be unique and all numbers will be covered, your random number can be:
random(k) = randomUniqueNumber(ModuloInverse(k), p) //this is Paul's function

How to make a function that never pick twice the same number in Lua

I'm trying to make a function that generate random number, but never twice.
Here is what I got so far, but it doesn't work. It compiles, but then again it insert multiple times the same number in my array.
quiz = 10
array = {}
array[1] = 0 -- just to have something in it because it won't work in my loop otherwise...
ok = false
repeat
rdm = math.ceil(math.random() * quiz)
for i = 0, #array do
if(rdm == array[i]) then
break -- to break the for loop to pick a new number
elseif(rdm ~= array[i]) then
ok = true -- to end the repeat loop
table.insert(array, rdm) -- to keep a track of what I got so far
end
end
until ok == true
for b = 0, #array do -- #array should be ten
print(array[b])
end
What it does is it generate multiple times the same number and says it's different from the one in the table...
I guess my problem comes from logic... but I don't know where cause it all make sense for me
If you know you are going to need at most N numbers, you could pregenerate the random numbers and insert them in a table according to their value. Then your function randomly picks a number from that table and removes the number. Something like:
local rands = {}
local numRands = 100
-- populate table of random numbers
while #rands < numRands do
local r = math.random(1,1000)
rands[r]=r -- if duplicate, table stays same
end
local function getNeverSameRandom()
local index = math.random(1,numRands)
return table.remove(rands, index)
end
If you don't know how many to populate, then keep track via table:
local randsUsed = {}
local maxRand = 1000000 -- largest random # you want
local function getNeverSameRandom()
local rnd
repeat
rnd = math.random(1,maxRand)
until randsUsed[rnd] == nil
randsUsed[rnd] = rnd
return rnd
end
The problem of course is that if you call getNeverSameRandom many times, like half the max random number, your randsUsed table is going to get quite full, and the repeat-until is going to take longer and longer. Eventually, the table will be full, and the function will be in an infinite loop. You could easily check by keeping track with a counter, but you cannot use #randsUsed because randsUsed is a table with "holes" so the # operation can't be used. For example:
local randsUsedCount = 0
local function getNeverSameRandom()
if randsUsedCount == maxRand then
error("No more random #'s left in range 1-"..maxRand)
end
local rnd
repeat
rnd = math.random(1,maxRand)
until randsUsed[rnd] == nil
randsUsed[rnd] = rnd
randsUsedCount = randsUsedCount + 1
return rnd
end
The simplest way is to probably prepopulate an array of elements with the sequence you need (for example, 1..1000) and then shuffle the elements in place using something like Fisher-Yates algorithm:
local rands, n = {}, 1000
-- prepopulate
for i = 1, n do rands[i] = i end
-- shuffle
for i = n, 2, -1 do
local j = math.random(i)
rands[j], rands[i] = rands[i], rands[j]
end
-- use
print(table.remove(rands))
The same page also has "inside-out" version of the algorithm that does both initialization and shuffling.

Using non-continuous integers as identifiers in cells or structs in Matlab

I want to store some results in the following way:
Res.0 = magic(4); % or Res.baseCase = magic(4);
Res.2 = magic(5); % I would prefer to use integers on all other
Res.7 = magic(6); % elements than the first.
Res.2000 = 1:3;
I want to use numbers between 0 and 3000, but I will only use approx 100-300 of them. Is it possible to use 0 as an identifier, or will I have to use a minimum value of 1? (The numbers have meaning, so I would prefer if I don't need to change them). Can I use numbers as identifiers in structs?
I know I can do the following:
Res{(last number + 1)} = magic(4);
Res{2} = magic(5);
Res{7} = magic(6);
Res{2000} = 1:3;
And just remember that the last element is really the "number zero" element.
In this case I will create a bunch of empty cell elements [] in the non-populated positions. Does this cause a problem? I assume it will be best to assign the last element first, to avoid creating a growing cell, or does this not have an effect? Is this an efficient way of doing this?
Which will be most efficient, struct's or cell's? (If it's possible to use struct's, that is).
My main concern is computational efficiency.
Thanks!
Let's review your options:
Indexing into a cell arrays
MATLAB indices start from 1, not from 0. If you want to store your data in cell arrays, in the worst case, you could always use the subscript k + 1 to index into cell corresponding to the k-th identifier (k ≥ 0). In my opinion, using the last element as the "base case" is more confusing. So what you'll have is:
Res{1} = magic(4); %// Base case
Res{2} = magic(5); %// Corresponds to identifier 1
...
Res{k + 1} = ... %// Corresponds to indentifier k
Accessing fields in structures
Field names in structures are not allowed to begin with numbers, but they are allowed to contain them starting from the second character. Hence, you can build your structure like so:
Res.c0 = magic(4); %// Base case
Res.c1 = magic(5); %// Corresponds to identifier 1
Res.c2 = magic(6); %// Corresponds to identifier 2
%// And so on...
You can use dynamic field referencing to access any field, for instance:
k = 3;
kth_field = Res.(sprintf('c%d', k)); %// Access field k = 3 (i.e field 'c3')
I can't say which alternative seems more elegant, but I believe that indexing into a cell should be faster than dynamic field referencing (but you're welcome to check that out and prove me wrong).
As an alternative to EitanT's answer, it sounds like matlab's map containers are exactly what you need. They can deal with any type of key and the value may be a struct or cell.
EDIT:
In your case this will be:
k = {0,2,7,2000};
Res = {magic(4),magic(5),magic(6),1:3};
ResMap = containers.Map(k, Res)
ResMap(0)
ans =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
I agree with the idea in #wakjah 's comment. If you are concerned about the efficiency of your program it's better to change the interpretation of the problem. In my opinion there is definitely a way that you could priorotize your data. This prioritization could be according to the time you acquired them, or with respect to the inputs that they are calculated. If you set any kind of priority among them, you can sort them into an structure or cell (structure might be faster).
So
Priority (Your Current Index Meaning) Data
1 0 magic(4)
2 2 magic(5)
3 7 magic(6)
4 2000 1:3
Then:
% Initialize Result structure which is different than your Res.
Result(300).Data = 0; % 300 the maximum number of data
Result(300).idx = 0; % idx or anything that represent the meaning of your current index.
% Assigning
k = 1; % Priority index
Result(k).idx = 0; Result(k).Data = magic(4); k = k + 1;
Result(k).idx = 2; Result(k).Data = magic(5); k = k + 1;
Result(k).idx = 7; Result(k).Data = magic(6); k = k + 1;
...

Resources