Maximum String Mismatches in Java - java

I was recently going through a question in codehub and I was unable to solve this query. Can anyone help me how can this be solved?
You are given a string S of length N. You can select and reverse any substring of S of any length. You are allowed to perform this operation many number of times.
Determine maximum number of mismatches by performing operation.
Mismatch(S) is defined as number of corresponding positions were characters are different in S and reverse(S). For example : S = abab, reverse(S) = baba. Number of mismatches = 4. S= abca. Number of mismatches = 2.
Pseudo code :
static int solve( String S, int n)
{
//To do
}
Will be helpful if some one can explain once the code is done how this can be interpreted more easily and approached to solve.

I recently encountered the same question in one of the competency tests, I don't know about above solution, but my implementation below in python works for above problem
import itertools
def maximum_mismatches(s,n):
if len(set(s)) == 1:
return 0
maxc = 0
for str_c in set(itertools.permutations(s,n)):
rev_str = str_c[::-1]
counter = 0
for i in range(n):
if str_c[i] != rev_str[i]:
counter += 1
if maxc < counter:
maxc = counter
return maxc
I have tested for multiple test cases, it is working

Calculate the frequency of each character in the string and then take the difference of frequency of each character. See the code example in Java. It returns the max mismatch of characters of a string & it's reverse, given that a substring in the original string can be reversed any number of times.
Examples: 1. cantaaaa (answer = 6), 2. cbbaa (answer = 4), 3. aaaaabbbbccdd (answer = 12)
public static int maxMismatch(String str){
if(str == null || str.length() <= 1) return 0;
int freq[] = new int[26];
for(int i = 0; i < str.length(); i++){
freq[str.charAt(i) - 97]++;
}
int diff = 0;
for(int i = 0; i < freq.length; i++){
diff = Math.abs(freq[i] - diff);
}
return str.length() - diff;
}

import itertools as it
def mismatch(S,n):
max =0
for x in set(it.permutations(S[::-1],n)):
cnt = 0
for i in range(n):
if x[i]!=S[i]:
cnt+=1
if cnt > max:
max=cnt
return max

#include <bits/stdc++.h>
using namespace std;
int max_mismatch(string s)
{
unordered_map<char,int> fmap;
for(auto &ch:s)
fmap[ch]++;
vector<int> tempV;
for(auto &[_,f]:fmap)
tempV.push_back(f);
sort(tempV.begin(),tempV.end(),greater<int>());
vector<int> freq(tempV.size());
int diff=0,left=0,right=freq.size()-1;
bool leftinsert=true;
for(auto f:tempV)
{
if(leftinsert)
freq[left++]=f;
else
freq[right--]=f;
leftinsert^=1;
}
/*for(auto &val:freq)
cout<<val<<" ";
cout<<endl; */
left=0;right=freq.size()-1;
for(int i=0;i<s.size()/2;i++)
{
if(left==right)
break;
if(!(--freq[left])) left++;
if(!(--freq[right])) right--;
diff+=2;
}
return diff;
}
int main()
{
string s="aatacanaa";
cout<<max_mismatch(s);
}

