find the maximum possible ones - java

I have a string of 0's and 1's
Now I want to change 0 to 1 only if adjacent elements for that 0 are not 1'string. Find the maximum ones possible after doing this operation.
Example:
110011000001 is the input string
Option 1:
I can change position 8 and position 10 from 0 to 1 to make the string: 110011010101, here there are 7 ones
Option 2:
Another way is to change position 9 from 0 to 1, to make the string: 110011001001, here there are 6 ones.
So the maximum between 6 and 7 is 7. So the result is 7.
Here is my code, I am able to find only one possible way here:
int process(String s) {
char[] ch = s.toCharArray();
int n = ch.length;
for(int i=1; i<n-1; i++) {
char e = ch[i];
if(e == '0' && ch[i-1] != '1' && ch[i+1] != '1') {
ch[i] = '1';
}
}
int count = 0;
for(char c : ch) {
if(c == '1') count++;
}
return count;
}
How to get the maximum possible ones here.

Notice that if the 0's are surrounded by 1's, you only need 2n + 1
adjacent 0's in order to add n 1's. In order to add one 1, you
need at least three 0's: 2*1+1=3. In order to add two 1's, you
need at least five 0's: 2*2+1=5. Since the number of 0's can be
described as, Z >= 2n + 1, we can instead solve for n. We get n <= (Z - 1) / 2. Thus, when surrounded by 1's, each group of 0's can
fit n=floor((Z-1)/2); we floor the value since we can't add half of a 1.
For groups of 0's only bounded by a 1 on a single side, we notice
that we need at least 2n 0's in order to add n 1's. Again, we
rearrange the equation Z >= 2n in order to get n <= Z / 2. Thus,
for groups bounded by a single 1, n=floor(Z/2).
For our last case, with a string of all 0's, we see that Z >= 2n - 1. So, n <= (Z + 1) / 2, or for our purposes floor((Z+1)/2).
Least common will be category 3. This will only happen if there are no 1's. If this is the case, you cannot have anything from category 1 or 2 -- so check this category first.
Second most common will be category 2. This happens when the beginning OR end of the string is a 0, but there are 1's elsewhere. Check this category second because you can fit more 1's with it than with the formula for the first case. Depending on your solution, you may have to keep track of the places you've already checked before moving on to using case 1 by using a substring of the original.
Most cases will land in category 1, since (in a random combination of 1's and 0's) most groups of 0's will be surrounded by 1's.
Your answer only checks the first case. Using these three cases together will give you the number of 1's that you can add to the string. Add this to the number of 1's you had originally and you'll have your answer.
Edited for clarity.

Count all existing ones as they are going to be a part of the answer.
To convert 0 to 1, count all zeroes between two ones.
If string is 100001, you have total 4 zeroes in between. Here let us leave boundary zeroes as we can't change them as they are adjacent to 1. So, now we are left with 2 zeroes in the middle out of which we can place only in 1 of them.
So count is just ceil(all valid zeroes / 2).
If you have a string like 00001, here you can place 2 ones excluding that boundary 0 adjacent to 1. So, count is ceil(3/2) which is 2. Your string would look like 10101.
Final answer is just step 1 + step 2.

Related

print random characters without repeat in square?

