Java: ordering elements without use of array [duplicate] - java

This question already has answers here:
Sort 4 numbers without array
(2 answers)
Closed 5 years ago.
I have a homework where I'm supposed to prompt the user to enter five numbers and arrange them from min to max and since we didn't take arrays
I'm only left with Math.min & Math.max or if statement.
I wrote a code where the first, second and last number are always correct But I can't seem to figure out how to do the 3rd and 4th number
Here's an example:
if (a <= b && a <= c && a <= d && a <= e) {
System.out.println("Numbers in Ascending order "
+ a + " " +Math.min(Math.min(b, c), Math.min(d, e)) +
" " + "?" +
" " + "?" +
" " +Math.max(Math.max(b, c), Math.max(d, e)));
}
If you know any idea that might help me solve this task?

Here is one possible solution
public static void main(String... args) {
int a = 32;
int b = 42;
int c = 2;
int d = 88;
int e = 92901;
int counter = 0;
while (counter < 5) {
int currentMin = findMin(a, b, c, d, e);
// Printing smallest number yeat
System.out.print(currentMin + " ");
if (a == currentMin){
a = Integer.MAX_VALUE;
}
if (b == currentMin){
b = Integer.MAX_VALUE;
}
if (c == currentMin){
c = Integer.MAX_VALUE;
}
if (d == currentMin){
d = Integer.MAX_VALUE;
}
if (e == currentMin){
e = Integer.MAX_VALUE;
}
counter++;
}
}
private static int findMin(int a, int b, int c, int d, int e) {
int smallest = Math.min(a, Math.min(b, Math.min(c, Math.min(d, e))));
return smallest;
}
Notice how I am using the Integer.MAX_VALUE to remove the smallest number yeat for example in the first iteration 2 will be returned which is equals to c now I have to make the code somehow to ignore c in the next iteration because it was already used if I was using the Integer object i could have set c to be null but int cannot be setted to null so what i can do is to set it to number so large that findMin function would never choose it again that's why I use MAX_VALUE

If you have to do it using if,else if statements then you will have to write one if statement and 119 else if statements i.e. number of ways in which 5 numbers can be arranged. 5!=120.
if you are allowed to use for loop check this link

int aux;
if (b < a){
aux = b; b = a; a = aux;
}
if (c < a){
aux = c; c = b; b = a; a = aux;
}
else{
if (c < b){
aux = c; c = b; b = aux;
}
}
...
I guess you get the idea, in the end a will be the smallest and e will be the biggest
For more information, since it looks like you're getting started to programming and sorting algorithms, this is called Insertion Sort (I believe). More information here https://en.wikipedia.org/wiki/Insertion_sort

This is a possible answer. Since loop and arrays cannot be used, much of the code is repetition. In the end a,b,c,d,e contain the values arranged from min to max. Hope this helps.
import java.io.*;
class SortFiveElements {
//utility function
//returns index as a:1, b:2, c:3, d:4, e:4
public static int find_min_index(int a,int b, int c,int d, int e, int min)
{
return a==min?1:(b==min?2:(c==min)?3:(d==min?4:5));
}
public static void main (String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int a = Integer.parseInt(br.readLine());
int b = Integer.parseInt(br.readLine());
int c = Integer.parseInt(br.readLine());
int d = Integer.parseInt(br.readLine());
int e = Integer.parseInt(br.readLine());
//temp is a temporary var to store the i-th value which may get replaced
//smallest stores the min value among i-th to 5th element
//idx stores the minimum value's index
int temp,smallest,idx;
//i=1, i.e element 'a'
//temp has value of 1st element that is a
//find minimum among 5 elements in 'smallest', its index in 'idx'
//then swap
temp = a;
smallest = Math.min(a,Math.min(b,Math.min(c,Math.min(d,e))));
idx = find_min_index(a,b,c,d,e,smallest);
a = smallest;
if(idx==1)
a=temp;
else if(idx==2)
b = temp;
else if(idx==3)
c = temp;
else if(idx==4)
d = temp;
else
e = temp;
//i=2, i.e element 'b'
//temp has value of 2nd element that is b
//find minimum among 4 elements in 'smallest', its index in 'idx'
//NB: a already has the smallest value, so replace a with MAX_VALUE while finding index
//then swap
temp = b;
smallest = Math.min(b,Math.min(c,Math.min(d,e)));
idx = find_min_index(Integer.MAX_VALUE,b,c,d,e,smallest);
b = smallest;
if(idx==1)
a=temp;
else if(idx==2)
b = temp;
else if(idx==3)
c = temp;
else if(idx==4)
d = temp;
else
e = temp;
//repeat above process for 'c' and 'd'.
//'e' will automatically fall in place
temp = c;
smallest = Math.min(c,Math.min(d,e));
idx = find_min_index(Integer.MAX_VALUE,Integer.MAX_VALUE,c,d,e,smallest);
c = smallest;
if(idx==1)
a=temp;
else if(idx==2)
b = temp;
else if(idx==3)
c = temp;
else if(idx==4)
d = temp;
else
e = temp;
temp = d;
smallest = Math.min(d,e);
idx = find_min_index(Integer.MAX_VALUE,Integer.MAX_VALUE,
Integer.MAX_VALUE,d,e,smallest);
d = smallest;
if(idx==1)
a=temp;
else if(idx==2)
b = temp;
else if(idx==3)
c = temp;
else if(idx==4)
d = temp;
else
e = temp;
//we have the values in sorted order in a,b,c,d,e
System.out.println(a+" "+b+" "+c+" "+d+" "+e);
}
}

