What is the most elegant way to pick a random value from a set defined in NS_OPTION in objective-c? - objective-c

I have an NS_OPTION that I'm defining as such :
typedef NS_OPTIONS(NSInteger, PermittedSize) {
SmallSize = 1 << 0,
MediumSize = 1 << 1,
LargeSize = 1 << 2
};
And later I set the values I need :
PermittedSize size = SmallSize | MediumSize;
I'm using it to randomly generate an various objects of small and medium sizes(duh) for a particular level of a game.
What is the best way to go about selecting which size of an object to generate? Meaning, I'd like to choose randomly for each object I'm generating whether it will be one of the 2 options allowed (small and medium in this case). Normally I would use an arc4random function with the range of numbers I need - but in this case, how can it be done with bits? (and then mapped back to the values of the PermittedSize type?

Use the result from arc4random to determine the amount of bit shifting you want to do. Something like this:
int bitShiftAmount = arc4random_uniform(numberOfPermittedSizes);
PermittedSize size = 1 << bitShiftAmount;

You are still working with integers. SmallSize is 1. MediumSize is 2. And LargeSize is 4.
So pick a random number from 1 to 3. 1 is small, 2 is medium, 3 is both.
Once you have a random number, assign it.
NSInteger val = arc4random_uniform(3) + 1; // give 1-3
PermittedSize size = (PermittedSize)val;

Related

How to get same rank for same scores in Redis' ZRANK?

If I have 5 members with scores as follows
a - 1
b - 2
c - 3
d - 3
e - 5
ZRANK of c returns 2, ZRANK of d returns 3
Is there a way to get same rank for same scores?
Example: ZRANK c = 2, d = 2, e = 3
If yes, then how to implement that in spring-data-redis?
Any real solution needs to fit the requirements, which are kind of missing in the original question. My 1st answer had assumed a small dataset, but this approach does not scale as dense ranking is done (e.g. via Lua) in O(N) at least.
So, assuming that there are a lot of users with scores, the direction that for_stack suggested is better, in which multiple data structures are combined. I believe this is the gist of his last remark.
To store users' scores you can use a Hash. While conceptually you can use a single key to store a Hash of all users scores, in practice you'd want to hash the Hash so it will scale. To keep this example simple, I'll ignore Hash scaling.
This is how you'd add (update) a user's score in Lua:
local hscores_key = KEYS[1]
local user = ARGV[1]
local increment = ARGV[2]
local new_score = redis.call('HINCRBY', hscores_key, user, increment)
Next, we want to track the current count of users per discrete score value so we keep another hash for that:
local old_score = new_score - increment
local hcounts_key = KEYS[2]
local old_count = redis.call('HINCRBY', hcounts_key, old_score, -1)
local new_count = redis.call('HINCRBY', hcounts_key, new_score, 1)
Now, the last thing we need to maintain is the per score rank, with a sorted set. Every new score is added as a member in the zset, and scores that have no more users are removed:
local zdranks_key = KEYS[3]
if new_count == 1 then
redis.call('ZADD', zdranks_key, new_score, new_score)
end
if old_count == 0 then
redis.call('ZREM', zdranks_key, old_score)
end
This 3-piece-script's complexity is O(logN) due to the use of the Sorted Set, but note that N is the number of discrete score values, not the users in the system. Getting a user's dense ranking is done via another, shorter and simpler script:
local hscores_key = KEYS[1]
local zdranks_key = KEYS[2]
local user = ARGV[1]
local score = redis.call('HGET', hscores_key, user)
return redis.call('ZRANK', zdranks_key, score)
You can achieve the goal with two Sorted Set: one for member to score mapping, and one for score to rank mapping.
Add
Add items to member to score mapping: ZADD mem_2_score 1 a 2 b 3 c 3 d 5 e
Add the scores to score to rank mapping: ZADD score_2_rank 1 1 2 2 3 3 5 5
Search
Get score first: ZSCORE mem_2_score c, this should return the score, i.e. 3.
Get the rank for the score: ZRANK score_2_rank 3, this should return the dense ranking, i.e. 2.
In order to run it atomically, wrap the Add, and Search operations into 2 Lua scripts.
Then there's this Pull Request - https://github.com/antirez/redis/pull/2011 - which is dead, but appears to make dense rankings on the fly. The original issue/feature request (https://github.com/antirez/redis/issues/943) got some interest so perhaps it is worth reviving it /cc #antirez :)
The rank is unique in a sorted set, and elements with the same score are ordered (ranked) lexically.
There is no Redis command that does this "dense ranking"
You could, however, use a Lua script that fetches a range from a sorted set, and reduces it to your requested form. This could work on small data sets, but you'd have to devise something more complex for to scale.
unsigned long zslGetRank(zskiplist *zsl, double score, sds ele) {
zskiplistNode *x;
unsigned long rank = 0;
int i;
x = zsl->header;
for (i = zsl->level-1; i >= 0; i--) {
while (x->level[i].forward &&
(x->level[i].forward->score < score ||
(x->level[i].forward->score == score &&
sdscmp(x->level[i].forward->ele,ele) <= 0))) {
rank += x->level[i].span;
x = x->level[i].forward;
}
/* x might be equal to zsl->header, so test if obj is non-NULL */
if (x->ele && x->score == score && sdscmp(x->ele,ele) == 0) {
return rank;
}
}
return 0;
}
https://github.com/redis/redis/blob/b375f5919ea7458ecf453cbe58f05a6085a954f0/src/t_zset.c#L475
This is the piece of code redis uses to compute the rank in sorted sets. Right now ,it just gives rank based on the position in the Skiplist (which is sorted based on scores).
What does the skiplistnode variable "span" mean in redis.h? (what is span ?)

Incrementing part of bit mask

Given enum:
typedef NS_OPTIONS(NSUInteger, BREBreathingProgram) {
BREBreathingProgramPaceSlowest = 0,
BREBreathingProgramPaceSlow = 1,
BREBreathingProgramPaceMedium = 2,
BREBreathingProgramPaceFast = 3,
BREBreathingProgramPaceFastest = 4,
BREBreathingProgramExcludeHold = 1 << 3,
};
To increment BreathingProgramPace I perform the following calculation:
breathingProgram = ((breathingProgram >> 3) & 1) << 3 | (breathingProgram & 3) + 1;
Is this the simplest way to do this?
Based on your 2nd comment to this answer I am rewriting the answer.
You have setup your enum so the first 3 bits represent a single value for the pace. You can have a value up to 7.
The fourth bit represents your "hold".
You wish to have some pace value and also some other bits set. You then wish to be able to increment that pace while keeping the other bits as they are.
This is simple.
breathingProgram++;
A simple increment is all you need. Example. Lets say your pace is set to "Slow" and the "hold" bit is set. This gives a value of 9 (1 for "slow" and 8 for "hold").
Now you wish to increment the pace to "medium". Simply incrementing from 9 to 10 does this.
While this works there is the risk that you could over increment the value and start messing with the flags.
A safer (and more complicated) way would be:
breathingProgram = (breathingProgram & 0xF8) | (((breathingProgram & 0x07) + 1) & 0x07);
This ensures that you can't do the increment past the allotted "pace" values and into the flags area. This would actually wrap the "pace" value back to zero if you went too far.

What is the Bitewise AND doing here

I have never used Bitewise AND in my life. I have researched this operator but it still eludes me as to what it exactly does. So, I will ask with some code I just came across, what is the Bitwise And doing here:
CASE
WHEN (ft.Receiver_Status & 2) = 2 THEN '3D'
WHEN (ft.Receiver_Status & 1) = 1 THEN '2D'
WHEN (ft.Receiver_Status & 32) = 32 THEN 'Invalid' -- AR 220312
ELSE 'None'
Is it enforcing the same datatype, such as smallint converts to int before comparing the value of Receiver_Status?
ft.Receiver_Status & 1: 1 is 20, so it is pulling out the value of the bit at position 0.
ft.Receiver_Status & 2: 2 is 21, so it is pulling out the value of the bit at position 1.
ft.Receiver_Status & 32: 32 is 25, so it is pulling out the value of the bit at position 5.
Note that, for example, the = 32 in (ft.Receiver_Status & 32) = 32 is actually redundant. This could instead be (ft.Receiver_Status & 32) != 0 because all you're interested in is whether that bit is a 0 or a 1.
The bitwise AND checks to see whether a particular bit is set. It appears ft.Receiver_Status is an integer which stores various flags in different bits.
1 in binary is 00001 so ft.Receiver_Status & 1 is checking to see if the first bit is set.
2 in binary is 00020 so ft.Receiver_Status & 1 is checking to see if the second bit is set.
32 in binary is 10000 so ft.Receiver_Status & 32 is checking to see if the fifth bit is set.
To see precisely how this works, the result of the AND operation will be the bit at position n will be 1 f and only if the bit at position n in both the first and the second number is 1. Consider the following binary numbers:
011010001 (209)
000010000 ( 32)
---------------
000010000 ( 32)
And alternatively,
011001001 (201)
000010000 ( 32)
---------------
000000000 ( 0)
(something & constant) == constant (where constant is a power of two) is a way of ensuring that the bit defined in constant is set. Consider your first case. All of the bits in 2 aren't set except for the second bit, so we know the rest will be zero. If the second bit is not set in Receiver_Status then the result will be zero, if it is set, that bit will be one and the result will be two, the same as the bit mask.
It could also be written as (ft.Receiver_Status & 2) > 0 to avoid repeating the bit mask in each case.
You should read about bit flags. That's the way to check, if particular bit within a bigger data type (e.g. byte) is set to 1 or not.
Example:
Consider having a bite with following bits content: 00110101. You'd like to check the fifth position. You need to change all other bits to 0 and check, if that one is 1 or 0. To do that, perform bitewise AND with 2^4:
00110101
00010000 &
--------
00010000
To give a concrete example with all these other great answers, if Receiver_Flags were 3, the 1 and 2 bits are on. Likewise, if it were 34, the 2 and 32 bits are on.
A lot of times an enum is used to set these fields. Consider this enum:
public enum Flags
{
ThreeD = 1,
TwoD = 2,
Invalid = 3
}
You might set the value like this:
Receiver_Flags = Flags.ThreeD | Flags.TwoD
and the value would be 3. In that case the 1 and 2 bits would be on.
This is very similar to Enum.HasFlag. Here's one way to implement that for a Test enum:
static bool HasFlag(Test flags, Test flag)
{
return (flags & flag) != 0;
}
Basically, (ft.Receiver_Status & 32) = 32 checks if the fifth bit is 1 or 0.

I'm new to visual basic and trying to understand how to set individual bits in a byte [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Hi, I am new to Visual Basic, I have a project where I need to be able to manipulate individual bits in a value.
I need to be able to switch these bits between 1 and 0 and combine multiple occurrences of bits into one variable in my code.
Each bit will represent a single TRUE / FALSE value, so I'm not looking for how to do a single TRUE / FALSE value in one variable, but rather multiple TRUE / FALSE values in one variable.
Can someone please explain to me how I can achieve this please.
Many thanks in advance.
Does it have to be exactly one bit?
Why don't you just use the actual built in VB data type of Boolean for this.
http://msdn.microsoft.com/en-us/library/wts33hb3(v=vs.80).aspx
It's sole reason for existence is so you can define variables that have 2 states, true or false.
Dim myVar As Boolean
myVar = True
myVar = Flase
if myVar = False Then
myVar = True
End If
UPDATE (1)
After reading through the various answers and comments from the OP I now understand what it is the OP is trying to achieve.
As others have said the smallest unit one can use in any of these languages is an 8 bit byte. There is simply no order of data type with a smaller bit size than this.
However, with a bit of creative thinking and a smattering of binary operations, you can refer to the contents of that byte as individual bits.
First however you need to understand the binary number system:
ALL numbers in binary are to the power of two, from right to left.
Each column is the double of it's predecessor, so:
1 becomes 2, 2 becomes 4, 4 becomes 8 and so on
looking at this purely in a binary number your columns would be labelled thus:
128 64 32 16 8 4 2 1 (Remember it's right to left)
this gives us the following:
The bit at position 1 = 1;
The bit at position 2 = 2;
The bit at position 3 = 4;
The bit at position 4 = 8;
and so on.
Using this method on the smallest data type you have (The byte) you can pack 8 bit's into one value. That is you could use one variable to hold 8 separate values of 1 or 0
So while you cannot go any smaller than a byte, you can still reduce memory consumption by packing 8 values into 1 variable.
How do you read and write the values?
Remember the column positions? well you can use something called Bit Shifting and Bit masks.
Bit Shifting is the process of using the
<<
and
>>
operators
A shifting operation takes as a parameter the number of columns to shift.
EG:
Dim byte myByte
myByte = 1 << 4
In this case the variable 'myByte' would become equal to 16, but you would have actually set bit position 5 to a 1, if we illustrate this, it will make better sense:
mybyte = 0 = 00000000 = 0
mybyte = 1 = 00000001 = 1
mybyte = 2 = 00000010 = (1 << 1)
mybyte = 4 = 00000100 = (1 << 2)
mybyte = 8 = 00001000 = (1 << 3)
mybyte = 16 = 00010000 = (1 << 4)
the 0 through to 16 if you note is equal to the right to left column values I mentioned above.
given what Iv'e just explained then, if you wanted to set bits 5, 4 and 1 to be equal to 1 and the rest to be 0, you could simply use:
mybyte = 25(16 + 8 + 1) = 00011001 = (1 << 4) + (1 << 3) + 1
to get your bits back out, into a singleton you just bit shift the other way
retrieved bit = mybyte >> 4 = 00000001
Now there is unfortunately however one small flaw with the bit shifting method.
by shifting back and forth you are highly likely to LOOSE information from any bits you might already have set, in order to prevent this from happening, it's better to combine your bit shifting operations with bit masks and boolean operations such as 'AND' & 'OR'
To understand what these do you first need to understand simple logic principles as follows:
AND
Output is one if both the A and B inputs are 1
Illustrating this graphically
A B | Output
-------------
0 0 | 0
0 1 | 0
1 0 | 0
1 1 | 1
As you can see if a bit position in our input number is a 1 and the same position in our input number B is 1, then we will keep that position in our output number, otherwise we will discard the bit and set it to a 0, take the following example:
00011001 = Bits 5,4 and 1 are set
00010000 = Our mask ONLY has bit 5 set
if we perform
00011001 AND 0010000
we will get a result of
00010000
which we can then shift down by 5
00010000 >> 5 = 00000001 = 1
so by using AND we now have a way of checking an individual bit in our byte for a value of 1:
if ((mybyte AND 16) >> 1) = 1 then
'Bit one is set
else
'Bit one is NOT set
end if
by using different masks, with the different values of 2 in the right to left columns as shown previously, we can easily extract different singular values from our byte and treat them as a simple bit value.
Setting a byte is just as easy, except you perform the operation the opposite way using an 'OR'
OR
Output is one if either the A or B inputs are 1
Illustrating this graphically
A B | Output
-------------
0 0 | 0
0 1 | 1
1 0 | 1
1 1 | 1
eg:
00011001 OR 00000100 = 00011101
as you can see the bit at position 4 has been set.
To answer the fundamental question that started all this off however, you cannot use a data type in VB that has any resolution less than 1 byte, I suspect if you need absolute bit wise accuracy I'm guessing you must be writing either a compression algorithm or some kind of encryption system. :-)
01010100 01110010 01110101 01100101, is the string value of the word "TRUE"
What you want is to store the information in a boolean
Dim v As Boolean
v = True
v = False
or
If number = 84 Then ' 84 = 01010100 = T
v = True
End If
Other info
Technicaly you can't store anything in a bit, the smallest value is a char which is 8 bit. You'll need to learn how to do bitwise operation. Or use the BitArray class.
VB.NET (nor any other .NET language that I know of) has a "bit" data type. The smallest that you can use is a Byte. (Not a Char, they are two-bytes in size). So while you can read and convert a byte of value 84 into a byte with value 1 for true, and convert a byte of value 101 into a byte of value 0 for false, you are not saving any memory.
Now, if you have a small and fixed number of these flags, you CAN store several of them in one of the integer data types (in .NET the largest integer data type is 64 bits). Or if you have a large number of these flags you can use the BitArray class (which uses the same technique but backs it with an array so storage capacity is greater).

Any way to give names to each of a set of successive integers?

I have an int called setupStage. This is simply a value I increment at the completion of each stage, so I can say, if (setupStage == 2), and I know that I am at the third stage (it defaults to 0).
Is there a way I can refer to these numbers in a better way? For example:
if (setupStage == stageEnterName)
Instead of having to refer to its actual raw int value.
It may be a misconception, but does what I am trying to achieve have anything to do with defining macros?
Yes!
Try this:
typedef enum {
MyType0,
MyType1,
MyType2,
MyType3
} MyType;
This is the same thing as this:
typedef enum {
MyType0 = 0,
MyType1,
MyType2,
MyType3
} MyType;
The values default to 0 at the first slot and then increment by 1 automatically. Note that the token names (MyTypeX) are arbitrary string values you set.
In this case they go from 0 to 3. Then you can say something like this:
if (setupStage == MyType3)
Which is identical to
if (setupStage == 3)
It sounds to me like you do want a macro like solution, and fortunately one exists.
STAGE_ONE = 0
STAGE_TWO = 1
STAGE_THREE = 2
# ...
if setupStage == STAGE_THREE:
will work.