I'm generating random characters via my code below:
static void printRandomWhatEver(int NUMBER_OF_CHARACTER,
int NUMBER_OF_LINES,
char char1, char char2) {
int DIFFERENCE_SQUARE = 4;
char oldChar, newChar, random;
for (int i = 0; i < NUMBER_OF_CHARACTER; i++) {
random = getRandomCharacter(char1, char2);
if ((i + 1) % NUMBER_OF_LINES == 0) { // new line each new NUMBER_OF_LINE
System.out.println(random);
} else {
System.out.print(random);
}
}
}
My getReandomCharacter:-
private static char getRandomCharacter(char ch1, char ch2) {
return (char) (ch1 + Math.random() * (ch2 - ch1 + 1));
}
All working fine, what i need is the chars inside square 2*2 numbers to not be equal, here is image to explain what i need.
The digit 4 is in the same square:-
**
**
How i can prevent digits to be equal in a part of square?
Thanks in advance.
Just store the last line of your output, and compare the digit at position N to the digits last_line[N-1], last_line[N] and last_line[N+1]. Take care of the array boundaries for N-1 and N+1.
But you should be aware that you reduce the strength of your random number generator this way. To a human it will most likely look "more random", though.
But there may be even more patterns a human may recognize as "not random", e.g. sequential digits:
154
298
364
To avoid repeats you are better off shuffling rather than picking randomly. You will have to repeatedly select different groups of digits to shuffle to avoid repeats.
To start, pick four digits from [0..9] and shuffle them:
0 1
2 3
Working from left to right, the next two digits come from [0, 2, 4..9] with 1 and 3 omitted:
0 1 7
2 3 8
Repeat the process, adding two from the eight possible digits at a time.
Use a similar "pick two from seven" process to add digits in the next row. You only have seven digits to pick from because it is dangerous to pick an '8' in the given configuration:
0 1 7
2 3 8
1 8
Would be an error, so the '8' cannot be picked:
0 1 7
2 3 8
1 5
Is safe.
Once you move away from the left hand edge, you will be picking from six, as there will be four digits in the row above that you must avoid.
ETA: Working with two rows is overly complex. Generate one row at a time, with any existing adjacent digits cut out of the pre-shuffle selection. That will be 3 digits in the row above, plus the previous digit in the current row, with appropriate adjustments for left and right boundaries.

Find a matrix which satisfies certain constraints