First a function to calculate the mismatch score, using this spec:
Mismatch(S) is defined as number of corresponding positions were characters are different in S and reverse(S). For example : S = abab, reverse(S) = baba. Number of mismatches = 4. S= abca. Number of mismatches = 2.
We don't need to actually reverse the string. Just compare the first character with the last, then the second with the second last, etc. I find it straightforward to use two index variables for something like this:
int mismatches(String s) {
int result = 0;
int i = 0;
int j = s.length() - 1;
while (j >= 0) {
if (s.charAt(i) != s.charAt(j)) result++;
i++;
j--;
}
return result;
}
And here are some tests to increase our confidence:
#Test
public void test_mismatches() {
assertEquals(0, mismatches(""));
assertEquals(0, mismatches("a"));
assertEquals(0, mismatches("aa"));
assertEquals(2, mismatches("ab"));
assertEquals(0, mismatches("aaa"));
assertEquals(2, mismatches("aab"));
assertEquals(2, mismatches("abc"));
assertEquals(0, mismatches("aaaa"));
assertEquals(2, mismatches("aaab"));
assertEquals(2, mismatches("aaba"));
assertEquals(4, mismatches("abcd"));
}
Now let's find the max mismatch. Here is the spec:
You are given a string S of length N. You can select and reverse any
substring of S of any length. You are allowed to perform this
operation many number of times.
Determine maximum number of mismatches by performing operation.
This is unclear and has typos. It is lazily written and if it was client work, I would be asking for a clarification. I've been burned in the past by working from unclear specs, and building something that the client didn't intend.
I think the use of the word "reverse" is a misnomer. I think it is to help hint at a solution for calculating the mismatch. The spec should be:
You are given a string. Determine maximum number of mismatches from any substring. For clarity, the original string is a valid substring of itself.
With this revised spec, we can just use a nested for loop to traverse the search space:
int maxMismatches(String s) {
int result = 0;
for (int i = 0; i < s.length(); i++)
for (int j = s.length(); j > i; j--) {
int mismatch = mismatches(s.substring(i, j));
if (mismatch > result)
result = mismatch;
}
return result;
}
And some tests:
#Test
public void test_max_mismatches() {
assertEquals(0, maxMismatches(""));
assertEquals(0, maxMismatches("a"));
assertEquals(0, maxMismatches("aa"));
assertEquals(2, maxMismatches("ab"));
assertEquals(2, maxMismatches("aba"));
assertEquals(4, maxMismatches("aabbaa"));
assertEquals(6, maxMismatches("aaabcda"));
}
There is a gap in this set of tests. Some of the test strings require truncating the start to find the max. Some require truncating the end, but none require truncating both the start and end.
Both functions have obvious optimisations but they reduce clarity in a scenario where I don't think performance is important.

Here you could first reverse the giving string and then just iterate through the giving string and compare character at each index in both the giving string and reversed string and if there is a mismatch increase the counter.
Check the below code
public static void main(String args[])throws IOException {
String s = "abab";
System.out.println(solve(s,s.length()));
}
static int solve( String s, int n)
{
//this can also be used to reverse string
//String reversed = new StringBuilder(s).reverse().toString();
String revStr = Stream.of(s)
.map(word->new StringBuilder(word).reverse())
.collect(Collectors.joining(" "));
int counter = 0;
for(int loop=0; loop < n; loop++){
if(s.charAt(loop)!=revStr.charAt(loop)){
++counter;
}
}
return counter;
}

Related

Java method to check if a given number is symmetric

iv made a method to check if a given number is symmetric or not.
-the method is based on the idea that the given number is an array .
-i gave the methood 4 deifferent parameters- numberLength , middle , point1,point2(both pointing at a certain digit in the number(as an array))
-although wrote the code correctly , and it works when im initializing a specific array ,
i dont know how to use the method for a given number .
How can i set this Method - with parameter (int number) , so i can chek on the given number.
Thank you A lot
update** i added the code :
public boolean isSymmetric(int num){
int digits;
int[] number;
number = new int[num];
int length = number.length;
int mid;
if(length%2 == 0) //
{
mid = length/2;
}else {
mid = length/2+1;
}
int pointer1 =0;
int pointer2 = mid;
while(pointer1<mid && pointer2 < length)
{
if(number[pointer1] == number[pointer2])
{
pointer1=pointer1+1;
pointer2=pointer2+1;
}
else
System.out.println("number is not symmetric");
return false;
}
System.out.println("number is symmetric");
return true;
}
The easiest way to check if number symmetric or not is to map it to String::class, just like this:
// Your input number
Integer maybeSymmetricNumber = 12321;
String str = String.valueOf(maybeSymmetricNumber), reverseStr = "";
int strLength = str.length();
for (int i = (strLength - 1); i >=0; --i) {
reverseStr = reverseStr + str.charAt(i);
}
if (str.toLowerCase().equals(reverseStr.toLowerCase())) {
System.out.println(str + " is a symmetric number.");
}
else {
System.out.println(str + " is not a symmetric number.");
}
First, here is a method to convert your number to an array of ints.
it works by using the Math.log10 to compute the exponent of 10 for that number.
e.g. Math.log10(1234) = 3.xxx. So convert to an int and add 1 to get 4.
e.g. Math.log10(1000) = 3 so do the same thing.
then use that number to create an array of proper size.
and use the remainder(%) and division(/) operators to populate it.
then return the array.
public static int[] toArray(int number) {
number = Math.abs(number);
int[] arr = new int[(int) Math.log10(number)+1];
int i = 0;
while (number > 0) {
arr[i++] = number%10;
number/=10;
}
return arr;
}
Unfortunately, your method doesn't work properly as it always returns false. This is because of missing {} around the following.
else
System.out.println("number is not symmetric");
return false;
But it still doesn't process all values properly. Try 1234321 and 112211. They both return false but are symmetric. This is because pointer1 starts at 0 and pointer2 starts at mid and they are both incremented by 1.
I suggest you start pointer2 at length-1, going from outside in toward mid. This should then solve the issue (with a little debugging of course).