Related

How to transform a string such that it only contains vowels which have occurences equal or greater than their given values?

I was asked this question in an interview. We have a string s (all lowercase characters) from which we need to make a new string p such that :
The total number of a's in the string should be equal or greater than the given value of an int variable a.
The total number of e's in the string should be equal or greater than the given value of an int variable e.
The total number of i's in the string should be equal or greater than the given value of an int variable i.
The total number of o's in the string should be equal or greater than the given value of an int variable o.
The total number of u's in the string should be equal or greater than the given value of an int variable u.
Constraint was the in order to get the resultant string, we can replace any character with any other lower case character. We can do this any number of times but each replacement has a cost associated with it. the cost of replacing c1 with c2 is the absolute difference of ASCII value of c1 and c2. For eg. replacing b with e has a cost 3 and c with a has a cost 2.
We need to find the minimum cost of converting s into p. Given is:
String s
Five ints - a, e, i, o, u
My approach was to first sort the string, then decrease the given value of given int's each time we encounter the respective character, and then whichever given variable is greater than 0, we'll start from the beginning of the string and ig teh char is not a vowel, we'll calculate the cost of replacing it with the vowel of which corresponding variable is greater than zero and decrease it. It doesn't seem to work out.
Please let me know your approach to solve it. If any information is obscure, let me know in comments. Thanks
here's my code:
public class VowelCount {
static int minCount(String s, int a, int e, int i, int o, int u) {
char[] array = s.toCharArray();
List<Character> list = new ArrayList<>();
list.add('a');
list.add('e');
list.add('i');
list.add('o');
list.add('u');
Arrays.sort(array);
for (int j = 0; j < s.length(); j++) {
if (s.charAt(j) == 'a' && a > 0) {
a--;
}
else if (s.charAt(j) == 'e' && a > 0) {
e--;
}
else if (s.charAt(j) == 'i' && a > 0) {
i--;
}
else if (s.charAt(j) == 'o' && a > 0) {
o--;
}
else if (s.charAt(j) == 'u' && a > 0) {
u--;
}
}
int count =0;
for (int j = 0; j < array.length; j++) {
int count1=0, count2=0, count3=0, count4=0, count5=0, semicount1=0, semicount2=0, fincount=0;
if (!list.contains(array[j])) {
if (a > 0) {
int c1 =(int) array[j];
int c2 = (int) 'a';
count1 = Math.abs(c1-c2);
a--;
}
if (e > 0) {
int c1 =(int) array[j];
int c2 = (int) 'e';
count1 = Math.abs(c1-c2);
e--;
}
if (i > 0) {
int c1 =(int) array[j];
int c2 = (int) 'i';
count1 = Math.abs(c1-c2);
i--;
}
if (o > 0) {
int c1 =(int) array[j];
int c2 = (int) 'o';
count1 = Math.abs(c1-c2);
o--;
}
if (u > 0) {
int c1 =(int) array[j];
int c2 = (int) 'u';
count1 = Math.abs(c1-c2);
u--;
}
if (count1!=0 && count2!=0) {
semicount1 = Math.min(count1, count2);
} else if (count1 == 0) {
semicount1 = count2;
} else if (count2 == 0) {
semicount1 = count1;
}
if (count3 != 0 && count4 != 0) {
semicount2 = Math.min(count3, count4);
} else if (count3 == 0) {
semicount2 = count4;
} else if (count4 == 0) {
semicount2 = count3;
}
System.out.println("adding to count");
fincount = Math.min(semicount1, semicount2);
if (count5 != 0) {
count+= Math.min(count5, fincount);
} else count+= fincount;
}
}
System.out.println(count);
return count;
}
public static void main(String[] args) {
minCount("beiou", 1, 1, 1, 1 ,1);
}
}
I'm assuming that the sum of a, b, c, d and e is at most s.length.
This problem can be solved in linear time. Before solving the problem, lets consider three scenarios:
s = "bc", a = 1, e = 1, best p = "ae", optimal cost = 1 + 2
s = "dj", a = 1, e = 1, best p = "ae", optimal cost = 3 + 5
s = "fj", a = 1, e = 1, best p = "ae", optimal cost = 5 + 5
We can think the characters as points in number line. In the first scenario, the consonants lie between the vowels. In the second one, on consonant lie between the vowels and other one is outside. In the third example, both of them are outside. And we can see that, it is always better to choose the vowel with lower ASCII key at first and grab the cheapest constant for it.
So, now the approach would be, to convert all the constant to 'a' that we need, in cheapest cost. Then go for b, then c and so on.
EDIT:
One particular case I've missed is that, if we've two options to choose from with same cost. Which one should we choose? The answer is to choose the one with lower ASCII value. Thanks to Tushar Makkar for pointing it out.