Another description of the problem: Compute a matrix which satisfies certain constraints
Given a function whose only argument is a 4x4 matrix (int[4][4] matrix), determine the maximal possible output (return value) of that function.
The 4x4 matrix must satisfy the following constraints:
All entries are integers between -10 and 10 (inclusively).
It must be symmetrix, entry(x,y) = entry(y,x).
Diagonal entries must be positive, entry(x,x) > 0.
The sum of all 16 entries must be 0.
The function must only sum up values of the matrix, nothing fancy.
My question:
Given such a function which sums up certain values of a matrix (matrix satisfies above constraints), how do I find the maximal possible output/return value of that function?
For example:
/* The function sums up certain values of the matrix,
a value can be summed up multiple or 0 times. */
// for this example I arbitrarily chose values at (0,0), (1,2), (0,3), (1,1).
int exampleFunction(int[][] matrix) {
int a = matrix[0][0];
int b = matrix[1][2];
int c = matrix[0][3];
int d = matrix[1][1];
return a+b+c+d;
}
/* The result (max output of the above function) is 40,
it can be achieved by the following matrix: */
0. 1. 2. 3.
0. 10 -10 -10 10
1. -10 10 10 -10
2. -10 10 1 -1
3. 10 -10 -1 1
// Another example:
// for this example I arbitrarily chose values at (0,3), (0,1), (0,1), (0,4), ...
int exampleFunction2(int[][] matrix) {
int a = matrix[0][3] + matrix[0][1] + matrix[0][1];
int b = matrix[0][3] + matrix[0][3] + matrix[0][2];
int c = matrix[1][2] + matrix[2][1] + matrix[3][1];
int d = matrix[1][3] + matrix[2][3] + matrix[3][2];
return a+b+c+d;
}
/* The result (max output of the above function) is -4, it can be achieved by
the following matrix: */
0. 1. 2. 3.
0. 1 10 10 -10
1. 10 1 -1 -10
2. 10 -1 1 -1
3. -10 -10 -1 1
I don't know where to start. Currently I'm trying to estimate the number of 4x4 matrices which satisfy the constraints, if the number is small enough the problem could be solved by brute force.
Is there a more general approach?
Can the solution to this problem be generalized such that it can be easily adapted to arbitrary functions on the given matrix and arbitrary constraints for the matrix?
You can try to solve this using linear programming techniques.
The idea is to express the problem as some inequalities, some equalities, and a linear objective function and then call a library to optimize the result.
Python code:
import scipy.optimize as opt
c = [0]*16
def use(y,x):
c[y*4+x] -= 1
if 0:
use(0,0)
use(1,2)
use(0,3)
use(1,1)
else:
use(0,3)
use(0,1)
use(0,1)
use(0,3)
use(0,3)
use(0,2)
use(1,2)
use(2,1)
use(3,1)
use(1,3)
use(2,3)
use(3,2)
bounds=[ [-10,10] for i in range(4*4) ]
for i in range(4):
bounds[i*4+i] = [1,10]
A_eq = [[1] * 16]
b_eq = [0]
for x in range(4):
for y in range(x+1,4):
D = [0]*16
D[x*4+y] = 1
D[y*4+x] = -1
A_eq.append(D)
b_eq.append(0)
r = opt.linprog(c,A_eq=A_eq,b_eq=b_eq,bounds=bounds)
for y in range(4):
print r.x[4*y:4*y+4]
print -r.fun
This prints:
[ 1. 10. -10. 10.]
[ 10. 1. 8. -10.]
[-10. 8. 1. -10.]
[ 10. -10. -10. 1.]
16.0
saying that the best value for your second case is 16, with the given matrix.
Strictly speaking you are wanting integer solutions. Linear programming solves this type of problem when the inputs can be any real values, while integer programming solves this type when the inputs must be integers.
In your case you may well find that the linear programming method already provides integer solutions (it does for the two given examples). When this happens, it is certain that this is the optimal answer.
However, if the variables are not integral you may need to find an integer programming library instead.
Sort the elements in the matrix in descending order and store in an array.Iterate through the elements in the array one by one
and add it to a variable.Stop iterating at the point when adding an element to variable decrease its value.The value stored in the variable gives maximum value.
maxfunction(matrix[][])
{
array(n)=sortDescending(matrix[][]);
max=n[0];
i=1;
for i to n do
temp=max;
max=max+n[i];
if(max<temp)
break;
return max;
}
You need to first consider what matrices will satisfy the rules. The 4 numbers on the diagonal must be positive, with the minimal sum of the diagonal being 4 (four 1 values), and the maximum being 40 (four 10 values).
The total sum of all 16 items is 0 - or to put it another way, sum(diagnoal)+sum(rest-of-matrix)=0.
Since you know that sum(diagonal) is positive, that means that sum(rest-of-matrix) must be negative and equal - basically sum(diagonal)*(-1).
We also know that the rest of the matrix is symmetrical - so you're guaranteed the sum(rest-of-matrix) is an even number. That means that the diagonal must also be an even number, and the sum of the top half of the matrix is exactly half the diagonal*(-1).
For any given function, you take a handful of cells and sum them. Now you can consider the functions as fitting into categories. For functions that take all 4 cells from the diagonal only, the maximum will be 40. If the function takes all 12 cells which are not the diagonal, the maximum is -4 (negative minimal diagonal).
Other categories of functions that have an easy answer:
1) one from the diagonal and an entire half of the matrix above/below the diagonal - the max is 3. The diagonal cell will be 10, the rest will be 1, 1, 2 (minimal to get to an even number) and the half-matrix will sum at -7.
2) two cells of the diagonal and half a matrix - the max is 9. the two diagonal cells are maximised to two tens, the remaining cells are 1,1 - and so the half matrix sums at -11.
3) three cells from the diagonal and half a matrix - the max is 14.
4) the entire diagonal and half the matrix - the max is 20.
You can continue with the categories of selecting functions (using some from the diagonal and some from the rest), and easily calculating the maximum for each category of selecting function. I believe they can all be mapped.
Then the only step is to put your new selecting function in the correct category and you know the maximum.

permutations of certain digits in Java