Return the count how many digits are 7 in the given number n

I'm writing a method for my CS151 class called countSevens(n). It Returns count how many digits are 7 in the given number n. This is what I have so far but I'm doing something wrong that I can't figure out.
public int countSevens(int n){
int count = 0;
String strI = Integer.toString(n);
for (int i = 0; i < strI.length(); i++){
if(strI.substring(i).equals("7")){
count++;
}
}
return count;
}
You can do it with java streams
public int countSevens(int n) {
return (int) String.valueOf(n).chars().filter(ch -> ch == '7').count();
}
(int) - cast to an int type, in this particular case it safe to cast long to int, because we can't get a conversation error. In other cases it's better to use Math.toIntExact(long)
String.valueOf(n) - convert to string
chars() - return stream of chars
filter(ch -> ch == '7') - filter all chars that equals to 7
count() - returns the count of elements in this stream
strI.substring(i)
Will return the part of string from i-character to the end.
Use strI.charAt(i) instead
From the definition of String.substring(int):
Returns a string that is a substring of this string. The substring begins with the character at the specified index and extends to the end of this string.
So this will only count the last instance of a 7 in your number, and only if it's the last digit in the number.
Instead, try this:
if(strI.substring(i, i+1).equals("7"))
Or, since you're dealing with ints, you can avoid using strings altogether. n % 10 will get you the last digit, and n /= 10 will bump the entire number right by one digit. That should be enough to get you started on doing this without Strings.
To count the number of 7s in an integer:
int counter = 0;
int number = 237123;
String str_number = String.valueOf(number);
for(char c : str_number.toCharArray()){
if(c == '7'){
counter++;
}
}
You can just use simple arithmetics:
public static int countSevens(int i) {
int count = 0;
for (i = i < 0 ? -i : i; i != 0; count += i % 10 == 7 ? 1 : 0, i /= 10);
return count;
}
But who can read this? Not many, so here is a cleaner solution, applying the same logic:
public static int countSevens(int i) {
int count = 0;
// ignore negative numbers
i = Math.abs(i);
while(i != 0) {
// if last digit is a 7
if(i % 10 == 7) {
// then increase the counter
count++;
}
// remove the last digit
i /= 10;
}
return count;
}

In Java, what is the best way to get each individual digit of an integer and its position for comparison?

New to programming: In Java, what is the best way to get each individual digit of an Integer and its position for comparisons? For example, with an input of an Integer i = 12345, I'd like to preform a comparison operation on each individual digit 1, 2, 3, 4, and 5. Since I can't get the index of the integer, I converted the integer to string, iterated, and used charAt().
String sI = Integer.toString(i);
for(int j = 0; j<i; j++){
if(charAt(j)>n){
//do something
}
}
why not try this... you will know that your int is printing from the last digit so you'll know the position.
public static void main(String[] args) {
Integer temp = 123456789;
do {
System.out.println(temp % 10);
temp = temp / 10;
} while (temp % 10 > 0);
}
I would do the same solution however your loop may result in some unexpected errors. That's because i can be greater than the length of your String sI.
And chars in Java are integers too so the comparison may fail: for example the character value of 1 is 49 so a comparison like if (sI.charAt(j) > 10) will always results in true. So you have to re-convert your character to an integer with the Character.getNumericValue() function.
So I'd change the loop to the following:
String sI = Integer.toString(i);
for(int j = 0; j < sI.length(); j++){
if(Character.getNumericValue(sI.charAt(j)) > n){
//do something
}
}
May be something like this helps
public int findallIntegers(int x, int n) {
if(x < 1) return 1;
if(x%10 > n) {
//do some thing
}
return findallIntegers(x/10, n);
}

Max Double Slice Sum codility O(1) space complexity fail performance test case

