I'm currently trying to learn Swift for iOS app development. I'm fairly new to programming in general but do have some experience in other languages
I've just learnt about the modulo operator, or the remainder operator depending on what you call it. (%)
It should return the remainder of an equation, right?
var equation = 500 % 30
When I print equation, it writes '20' but I can't figure out why? 30 does not fit into 500 20 times, it's 16.6. The / operator would return 16 so I expected % to return whatever the remainder is?
Please tell me if I'm being stupid but I can't figure it out.
a % b does not determine how many times b fits into a. The modulo operator determines what remains when you subtract the largest multiple of b that is smaller than a from a. In this case, the largest multiple of 30 that is smaller than 500 is 480, and 500 - 480 = 20, so 500 % 30 = 20.
I feel stupid. Sorry.
480 is the highest number 30 can perfectly fit into, which leaves 20 remaining.
I'm looking to generate a table of random values, but want to make sure that none of those values are repeated within the table.
So my basic table generation looks like this:
numbers = {}
for i = 1, 5 do
table.insert(numbers, math.random(20))
end
So that will work in populating a table with 5 random values between 1-20. However, it's the making sure none of those values repeat is where I'm stuck.
One approach would be to shuffle an array of numbers and then take the first n numbers. The wrong way to go about shuffling an array is to maintain a list of previously generated random numbers, checking against that with each newly generated random number before adding it to the final array. Such a solution is O(n^2) in time complexity when iterating over the array during the check; this will be painful for large arrays, or for small arrays when many must be created. Lua has constant time array access since tables are really hash tables, so you could get away with this, except: sometimes many random numbers will need to be tried before a suitable one (that has not already been used) is found. This can be a real problem near the end of an array of many random numbers, i.e., when you want 1000 random numbers and have filled all but the last slot, how many random tries (and how many iterations of the 999 numbers already selected) will it take to find the only number (42, of course) that is still available?
The right way to go about shuffling is to use a shuffling algorithm. The Fisher-Yates shuffle is a common solution to this problem. The idea is that you start at one end of an array, and swap each element with a random element that occurs later in the list until the entire array has been shuffled. This solution is O(n) in time complexity, thus much less wasteful of computational resources.
Here is an implementation in Lua:
function shuffle (arr)
for i = 1, #arr - 1 do
local j = math.random(i, #arr)
arr[i], arr[j] = arr[j], arr[i]
end
end
Testing in the REPL:
> t = { 1, 2, 3, 4, 5, 6 }
> table.inspect(t)
1 = 1
2 = 2
3 = 3
4 = 4
5 = 5
6 = 6
> shuffle(t)
> table.inspect(t)
1 = 4
2 = 5
3 = 1
4 = 6
5 = 2
6 = 3
This can easily be extended to create lists of random numbers:
function shuffled_numbers (n)
local numbers = {}
for i = 1, n do
numbers[i] = i
end
shuffle(numbers)
return numbers
end
REPL interaction:
> s = shuffled_numbers(10)
> table.inspect(s)
1 = 9
2 = 5
3 = 3
4 = 4
5 = 7
6 = 6
7 = 2
8 = 10
9 = 8
10 = 1
If you want to see what is happening during the shuffle, add a print statement in the shuffle function:
function shuffle (arr)
for i = 1, #arr - 1 do
local j = math.random(i, #arr)
print(string.format("%d (%d) <--> %d (select %d)", i, arr[i], j, arr[j]))
arr[i], arr[j] = arr[j], arr[i]
end
end
Now you can see the swaps as they occur if you recall that in the above implementation of shuffled_numbers the array { 1, 2, ..., n } is the starting point of the shuffle. Note that sometimes a number is swapped with itself, which is to say that the number in the current unselected position is a valid choice, too. Also note that the last number is automatically the correct selection, since it is the only number that has not yet been randomly selected:
> s = shuffled_numbers(10)
1 (1) <--> 5 (select 5)
2 (2) <--> 10 (select 10)
3 (3) <--> 5 (select 1)
4 (4) <--> 9 (select 9)
5 (3) <--> 8 (select 8)
6 (6) <--> 9 (select 4)
7 (7) <--> 8 (select 3)
8 (7) <--> 10 (select 2)
9 (6) <--> 9 (select 6)
> table.inspect(s)
1 = 5
2 = 10
3 = 1
4 = 9
5 = 8
6 = 4
7 = 3
8 = 2
9 = 6
10 = 7
Obtaining a selection of 5 random numbers between 1 and 20 is easy enough to accomplish using the shuffle function; one of the virtues of this approach is that the shuffling operation has been abstracted to an O(n) procedure which can shuffle any array, numeric or otherwise. The function that calls shuffle is responsible for supplying the input and returning the results.
A simple solution for more flexibility in the range of random numbers returned:
-- Take the first N numbers from a shuffled range [A, B].
function shuffled_range_take (n, a, b)
local numbers = {}
for i = a, b do
numbers[i] = i
end
shuffle(numbers)
return { table.unpack(numbers, 1, n) }
-- table.unpack won't work for very large ranges, e.g. [1, 1000000]
-- You could instead use this for arbitrarily large ranges:
-- local take = {}
-- for i= 1, n do
-- take[i] = numbers[i]
-- end
-- return take
end
REPL interaction creating a table containing 5 random values between 1 and 20:
> s = shuffled_range_take(5, 1, 20)
> table.inspect(s)
1 = 1
2 = 10
3 = 4
4 = 8
5 = 20
But, there is a disadvantage to the shuffle method in some circumstances. When the number of elements needed is small compared with the number of available elements, the above solution must shuffle a large array to obtain comparatively few random elements. The shuffle is O(n) in the number of elements available, while the memoization method is roughly O(n) in the number of elements chosen. A memoization method like that of #AlexanderMashin performs poorly when the goal is to create an array of 20 random numbers between 1 and 20, because the final numbers chosen may need to be chosen many times before suitable numbers are found. But when only 5 random numbers between 1 and 20 are needed, this problem with duplicate choices is less of an issue. This approach seems to perform better than the shuffle, up to about 10 numbers needed from 20 random numbers. When more than 10 numbers are needed from 20, the shuffle begins to perform better. This break-even point is different for larger numbers of elements to choose from; for 1000 available elements, parity is reached at about 700 chosen. When performance is critical, testing is the only way to determine the best solution.
numbers = {}
local i = 1;
while i<=5 do
n = 0
local rand = math.random(20)
for x=1,#numbers do
if numbers[x] == rand then
n = n + 1
end
end
if n == 0 then
table.insert(numbers, rand)
i = i + 1
end
n = 0
end
the method I used for this process was to use a for to scan each of the elements in the table and increase the variable n if one of them was equal to the random value given, so if x was different from 0, the value would not be inserted in the table and would not increment the variable i (I had to use the while to work with i)
if you want to print each of the elements in the table to check the values you can use this:
for i=1,#numbers do
print(numbers[i])
end
I suggest an alternative method based on the fact that it is easy to make sets in Lua: they are just tables with true values.
-- needed is how many random numbers in the table are needed,
-- maximum is the maximum value of a random non-negtive integer.
local function fill_table( needed, maximum )
math.randomseed ( os.time () ) -- reseed the random numbers generator
local numbers = {}
local used = {} -- which numbers are already used
for i = 1, needed do
local random
repeat
random = math.random( maximum )
until not used[random]
used[random] = true
numbers[i] = random
end
return numbers
end
Making a table with 20 keys (use for/do/end) and then do your desired times
rand_number=table.remove(tablename, math.random(1,#tablename))
EDIT: Corrected - See first comment
And rand_number never holds the same value. I use this as a simulation for a "Lottozahlengenerator" (german, sorry) or random video/music clips playing where duplicates are unwanted.
I want to calculate a score out of 1000 based on some seconds that was given to me. The score should be high if seconds is a small value and it should be low if seconds is a large value.
For eg. If a folder A was accessed 30 secs ago and folder B was accessed 500 secs ago then score of folder A should be higher compared to score of folder B since folder A is the one that was recently accessed compared to folder B. The score cannot exceed more than 1000.
What you can do in a simple way is to multiply the numbers by -1 so you get negative values on both sides and then you can start comparing them.
Example :
folder A was accessed 30 secs
folder B was accessed 500 secs
And you want folder A to be a higher value than Folder B
so :
A = (30 * -1) = -30 sec
B = (500 * -1) = -500 sec
so comparing: A > B
And then add a condition where the score cannot exceed 1000.
I'm in the middle of creating a small lua program. In the program I want to calculate the percentage of hits (numPercent) from the number of hits (numHits) and the number of misses (numMiss).
For instance, if I were to hit the target 5 times and missed 0, it would show the percentage as 100% Hits
How would I formulate this problem?
This is what I got so far, which as you can see is completely incorrect.
if ( numHit > numMiss) then --calculates percentage
numPercent = numHit / numMiss * 100/2
else
numPercent = numMiss / numHit * 100/2
end
Could I get some guidance in formulating it correctly?
numPercent = 100 * numHit / (numHit + numMiss)
You may need to test if "numHit + numMiss" is zero before that, and return whatever you want in that case.
I'm using this code to calculate the average of some numbers - note that the rankings column is serialized and contains a hash:
#reviews.collect{|review| review.rankings[label].to_i}.sum.to_f/#reviews.length if #reviews.length > 0
The drawback with this code is this: if one of the values is nil, the average calculates as if it existed as a zero. The problem is basically that the #reviews.length denominator assumes every review has a relevant value.
How do I exclude from the denominator those reviews that don't count?
Thank you very much for your answers. The problem ended up being with the denominator, i.e. the /#reviews.length part. When I used reject on both numerator and denominator, the equation stopped dividing by total length and started dividing by (length - no of nils).
End result - 2 scores [0 and 100] average to 50; [nil and 100] average to 100.
Array#reject to the rescue.
#reviews.reject{|review| review.rankings[label].nil?}.collect{|review| review.rankings[label].to_i}.sum.to_f/#reviews.length if #reviews.length > 0
I would go with that approach (using compact to kill the nils):
rankings = #reviews.map{ |review| review.rankings[label] }.compact
rankings.map(&:to_i).sum.to_f / rankings.count unless rankings.count == 0
if #reviews.length > 0
#reviews.collect{|r| r.rankings[label]}.compact.map(&:to_f).sum / #reviews.length
else
0
end