I realize permutations in programming language is a very frequently asked question, however I feel like my question is sort of unique.
I have received input of a certain length integer N and stored each digit in an array where the index of the array stores the number of times that digit occurs in N.
now I want to test if some function holds true with all permutations of N's original length with no leading zeroes. Ex:
int[] digits = new int[10];
String n = "12345675533789025";
for (char c : n.toCharArray())
digits[c-'0']++;
for (Long f : allPermutationsOf(digits))
if (someCondition(f))
System.out.println(f);
a precondition to the following code is that N must be less than 2^64-1, (long's maximum value.)
The question is, how would I take all permutations of the digits array and return a Long[] or long[] without using some kind of String concatenation? Is there a way to return a long[] with all permutations of digits[] in the "Integer scope of things" or rather using only integer arithmetic?
To elaborate on one of the above comments, putting a digit d in a given place in the resulting long is easy: d*1 puts it in the 1s place, d*1000 puts it in the thousands place, and in general d * (10^k) puts d into the k+1th digit. You have N total digits to fill, so you need to do permutations on the powers of 10 from 1 to 10^(N-1).
If you are expecting the permutations to be Longs anyway, instead of representing n as an array of counts, it might be easier to represent it as a Long too.
Here are a couple of ways you can generate the permutations.
Think of generating permutations as finding the next largest number with the same set of digits, starting from the number consisting of the sorted digits of n. In this case, the answers to this StackOverflow question is helpful. You can use arithmetic operations and modding instead of string concatenation to implement the algorithm there (I can provide more details if you like). A benefit of this is that the permutations you generate will automatically be in order.
If you don't care about the order of the permutations and you expect the number of digit duplicates to be small, you can use the Steinhaus-Johnson-Trotter algorithm, which (according to Robert Sedgewick) is the fastest algorithm for generating permutations of unique elements. To make sure duplicate permutations are not generated, you would have to distinguish every duplicate digit and only emit the permutations where they appear in order (i.e., if 2 appears three times, then create the elements 2_1, 2_2, 2_3 and make sure those three elements always appear in that order in an emitted permutation).
For the requirement, assuming that the length of N is n, we can generate all permutations by going from digit to digit, starting from 0 and end at n - 1. With 0 is the leading digit.
For each digit, we only go through each possibility (0 to 9) once , which will avoid duplicate permutation.
From digit x to digit x + 1, we can easily generate the current value by passing a number called current
For example: at digit 3, we have current = 1234, so at digit 4, if we choose 5 to be at digit 4, the current will be 1234*10 + 5 = 12345
Sample code in Java:
public void generate(int index, int length, int[] digits, long current, ArrayList<Long> result) {
//All the permutation will be stored in result ArrayList
for (int i = 0; i < 10; i++) {
if (digits[i] > 0 && (i != 0 || index != 0)) {
digits[i]--;
if (index + 1 == length) {//If this is the last digit, add its value into result
result.add(current * 10 + i);
} else {//else, go to next digit
generate(index + 1, length, digits, current * 10 + i, result);
}
digits[i]++;
}
}
}

truncated binary logarithm

I have a question about this problem, and any help would be great!
Write a program that takes one integer N as an
argument and prints out its truncated binary logarithm [log2 N]. Hint: [log2 N] = l is the largest integer ` such that
2^l <= N.
I got this much down:
int N = Integer.parseInt(args[0]);
double l = Math.log(N) / Math.log(2);
double a = Math.pow(2, l);
But I can't figure out how to truncate l while keeping 2^l <= N
Thanks
This is what i have now:
int N = Integer.parseInt(args[0]);
int i = 0; // loop control counter
int v = 1; // current power of two
while (Math.pow(2 , i) <= N) {
i = i + 1;
v = 2 * v;
}
System.out.println(Integer.highestOneBit(N));
This prints out the integer that is equal to 2^i which would be less than N. My test still comes out false and i think that is because the question is asking to print the i that is the largest rather than the N. So when i do
Integer.highestOneBit(i)
the correct i does not print out. For example if i do: N = 38 then the highest i should be 5, but instead it prints out 4.
Then i tried this:
int N = Integer.parseInt(args[0]);
int i; // loop control counter
for (i= 0; Math.pow(2 , i) == N; i++) {
}
System.out.println(Integer.highestOneBit(i));
Where if i make N = 2 i should print out to be 1, but instead it is printing out 0.
I've tried a bunch of things on top of that, but cant get what i am doing wrong. Help would be greatly appreciated. Thanks
I believe the answer you're looking for here is based on the underlying notion of how a number is actually stored in a computer, and how that can be used to your advantage in a problem such as this.
Numbers in a computer are stored in binary - a series of ones and zeros where each column represents a power of 2:
(Above image from http://www.mathincomputers.com/binary.html - see for more info on binary)
The zeroth power of 2 is over on the right. So, 01001, for example, represents the decimal value 2^0 + 2^3; 9.
This storage format, interestingly, gives us some additional information about the number. We can see that 2^3 is the highest power of 2 that 9 is made up of. Let's imagine it's the only power of two it contains, by chopping off all the other 1's except the highest. This is a truncation, and results in this:
01000
You'll now notice this value represents 8, or 2^3. Taking it down to basics, lets now look at what log base 2 really represents. It's the number that you raise 2 to the power of to get the thing your finding the log of. log2(8) is 3. Can you see the pattern emerging here?
The position of the highest bit can be used as an approximation to it's log base 2 value.
2^3 is the 3rd bit over in our example, so a truncated approximation to log base 2(9) is 3.
So the truncated binary logarithm of 9 is 3. 2^3 is less than 9; This is where the less than comes from, and the algorithm to find it's value simply involves finding the position of the highest bit that makes up the number.
Some more examples:
12 = 1100. Position of the highest bit = 3 (starting from zero on the right). Therefore the truncated binary logarithm of 12 = 3. 2^3 is <= 12.
38 = 100110. Position of the highest bit = 5. Therefore the truncated binary logarithm of 38 = 5. 2^5 is <= 38.
This level of pushing bits around is known as bitwise operations in Java.
Integer.highestOneBit(n) returns essentially the truncated value. So if n was 9 (1001), highestOneBit(9) returns 8 (1000), which may be of use.
A simple way of finding the position of that highest bit of a number involves doing a bitshift until the value is zero. Something a little like this:
// Input number - 1001:
int n=9;
int position=0;
// Cache the input number - the loop destroys it.
int originalN=n;
while( n!=0 ){
position++; // Also position = position + 1;
n = n>>1; // Shift the bits over one spot (Overwriting n).
// 1001 becomes 0100, then 0010, then 0001, then 0000 on each iteration.
// Hopefully you can then see that n is zero when we've
// pushed all the bits off.
}
// Position is now the point at which n became zero.
// In your case, this is also the value of your truncated binary log.
System.out.println("Binary log of "+originalN+" is "+position);

Adding a while and for loop

The question asks: Design and implement an application that first reads a list of 10 three-digit integers and then counts the number of appearances for each digit from 0 to 9.
Here is an example of 3 three-digit numbers
Input number [123, 456, 789]
Output:
Digit 0 has appeared 0 times
Digit 1 has appeared 1 times
Digit 2 has appeared 1 times
…
Digit 9 has appeared 1 times
I believe that I have figured out the correct formulas to computate the amount of times each number appears, but I am not sure how to create the array and begin searching through it. I think I need a while and a for loop, but I am not sure how to incorporate them. I am afraid however, that my current if statements will need to change once the loops are implemented. Am I going in the right direction here? Any help would be greatly appreciated!
double i1, i2, i3, i4, i5, i6, i7, i8, i9, i10;
int c0=0, c1=0, c2=0, c3=0, c4=0, c5=0, c6=0, c7=0, c8=0, c9=0;
Scanner scan = new Scanner(System.in);
System.out.println ("Enter 10 3-digit integers");
//Counts the 1st number
System.out.println ("Enter first 3-digit integer");
i1 = scan.nextDouble();
if (i1%10==0)
c0++;
if (i1%10==1)
c1++;
if (i1%10==2)
c2++;
if (i1%10==3)
c3++;
if (i1%10==4)
c4++;
if (i1%10==5)
c5++;
if (i1%10==6)
c6++;
if (i1%10==7)
c7++;
if (i1%10==8)
c8++;
if (i1%10==9)
c9++;
if ((i1%100>=0) & (i1%100<10))
c0++;
if ((i1%100>=10) & (i1%100<20))
c1++;
if ((i1%100>=20) & (i1%100<30))
c2++;
if ((i1%100>=30) & (i1%100<40))
c3++;
if ((i1%100>=40) & (i1%100<50))
c4++;
if ((i1%100>=50) & (i1%100<60))
c5++;
if ((i1%100>=60) & (i1%100<70))
c6++;
if ((i1%100>=70) & (i1%100<80))
c7++;
if ((i1%100>=80) & (i1%100<90))
c8++;
if ((i1%100>=90) & (i1%100<100))
c9++;
if((i1/1000>=.0) & (i1/1000<.1))
c0++;
if((i1/1000>=.1) & (i1/1000<.2))
c1++;
if((i1/1000>=.2) & (i1/1000<.3))
c2++;
if((i1/1000>=.3) & (i1/1000<.4))
c3++;
if((i1/1000>=.4) & (i1/1000<.5))
c4++;
if((i1/1000>=.5) & (i1/1000<.6))
c5++;
if((i1/1000>=.6) & (i1/1000<.7))
c6++;
if((i1/1000>=.7) & (i1/1000<.8))
c7++;
if((i1/1000>=.8) & (i1/1000<.9))
c8++;
if((i1/1000>=.9) & (i1/1000<1.00))
c9++;
Hints:
Get rid of all of the c<n> and i<n> declarations and all of the if tests. They don't help you solve the problem.
Make use of the fact that '0' + <n> == '<n>' where <n> is 0 .. 9.
Or use Character.digit(char, 10). Read the javadocs.
You don't use nextDouble() to read an integer. Read the javadocs.
More Hints:
Generalise the problem to 'count the distinct characters in a string'. Since you're reading the input as a string anyway, just forget that you're counting integers for the moment, and focus on counting char appearances within a string.
Think of a data structure that can contain a pair of (distinct char, count).
Iterate through the characters within a string, add the character to your data structure in point 2 if it doesn't exist with a default value of 0, then increment the count of the char you're currently looking at.
When showing the output of your program, iterate through the entries of your data structure, validate that the char is an integer (if validation is important), and return the count for that char.
I'm not sure if you have trouble with iteration or not, but here is how to loop through the characters of a string:
String s = "123 456 789";
for (int i = 0; i < s.length(); i++){
char c = s.charAt(i);
// process c
}
// or, if you know what 'smart loops' in Java are...
for(char c : s.toCharArray()) {
// process c
}
To confuse matters, here it is in... 'pseudocode' (edited based on comments) ;)
>>> s = "012 345 678 900"
>>> datastructure = {}
>>> for c in s:
... if c not in datastructure:
... datastructure[c] = 0
... datastructure[c] += 1
...
>>> for c in '0123456789':
... if c not in datastructure:
... datastructure[c] = 0
... print 'Digit %s appeared %d times' % (c, datastructure[c])
...
Digit 0 appeared 3 times
Digit 1 appeared 1 times
Digit 2 appeared 1 times
Digit 3 appeared 1 times
Digit 4 appeared 1 times
Digit 5 appeared 1 times
Digit 6 appeared 1 times
Digit 7 appeared 1 times
Digit 8 appeared 1 times
Digit 9 appeared 1 times
Your idea isn't that bad, you just obviously need some loops :)
1: loop to get numbers - you can't duplicate the same code 10x - write it once, in a loop.
2: loop to check digits - you can use your's ifs, or do it as Josh said
but before - you need data structure to store your data - occurs of digits. 10 variables is bad, BAD:), idea.
use array[2][10] or simply array[10] (where number of digits = index of array and value = occurs) or even better - HashMap<> - google it.
then inside loop you do:
for(int i = 0; i<10; i++){
if (myCurrentNumberToCheck %10 == i)
array[i] = array[i] + 1; // approach with simple array[10]
if ((myCurrentNumberToCheck %100 >= i*10) && (myCurrentNumberToCheck %100 < (i+1)*10 )) // needs to be tested
array[i] = array[i] + 1;
if ((myCurrentNumberToCheck %1000 >= i*100) && (myCurrentNumberToCheck %1000 < (i+1)*100 )) // needs to be tested
array[i] = array[i] + 1;
}
ahh and your inserted numbers should be in some structure too - try List numbers = new ArrayList<int>() here :) and iterate thou list, to take a look at next number.
so you will need to add numbers to List, and nextly - go thou that list and check them and here use that loop i wrote above
the problem with readInt() and readDouble() is that it ignores leading 0 and trailing 0 after the decimal i.e. 01.10 => 1.1
A much simpler approach is to just read every character.
int ch;
while((ch = System.in.read())>=0) {
// you have one character
}

Categories

Resources