I was trying figure out why the below solution failed for a single performance test case for the 'Max Double Slice Sum' problem in the codility website: https://codility.com/demo/take-sample-test/max_double_slice_sum
There is another solution O(n) space complexity which is easier to comprehend overhere: Max double slice sum. But i am just wondering why this O(1) solution doesn't work. Below is the actual code:
import java.util.*;
class Solution {
public int solution(int[] A) {
long maxDS = 0;
long maxDSE = 0;
long maxS = A[1];
for(int i=2; i<A.length-1; ++i){
//end at i-index
maxDSE = Math.max(maxDSE+A[i], maxS);
maxDS = Math.max(maxDS, maxDSE);
maxS = Math.max(A[i], maxS + A[i]);
}
return (int)maxDS;
}
}
The idea is simple as follow:
The problem can be readdress as finding max(A[i]+A[i+1]+...+A[j]-A[m]); 1<=i<=m<=j<=n-2; while n = A.length; we call A[m] is missing element within the slice.
maxS[i] will keep max slice which end at current index i; in other words, = max(A[t] + ... + A[i]); while t < i; so when i=1; maxS = A[1]; Note that in solution, we don't keep array but rather latest maxS at current index (See above code).
maxDSE[i] is max of all double slice which end at i; in other words, = max(A[t]+A[t+1]+...+A[i]-A[m])--end at A[i]; maxDS is the final max of double slice sum which we try to find.
Now, we just use a for-loop from i=2; -> i=A.length-2; For each index i, we notice some findings:
If the missing element is A[i], then maxDSE[i] = maxS[i-1] (max sum of
all slice which end at i-1 => or A[t] + ... + A[i] - A[i]);
If missing element is not A[i] -> so it must be somewhere from A[1]->A[i-1] -> maxDSE = maxDSE[i-1] + A[i]; such as A[t] + ... + A[i] - A[m] (not that A[i] must be last element) with t
so maxDSE[i] = Math.max(maxDSE[i-1]+A[i], maxS[i-1]);
maxDS = Math.max(maxDS, maxDSE); max amount all maxDSE;
and maxS[i] = Math.max(A[i], maxS[i-1]+A[i]);
by that way, maxDS will be the final result.
But strange that, I was only able to get 92%; with one failed performance test case as shown here:
medium_range
-1000, ..., 1000
WRONG ANSWER
got 499499 expected 499500
Could anyone please enlighten me where is problem in my solution? Thanks!
Ok, I found the error with my code. Seems that I forgot one corner cases. When calculate DSE[i], in cases A[i] is missing number, maxS should contain the case when array is empty. In other word, maxS should be calculated as:
maxS[i] = Math.max(0, Math.max(A[i]+maxS[i-1], A[i])); while 0 is for case of empty subarray (end at i-th); Math.max(A[i]+maxS[i-1], A[i]) is max of all slice with at least one element (end at i-index). The complete code as follow:
import java.util.*;
class Solution {
public int solution(int[] A) {
long maxDS = 0;
long maxDSE = 0;
long maxS = A[1];
for(int i=2; i<A.length-1; ++i){
maxDSE = Math.max(maxDSE+A[i], maxS);
maxDS = Math.max(maxDS, maxDSE);
maxS = Math.max(0, Math.max(A[i], maxS + A[i]));
}
return (int)maxDS;
}
}
It seems that for the input [-11, -53, -4, 38, 76, 80], your solution doesn't work. Yes, it tricks all the codility test cases, but I managed to trick all codility test cases for other problems too.
If you don't just want to trick codility, but also you want to come with a good solution, I suggest that you create a loop and a large number of random test cases (in number of elements and element values), and create a test method of your own, that you are sure works (even if the complexity is quadratic), compare the results from both methods and then analyze the current random input that doesn't fit.
Here is clear solution. Best approach is to use algorithm of Kanade O(N) and O(1) by space
public class DuplicateDetermineAlgorithm {
public static boolean isContainsDuplicate(int[] array) {
if (array == null) {
throw new IllegalArgumentException("Input array can not be null");
}
if (array.length < 2) {
return false;
}
for (int i = 0; i < array.length; i++) {
int pointer = convertToPositive(array[i]) - 1;
if (array[pointer] > 0) {
array[pointer] = changeSign(array[pointer]);
} else {
return true;
}
}
return false;
}
private static int convertToPositive(int value) {
return value < 0 ? changeSign(value) : value;
}
private static int changeSign(int value) {
return -1 * value;
}
}
I have coded it in vb.net and got 100/100 getting idea form solution by Guillermo
Private Function solution(A As Integer()) As Integer
' write your code in VB.NET 4.0
Dim Slice1() As Integer = Ending(A)
Dim slice2() As Integer = Starting(A)
Dim maxSUM As Integer = 0
For i As Integer = 1 To A.Length - 2
maxSUM = Math.Max(maxSUM, Slice1(i - 1) + slice2(i + 1))
Next
Return maxSUM
End Function
Public Shared Function Ending(input() As Integer) As Integer()
Dim result As Integer() = New Integer(input.Length - 1) {}
result(0) = InlineAssignHelper(result(input.Length - 1), 0)
For i As Integer = 1 To input.Length - 2
result(i) = Math.Max(0, result(i - 1) + input(i))
Next
Return result
End Function
Public Shared Function Starting(input() As Integer) As Integer()
Dim result As Integer() = New Integer(input.Length - 1) {}
result(0) = InlineAssignHelper(result(input.Length - 1), 0)
For i As Integer = input.Length - 2 To 1 Step -1
result(i) = Math.Max(0, result(i + 1) + input(i))
Next
Return result
End Function
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
target = value
Return value
End Function
Visit Codility to see the results

