K_count = (K_count < (byte)(CharacterMask[0][(customKey - '0') - 1][0]) ? ++K_count : 1);
It is a part of this simple code, and i cant understand how precisely does it work?
this basically increments through the available options on a standard US telephone keypad for the "3" key, looping back to the first option after the last is reached. it does so by referencing a 3-dimensional array containing the options for each key layed out as row/column/options. it is written in such a way that it can be reused for other keys with minor modifications.
the "...?...:..." construct is basically a shortcut for if/else. so you can rewrite the statement like this:
if (K_count < (byte)(CharacterMask[0][(customKey - '0') - 1][0])) {
K_count = ++K_count;
} else {
K_count = 1;
}
the "++" operator simply adds 1 to the variable, so you can rewrite as:
if (K_count < (byte)(CharacterMask[0][(customKey - '0') - 1][0])) {
K_count = K_count + 1;
} else {
K_count = 1;
}
CharacterMask is a 3-dimensional array that describes a typical telephone keypad. the first 2 dimensionsindicate the row and column of the keypad. the third dimension contains the options available on that key. so, for example, the 3 key on a telephone has 4 options (3,d,e, and f). for some reason, the author also includes the option count as the first item in the array (index 0). so CharacterMask[0][2] would give you an array containing the number 4 followed by the characters '3','d','e', and 'f'. as such, CharacterMask[0][2][0] will return the number 4. similarly CharacterMask[0][2][1] would return the char '3'. since this line of code is only really concerned with the number of options, not their values, the final array index is hard-coded to 0. given that, you can rewrite the code like this to clarify:
rowIndex = 0;
columnIndex = (customKey - '0') - 1;
optionCountIndex = 0;
if (K_count < (byte)(CharacterMask[rowIndex][columnIndex][optionCountIndex])) {
K_count = K_count + 1;
} else {
K_count = 1;
}
since customKey is a char and not a number, we can use the "-" operator to subtract the '0' char. this implicitly casts both values to a byte and returns the difference between those bytes. since the numbers are ordered 0-9 in most character sets, this effectively gets us the numerical value of the character stored in the customKey variable (e.g. char 3 becomes byte 3). so the code can be rewritten as follows:
rowIndex = 0;
keyNumber = (customKey - '0');
columnIndex = keyNumber - 1;
optionCountIndex = 0;
if (K_count < (byte)(CharacterMask[rowIndex][columnIndex][optionCountIndex])) {
K_count = K_count + 1;
} else {
K_count = 1;
}
since they keys 1,2,3 are found in columns 0,1,2 in a zero-based indexed column count, we need to subtract 1 from the keyNumber to get the column index as shown above
because CharacterMask is a char array, we need to cast the first value to a byte to get the value initially entered back. this rewrite clarifies that:
rowIndex = 0;
keyNumber = (customKey - '0');
columnIndex = keyNumber - 1;
optionCountIndex = 0;
optionCountAsCharType = (CharacterMask[rowIndex][columnIndex][optionCountIndex]);
if (K_count < (byte)optionCountAsCharType) {
K_count = K_count + 1;
} else {
K_count = 1;
}
the comparison with K_count relies on the fact that the option array length is equal to the option count plus 1. since it is zero-based indexed, that means the last index is equal to the option count. so as long as the current K_count (aka option index) is less than the option count, you can still add 1 without exceeding the max index value. but if you are on the last index, you must roll back to 1 (the index of the first option). it could be made more clear with one more refactor:
rowIndex = 0;
keyNumber = (customKey - '0');
columnIndex = keyNumber - 1;
optionCountIndex = 0;
optionCountAsCharType = (CharacterMask[rowIndex][columnIndex][optionCountIndex]);
nextIndexIsInsideArrayBounds = K_count < (byte)optionCountAsCharType
if (nextIndexIsInsideArrayBounds) {
K_count = K_count + 1;
} else {
K_count = 1;
}
You can expand that single line of code to:
int temp = (byte)(CharacterMask[0][(customKey - '0') - 1][0]);
if ( K_count < temp )
{
K_count = ++K_count;
// This is bad. See the comment about sequence points.
// It should be
K_count = K_count + 1;
}
else
{
K_count = 1;
}
(customKey - '0') - 1
This takes the value of customKey, subtracts the ASCII value of "0" (0x30), and then subtracts 1 from that.
CharacterMask[0][x][0]
This takes the 0th element of CharacterMask, takes the xth element of the result, and then takes the 0th element of that result.
(byte)x
This truncates x to its 8 least significant bits.
K_count < x
This is true (i.e. non-zero) if K_count is less than x.
x ? y : z;
This results in y if x is true, otherwise it results in z.
As to what it actually does, that depends on what CharacterMask and customKey are.
Related
I am practicing to solve this problem, and have gotten 5 test cases passed but some test cases are failing I am not able to figure out what's the issue in my algorithm. Although I tried with some test data from failed test cases, most of them are coming correctly but I believe some are incorrect hence leading to my algorithm failure. So If someone can give an insight on the correct way to implement this algorithm that would be very helpful or where am I going wrong in my implementation.
My Algo:
1. Index for the move is at index '0' of string (say moving index)
2. Loop over the string starting with index '1' of string:
2.1. check if (moving index + leap) can outrun the array:
2.2. If not then, check whether the character is 1 or 0 :
2.2.1 Check for the number of '1's that are continuous, if they exceed the leap value then return false (as anyway we will not be able to jump).
2.2.2 If its 0, then check whether its a zero after continuous '1's.
If not so, continue moving forward one step at a time.
If so, first try to skip over those continuous '1's by checking whether (moving index + leap) is allowed or not as per the rule.
If not allowed, check in a while loop till what point we can move backwards one step at a time to get (moving index + leap) to satisfy.
If not possible, return false.
I don't know whether this is an efficient way to implement solution of this sort of problem, any other possible methods are much appreciated.
code:
import java.util.*;
public class Solution {
public static int leapStep(int index,int leap,int len,int[] game){
if(game[index+leap]==0){
index += leap;
}
return index;
}
public static boolean canWin(int leap, int[] game) {
int index = 0;
int len = game.length;
int consecutiveLength=0;
for(int i=1;i<len;){
if(index+leap>len-1){
return true;
}
if(game[i]==1){
consecutiveLength++;
if(consecutiveLength>=leap){
return false;
}
i++;
}else{
if(consecutiveLength==0){
index =i;
i++;
}else{
if(index+leap<=len-1){
int tryLeap = leapStep(index,leap,len,game);
if(index < tryLeap){
index = tryLeap;
tryLeap =0;
i = index+1;
}else if(index>0 && game[index-1]==0 ){
boolean notViable = false;
while(index>0){
if(game[index-1]!=0)
return false;
index -= 1;
i = index+1;
tryLeap = leapStep(index,leap,len,game);
if(index<tryLeap){
index = tryLeap;
i = index+1;
tryLeap=0;
notViable = false;
break;
}
else{
notViable = true;
}
}
if(notViable){
return false;
}
}else{
return false;
}
}
consecutiveLength=0;
}
}
}//closing for
return true;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int q = scan.nextInt();
while (q-- > 0) {
int n = scan.nextInt();
int leap = scan.nextInt();
int[] game = new int[n];
for (int i = 0; i < n; i++) {
game[i] = scan.nextInt();
}
System.out.println( (canWin(leap, game)) ? "YES" : "NO" );
}
scan.close();
}
}
To me, a better approach is to solve this recursively as below (it passed all the tests):
public static boolean canWin(int[] array, int index, int leap) {
// the only case when we lose
if (index < 0 || array[index] > 0) {
return false;
}
// if you're standing in the last entry or (index + leap) >= array.length then win
if ((index >= array.length - 1) || ((index + leap) >= array.length)) {
return true;
}
// mark it as visited so that not to iterate over it again
array[index] = 1;
// check all 3 conditions then recursively again
return canWin(array, index + 1, leap) || canWin(array, index - 1, leap) || canWin(array, index + leap, leap);
}
In the input below several pairs of lines are shown. The first element of each pair stands for leap and the second one for an array.
Input:
3
0 0 0 0 0
5
0 0 0 1 1 1
3
0 0 1 1 1 0
1
0 1 0
Output:
true
true
false
false
Explanation:
Let's say your current position is index.
If it's negative or the array value is larger than 0 then the game is lost. If it's the last position or index + leap reaches at least the length of the array then the game is won by definition.
Otherwise, the only possible moves from here could be index - 1 or index + 1 or index + leap. So, you repeat step 1 for each of the latter indices and take OR of the result because finding a single path is enough. Don't forget to set a value of the cell to 1 because it doesn't make sense to visit it the second time - we don't want to repeat the same moves over and over again and crash.
Your pseudo-code seems fine, but there a few mistake in your code, that may be the cause of your trouble.
The least problematic first, if(index+leap<=len-1) inside your loop is useless, you can remove it without modify the behaviour of your algorithm. It is the case because you already checked it in the first line of the loop and entered an else keyword.
This one is about your variables index and i. Their meaning isn't clear to me after a few complete read, and they look like the same. It might cause you trouble because you use the variable index inside your call to leapStep, but index is often one step behind i. It's confusing.
I did not found an example where your code fails.
Here is my solution HackerRank accepted. It is an iterative one, close to yours. Its principle is simple: starting from position 0, as we increase step by step our position, keep track of the positions you have access to (in variable memoTab, I removed the dp name as it can be frightening): if we are on a position we already reached before, then we can go to +1 or +leap.
It would be enough if it wasn't allowed to backtrack and go the reverse direction. To deal with that, whenever we reach some 1s, I keep in memory the next 0. And if I encounter a position I can reach just after, I go back to that 0 and say I can go there.
Here is the code, first a little helper function that returns true if the game is finished. Given a game and an index it says if we can go to that index and write it to the memo.
public static boolean check(int[] game, boolean[] memo, int index){
if(index >= 0 && index < game.length){
if(game[index] != 1){
memo[index] = true;
}
}
return index >= game.length;
}
This is the solver function, it first reads the values, then starts looping.
public static void solveOne(){
int n = sc.nextInt();
int leap = sc.nextInt();
int[] game = new int[n];
for (int i = 0; i < n; i++) {
game[i] = sc.nextInt();
}
int index = 0;
boolean[] memoTab = new boolean[n];
for (int i = 0; i < n; i++) {
memoTab[i] = false;
}
memoTab[0] = true;
boolean rememberIndex0 = false;
boolean gotoIndex0 = false;
int index0 = 0;
boolean finished = false;
We are done with the initialization, let's loop:
while(index < game.length){
// we encounter the first 0 after some 1, keep it in memory !
if(rememberIndex0 && game[index] == 0){
index0 = index;
gotoIndex0 = true;
rememberIndex0 = false;
}
// this index is an index we reached before, we can continue from here
if(memoTab[index]){
// we previously said we need to go back to a lower position
if(gotoIndex0){
gotoIndex0 = false;
index = index0;
memoTab[index] = true;
continue;
}
// it's finished if either is true
finished = check(game, memoTab, index + 1)
|| check(game, memoTab, index + leap);
if(finished) break;
}
// if this position is a 1, then we will keep in memory the next 0
if(game[index] == 1){
rememberIndex0= true;
}
// don't forget incrementing
index += 1;
}
System.out.println(finished?"YES":"NO");
}
There is a String of 1's and 0's for example 110001110. I have given two numbers k and p and I have to check whether I can get atmost p consecutive 1's or 0's by doing k swaps and by swaps I mean if it is 1 then make it 0 and vice versa.
EDIT- I think I have not clearly explained.
For example let the string be 1110000111 and let p = 3 and k = 1. So can I by doing 1 swaps get atmost 3 consective 1's or 0's for which the answer is yes since I can change it into 1110010111.
You could do this in linear time with a straightforward loop. After detecting a monotonous sequence of either all 0 or all 1, you would calculate how many flips would be necessary with a simple formula. These flips can always be made in such a way that the outer digits of that sequence will remain untouched, except for the case where p is 1. In that case the flips must be made to either get 01010101... or else 101010101.... Also that can be done with a simple modulo expression. The best of the two would then be taken (fewer swaps).
Here is an implementation in JavaScript with two sample runs for the generic case (p > 1) and the mentioned special case (p = 1):
function swapsForMaxSequence(s, maxSize) {
var head, tail, swaps;
if (maxSize < 1) return false;
swaps = 0;
if (maxSize === 1) { // Special case
// 0 and 1 should be alternating:
for (head = 0; head < s.length; head++) { // n iterations
if (Number(s[head]) == head % 2) swaps++;
}
// Either the made swaps or the opposite swaps would do it:
return Math.min(swaps, s.length - swaps);
}
tail = 0;
for (head = 1; head <= s.length; head++) { // n iterations
if (head === s.length || s[head] != s[tail]) { // end of sequence?
swaps += Math.floor((head - tail)/(maxSize+1));
tail = head; // Start of new sequence
}
}
return swaps;
}
// Sample input:
var s = '10110101010', // Special case
k = 1,
p = 1;
// Display input:
console.log('s:', s, 'k:', k, 'p:', p);
// Run the algorithm
result = swapsForMaxSequence(s, p);
// Display outcome:
console.log('result:', result);
// Second sample:
var s = '1110000111', // Special case
k = 1,
p = 3;
// Display input:
console.log('s:', s, 'k:', k, 'p:', p);
// Run the algorithm
result = swapsForMaxSequence(s, p);
// Display outcome:
console.log('result:', result);
I was asked this question in an interview. The first part was fairly simple in which I had to write a code to get maximum number of consecutive integers in an array. Following is the code that I wrote:
int count = 0, max = 0;
for(int i = 1; i < array.length; i++) {
if((array[i - 1] + 1) == array[i])) //curr is consecutive to prev
count++;
else
count = 0; //reset the counter as sequence is broken
//Keep track of maximum
if(count > max)
max = count;
}
System.out.println(max); //print the length of largest consecutive integers
The second part was follow up question on it:
How would you modify this logic to work for arrays that are stored in multiple machines?
You can implement it using the Reduce Parallel Pattern
Example in Python (sorry for bad namings):
def longest_seq(seq):
Result = namedtuple("Result", ["left", "left_n", "max_n", "right", "right_n", "is_const"])
def _longest_seq(seq):
if 1 == len(seq):
x = seq[0]
return Result(left=x, left_n=1, max_n=1, is_const=True, right=x, right_n=1)
l_res = _longest_seq(seq[0: int(len(seq) / 2)])
r_res = _longest_seq(seq[int(len(seq) / 2): len(seq)])
left_n = l_res.left_n + r_res.left_n if l_res.is_const and l_res.right == r_res.left else l_res.left_n
right_n = r_res.right_n + l_res.right_n if r_res.is_const and r_res.left == l_res.right else r_res.right_n
max_n = max(l_res.max_n, r_res.max_n, l_res.right_n + r_res.left_n if l_res.right == r_res.left else 0)
is_const = l_res.is_const and r_res.is_const and l_res.right == r_res.left
return Result(left=l_res.left,
left_n=left_n,
max_n=max_n,
right=r_res.right,
right_n=right_n,
is_const=is_const)
return _longest_seq(seq).max_n
Suppose we are distributing the whole array left to right to each machine sequentially. For example, for only two machine(machine1 and machine2), we will distribute array 0.... i to machine1 and i + 1....n to machine2. From each machine, we can return several additional information along with local maximum.
class result {
public int machineId;
public int maxSoFar; // the max value as your code
public int leftElement; // the leftmost element
public int leftLength; // number of times the leftElement appears consecutively in left
public int rightElement; // the rightmost element
public int rightLength; // number of times the rightElement appears consecutively in right
};
During merging two machine's result, for any two machine whose machineId are consecutive(e.g. 3 and 4), we can maximize like this -
return Math.max(((machine1.rightElement == machine2.leftElement) ? machine1.rightLength + machine2.leftLength : 0),
Math.max(machine1.maxSoFar, machine2.maxSoFar));
I have a buffer with IDs which looks like this
InBuffer={ID1,ID2,ID3,...}
I need to iterate through, every time using the ID in a function that returns pointers to the Data assigned to this ID and the size of the Data. I then need to fill in another buffer with the result which is of the form
OutBuffer={ID1,SIZE1,DATA1.WORD1,...,DATA1.WORDSIZE1,
ID2,SIZE2,DATA2.WORD1,...,DATA2.WORDSIZE2,
...,
IDN,SIZEN,DATAN.WORD1,...,DATAN.WORDSIZEN
}
I am having problems with forming the whole for-loop for this and the indexing of it, mainly because each SIZE variable can be different. It should be simple but I can't seem to make it work.
Thanks in advance for any help.
// For example
// Iterate through the remaining of the Request Buffer (m=0,1 already set)
for (m = 2; m < InBuffer; m++)`
{
OutBuffer[m] = InBuffer[m];
returnPointersToDataAndSizeFunction(InBuffer[m], &SIZE, &DATA);
OutBuffer[m + 1] = SIZE; // e.g. SIZE = 2, therefore DATA has 2 fields
OutBuffer[m + 2] = DATA.1; // first field
OutBuffer[m + 3] = DATA.2; // second field
// and so on
}
The first thing I notice is that you're using m to index both buffers:
for (m = 2; m < InBuffer; m++)
{
OutBuffer[m]=InBuffer[m];
but then you're using offsets from m for the additional data in OutBuffer:
OutBuffer[m+1]=SIZE;
OutBuffer[m+2]=DATA;
So, what you do think is going to happen in the next iteration of the loop? Say you go through the loop the first time, so that m is 2. The next time, it's m++, i.e. 3, and you make this assignment again:
OutBuffer[m]=InBuffer[m];
But you already assigned something at m[3], and that's the SIZE value from the previous iteration. You also assigned DATA at m[4], and that's going to be overwritten by the SIZE value in this iteration. Eventually, you'll end up with OutBuffer containing exactly what's in InBuffer, plus the SIZE and DATA values for the very last ID.
You need to use a different variable to index OutBuffer, something like:
for (m = 2, n = m; m < InBuffer; m++) {
OutBuffer[n++] = InBuffer[m];
returnPointersToDataAndSizeFunction(InBuffer[m],&SIZE,&DATA);
OutBuffer[n++] = SIZE;
OutBuffer[n++] = DATA;
}
There are some other problems as well. For example, the condition in the for loop shouldn't compare m to InBuffer, but should instead compare m and the number of entries in InBuffer. But just straightening out your indexing should be a big step forward.
Update: I just noticed that the data for each ID is larger than just one field. You'll need another loop inside the first one, then, so that you end up with something like this:
for (m = 2, n = m; m < InBuffer; m++) {
OutBuffer[n++] = InBuffer[m];
returnPointersToDataAndSizeFunction(InBuffer[m],&SIZE,&DATA);
OutBuffer[n++] = SIZE;
for (i = 0; i < SIZE; i++) {
OutBuffer[n++] = DATA[i];
}
}
If DATA is a structure with fields rather than an array, then you may need a series of if statements to check whether each field should be included or not. You can't use the value of a variable like i as the name of a field, i.e. you can't say DATA.i where i is a variable. I don't think a C structure can have field names that are numbers -- identifiers generally have to start with a letter or underscore, so trying to do that won't make much sense anyway. If you have control over the type of DATA, you should make it an array instead of a structure. So your loop would look more like this:
for (m = 2, n = m; m < InBuffer; m++) {
OutBuffer[n++] = InBuffer[m];
returnPointersToDataAndSizeFunction(InBuffer[m],&SIZE,&DATA);
OutBuffer[n++] = SIZE;
i = 0;
if (i++ < SIZE) { OutBuffer[n++] = DATA.field1; }
if (i++ < SIZE) { OutBuffer[n++] = DATA.field2; }
// and so on for each field in DATA's type
}
As Caleb pointed out you should use one variable for each array.
If you're saying that DATA can contain more than one element then you should increase the variable for outBuffer by SIZE each iteration. Also use a loop to asign DATAs fields to OutBuffer
int n = XXX; // set n to the first element you need to assign an ID to
for (m = 2; m < ElementsInBuffer; m++)
{
OutBuffer[n] = InBuffer[m];
returnPointersToDataAndSizeFunction(InBuffer[m],&SIZE,&DATA);
OutBuffer[n + 1] = SIZE;
for (int i = 0; i < SIZE; i++)
{
OutBuffer[n + 2 + i] = DATA[i]; // works for array only see Calebs answer to see how it works for structs
}
n += SIZE + 1; // +1 to also skip the field for SIZE
}
The goal is that for a variable that is an array of:
typedef struct {
GLuint vertex;
GLuint normal;
} indice_pairs_t;
, we want to find all the pairs that are unique and put them in an appropriate order of appearance with unique pair indices intact.
For example: if initial pairs are
2 3
6 7
6 7
4 5
(the 2nd and 3rd pairs are same)
then the final order will be
0 1 1 2
('2 3' was 0, first '6 7' was 1 but also the second '6 7'; '4 5' was 2 and so on)
The following code attempts to do that but final order appears to be always '0 1 2 3 4 5' and so on. If 'break;' is removed, it becomes a mess; too many increments.
// First is always unique and first in order:
unique[0] = pairs[0];
order[0] = 0;
num_unique = 1;
// Skip first, we just did it:
for (i = 1; i < num_pairs; i++) {
// Check if what we have is already the same
for (y = 0; y < num_unique; y++) {
if (unique[y].vertex == pairs[i].vertex&&unique[y].normal == pairs[i].normal) {
/* A new pair was found to be the same; put the old unique index in order;
keep num of unique items same: */
order[i] = y;
} else {
/* A new pair was unique; copy it in unique pairs and increment number
of unique items; put in order the new number */
unique[num_unique] = pairs[i];
order[i] = num_unique;
num_unique++; // it follows since it was already incremented to 1.
break;
}
}
}
It's a pretty inefficient algorithm. The complexity is O(n2). You could do better, by using a sorted sequence.
What you have is obviously buggy, but the idea seems clear. For every new value (next i) it is checked, if that value is already among unique values stored so far. That's what the inner loop is for. If the match is found, order[i] = y and the next i should be checked, so you can break. If the match is not found for current y however, you need to check next y. Only after all y were checked, you know the value is unique, so the part in the else clause should be moved outside the inner loop. I think the fixed version should look like this:
unique[0] = pairs[0];
order[0] = 0;
num_unique = 1;
// Skip first, we just did it:
for (i = 1; i < num_pairs; i++) {
// Check if what we have is already the same
for (y = 0; y < num_unique; y++) {
if (unique[y].vertex == pairs[i].vertex && unique[y].normal == pairs[i].normal) {
/* A new pair was found to be the same; put the old unique index in order;
keep num of unique items same: */
order[i] = y;
break;
}
}
if(y == num_unique){
/* No match was found in the inner loop,
so y reached num_unique. You could use a flag
to indicate this, which might be more readable*/
/* A new pair was unique; copy it in unique pairs and increment number
of unique items; put in order the new number */
unique[num_unique] = pairs[i];
order[i] = num_unique;
num_unique++; // it follows since it was already incremented to 1 in the beginning.
}
}