I have a very odd situation,
I'm writing a filter engine for another program, and that program has what are called "save areas". Each of those save areas is numbered 0 through 32 (why there are 33 of them, I don't know). They are turned on or off via a binary string,
1 = save area 0 on
10 = save area 1 on, save area 0 off
100 = save area 2 on, save areas 1 and 0 off.
and so on.
I have another program passing in what save areas it needs, but it does so with decimal representations and underscores - 1_2_3 for save areas 1, 2, and 3 for instance.
I would need to convert that example to 1110.
What I came up with is that I can build a string as follows:
I break it up (using split) into savePart[i]. I then iterate through savePart[i] and build strings:
String saveString = padRight("0b1",Integer.parseInt(savePart[i]));
That'll give me a string that reads "0b1000000" in the case of save area 6, for instance.
Is there a way to read that string as if it was a binary number instead. Because if I were to say:
long saveBinary = 0b1000000L
that would totally work.
or, is there a smarter way to be doing this?
long saveBinary = Long.parseLong(saveString, 2);
Note that you'll have to leave off the 0b prefix.
This will do it:
String input = "1_2_3";
long areaBits = 0;
for (String numTxt : input.split("_")) {
areaBits |= 1L << Integer.parseInt(numTxt);
}
System.out.printf("\"%s\" -> %d (decimal) = %<x (hex) = %s (binary)%n",
input, areaBits, Long.toBinaryString(areaBits));
Output:
"1_2_3" -> 14 (decimal) = e (hex) = 1110 (binary)
Just take each number in the string and treat it as an exponent. Accumulate the total for each exponent found and you will get your answer w/o the need to remove prefixes or suffixes.
// will contain our answer
long answer = 0;
String[] buckets = givenData.split("_"); // array of each bucket wanted, exponents
for (int x = 0; x < buckets.length; x++){ // iterate through all exponents found
long tmpLong = Long.parseLong(buckets[x]); // get the exponent
answer = (10^tmpLong) + answer; // add 10^exponent to our running total
}
answer will now contain our answer in the format 1011010101 (what have you).
In your example, the given data was 1_2_3. The array will contain {"1", "2", "3"}
We iterate through that array...
10^1 + 10^2 + 10^3 = 10 + 100 + 1000 = 1110
I believe this is also why your numbers are 0 - 32. x^0 = 1, so you can dump into the 0 bucket when 0 is in the input.
Related
You are given two strings S and T. An infinitely long string is formed in the following manner:
Take an empty string,
Append S one time,
Append T two times,
Append S three times,
Append T four times,
and so on, appending the strings alternately and increasing the number of repetitions by 1 each time.
You will also be given an integer K.
You need to tell the Kth Character of this infinitely long string.
Sample Input (S, T, K):
a
bc
4
Sample Output:
b
Sample Explanation:
The string formed will be "abcbcaaabcbcbcbcaaaaa...". So the 4th character is "b".
My attempt:
public class FindKthCharacter {
public char find(String S, String T, int K) {
// lengths of S and T
int s = S.length();
int t = T.length();
// Counters for S and T
int sCounter = 1;
int tCounter = 2;
// To store final chunks of string
StringBuilder sb = new StringBuilder();
// Loop until K is greater than zero
while (K > 0) {
if (K > sCounter * s) {
K -= sCounter * s;
sCounter += 2;
if (K > tCounter * t) {
K -= tCounter * t;
tCounter += 2;
} else {
return sb.append(T.repeat(tCounter)).charAt(K - 1);
}
} else {
return sb.append(S.repeat(sCounter)).charAt(K - 1);
}
}
return '\u0000';
}
}
But is there any better way to reduce its time complexity?
I've tried to give a guide here, rather than just give the solution.
If s and t are the lengths of the strings S and T, then you need to find the largest odd n such that
(1+3+5+...+n)s + (2+4+6+...+(n+1))t < K.
You can simplify these expressions to get a quadratic equation in n.
Let N be (1+3+..+n)s + (2+4+6+...+(n+1))t. You know that K will lie either in the next (n+2) copies of S, or the (n+3) copies of T that follow. Compare K to N+(n+2)s, and take the appropriate letter of either S or T using a modulo.
The only difficult step here is solving the large quadratic, but you can do it in O(log K) arithmetic operations easily enough by doubling n until it's too large, and then using a binary search on the remaining range. (If K is not too large so that floating point is viable, you can do it in O(1) time using the well-known quadratic formula).
Here my quick attempt, there probably is a better solution. Runtime is still O(sqrt n), but memory is O(1).
public static char find(String a, String b, int k) {
int lenA = a.length();
int lenB = b.length();
int rep = 0;
boolean isA = false;
while (k >= 0) {
++rep;
isA = !isA;
k -= (isA ? lenA : lenB) * rep;
}
int len = (isA ? lenA : lenB);
int idx = (len * rep + k) % len;
return (isA ? a : b).charAt(idx);
}
Here's a O(1) solution that took me some time to come up with (read I would have failed an interview on time). Hopefully the process is clear and you can implement it in code.
Our Goal is to return the char that maps to the kth index.
But How? Just 4 easy steps, actually.
Step 1: Find out how many iterations of our two patterns it would take to represent at least k characters.
Step 2: Using this above number of iterations i, return how many characters are present in the previous i-1 iterations.
Step 3: Get the number of characters n into iteration i that our kth character is. (k - result of step 2)
Step 4: Mod n by the length of the pattern to get index into pattern for the specific char. If i is odd, look into s, else look into t.
For step 1, we need to find a formula to give us the iteration i that character k is in. To derive this formula, it may be easier to first derive the formula needed for step 2.
Step 2's formula is basically given an iteration i, return how many characters are present in that iteration. We are solving for 'k' in this equation and are given i, while it's the opposite for step 1 where were are solving for i given k. If we can derive the equation of find k given i, then we can surely reverse it to find i given k.
Now, let's try to derive the formula for step 2 and find k given i. Here it's best to start with the most basic example to see the pattern.
s = "a", t = "b"
i=1 a
i=2 abb
i=3 abbaaa
i=4 abbaaabbbb
i=5 abbaaabbbbaaaaa
i=6 abbaaabbbbaaaaabbbbbb
Counting the total number of combined chars for each pattern during its next iteration gives us:
#iterations of pattern: 1 2 3 4 5 6 7 8 9 10
every new s iteration: 1, 4, 9, 16, 25, 36, 49, 64, 81, 100
every new t iteration: 2, 6, 12, 20, 30, 42, 56, 72, 90, 110
You might notice some nice patterns here. For example, s has a really nice formula to find out how many combined characters it has at any given iteration. It's simply (# of s iterations^2)*s.length. t also has a simple formula. It is (# of t iterations * (# of t iterations + 1))*t.length. You may have noticed that these formulas are the formulas for sum of odd and even numbers (if you did you get a kudos). This makes sense because each pattern's sum for an iteration i is the sum of all of its previous iterations.
Using s,t as length of their respective patterns, we now have the following formula to find the total number of chars at a given iteration.
#chars = s*(# of s iterations)^2 + t * (# of t iterations * (# of t iterations + 1))
Now we just need to do some math to get the number of iterations for each pattern given i.
# of s iterations given i = ceil(i/2.0)
# of t iterations given i = floor(i/2) which / operation gives us by default
Plugging these back into our formula we get:
total # of chars = s*(ceil(i/2.0)^2) + t*((i/2)*((i/2)+1))
We have just completed step 2, and we now know at any given iteration how many total chars there are. We could stop here and start picking random iterations and adjusting accordingly until we get near k, but we can do better than that. Let's use the above formula now to complete step 1 which we skipped. We just need to reorganize our equation to solve for i now.
Doing some simplyfying we get:
// 2
// i i i
// s (-) + t - ( - + 1 ) = k
// 2 2 2
// ----------------------------
// 2
// i t i
// s - + - ( - + 1 )i = k
// 4 2 2
// ----------------------------
// 2 2
// si ti ti
// ---- + ---- + ---- - k = 0
// 4 4 2
// ----------------------------
//
// 2 2
// si + ti + 2ti - 4k = 0
// ----------------------------
// 2
// (s + t)i + 2ti - 4k = 0
// ----------------------------
This looks like a polynomial. Wow! You're right! That means we can solve it using the quadratic formula.
A=(s+t), B=2t, C=-4k
quadratic formula = (-2t + sqrt(2t^2 + 16(s+t)k)) / 2(s+t)
This is our formula for step 1, and it will give us the iteration that the kth character is on. We just need to ceil it. I'm actually not smart enough to know why this works. It just does. Here is a desmos graph that graphs our two polynomials from step 2: s(Siterations)^2 and t(Titerations (Titerations + 1)).
The area under both curves is our total number of chars at an iteration (the vertical line). The formula from step 1 is also graphed, and we can see that for any s, t, k that the x intercept (which represents our xth iteration) is always: previous iteration < x <= current iteration, which is why the ceil works.
We have now completed steps 1 and 2. We have a formula to get the ith iteration that the kth character is on and a formula that gives us how many characters are in an ith iteration. Steps 3 and 4 should follow and we get our answer. This is constant time.
This my Button OnClick() Method on Click of the button All Four random numbers will be Displayed on the Logcat
public void onClick(View v) {
/* the Code for Four Random Numbers*/
final Random random = new Random();
final Set<Integer> mySet = new HashSet<>();
while (mySet.size() < 4) {
mySet.add(random.nextInt(69) + 1);
}
// Now Adding it to the ArrayList
ArrayList<Integer> Elements = new ArrayList<>(mySet);
Log.i("Elements","A:" + Elements.get(0));
Log.i("Elements","B:" + Elements.get(1));
Log.i("Elements","C:" + Elements.get(2));
Log.i("Elements","D:" + Elements.get(3));
}
});
The Output Will be Look Like this (I just give an Example of one case It is Different in every case Whenever I run a App)
A : 11
B : 28
C : 57
D : 1
Now the Problem is :
The sum of all the numbers is greater than the specified range which is 0 to 69
When We Add A,B,C,D values which is equals to 97
Which is greater than the Specified Range 0 to 69
So I Want the Random Numbers in such a way that :
when we Add A,B,C,D the their Sum Should no Exceed the Range that is 69
So My Question is How can i Do That ?
Please Help!! I am Stuck in that part of the Code
and I find no Solution
In addition to what other people have suggested, you might want to read this: find all subsets that sum to a particular value
First, note that this bears some resemblance to the subset sum problem. Given the set of all numbers between 1 and 69, you're looking for a subset of 4 of them that adds up to 69. For any natural number, there are only a finite number of such sets (although it obviously eventually gets computationally infeasible to enumerate all of them). Either way, your answer is guaranteed to be one of these sets regardless of what algorithm you use.
The linked question shows code to find all of the subsets that add up to a particular value. Once you have this, just filter on all the subsets that have length 4 and randomly pick one of them.
There are two ways, depending on how you want to do it:
Rereoll the random numbers until a valid sum is achieved. This will be truly random.
Change the max value for the 2nd, 3rd, 4th, etc random number so that it can't be too big. However this will change it from every number being equally likely to smaller numbers being more likely.
This is a tricky question. These is no mention of a sample space, so one can assume it has to be valid integer of sorts. Generate any number of a number signed 32 bit integer. This would be –2147483648 and 2147483647 until you have four unique ones which sum is between 0 and 69.
Best of luck!
you can use this code :
final Random random = new Random();
final Set<Integer> mySet = new HashSet<>();
int thesum = 0 ;
while (mySet.size() < 4 && thesum< 69) {
int nmbr = random.nextInt(69) + 1 ;
thesum = thesum + nmbr ;
mySet.add(nmbr) ;
}
if( mySet.size() == 3)
{ArrayList<Integer> Elements = new ArrayList<>(mySet);
Log.i("Elements","A:" + Elements.get(0));
Log.i("Elements","B:" + Elements.get(1));
Log.i("Elements","C:" + Elements.get(2));
Log.i("Elements","D:" + Elements.get(3));}
I have something like this:
int[0] = 4123;
int[1] = 2571;
I would like to combine them and make one long value in Java.
This is my attempt:
int[] r = { 4123, 2571 };
long result = ( (r[1] & 0xFFFF) << 16 | (rs[0] & 0xFFFF) );
System.out.prinln(result);
The output should be: 10111627 but I get 168497179. Probably I miss something in conversion but don't have idea what...
EDIT
This is example how the value is placed into 32-bit register.
I try the summarize and hopefully clarify what the several comments on your question already indicate:
If you want to get the number from your image which is
00001010 00001011 00010000 00011011 = 0x0A0B101B = 168497179
in one single long value and you have two ints
0001000000011011 = 0x101B = 4123 and
0000101000001011 = 0x0A0B = 2571
than your code is correct.
I would recommend you to get used to hexadecimal numbers as they show easily that there is no binary relation between 0x0A0B & 0x101B and 0x009A4A8B = 10111627.
BTW your image is contradictory: the binary numbers represent as seen above the number 0x0A0B101B but the hexadecimals read 0x0A0B101E (notice the E) while the decimals support the binary value.
Finally, I figured out your flaw:
You seem to expect to get the decimal number concatenated together as result. But unlike the hexadecimals here it does not work this way in decimal!
Let me elaborate that. You have the binary number:
00001010 00001011 00010000 00011011
Which you can easily convert to hex block by block
0x0A 0x0B 0x10 0x1B
and than just join them together
0x0A0B101B
But that magic join is just a simplification only applying to hex (and the reason why hex is so popular among programmers).
The long version is you have to multiply the higher blocks/bytes (towards the left) with the 'basis' of the preceding block (to the right). The right most block is always multiplied by 1. The base for the next block is (since there are 8 bits in the first block) 28 = 256 = 0x100. The base for the third block is (8+8 bits) 216 = 65536 = 0x10000. The last (left most) has to be multiplied by (8+8+8 bits) 224 = 16777216 = 0x1000000.
Lets make an example for the first two blocks:
Hexadecimal:
0x10 || 0x1B
(0x10 * 0x100) + (0x1B* 0x1)
0x1000 + 0x1B = 0x101B
Decimal:
16 || 27
(16 * 256) + (27 * 1)
4096 + 27 = 4123
As you can see on your image they both in it (notice the E/B issue which is in decimal a 6/3 issue) but there is no 1627. So converting binary or hexadecimal numbers to decimal is a nontrivial task (for humans), best to use a calculator.
Develop a hash function to generate an index value between 0-4999 inclusive for a given traffic license number. Your hash function should generate as few as possible collisions. Hash function should use the properties of license numbers. Hash method should take the license number as a single String and return an index value. We assume that the license numbers to be in the following format: City code is a number between 10 and 99 inclusive. Three letters are any letter combination from English alphabet with 26 chars. Two digits number is a number between 10 and 99 inclusive.
I wrote something about this question but, collisions are a lot (1800 for 5k)
static long printValue(String s) {
long result = 0;
for (int i = 0; i < s.length(); i++) {
result += Math.pow(27, MAX_LENGTH - i - 1) * (1 + s.charAt(i) - 'A');
}
result = result % 5009;
return (int) result;
}
public int hashF(String str) {
String a = str.substring(0, 2);
String b = str.substring(5, 7);
String middle = str.substring(2, 5);
int q = (int) printValue(middle);
String last = a + q + b;
int index = Integer.parseInt(last);
index = index % 5009;
return index;
}
Link for orjinal file of licence numbers.
These are some examples from file of traffic licence number. Collisions must be 300 (maximum).
65HNM25
93DTV23
94WPX23
31RKK46
15YXX90
31MDV74
45BOG99
65JRM50
77VXR55
39TKY41
80MJU73
63QYE57
38FCO80
45ORI16
17CHN73
70SXR63
87CVM74
27EEE85
32PFJ91
50PBA66
70TVK72
15YLS20
80MPM74
21ZRN20
36VVE84
58IDW24
77VDC89
19BVK93
28SUF63
Your problem is not your code, but mathematics. Even a (perfect for you, but not very useful) hash code that produces consecutive hashes that are then mod 5000, ie
10AAA10 -> 0
10AAA11 -> 1
... etc
99ZZZ99 -> 600 (90 * 26 * 26 * 26 * 90) % 5000
will statistically produce over 1800 collisions and is no better than the simplest implementation, which is to use String's hashCode:
int hash = Math.abs(number.hashCode() % 5000);
It's a silly exercise, as it has no real world use.
Your split of the license plate into 3 parts is fine. But converting the middle to a number, hashing it, then adding the two outside strings, converting that all to an integer, and then finally executing a modulo on that is ... awkward.
I would start off with converting the prefix (10-99) to an integer, and then subtracting 10 to get the range 0-89.
Then, for each letter, I'd multiply the result by 26, and add the index of the letter (0-25).
Third, I'd multiply the whole result by 90 (the range of the final part), convert the final 2 characters to an integer, subtract 10 to convert the 10-99 range to 0-89, and add to the result from earlier.
Finally, mod the result with 5000 to get to required 0-4999 range.
Pseudo code:
result = toInt(prefix) - 10
foreach letter in middle:
result = result * 26 + ( letter - 'A' )
result = result * 90 + ( toInt(suffix) - 10)
result = result % 5000
I am writing a program which I found on a coding competition website, I have sort of figured out how to solve the problem but, I am stuck on a math part of it, I am completely diluting the problem and showing what I need.
first I need to check if a number is part of a sequence, my sequence is 2*a+1 where a is the previous element in the sequence or 2^n-1 to get nth item in the sequence. so it is 1,3,7,15,31,63...
I don't really want to create the whole sequence and check if a number is present, but I am not sure what a quicker method to do this would be.
Second if I am given a number lets say 25, I want to figure out the next highest number in my sequence to this number. So for 25 it would be 31 and for 47 it would be 63, for 8 it would be 13.
How can i do these things without creating the whole sequence.
I have seen similar questions here with different sequences but I am still not sure how to solve this
Start by finding the explicit formula for any term in your sequence. I'm too lazy to write out a proof, so just add 1 to each term in your sequence:
1 + 1 = 2
3 + 1 = 4
7 + 1 = 8
15 + 1 = 16
31 + 1 = 32
63 + 1 = 64
...
You can clearly see that a_n = 2^n - 1.
To check if a particular number is in your sequence, assume that it is:
x = 2^n - 1
x + 1 = 2^n
From Wikipedia:
The binary representation of integers makes it possible to apply a
very fast test to determine whether a given positive integer x is a
power of two:
positive x is a power of two ⇔ (x & (x − 1)) equals to zero.
So to check, just do:
bool in_sequence(int n) {
return ((n + 1) & n) == 0;
}
As #Blender already pointed out your sequence is essentially 2^n - 1, you can use this trick if you use integer format to store it:
boolean inSequence(int value) {
for (int i = 0x7FFF; i != 0; i >>>= 1) {
if (value == i) {
return true;
}
}
return false;
}
Note that for every elements in your sequence, its binary representation will be lots of 0s and then lots of 1s.
For example, 7 in binary is 0000000000000000000000000000111 and 63 in binary is 0000000000000000000000000111111.
This solution starts from 01111111111111111111111111111111 and use an unsigned bitshift, then compare if it is equal to your value.
Nice and simple.
How to find the next higher number :
For example, we get 19 ( 10011 ) , should return 31 (11111)
int findNext(int n){
if(n == 0) return 1;
int ret = 2; // start from 10
while( (n>>1) > 0){ // end with 100000
ret<<1;
}
return ret-1;
}