the next palindrome in Java [duplicate]

Firstly here is the problem:
A positive integer is called a palindrome if its representation in the decimal system is the same when read from left to right and from right to left. For a given positive integer K of not more than 1000000 digits, write the value of the smallest palindrome larger than K to output. Numbers are always displayed without leading zeros.
Input: The first line contains integer t, the number of test cases. Integers K are given in the next t lines.
Output: For each K, output the smallest palindrome larger than K.
Example
Input:
2
808
2133
Output:
818
2222
Secondly here is my code:
// I know it is bad practice to not cater for erroneous input,
// however for the purpose of the execise it is omitted
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.lang.Exception;
import java.math.BigInteger;
public class Main
{
public static void main(String [] args){
try{
Main instance = new Main(); // create an instance to access non-static
// variables
// Use java.util.Scanner to scan the get the input and initialise the
// variable
Scanner sc=null;
BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
String input = "";
int numberOfTests = 0;
String k; // declare any other variables here
if((input = r.readLine()) != null){
sc = new Scanner(input);
numberOfTests = sc.nextInt();
}
for (int i = 0; i < numberOfTests; i++){
if((input = r.readLine()) != null){
sc = new Scanner(input);
k=sc.next(); // initialise the remainder of the variables sc.next()
instance.palindrome(k);
} //if
}// for
}// try
catch (Exception e)
{
e.printStackTrace();
}
}// main
public void palindrome(String number){
StringBuffer theNumber = new StringBuffer(number);
int length = theNumber.length();
int left, right, leftPos, rightPos;
// if incresing a value to more than 9 the value to left (offset) need incrementing
int offset, offsetPos;
boolean offsetUpdated;
// To update the string with new values
String insert;
boolean hasAltered = false;
for(int i = 0; i < length/2; i++){
leftPos = i;
rightPos = (length-1) - i;
offsetPos = rightPos -1; offsetUpdated = false;
// set values at opposite indices and offset
left = Integer.parseInt(String.valueOf(theNumber.charAt(leftPos)));
right = Integer.parseInt(String.valueOf(theNumber.charAt(rightPos)));
offset = Integer.parseInt(String.valueOf(theNumber.charAt(offsetPos)));
if(left != right){
// if r > l then offest needs updating
if(right > left){
// update and replace
right = left;
insert = Integer.toString(right);
theNumber.replace(rightPos, rightPos + 1, insert);
offset++; if (offset == 10) offset = 0;
insert = Integer.toString(offset);
theNumber.replace(offsetPos, offsetPos + 1, insert);
offsetUpdated = true;
// then we need to update the value to left again
while (offset == 0 && offsetUpdated){
offsetPos--;
offset =
Integer.parseInt(String.valueOf(theNumber.charAt(offsetPos)));
offset++; if (offset == 10) offset = 0;
// replace
insert = Integer.toString(offset);
theNumber.replace(offsetPos, offsetPos + 1, insert);
}
// finally incase right and offset are the two middle values
left = Integer.parseInt(String.valueOf(theNumber.charAt(leftPos)));
if (right != left){
right = left;
insert = Integer.toString(right);
theNumber.replace(rightPos, rightPos + 1, insert);
}
}// if r > l
else
// update and replace
right = left;
insert = Integer.toString(right);
theNumber.replace(rightPos, rightPos + 1, insert);
}// if l != r
}// for i
System.out.println(theNumber.toString());
}// palindrome
}
Finally my explaination and question.
My code compares either end and then moves in
if left and right are not equal
if right is greater than left
(increasing right past 9 should increase the digit
to its left i.e 09 ---- > 10) and continue to do
so if require as for 89999, increasing the right
most 9 makes the value 90000
before updating my string we check that the right
and left are equal, because in the middle e.g 78849887
we set the 9 --> 4 and increase 4 --> 5, so we must cater for this.
The problem is from spoj.pl an online judge system. My code works for all the test can provide but when I submit it, I get a time limit exceeded error and my answer is not accepted.
Does anyone have any suggestions as to how I can improve my algorithm. While writing this question i thought that instead of my while (offset == 0 && offsetUpdated) loop i could use a boolean to to make sure i increment the offset on my next [i] iteration. Confirmation of my chang or any suggestion would be appreciated, also let me know if i need to make my question clearer.
This seems like a lot of code. Have you tried a very naive approach yet? Checking whether something is a palindrome is actually very simple.
private boolean isPalindrome(int possiblePalindrome) {
String stringRepresentation = String.valueOf(possiblePalindrome);
if ( stringRepresentation.equals(stringRepresentation.reverse()) ) {
return true;
}
}
Now that might not be the most performant code, but it gives you a really simple starting point:
private int nextLargestPalindrome(int fromNumber) {
for ( int i = fromNumber + 1; ; i++ ) {
if ( isPalindrome( i ) ) {
return i;
}
}
}
Now if that isn't fast enough you can use it as a reference implementation and work on decreasing the algorithmic complexity.
There should actually be a constant-time (well it is linear on the number of digits of the input) way to find the next largest palindrome. I will give an algorithm that assumes the number is an even number of digits long (but can be extended to an odd number of digits).
Find the decimal representation of the input number ("2133").
Split it into the left half and right half ("21", "33");
Compare the last digit in the left half and the first digit in the right half.
a. If the right is greater than the left, increment the left and stop. ("22")
b. If the right is less than the left, stop.
c. If the right is equal to the left, repeat step 3 with the second-last digit in the left and the second digit in the right (and so on).
Take the left half and append the left half reversed. That's your next largest palindrome. ("2222")
Applied to a more complicated number:
1. 1234567887654322
2. 12345678 87654322
3. 12345678 87654322
^ ^ equal
3. 12345678 87654322
^ ^ equal
3. 12345678 87654322
^ ^ equal
3. 12345678 87654322
^ ^ equal
3. 12345678 87654322
^ ^ equal
3. 12345678 87654322
^ ^ equal
3. 12345678 87654322
^ ^ equal
3. 12345678 87654322
^ ^ greater than, so increment the left
3. 12345679
4. 1234567997654321 answer
This seems a bit similar to the algorithm you described, but it starts at the inner digits and moves to the outer.
There is no reason to fiddle with individual digits when the only needed operation is one simple addition. The following code is based on Raks' answer.
The code stresses simplicity over execution speed, intentionally.
import static org.junit.Assert.assertEquals;
import java.math.BigInteger;
import org.junit.Test;
public class NextPalindromeTest {
public static String nextPalindrome(String num) {
int len = num.length();
String left = num.substring(0, len / 2);
String middle = num.substring(len / 2, len - len / 2);
String right = num.substring(len - len / 2);
if (right.compareTo(reverse(left)) < 0)
return left + middle + reverse(left);
String next = new BigInteger(left + middle).add(BigInteger.ONE).toString();
return next.substring(0, left.length() + middle.length())
+ reverse(next).substring(middle.length());
}
private static String reverse(String s) {
return new StringBuilder(s).reverse().toString();
}
#Test
public void testNextPalindrome() {
assertEquals("5", nextPalindrome("4"));
assertEquals("11", nextPalindrome("9"));
assertEquals("22", nextPalindrome("15"));
assertEquals("101", nextPalindrome("99"));
assertEquals("151", nextPalindrome("149"));
assertEquals("123454321", nextPalindrome("123450000"));
assertEquals("123464321", nextPalindrome("123454322"));
}
}
Well I have constant order solution(atleast of order k, where k is number of digits in the number)
Lets take some examples
suppose n=17208
divide the number into two parts from middle
and reversibly write the most significant part onto the less significant one.
ie, 17271
if the so generated number is greater than your n it is your palindrome, if not just increase the center number(pivot) ie, you get 17371
other examples
n=17286
palidrome-attempt=17271(since it is less than n increment the pivot, 2 in this case)
so palidrome=17371
n=5684
palidrome1=5665
palidrome=5775
n=458322
palindrome=458854
now suppose n = 1219901
palidrome1=1219121
incrementing the pivot makes my number smaller here
so increment the number adjacent pivot too
1220221
and this logic could be extended
public class NextPalindrome
{
int rev, temp;
int printNextPalindrome(int n)
{
int num = n;
for (int i = num+1; i >= num; i++)
{
temp = i;
rev = 0;
while (temp != 0)
{
int remainder = temp % 10;
rev = rev * 10 + remainder;
temp = temp / 10;
}
if (rev == i)
{
break;
}
}
return rev;
}
public static void main(String args[])
{
NextPalindrome np = new NextPalindrome();
int nxtpalin = np.printNextPalindrome(11);
System.out.println(nxtpalin);
}
}
Here is my code in java. Whole idea is from here.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter number of tests: ");
int t = sc.nextInt();
for (int i = 0; i < t; i++) {
System.out.println("Enter number: ");
String numberToProcess = sc.next(); // ne proveravam dal su brojevi
nextSmallestPalindrom(numberToProcess);
}
}
private static void nextSmallestPalindrom(String numberToProcess) {
int i, j;
int length = numberToProcess.length();
int[] numberAsIntArray = new int[length];
for (int k = 0; k < length; k++)
numberAsIntArray[k] = Integer.parseInt(String
.valueOf(numberToProcess.charAt(k)));
numberToProcess = null;
boolean all9 = true;
for (int k = 0; k < length; k++) {
if (numberAsIntArray[k] != 9) {
all9 = false;
break;
}
}
// case 1, sve 9ke
if (all9) {
whenAll9(length);
return;
}
int mid = length / 2;
if (length % 2 == 0) {
i = mid - 1;
j = mid;
} else {
i = mid - 1;
j = mid + 1;
}
while (i >= 0 && numberAsIntArray[i] == numberAsIntArray[j]) {
i--;
j++;
}
// case 2 already polindrom
if (i == -1) {
if (length % 2 == 0) {
i = mid - 1;
j = mid;
} else {
i = mid;
j = i;
}
addOneToMiddleWithCarry(numberAsIntArray, i, j, true);
} else {
// case 3 not polindrom
if (numberAsIntArray[i] > numberAsIntArray[j]) { // 3.1)
while (i >= 0) {
numberAsIntArray[j] = numberAsIntArray[i];
i--;
j++;
}
for (int k = 0; k < numberAsIntArray.length; k++)
System.out.print(numberAsIntArray[k]);
System.out.println();
} else { // 3.2 like case 2
if (length % 2 == 0) {
i = mid - 1;
j = mid;
} else {
i = mid;
j = i;
}
addOneToMiddleWithCarry(numberAsIntArray, i, j, false);
}
}
}
private static void whenAll9(int length) {
for (int i = 0; i <= length; i++) {
if (i == 0 || i == length)
System.out.print('1');
else
System.out.print('0');
}
}
private static void addOneToMiddleWithCarry(int[] numberAsIntArray, int i,
int j, boolean palindrom) {
numberAsIntArray[i]++;
numberAsIntArray[j] = numberAsIntArray[i];
while (numberAsIntArray[i] == 10) {
numberAsIntArray[i] = 0;
numberAsIntArray[j] = numberAsIntArray[i];
i--;
j++;
numberAsIntArray[i]++;
numberAsIntArray[j] = numberAsIntArray[i];
}
if (!palindrom)
while (i >= 0) {
numberAsIntArray[j] = numberAsIntArray[i];
i--;
j++;
}
for (int k = 0; k < numberAsIntArray.length; k++)
System.out.print(numberAsIntArray[k]);
System.out.println();
}
}
Try this
public static String genNextPalin(String base){
//check if it is 1 digit
if(base.length()==1){
if(Integer.parseInt(base)==9)
return "11";
else
return (Integer.parseInt(base)+1)+"";
}
boolean check = true;
//check if it is all 9s
for(char a: base.toCharArray()){
if(a!='9')
check = false;
}
if(check){
String num = "1";
for(int i=0; i<base.length()-1; i++)
num+="0";
num+="1";
return num;
}
boolean isBasePalin = isPalindrome(base);
int mid = base.length()/2;
if(isBasePalin){
//if base is palin and it is odd increase mid and return
if(base.length()%2==1){
BigInteger leftHalf = new BigInteger(base.substring(0,mid+1));
String newLeftHalf = leftHalf.add(BigInteger.ONE).toString();
String newPalin = genPalin2(newLeftHalf.substring(0,mid),newLeftHalf.charAt(mid));
return newPalin;
}
else{
BigInteger leftHalf = new BigInteger(base.substring(0,mid));
String newLeftHalf = leftHalf.add(BigInteger.ONE).toString();
String newPalin = genPalin(newLeftHalf.substring(0,mid));
return newPalin;
}
}
else{
if(base.length()%2==1){
BigInteger leftHalf = new BigInteger(base.substring(0,mid));
BigInteger rightHalf = new BigInteger(reverse(base.substring(mid+1,base.length())));
//check if leftHalf is greater than right half
if(leftHalf.compareTo(rightHalf)==1){
String newPalin = genPalin2(base.substring(0,mid),base.charAt(mid));
return newPalin;
}
else{
BigInteger leftHalfMid = new BigInteger(base.substring(0,mid+1));
String newLeftHalfMid = leftHalfMid.add(BigInteger.ONE).toString();
String newPalin = genPalin2(newLeftHalfMid.substring(0,mid),newLeftHalfMid.charAt(mid));
return newPalin;
}
}
else{
BigInteger leftHalf = new BigInteger(base.substring(0,mid));
BigInteger rightHalf = new BigInteger(reverse(base.substring(mid,base.length())));
//check if leftHalf is greater than right half
if(leftHalf.compareTo(rightHalf)==1){
return genPalin(base.substring(0,mid));
}
else{
BigInteger leftHalfMid = new BigInteger(base.substring(0,mid));
String newLeftHalfMid = leftHalfMid.add(BigInteger.ONE).toString();
return genPalin(newLeftHalfMid);
}
}
}
}
public static String genPalin(String base){
return base + new StringBuffer(base).reverse().toString();
}
public static String genPalin2(String base, char middle){
return base + middle +new StringBuffer(base).reverse().toString();
}
public static String reverse(String in){
return new StringBuffer(in).reverse().toString();
}
static boolean isPalindrome(String str) {
int n = str.length();
for( int i = 0; i < n/2; i++ )
if (str.charAt(i) != str.charAt(n-i-1))
return false;
return true;
}
HI Here is another simple algorithm using python,
def is_palindrome(n):
if len(n) <= 1:
return False
else:
m = len(n)/2
for i in range(m):
j = i + 1
if n[i] != n[-j]:
return False
return True
def next_palindrome(n):
if not n:
return False
else:
if is_palindrome(n) is True:
return n
else:
return next_palindrome(str(int(n)+1))
print next_palindrome('1000010')
I have written comments to clarify what each step is doing in this python code.
One thing that need to be taken into consideration is that input can be very large that we can not simply perform integer operations on it. So taking input as string and then manipulating it would be much easier.
tests = int(input())
results = []
for i in range(0, tests):
pal = input().strip()
palen = len(pal)
mid = int(palen/2)
if palen % 2 != 0:
if mid == 0: # if the number is of single digit e.g. next palindrome for 5 is 6
ipal = int(pal)
if ipal < 9:
results.append(int(pal) + 1)
else:
results.append(11) # for 9 next palindrome will be 11
else:
pal = list(pal)
pl = l = mid - 1
pr = r = mid + 1
flag = 'n' # represents left and right half of input string are same
while pl >= 0:
if pal[pl] > pal[pr]:
flag = 'r' # 123483489 in this case pal[pl] = 4 and pal[pr] = 3 so we just need to copy left half in right half
break # 123484321 will be the answer
elif pal[pl] < pal[pr]:
flag = 'm' # 123487489 in this case pal[pl] = 4 and pal[pr] = 9 so copying left half in right half will make number smaller
break # in this case we need to take left half increment by 1 and the copy in right half 123494321 will be the anwere
else:
pl = pl -1
pr = pr + 1
if flag == 'm' or flag == 'n': # increment left half by one and copy in right half
if pal[mid] != '9': # if mid element is < 9 the we can simply increment the mid number only and copy left in right half
pal[mid] = str(int(pal[mid]) + 1)
while r < palen:
pal[r] = pal[l]
r = r + 1
l = l - 1
results.append(''.join(pal))
else: # if mid element is 9 this will effect entire left half because of carry
pal[mid] = '0' # we need to take care of large inputs so we can not just directly add 1 in left half
pl = l
while pal[l] == '9':
pal[l] = '0'
l = l - 1
if l >= 0:
pal[l] = str(int(pal[l]) + 1)
while r < palen:
pal[r] = pal[pl]
r = r + 1
pl = pl - 1
if l < 0:
pal[0] = '1'
pal[palen - 1] = '01'
results.append(''.join(pal))
else:
while r < palen: # when flag is 'r'
pal[r] = pal[l]
r = r + 1
l = l - 1
results.append(''.join(pal))
else: # even length almost similar concept here with flags having similar significance as in case of odd length input
pal = list(pal)
pr = r = mid
pl = l = mid - 1
flag = 'n'
while pl >= 0:
if pal[pl] > pal[pr]:
flag = 'r'
break
elif pal[pl] < pal[pr]:
flag = 'm'
break
else:
pl = pl -1
pr = pr + 1
if flag == 'r':
while r < palen:
pal[r] = pal[l]
r = r + 1
l = l - 1
results.append(''.join(pal))
else:
if pal[l] != '9':
pal[l] = str(int(pal[l]) + 1)
while r < palen:
pal[r] = pal[l]
r = r + 1
l = l - 1
results.append(''.join(pal))
else:
pal[mid] = '0'
pl = l
while pal[l] == '9':
pal[l] = '0'
l = l - 1
if l >= 0:
pal[l] = str(int(pal[l]) + 1)
while r < palen:
pal[r] = pal[pl]
r = r + 1
pl = pl - 1
if l < 0:
pal[0] = '1'
pal[palen - 1] = '01'
results.append(''.join(pal))
for xx in results:
print(xx)
We can find next palindrome easily like below.
private void findNextPalindrom(int i) {
i++;
while (!checkPalindrom(i)) {
i++;
}
Log.e(TAG, "findNextPalindrom:next palindrom is===" + i);
}
private boolean checkPalindrom(int num) {
int temp = num;
int rev = 0;
while (num > 0) {
int rem = num % 10;
rev = rev * 10 + rem;
num = num / 10;
}
return temp == rev;
}
Simple codes and test output:
class NextPalin
{
public static void main( String[] args )
{
try {
int[] a = {2, 23, 88, 234, 432, 464, 7887, 7657, 34567, 99874, 7779222, 2569981, 3346990, 229999, 2299999 };
for( int i=0; i<a.length; i++)
{
int add = findNextPalin(a[i]);
System.out.println( a[i] + " + " + add + " = " + (a[i]+add) );
}
}
catch( Exception e ){}
}
static int findNextPalin( int a ) throws Exception
{
if( a < 0 ) throw new Exception();
if( a < 10 ) return a;
int count = 0, reverse = 0, temp = a;
while( temp > 0 ){
reverse = reverse*10 + temp%10;
count++;
temp /= 10;
}
//compare 'half' value
int halfcount = count/2;
int base = (int)Math.pow(10, halfcount );
int reverseHalfValue = reverse % base;
int currentHalfValue = a % base;
if( reverseHalfValue == currentHalfValue ) return 0;
if( reverseHalfValue > currentHalfValue ) return (reverseHalfValue - currentHalfValue);
if( (((a-currentHalfValue)/base)%10) == 9 ){
//cases like 12945 or 1995
int newValue = a-currentHalfValue + base*10;
int diff = findNextPalin(newValue);
return base*10 - currentHalfValue + diff;
}
else{
return (base - currentHalfValue + reverseHalfValue );
}
}
}
$ java NextPalin
2 + 2 = 4
23 + 9 = 32
88 + 0 = 88
234 + 8 = 242
432 + 2 = 434
464 + 0 = 464
7887 + 0 = 7887
7657 + 10 = 7667
34567 + 76 = 34643
99874 + 25 = 99899
7779222 + 555 = 7779777
2569981 + 9771 = 2579752
3346990 + 443 = 3347433
229999 + 9933 = 239932
2299999 + 9033 = 2309032