Java program that converts binary numbers to decimal numbers. The input is a string of zeros and ones

I have to create a java program that converts binary to decimal using the following steps. Being new at this I did something, but I don't know what I did wrong or how to continue.
public class BinaryToDecimal {
public static void main(String args[]){
long sum = 0;
int result;
String s = "1001010101011010111001011101010101010101";
for(int i = s.length()-1; i <= 0; i--){
result = (int)Math.pow(2, i);
if(s.charAt(i) == '1')
sum=sum + result;
}
System.out.println(sum);
}
}
Use a loop to read (charAt()) each digit (0/1 char) in the input string, scanning from right to left;
Use the loop to build the required powers of 2;
Use a conditional statement to deal with 0 and 1 separately;
Debug using simple input, e.g. 1, 10, 101, and print intermediate values in the loop.
Use your program to find the decimal value of the following binary number:
1001010101011010111001011101010101010101
Do this only if your decimal value is at most 2147483647 or the maximum value an int can be in Java. If you don't know, just check the length of your string. If it's less than or equal to 32 i.e. 4 bytes, then you can use parseInt.:
int decimalValue = Integer.parseInt(s, 2);
Refer HERE for more info on the Integer.parseInt();
But if it's more, you can use your code. I modified your loop which is where your problem was:
String s = "1001010101011010111001011101010101010101";
long result = 0;
for(int i = 0; i < s.length(); i++){
result = (long) (result + (s.charAt(i)-'0' )* Math.pow(2, s.length()-i-1));
}
System.out.println(result);
The first thing I notice is that your binary number has more than 32 bits. This cannot be represented in the space of an int, and will result in overflow.
As a simpler answer, I ran the following and got the correct value at the end, it just uses simple bit shifts.
For each index in the string, if the character is 1, it sets the corresponding bit in the result.
public class BinaryToDecimal {
public static void main(String[] args) {
long sum;
String bin = "1001010101011010111001011101010101010101";
sum = 0;
for (int i = 0; i < bin.length(); i++) {
char a = bin.charAt(i);
if (a == '1') {
sum |= 0x01;
}
sum <<= 1;
}
sum >>= 1;
System.out.println(sum);
}
}
The loop runs from i = s.length()-1 until i <= 0. This should be i>=0.
The next problem is "int result". It works fine with result as a long ;) (Reason: You calculate a 40-bit value at the MostSignificantBit, but Integers only use 32-bit)
Also: You start at the rightmost Bit with i=s.length()-1. But the power that you calculate for it is 2^(s.length()-1) though it should be 2^0=1.
The solution is: result = (long)Math.pow(2, s.length()-1-i)
Edit:
I really like the solution of user2316981 because of its clear structure (without Math.pow, should be faster by using shift instead). And loops from 0 to MSB as I do with Double&Add algorithm. Can't comment on it yet, but thanks for the reminder ;)
import java.util.*;
import java.lang.Math;
class deci {
int convert(int n) {
int tem=1,power=0;
int decimal=0;
for (int j=0;j<n;j++) {
if(n==0) {
break;
} else {
while(n>0) {
tem=n%10;
decimal+=(tem*(Math.pow(2,power)));
n=n/10;
power++;
}
}
}
return decimal;
}
public static void main(String args[]) {
System.out.print("enter the binary no");
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
deci dc=new deci();
int i=dc.convert(n);
System.out.print(i);
}
}

Categories

Resources