Hackerrank: Sherlock and Anagrams(Moderate under Strings section)

Problem description: https://www.hackerrank.com/challenges/sherlock-and-anagrams
Can somebody please tell me what am I doing wrong? My algorithm is:
Input the string ; str
Generate a pattern string from length i=1 to str.length-2
Check whether anagram of pattern string exist in str.substring(i+1)
Below are the test cases which are NOT passing :
input-string My OP Expected OP
ifailuhkqq 2 3
My code:
public class SherlockandAnagrams
{
static int count = 0;
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
generatePairs(sc.next());
int len = 1;
}
public static void generatePairs(String str)
{
int len = 1;
//int i=0;
while (len < str.length())
{
for (int i = 0; i + len <= str.length(); i++)
findAnagramPairs(str, len, str.substring(i, i + len), i + 1);
len++;
}
System.out.println(count);
}
private static void findAnagramPairs(String str, int len, String pattern, int p)
{
int i = p;
while (i + len <= str.length())
{
if (checkAnagram(pattern, str.substring(i, i + len)))
{
count++;
}
i++;
}
}
private static boolean checkAnagram(String pattern, String text)
{
if (pattern.length() == 1)
{
if (pattern.equals(text))
return true;
else
return false;
}
else
{
int i = 0;
int j = pattern.length() - 1;
while (i < pattern.length())
{
if (pattern.charAt(i) == text.charAt(j))
{
i++;
j--;
}
else
return false;
}
return true;
}
}
}
A simpler solution to the problem would be the following:
An anagramic pair with starting-indices at (n , m) and length l can only exist, if another pair with length l - 1 at (n or n - 1 or n + 1 , m or m - 1 or m - 1) exists. Thus we can easily reduce efficiency from bruteforce to a more efficient solution.
An example:
A B C B A A B C A
len 1 A A A A //all pairs containing A
len 2 A B B A //all pairs that match A B or its reverse
len 3 A B C B A //all pairs that match A B C or its reverse
OR
A B C B A A B C A
len 1 B B B //all pairs containing B
len 2 B C B B C //all pairs that match B C or its reverse
len 3 A B C B A A B C //all pairs that match A B C or its reverse
The same applies to any other pair of length l and it's matching pairs with length l + 1. In general, a pair of length l + 1 only exists, if two pairs (a , b) and (c , d) of length l exists, such that either a = c - l and b = d + l or a = c + l and b = d - l exist.
In pseudocode this would look like this:
set pairs = listAnagrams(input , 1)
int len = 1
while NOT pairs.isEmpty()
set next_len
//generate pairs with length len + 1
for pair p in pairs
pair left = pair(p.a - len , p.b + len)
pair right = pair(p.a + len , p.b - len)
if pairs.contains(left)
next_len.add(pair(p.a , left.b)
if pairs.contains(right)
next_len.add(pair(left.a , p.b)
pairs = next_len
++len

Sorting three command line integers

Hello I'm trying to make a code that takes three integers from the command line and sorts them into the min, mid, and max values. I can't figure out the mid programming. It won't always sort them properly. Can you help?
public class SortInteger{
public static int max3(int a, int b, int c) {
int max = a;
if (b > max) max = b;
if (c > max) max = c;
return max;
}
public static int min3(int a, int b, int c) {
int min = a;
if (b < min) min = b;
if (c < min) min = c;
return min;}
public static int sort(int a, int b, int c){
int sort = a;
if (sort > b && sort < c) sort = a;
else sort = b;
if (sort > a && sort < c) sort = b;
else sort =c;
if (sort > c && sort < a) sort = c;
else sort =b;
if (sort > c && sort < b) sort = c;
else sort = b;
if (sort > a && sort < b) sort = c;
else sort = c;
return sort;
}
public static void main(String[] args){
int a= Integer.parseInt(args [0]);
int b=Integer.parseInt(args[1]);
int c=Integer.parseInt(args[2]);
StdOut.println("Min is " + min3(a, b, c));
StdOut.println("Mid is " + sort(a, b, c));
StdOut.println("Max is " + max3(a, b, c));
}
}
Try:
public static int mid(int a, int b, int c){
return a + b + c - max(a,b,c) - min(a,b,c);
}
Also for the min and max just use Math:
public static int min(int a, int b, int c){
return Math.min(Math.min(a,b),c);//Replace with Math.max for max.
}
You're stepping all over your own toes inside the sort function. Take, for instance, your first two if statements:
if (sort > b && sort < c) sort = a;
else sort = b;
if (sort > a && sort < c) sort = b;
else sort =c;
If a is between b and c, your first if statement will be true, and sort will be kept as the value of a. But, then consider your next one. The value in a will not be greater than a, so the second if statement will be false, and change sort to c, even though you already found a to be the middle value. Not what you wanted. To fix this, you could change the code you execute when your if statements are true to just return the value of sort. So, like:
if (sort > b && sort < c) return sort;
else sort = b;
if (sort > a && sort < c) return sort;
else sort =c;
// etc.
Try the following:
public class SortInteger
{
//use general sorting algorithm for arbitrary length, this is for 3 length specifically
public static int[] sort(int[] inputs)
{
int k;
if(inputs[0] >= inputs[1])
{
k = inputs[0];
inputs[0] = inputs[1];
inputs[1] = k;
}
if(inputs[1] >= inputs[2])
{
k = inputs[1];
inputs[1] = inputs[2];
inputs[2] = k;
}
//incase our last element is less than our first we repeat:
if(inputs[0] >= inputs[1])
{
k = inputs[0];
inputs[0] = inputs[1];
inputs[1] = k;
}
return inputs
}
public static void main(String[] args)
{
int[] x = new int[3];
x[0] = Integer.parseInt(args[0]);
x[1] = Integer.parseInt(args[1]);
x[2] = Integer.parseInt(args[2]);
x = sort(x);
System.out.println("min is: " + x[0]);
System.out.println("mid is: " + x[1]);
System.out.println("max is: " + x[2]);
}
}

Solving a using Segment Tree

You are given a sequence A of N (N <= 50000) integers between -10000 and 10000. On this sequence you have to apply M (M <= 50000) operations:
modify the i-th element in the sequence or for given x y print max{Ai + Ai+1 + .. + Aj | x<=i<=j<=y }.
Problem Link
I am using Segment Tree for this but i am not getting the correct output , please Help me where i have committed the mistake
CODE:
Making a Tree:
public static void maketree(int current , int a , int b ,int[] arr){
if(b<a) return;
if(b==a) {dp[current] = arr[a]; return ;}
maketree(2*current, a, (a+b)/2, arr);
maketree(2*current+1,1+ (a+b)/2, b, arr);
if(dp[2*current]>0 && dp[2*current+1]>0) dp[current] = dp[2*current] + dp[2*current+1];
else if(dp[2*current]>dp[2*current+1]) dp[current] = dp[2*current];
else dp[current] = dp[2*current+1];
}
Updating Function
public static void update(int current , int a , int b , int c , int value){
if(a>b || c<a || c>b) return ;
if(a==b){ dp[current] = value; return ; }
update(2*current, a, (a+b)/2, c, value);
update(2*current+1, (b+a)/2 +1, b, c, value);
if(dp[2*current]>0 && dp[2*current+1]>0) dp[current] = dp[2*current] + dp[2*current+1];
else if(dp[2*current]>dp[2*current+1]) dp[current] = dp[2*current];
else dp[current] = dp[2*current+1];
}
Query Function:
public static int query(int current , int a , int b , int i , int j){
int ans =0;
if(a>j || b<i || a>b) return Integer.MIN_VALUE;
if(a>=i && b<=j) return dp[current];
int x = query(2*current, a, (a+b)/2, i, j);
int y = query(2*current+1, (a+b)/2 +1, b, i, j);
if(x>0 && y>0) ans= x+y;
else if(x>y) ans = x;
else ans =y;
return ans;
}
I don;t know where i have made mistake please help , What will storage capacity required for dp array i.e. size of dp
when you are merging two nodes,then it may be like given below.execute any simple example so that you can feel it :)
void merge(node a , node b)
{
sum = a.sum + b.sum;
pre = max(a.pre , (a.sum + b.pre));
suf = max(b.suf , (b.sum + a.suf));
result = max(a.suf + b.pre,max(a.result , b.result));
}
it is quite overcomplicated imo...
int tree[1 << 17]; // 2 ^ 17 >= N * 2
int M = 1; //base of tree or sth i dont remember english name
int query(int L, int R){
int res = -10000; //minimum possible value in array
L += M - 1;
R += M - 1;
while(L <= R){
if(L % 2 == 1) res = max(res, tree[L++];
if(R % 2 == 0) res = max(res, tree[R++];
L /= 2;
R /= 2;
}
return res;
}
void update(int v, int value){
v += M - 1;
tree[v] = value;
while(v > 0){
v /= 2;
tree[v] = max(tree[v * 2], tree[v * 2 + 1]);
}
}
void make_tree(){
int n;
cin >> n;
while(M < n) M *= 2; // M is half of the size of tree
for(int i = 0;i < n;i++)
cin >> tree[i + M]; // just reading input to tree;
for(int i = M - 1;i > 0;i--) // first update for all nodes other than leafs
tree[i] = max(tree[i * 2], tree[i * 2 + 1]);
}

Categories