Related
I was asked this question in an contest.
Given a string containing only M and L, we can change any "M" to "L" or any "L" to "M". The objective of this function is to calculate the minimum number of changes we have to make in order to achieve the desired longest M-interval length K.
For example, given S = "MLMMLLM" and K = 3, the function should return 1. We can change the letter at position 4 (counting from 0) to obtain "MLMMMLM", in which the longest interval of letters "M" is exactly three characters long.
For another example, given S = "MLMMMLMMMM" and K = 2, the function should return 2. We can, for example, modify the letters at positions 2 and 7 to get the string "MLLMMLMLMM", which satisfies the desired property.
Here's what I have tried till now, but I am not getting correct output:
I am traversing the string and whenever longest char count exceeds K, I'm replacing M with L that point.
public static int solution(String S, int K) {
StringBuilder Str = new StringBuilder(S);
int longest=0;int minCount=0;
for(int i=0;i<Str.length();i++){
char curr=S.charAt(i);
if(curr=='M'){
longest=longest+1;
if(longest>K){
Str.setCharAt(i, 'L');
minCount=minCount+1;
}
}
if(curr=='L')
longest=0;
}
if(longest < K){
longest=0;int indexoflongest=0;minCount=0;
for(int i=0;i<Str.length();i++){
char curr=S.charAt(i);
if(curr=='M'){
longest=longest+1;
indexoflongest=i;
}
if(curr=='L')
longest=0;
}
Str.setCharAt(indexoflongest, 'M');
minCount=minCount+1;
}
return minCount;
}
There are 2 parts to this algorithm as we want to get the longest character interval equal to K.
We already have a interval >= K so now we need to appropriately change some characters so we greedily change every (k + 1) th character and again start counting from 0.
Now if the interval was less than K I will need to run a sliding window over the array. While running this window I am basically considering converting all L's to M's in this window of length K. But this comes with a side effect of increasing the length of the interval as there could be K's outside so this variable (int nec) keeps track of that. So now I have to also consider converting the 2 possible M's outside the (K length) window to L's.
Here's the complete runnable code in C++. Have a good day.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector <int> vi;
typedef pair<int, int> ii;
int change(string s, int k) {
// handling interval >= k
bool flag = false;
int ans = 0;
int cnt = 0;
for(int i=0; i<s.size(); i++) {
if(s[i] == 'M') cnt++;
else cnt = 0;
if(cnt == k) flag = true;
if(cnt > k) s[i] = 'L', ans++, cnt = 0;
}
if(flag) return ans;
// handling max interval < k
// If the interval is too big.
if(k > s.size()) {
cerr << "Can't do it.\n"; exit(0);
}
// Sliding window
cnt = 0;
for(int i=0; i<k; i++) {
if(s[i] == 'L') cnt++;
}
ans = cnt + (s[k] == 'M'); // new edit
int nec = 0; // new edit
for(int i=k; i<s.size(); i++) {
if(s[i-k] == 'L') cnt--;
if(s[i] == 'L') cnt++;
nec = 0;
if(i-k != 0 && s[i-k-1] == 'M')
nec++;
if(i < s.size()-1 && s[i+1] == 'M')
nec++;
ans = min(ans, cnt + nec);
}
return ans;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
string s;
int k;
cin >> s >> k;
int ans = change(s, k);
cout << ans << "\n";
return 0;
}
int
process_data(const char *m, int k)
{
int m_cnt = 0, c_cnt = 0;
char ch;
const char *st = m;
int inc_cnt = -1;
int dec_cnt = -1;
while((ch = *m++) != 0) {
if (m_cnt++ < k) {
c_cnt += ch == 'M' ? 0 : 1;
if ((m_cnt == k) && (
(inc_cnt == -1) || (inc_cnt > c_cnt))) {
inc_cnt = c_cnt;
}
}
else if (ch == 'M') {
if (*st++ == 'M') {
/*
* losing & gaining M carries no change provided
* there is atleast one L in the chunk. (c_cnt != 0)
* Else it implies stretch of Ms
*/
if (c_cnt <= 0) {
int t;
c_cnt--;
/*
* compute min inserts needed to brak the
* stretch to meet max of k.
*/
t = (k - c_cnt) / (k+1);
dec_cnt += t;
}
}
else {
ASSERT(c_cnt > 0, "expect c_cnt(%d) > 0", c_cnt);
ASSERT(inc_cnt != -1, "expect inc_cnt(%d) != -1", inc_cnt);
/* Losing L and gaining M */
if (--c_cnt < inc_cnt) {
inc_cnt = c_cnt;
}
}
}
else {
if (c_cnt <= 0) {
/*
* take this as a first break and restart
* as any further addition of M should not
* happen. Ignore this L
*/
st = m;
c_cnt = 0;
m_cnt = 0;
}
else if (*st++ == 'M') {
/* losing m & gaining l */
c_cnt++;
}
else {
// losing & gaining L; no change
}
}
}
return dec_cnt != -1 ? dec_cnt : inc_cnt;
}
Corrected code:
int
process_data(const char *m, int k)
{
int m_cnt = 0, c_cnt = 0;
char ch;
const char *st = m;
int inc_cnt = -1;
int dec_cnt = -1;
while((ch = *m++) != 0) {
if (m_cnt++ < k) {
c_cnt += ch == 'M' ? 0 : 1;
if ((m_cnt == k) && (
(inc_cnt == -1) || (inc_cnt > c_cnt))) {
inc_cnt = c_cnt;
}
}
else if (ch == 'M') {
if (*st++ == 'M') {
/*
* losing & gaining M carries no change provided
* there is atleast one L in the chunk. (c_cnt != 0)
* Else it implies stretch of Ms
*/
if (c_cnt <= 0) {
c_cnt--;
}
}
else {
ASSERT(c_cnt > 0, "expect c_cnt(%d) > 0", c_cnt);
ASSERT(inc_cnt != -1, "expect inc_cnt(%d) != -1", inc_cnt);
/* Losing L and gaining M */
if (--c_cnt < inc_cnt) {
inc_cnt = c_cnt;
}
}
}
else {
if (c_cnt <= 0) {
/*
* compute min inserts needed to brak the
* stretch to meet max of k.
*/
dec_cnt += (dec_cnt == -1 ? 1 : 0) + ((k - c_cnt) / (k+1));
/*
* take this as a first break and restart
* as any further addition of M should not
* happen. Ignore this L
*/
st = m;
c_cnt = 0;
m_cnt = 0;
}
else if (*st++ == 'M') {
/* losing m & gaining l */
c_cnt++;
}
else {
// losing & gaining L; no change
}
}
}
if (c_cnt <= 0) {
/*
* compute min inserts needed to brak the
* stretch to meet max of k.
*/
dec_cnt += (dec_cnt == -1 ? 1 : 0) + ((k - c_cnt) / (k+1));
}
return dec_cnt != -1 ? dec_cnt : inc_cnt;
}
The problem is:
Reverse digits of an integer.
Example1: x = 123, return 321
Example2: x = -123, return -321
Did you notice that the reversed integer might overflow? Assume the input is a 32-bit integer, then the reverse of 1000000003 overflows. How should you handle such cases?
Throw an exception? Good, but what if throwing an exception is not an option? You would then have to re-design the function (ie, add an extra parameter).
The solution from the website I search is:
public class Solution {
public static int reverse(int x) {
int ret = 0;
boolean zero = false;
while (!zero) {
ret = ret * 10 + (x % 10);
x /= 10;
if(x == 0){
zero = true;
}
}
return ret;
}
public static void main(String[] args) {
int s = 1000000003;
System.out.println(reverse(s));
}
}
However when s = 1000000003, the console prints -1294967295 instead of 3000000001. So this solution still does not solve the overflow problem if we cannot use exception. Any help here?(Although there is a hint: add an extra parameter, I still cannot figure out what parameter I should add)
There's no need for any data type other than int.
Just make sure when there's an operation that increases a number, reversing the operation should give you the previous number. Otherwise, there's overflow.
public int reverse(int x) {
int y = 0;
while(x != 0) {
int yy = y*10 + x%10;
if ((yy - x%10)/10 != y) return 0;
else y = yy;
x = x/10;
}
return y;
}
Above most of the answers having a trivial problem is that the int variable possibly might overflow. You can try this : x = -2147483648 as parameter.
There has an easy way to solve the problem. Convert x to long, and check if the result >= Integer.MAX_VALUE, otherwise return 0.
The solution passed all test cases on https://leetcode.com/problems/reverse-integer/
This is a java version.
public int reverse(int x) {
long k = x;
boolean isNegtive = false;
if(k < 0){
k = 0 - k;
isNegtive = true;
}
long result = 0;
while(k != 0){
result *= 10;
result += k % 10;
k /= 10;
}
if(result > Integer.MAX_VALUE) return 0;
return isNegtive ? 0 - ((int)result) : (int)result;
}
C# version
public int Reverse(int x)
{
long value = 0;
bool negative = x < 0;
long y = x;
y = Math.Abs(y);
while (y > 0)
{
value *= 10;
value += y % 10;
y /= 10;
}
if(value > int.MaxValue)
{
return int.MaxValue;
}
int ret = (int)value;
if (negative)
{
return 0 - ret;
}
else
{
return ret;
}
}
Python version
def reverse(self, x):
isNegative = x < 0
ret = 0
x = abs(x)
while x > 0:
ret *= 10
ret += x % 10
x /= 10
if ret > 1<<31:
return 0
if isNegative:
return 0 - ret
else:
return ret
This java code handles the overflow condition:
public int reverse(int x) {
long reverse = 0;
while( x != 0 ) {
reverse = reverse * 10 + x % 10;
x = x/10;
}
if(reverse > Integer.MAX_VALUE || reverse < Integer.MIN_VALUE) {
return 0;
} else {
return (int) reverse;
}
}
This is an old question, but anyway let me have a go at it too! I just solved it on leetcode. With this check, you never hit the overflow/ underflow in either direction, and I think the code is more concise than all the listed codes. It passes all test cases.
public int reverse(int x) {
int y = 0;
while(x != 0) {
if(y > Integer.MAX_VALUE/10 || y < Integer.MIN_VALUE/10) return 0;
y *= 10;
y += x % 10;
x /= 10;
}
return y;
}
you can try this code using strings in java
class Solution {
public int reverse(int x) {
int n = Math.abs(x);
String num = Integer.toString(n);
StringBuilder sb = new StringBuilder(num);
sb.reverse();
String sb1;
sb1 = sb.toString();
int foo;
try {
foo = Integer.parseInt(sb1);
}
catch (NumberFormatException e){
foo = 0;
}
if(x < 0){
foo *= -1;
}
return foo;
}
}
My soluton for this problem is to convert integer inputed to c-string, then everthing will be easy.
class Solution {
public:
int reverse(int x) {
char str[11];
bool isNegative = false;
int i;
int ret = 0;
if ( x < 0 ) {
isNegative = true;
x = -x;
}
i = 0;
while ( x != 0 ) {
str[i++] = x % 10 + '0';
x = x / 10;
}
str[i] = '\0';
if ( (isNegative && strlen(str) == 10 && strcmp(str, "2147483648") > 0) || (!isNegative && strlen(str) == 10 && strcmp(str, "2147483647") > 0) ) {
cout << "Out of range!" << endl;
throw new exception();
}
i = 0;
int strLen = (int)strlen(str);
while ( str[i] != '\0' ) {
ret += ((str[i] - '0') * pow(10.0, strLen - 1 - i));
i++;
}
return (isNegative ? -ret : ret);
}
};
This works:
public class Solution {
public int reverse(int x) {
long tmp = Math.abs((long)x);
long res = 0;
while(tmp >= 10){
res += tmp%10;
res*=10;
tmp=tmp/10;
}
res+=tmp;
if(x<0){
res = -res;
}
return (res>Integer.MAX_VALUE||res<Integer.MIN_VALUE)? 0: (int)res;
}
}
I tried to improve the performance a bit but all I could come up with was this:
public class Solution {
public int reverse(int x) {
long tmp = x;
long res = 0;
if(x>0){
while(tmp >= 10){
res += tmp%10;
res*=10;
tmp=tmp/10;
}
}
else{
while(tmp <= -10){
res += tmp%10;
res*=10;
tmp=tmp/10;
}
}
res+=tmp;
return (res>Integer.MAX_VALUE||res<Integer.MIN_VALUE)? 0: (int)res;
}
}
Its C# equivalent runs 5% faster than the 1st version on my machine, but their server says it is slower, which can't be - I got rid of extra function call here, otherwise it is essentially the same. It places me between 60-30% depending on the language (C# or Java). Maybe their benchmarking code is not very good - if you submit several times - resulting times vary a lot.
Solution In Swift 4.0 (in reference to problem from https://leetcode.com/problems/reverse-integer/description/)
func reverse(_ x : Int) -> Int {
var stringConversion = String(x)
var negativeCharacter = false
var finalreversedString = String()
let signedInt = 2147483647 //Max for Int 32
let unSignedInt = -2147483647 // Min for Int 32
if stringConversion.contains("-"){
stringConversion.removeFirst()
negativeCharacter = true
}
var reversedString = String(stringConversion.reversed())
if reversedString.first == "0" {
reversedString.removeFirst()
}
if negativeCharacter {
finalreversedString = "-\(reversedString)"
} else {
finalreversedString = reversedString
}
return (x == 0 || Int(finalreversedString)! > signedInt || Int(finalreversedString)! < unSignedInt) ? 0 : Int(finalreversedString)!
}
Last night, i have tried this same problem and i have found a simple solution in python, which is given below, here after checking the number type positive or negative, though i have tried in different section for both of them, i have convert the negative number into positive and before returning the reverse number, i had converted the number into negative.
For handling overflow, i have just simply checked with the upper limit of our 32-bit signed number and lower limit of the number, and it accepted my answer, thank you.
class Solution:
def reverse(self, x: int):
reverse = 0
if x > 0:
while x != 0:
remainder = x % 10
if reverse > (2147483647/10):
return 0
reverse = reverse * 10 + remainder
x = int(x / 10)
return reverse
elif x < 0:
x = x * (-1)
while x != 0:
remainder = x % 10
if reverse > ((2147483648)/10):
return 0
reverse = reverse * 10 + remainder
x = int(x / 10)
reverse = reverse * (-1)
return reverse
else:
return 0
public static int reverse(int x) {
boolean pos = x >= +0;
int y = (pos) ? x : -x;
StringBuilder sb = new StringBuilder(
String.valueOf(y));
sb.reverse();
int z = Integer.parseInt(sb.toString());
return pos ? z : -z;
}
public static void main(String[] args) {
for (int i = -10; i < 11; i++) {
System.out.printf("%d r= '%d'\n", i, reverse(i));
}
}
Outputs
-10 r= '-1'
-9 r= '-9'
-8 r= '-8'
-7 r= '-7'
-6 r= '-6'
-5 r= '-5'
-4 r= '-4'
-3 r= '-3'
-2 r= '-2'
-1 r= '-1'
0 r= '0'
1 r= '1'
2 r= '2'
3 r= '3'
4 r= '4'
5 r= '5'
6 r= '6'
7 r= '7'
8 r= '8'
9 r= '9'
10 r= '1'
Did you notice the reverse of 10 and -10? Or 20? You could just return a String, for example
public static String reverse(int x) {
boolean pos = x >= +0;
int y = (pos) ? x : -x;
StringBuilder sb = new StringBuilder(
String.valueOf(y));
sb.reverse();
if (!pos) {
sb.insert(0, '-');
}
return sb.toString();
}
public static void main(String[] args) {
for (int i = -10; i < 11; i++) {
System.out.printf("%d r= '%s'\n", i, reverse(i));
}
}
Works as I would expect.
If you are required to return a 32 bit int, and still need to know if there was an overflow perhaps you could use a flag as an extra parameter. If you were using c or c++ you could use pointers to set the flag, or in Java you can use an array (since Java objects pass by value).
Java example:
public class Solution {
public static int reverse(int x, Boolean[] overflowed) {
int ret = 0;
boolean zero = false;
boolean inputIsNegative = x < 0;
while (!zero) {
ret = ret * 10 + (x % 10);
x /= 10;
if(x == 0){
zero = true;
}
}
//Set the flag
if ( (inputIsNegative && (ret > 0)) || ((!inputIsNegative) && (ret < 0)))
overflowed[0] = new Boolean(true);
else
overflowed[0] = new Boolean(false);
return ret;
}
public static void main(String[] args) {
int s = 1000000004;
Boolean[] flag = {null};
System.out.println(s);
int n = reverse(s,flag); //reverse() will set the flag.
System.out.println(flag[0].booleanValue() ? "Error: Overflow": n );
}
}
Notice if the reversed number is too large for a 32 bit integer the flag will be set.
Hope this helps.
Use string to store the reverse and then print or use long or BigInt
public class Solution {
/**
* OVERFLOW
* #param x
* #return
*/
public int reverse(int x) {
int sign = x>0? 1: -1;
x *= sign;
int ret = 0;
while(x>0) {
ret *= 10;
if(ret<0 || x>10&&ret*10/10!=ret) // overflow
return 0;
ret += x%10;
x /= 10;
}
return ret*sign;
}
public static void main(String[] args) {
assert new Solution().reverse(-2147483412)==-2147483412;
}
}
public class Solution {
public int Reverse(int x) {
var sign = x < 0 ? -1 : 1;
var reverse = 0;
if (x == int.MinValue)
{
return 0;
}
x = Math.Abs(x);
while(x > 0)
{
var remainder = x % 10;
if (reverse > ((int.MaxValue - remainder)/10))
{
return 0;
}
reverse = (reverse*10) + remainder;
x = x/10;
}
return sign * Convert.ToInt32(reverse);
}
}
Here we will use long to handle the the over flow:
public class Solution {
public int reverse(int A) {
// use long to monitor Overflow
long result = 0;
while (A != 0) {
result = result * 10 + (A % 10);
A = A / 10;
}
if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
return 0;
} else {
return (int) result;
}
}
}
Well This Suitable Code in Java Can be:-
public class Solution {
public int reverse(int x) {
int r;
long s = 0;
while(x != 0)
{
r = x % 10;
s = (s * 10) + r;
x = x/10;
}
if(s >= Integer.MAX_VALUE || s <= Integer.MIN_VALUE) return 0;
else
return (int)s;
}
}
My solution without using long:
public class ReverseInteger {
public static void main(String[] args) {
int input = Integer.MAX_VALUE;
int output = reverse(input);
System.out.println(output);
}
public static int reverse(int x) {
int remainder = 0;
int result = 0;
if (x < 10 && x > -10) {
return x;
}
while (x != 0) {
remainder = x % 10;
int absResult = Math.abs(result);
int maxResultMultipliedBy10 = Integer.MAX_VALUE / 10;
if (absResult > maxResultMultipliedBy10) {
return 0;
}
int resultMultipliedBy10 = absResult * 10;
int maxRemainder = Integer.MAX_VALUE - resultMultipliedBy10;
if (remainder > maxRemainder) {
return 0;
}
result = result * 10 + remainder;
x = x / 10;
}
return result;
}
}
here is the JavaScript solution.
/**
* #param {number} x
* #return {number}
*/
var reverse = function(x) {
var stop = false;
var res = 0;
while(!stop){
res = res *10 + (x % 10);
x = parseInt(x/10);
if(x==0){
stop = true;
}
}
return (res <= 0x7fffffff && res >= -0x80000000) ? res : 0
};
Taking care if the input is negative
public int reverse(int x)
{
long result = 0;
int res;
int num = Math.abs(x);
while(num!=0)
{
int rem = num%10;
result = result *10 + rem;
num = num / 10;
}
if(result > Integer.MAX_VALUE || result < Integer.MIN_VALUE)
{
return 0;
}
else
{
res = (int)result;
return x < 0 ? -res : res;
}
}
This solution in Java will work:
class Solution {
public int reverse(int x) {
long rev = 0, remainder = 0;
long number = x;
while (number != 0) {
remainder = number % 10;
rev = rev * 10 + remainder;
number = number / 10;
}
if (rev >= Integer.MAX_VALUE || rev <= Integer.MIN_VALUE || x >= Integer.MAX_VALUE || x <= Integer.MIN_VALUE)
return 0;
else
return (int) rev;
}
}
Much simpler solution. Ensure that intermittent result does not exceed INT_MAX or get below INT_MIN
int reverse(int x) {
int y = 0;
while(x != 0) {
if ( (long)y*10 + x%10 > INT_MAX || (long)y*10 + x%10 < INT_MIN) {
std::cout << "overflow occurred" << '\n'
return 0;
}
y = y*10 + x%10;
x = x/10;
}
return y;
}
Here is the solution coded in JS(Javascript, it has passed all the 1032 test cases successfully in Leetcode for the problem (https://leetcode.com/problems/reverse-integer), also as asked in the question about the same.
/**
* #param {number} x
* #return {number}
*/
var reverse = function(x) {
let oldNum = x, newNum = 0, digits = 0, negativeNum = false;
if(oldNum < 0){
negativeNum = true;
}
let absVal = Math.abs(x);
while(absVal != 0){
let r = Math.trunc(absVal % 10);
newNum = (newNum*10) + r; digits++;
absVal = Math.floor(absVal/10);
}
if( !(newNum < Number.MAX_VALUE && newNum >= -2147483648 && newNum <= 2147483647)){
return 0;
}
return negativeNum ? -newNum :newNum;
};
Here is the solution coded in JS(Javascript, it has passed all the 1032 test cases successfully in Leetcode for the problem (https://leetcode.com/problems/reverse-integer), also as asked in the question about the same.
/**
* #param {number} x
* #return {number}
*/
var reverse = function(x) {
let oldNum = x, newNum = 0, digits = 0, negativeNum = false;
if(oldNum < 0){
negativeNum = true;
}
let absVal = Math.abs(x);
while(absVal != 0){
let r = Math.trunc(absVal % 10);
newNum = (newNum*10) + r; digits++;
absVal = Math.floor(absVal/10);
}
if( !(newNum < Number.MAX_VALUE && newNum >= -2147483648 && newNum <= 2147483647)){
return 0;
}
return negativeNum ? -newNum :newNum;
};
The earlier answer was posted by the same user (unregistered). Consider this one.
There are several good solutions posted. Here is my JS solution:
const reverse = function (x) {
const strReversed = x.toString().split("").reverse().join("");
rv =
parseInt(strReversed) > Math.pow(2, 31)
? 0
: Math.sign(x) * parseInt(strReversed);
return rv;
};
I got all 1032 cases to work in python, I don't know how to remove multiple 0's such as 100, 1000, 10000 etc thus I used my if statement multiple times lol.
class Solution:
def reverse(self, x: int) -> int:
string = ""
y = str(x)
ab = list(reversed(y))
if len(ab) > 1 and ab[0] == "0":
ab.remove("0")
if len(ab) > 1 and ab[0] == "0":
ab.remove("0")
if len(ab) > 1 and ab[0] == "0":
ab.remove("0")
if len(ab) > 1 and ab[0] == "0":
ab.remove("0")
if len(ab) > 1 and ab[0] == "0":
ab.remove("0")
if ab[-1] == "-":
ab.remove("-")
ab.insert(0, "-")
for i in ab:
string += i
if int(string) > 2**31 - 1 or int(string) < -2**31:
return 0
return string
public static int reverse(int x) {
if (x == 0) return 0;
int sum = 0;
int y = 0;
while (x != 0) {
int value = (x % 10);
x = x - value;
y = sum;
sum = (sum * 10) + value;
if(sum / 10 != y) return 0;
x = x / 10;
}
return sum;
}
Extracting the first digit and dividing x to ten until x will be equal to 0. Therefore integer will be tokenized its digits.
Every extracted value will be adding the sum value after multiplying the sum by 10. Because adding a new digit means that adding a new 10th to the sum value. Also added if block to check any corruption of data because after 9th digit data will be corrupted.
1032 / 1032 test cases passed.
Status: Accepted
Runtime: 3 ms
Memory Usage: 38 MB
Public int reverse(int A) {
int N, sum = 0;
int rem = 0;
boolean flag = false;
int max = Integer.MAX_VALUE;
int min = Integer.MIN_VALUE;
if (A < 0) {
flag = true;
A = A * -1;} // 123 // 10 1
while (A > 0) {
rem = A % 10;
if (flag == true) {
if ((min + rem) / 10 > -sum) {
return 0;}}else{
if ((max - rem) / 10 < sum) {
return 0;}}
sum = (sum * 10) + rem;
A = A / 10;}
return (flag == true) ? —sum : sum;}}
#java #Algo
def reverse(self, x: int) -> int:
if x<=-2**31 or x>=2**31-1:
return 0
else:
result = 0
number = x
number = abs(number)
while (number) > 0:
newNumber = number % 10
result = result * 10 + newNumber
number = (number // 10)
if x<0:
result = "-"+str(result)
if int(result)<=-2**31:
return 0
return result
else:
if result>=2**31-1:
return 0
return result
if __name__ == '__main__':
obj = Solution()
print(obj.reverse(1534236469))
Note that there are previous solutions that do not work for input: 1000000045
try this:
public int reverse(int A) {
int reverse=0;
int num=A;
boolean flag=false;
if(A<0)
{
num=(-1)*A;
flag=true;
}
int prevnum=0;
while(num>0)
{
int currDigit=num%10;
reverse=reverse*10+currDigit;
if((reverse-currDigit)/10!=prevnum)
return 0;
num=num/10;
prevnum=reverse;
}
if(flag==true)
reverse= reverse*-1;
return reverse;
}
I'm trying to solve a question and my question here is why doesn't my solution work?. Here's the question and below's the answer.
Question taken from leetcode: http://oj.leetcode.com/problems/decode-ways/
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given an encoded message containing digits, determine the total number of ways to decode it.
For example,Given encoded message "12", it could be decoded as "AB" (1 2) or "L" (12). The number of ways decoding "12" is 2.
My solution:
The point with my solution is going backwards and multiplying the number of options if a split is found. By split I mean that digits can be interpreted in two ways. For example: 11 can interpreted in two ways 'aa' or 'k'.
public class Solution {
public int numDecodings(String s) {
if (s.isEmpty() || s.charAt(0) == '0') return 0;
int decodings = 1;
boolean used = false; // Signifies that the prev was already use as a decimal
for (int index = s.length()-1 ; index > 0 ; index--) {
char curr = s.charAt(index);
char prev = s.charAt(index-1);
if (curr == '0') {
if (prev != '1' && prev != '2') {
return 0;
}
index--; // Skip prev because it is part of curr
used = false;
} else {
if (prev == '1' || (prev == '2' && curr <= '6')) {
decodings = decodings * 2;
if (used) {
decodings = decodings - 1;
}
used = true;
} else {
used = false;
}
}
}
return decodings;
}
}
The failure is on the following input:
Input:"4757562545844617494555774581341211511296816786586787755257741178599337186486723247528324612117156948"
Output: 3274568
Expected: 589824
This is a really interesting problem. First, I will show how I would solve this problem. We will see that it is not that complicated when using recursion, and that the problem can be solved using dynamic programming. We will produce a general solution that does not hardcode an upper limit of 26 for each code point.
A note on terminology: I will use the term code point (CP) not in the Unicode sense, but to refer to one of the code numbers 1 though 26. Each code point is represented as a variable number of characters. I will also use the terms encoded text (ET) and clear text (CT) in their obvious meanings. When talking about a sequence or array, the first element is called the head. The remaining elements are the tail.
Theoretical Prelude
The EC "" has one decoding: the CT "".
The EC "3" can be destructured into '3' + "", and has one decoding.
The EC "23" can be destructured as '2' + "3" or '23' + "". Each of the tails has one decoding, so the whole EC has two decodings.
The EC "123" can be destructured as '1' + "23" or '12' + "3". The tails have two and one decodings respectively. The whole EC has three decodings. The destructuring '123' + "" is not valid, because 123 > 26, our upper limit.
… and so on for ECs of any length.
So given a string like "123", we can obtain the number of decodings by finding all valid CPs at the beginning, and summing up the number of decodings of each tail.
The most difficult part of this is to find valid heads. We can get the maximal length of the head by looking at a string representation of the upper limit. In our case, the head can be up to two characters long. But not all heads of appropriate lengths are valid, because they have to be ≤ 26 as well.
Naive Recursive Implementation
Now we have done all the necessary work for a simple (but working) recursive implementation:
static final int upperLimit = 26;
static final int maxHeadSize = ("" + upperLimit).length();
static int numDecodings(String encodedText) {
// check base case for the recursion
if (encodedText.length() == 0) {
return 1;
}
// sum all tails
int sum = 0;
for (int headSize = 1; headSize <= maxHeadSize && headSize <= encodedText.length(); headSize++) {
String head = encodedText.substring(0, headSize);
String tail = encodedText.substring(headSize);
if (Integer.parseInt(head) > upperLimit) {
break;
}
sum += numDecodings(tail);
}
return sum;
}
Cached Recursive Implementation
Obviously this isn't very efficient, because (for longer ETs), the same tail will be analyzed multiple times. Also, we create a lot of temporary strings, but we'll let that be for now. One thing we can easily do is to memoize the number of decodings of a specific tail. For that, we use an array of the same length as the input string:
static final int upperLimit = 26;
static final int maxHeadSize = ("" + upperLimit).length();
static int numDecodings(String encodedText) {
return numDecodings(encodedText, new Integer[1 + encodedText.length()]);
}
static int numDecodings(String encodedText, Integer[] cache) {
// check base case for the recursion
if (encodedText.length() == 0) {
return 1;
}
// check if this tail is already known in the cache
if (cache[encodedText.length()] != null) {
return cache[encodedText.length()];
}
// cache miss -- sum all tails
int sum = 0;
for (int headSize = 1; headSize <= maxHeadSize && headSize <= encodedText.length(); headSize++) {
String head = encodedText.substring(0, headSize);
String tail = encodedText.substring(headSize);
if (Integer.parseInt(head) > upperLimit) {
break;
}
sum += numDecodings(tail, cache); // pass the cache through
}
// update the cache
cache[encodedText.length()] = sum;
return sum;
}
Note that we use an Integer[], not an int[]. This way, we can check for non-existent entries using a test for null. This solution is not only correct, it is also comfortably fast – naive recursion runs in O(number of decodings) time, while the memoized version runs in O(string length) time.
Towards a DP Solution
When you run above code in your head, you will notice that the first invocation with the whole string will have a cache miss, then calculate the number of decodings for the first tail, which also misses the cache every time. We can avoid this by evaluating the tails first, starting from the end of the input. Because all tails will have been evaluated before the whole string is, we can remove the checks for cache misses. Now we also don't have any reason for recursion, because all previous results are already in the cache.
static final int upperLimit = 26;
static final int maxHeadSize = ("" + upperLimit).length();
static int numDecodings(String encodedText) {
int[] cache = new int[encodedText.length() + 1];
// base case: the empty string at encodedText.length() is 1:
cache[encodedText.length()] = 1;
for (int position = encodedText.length() - 1; position >= 0; position--) {
// sum directly into the cache
for (int headSize = 1; headSize <= maxHeadSize && headSize + position <= encodedText.length(); headSize++) {
String head = encodedText.substring(position, position + headSize);
if (Integer.parseInt(head) > upperLimit) {
break;
}
cache[position] += cache[position + headSize];
}
}
return cache[0];
}
This algorithm could be optimized further by noticing that we only ever query the last maxHeadSize elements in the cache. So instead of an array, we could use a fixed-sized queue. At that point, we would have a dynamic programming solution that runs in *O(input length) time and O(maxHeadSize) space.
Specialization for upperLimit = 26
The above algorithms were kept as general as possible, but we can go and manually specialize it for a specific upperLimit. This can be useful because it allows us to do various optimizations. However, this introduces “magic numbers” that make the code harder to maintain. Such manual specializations should therefore be avoided in non-critical software (and the above algorithm is already as fast as it gets).
static int numDecodings(String encodedText) {
// initialize the cache
int[] cache = {1, 0, 0};
for (int position = encodedText.length() - 1; position >= 0; position--) {
// rotate the cache
cache[2] = cache[1];
cache[1] = cache[0];
cache[0] = 0;
// headSize == 1
if (position + 0 < encodedText.length()) {
char c = encodedText.charAt(position + 0);
// 1 .. 9
if ('1' <= c && c <= '9') {
cache[0] += cache[1];
}
}
// headSize == 2
if (position + 1 < encodedText.length()) {
char c1 = encodedText.charAt(position + 0);
char c2 = encodedText.charAt(position + 1);
// 10 .. 19
if ('1' == c1) {
cache[0] += cache[2];
}
// 20 .. 26
else if ('2' == c1 && '0' <= c2 && c2 <= '6') {
cache[0] += cache[2];
}
}
}
return cache[0];
}
Comparision with your code
The code is superficially similar. However, your parsing around characters is more convoluted. You have introduced a used variable that, if set, will decrement the decode count in order to account for double-character CPs. This is wrong, but I am not sure why. The main problem is that you are doubling the count at almost every step. As we have seen, the previous counts are added, and may very well be different.
This indicates that you wrote the code without proper preparation. You can write many kinds of software without having to think too much, but you can't do without careful analysis when designing an algorithm. For me, it is often helpful to design an algorithm on paper, and draw diagrams of each step (along the lines of the “Theoretical Prelude” of this answer). This is especially useful when you are thinking too much about the language you are going to implement in, and too little about possibly wrong assumptions.
I suggest that you read up on “proofs by induction” to understand how to write a correct recursive algorithm. Once you have a recursive solution, you can always translate it into an iterative version.
So here is some what simpler way out for your problem. This is pretty close to calculating Fibonacci, with the difference that there are condition checks on each smaller size subproblem.
The space complexity is O(1) and time is O(n)
The code is in C++.
int numDecodings(string s)
{
if( s.length() == 0 ) return 0;
int j = 0;
int p1 = (s[j] != '0' ? 1 : 0); // one step prev form j=1
int p2 = 1; // two step prev from j=1, empty
int p = p1;
for( int j = 1; j < s.length(); j++ )
{
p = 0;
if( s[j] != '0' )
p += p1;
if( isValidTwo(s, j-1, j) )
p += p2;
if( p==0 ) // no further decoding necessary,
break; // as the prefix 0--j is has no possible decoding.
p2 = p1; // update prev for next j+1;
p1 = p;
}
return p;
}
bool isValidTwo(string &s, int i, int j)
{
int val= 10*(s[i]-'0')+s[j]-'0';
if ( val <= 9 )
return false;
if ( val > 26 )
return false;
return true;
}
Here is my code to solve the problem. I use DP , I think it's clear to understand.
Written in Java
public class Solution {
public int numDecodings(String s) {
if(s == null || s.length() == 0){
return 0;
}
int n = s.length();
int[] dp = new int[n+1];
dp[0] = 1;
dp[1] = s.charAt(0) != '0' ? 1 : 0;
for(int i = 2; i <= n; i++){
int first = Integer.valueOf(s.substring(i-1,i));
int second = Integer.valueOf(s.substring(i-2,i));
if(first >= 1 && first <= 9){
dp[i] += dp[i-1];
}
if(second >= 10 && second <= 26){
dp[i] += dp[i-2];
}
}
return dp[n];
}
}
Since I struggled with this problem myself, here is my solution and reasoning. Probably I will mostly repeat what amon wrote, but maybe someone will find it helpful. Also it's c# not java.
Let's say that we have input "12131" and want to obtain all possible decoded strings.
Straightforward recursive solution would do iterate from left to right, obtain valid 1 and 2 digits heads, and invoke function recursively for tail.
We can visualize it using a tree:
There are 5 leaves and this is number of all possible decoded strings. There are also 3 empty leaves, because number 31 cannot be decoded into letter, so these leaves are invalid.
Algorithm might look like this:
public IList<string> Decode(string s)
{
var result = new List<string>();
if (s.Length <= 2)
{
if (s.Length == 1)
{
if (s[0] != '0')
result.Add(this.ToASCII(s));
}
else if (s.Length == 2)
{
if (s[0] != '0' && s[1] != '0')
result.Add(this.ToASCII(s.Substring(0, 1)) + this.ToASCII(s.Substring(1, 1)));
if (s[0] != '0' && int.Parse(s) > 0 && int.Parse(s) <= 26)
result.Add(this.ToASCII(s));
}
}
else
{
for (int i = 1; i <= 2; ++i)
{
string head = s.Substring(0, i);
if (head[0] != '0' && int.Parse(head) > 0 && int.Parse(head) <= 26)
{
var tails = this.Decode(s.Substring(i));
foreach (var tail in tails)
result.Add(this.ToASCII(head) + tail);
}
}
}
return result;
}
public string ToASCII(string str)
{
int number = int.Parse(str);
int asciiChar = number + 65 - 1; // A in ASCII = 65
return ((char)asciiChar).ToString();
}
We have to take care of numbers starting with 0 ("0", "03", etc.), and greater than 26.
Because in this problem we need only count decoding ways, and not actual strings, we can simplify this code:
public int DecodeCount(string s)
{
int count = 0;
if (s.Length <= 2)
{
if (s.Length == 1)
{
if (s[0] != '0')
count++;
}
else if (s.Length == 2)
{
if (s[0] != '0' && s[1] != '0')
count++;
if (s[0] != '0' && int.Parse(s) > 0 && int.Parse(s) <= 26)
count++;
}
}
else
{
for (int i = 1; i <= 2; ++i)
{
string head = s.Substring(0, i);
if (head[0] != '0' && int.Parse(head) > 0 && int.Parse(head) <= 26)
count += this.DecodeCount(s.Substring(i));
}
}
return count;
}
The problem with this algorithm is that we compute results for the same input string multiple times. For example there are 3 nodes ending with 31: ABA31, AU31, LA31. Also there are 2 nodes ending with 131: AB131, L131.
We know that if node ends with 31 it has only one child, since 31 can be decoded only in one way to CA. Likewise, we know that if string ends with 131 it has 2 children, because 131 can be decoded into ACA or LA. Thus, instead of computing it all over again we can cache it in map, where key is string (eg: "131"), and value is number of decoded ways:
public int DecodeCountCached(string s, Dictionary<string, int> cache)
{
if (cache.ContainsKey(s))
return cache[s];
int count = 0;
if (s.Length <= 2)
{
if (s.Length == 1)
{
if (s[0] != '0')
count++;
}
else if (s.Length == 2)
{
if (s[0] != '0' && s[1] != '0')
count++;
if (s[0] != '0' && int.Parse(s) > 0 && int.Parse(s) <= 26)
count++;
}
}
else
{
for (int i = 1; i <= 2; ++i)
{
string head = s.Substring(0, i);
if (head[0] != '0' && int.Parse(head) > 0 && int.Parse(head) <= 26)
count += this.DecodeCountCached(s.Substring(i), cache);
}
}
cache[s] = count;
return count;
}
We can refine this even further. Instead of using strings as a keys, we can use length, because what is cached is always tail of input string. So instead of caching strings: "1", "31", "131", "2131", "12131" we can cache lengths of tails: 1, 2, 3, 4, 5:
public int DecodeCountDPTopDown(string s, Dictionary<int, int> cache)
{
if (cache.ContainsKey(s.Length))
return cache[s.Length];
int count = 0;
if (s.Length <= 2)
{
if (s.Length == 1)
{
if (s[0] != '0')
count++;
}
else if (s.Length == 2)
{
if (s[0] != '0' && s[1] != '0')
count++;
if (s[0] != '0' && int.Parse(s) > 0 && int.Parse(s) <= 26)
count++;
}
}
else
{
for (int i = 1; i <= 2; ++i)
{
string head = s.Substring(0, i);
if (s[0] != '0' && int.Parse(head) > 0 && int.Parse(head) <= 26)
count += this.DecodeCountDPTopDown(s.Substring(i), cache);
}
}
cache[s.Length] = count;
return count;
}
This is recursive top-down dynamic programming approach. We start from the begining, and then recursively compute solutions for tails, and memoize those results for further use.
We can translate it to bottom-up iterative DP solution. We start from the end and cache results for tiles like in previous solution. Instead of map we can use array because keys are integers:
public int DecodeCountBottomUp(string s)
{
int[] chache = new int[s.Length + 1];
chache[0] = 0; // for empty string;
for (int i = 1; i <= s.Length; ++i)
{
string tail = s.Substring(s.Length - i, i);
if (tail.Length == 1)
{
if (tail[0] != '0')
chache[i]++;
}
else if (tail.Length == 2)
{
if (tail[0] != '0' && tail[1] != '0')
chache[i]++;
if (tail[0] != '0' && int.Parse(tail) > 0 && int.Parse(tail) <= 26)
chache[i]++;
}
else
{
if (tail[0] != '0')
chache[i] += chache[i - 1];
if (tail[0] != '0' && int.Parse(tail.Substring(0, 2)) > 0 && int.Parse(tail.Substring(0, 2)) <= 26)
chache[i] += chache[i - 2];
}
}
return chache.Last();
}
Some people simplify it even further, initializing cache[0] with value 1, so they can get rid of conditions for tail.Length==1 and tail.Length==2. For me it is unintuitive trick though, since clearly for empty string there is 0 decode ways not 1, so in such case additional condition must be added to handle empty input:
public int DecodeCountBottomUp2(string s)
{
if (s.Length == 0)
return 0;
int[] chache = new int[s.Length + 1];
chache[0] = 1;
chache[1] = s.Last() != '0' ? 1 : 0;
for (int i = 2; i <= s.Length; ++i)
{
string tail = s.Substring(s.Length - i, i);
if (tail[0] != '0')
chache[i] += chache[i - 1];
if (tail[0] != '0' && int.Parse(tail.Substring(0, 2)) > 0 && int.Parse(tail.Substring(0, 2)) <= 26)
chache[i] += chache[i - 2];
}
return chache.Last();
}
My solution is based on the idea that the arrangement of items(char/digit) within a particular substring is completely independent of the same within a different substring.
So we need to multiply each of those independent ways to get the total number of ways.
// nc is the number of consecutive 1's or 2's in a substring.
// Returns the number of ways these can be arranged within
// themselves to a valid expr.
int ways(int nc){
int n = pow(2, (nc/2)); //this part can be memorized using map for optimization
int m = n;
if (nc%2) {
m *= 2;
}
return n + m - 1;
}
bool validTens(string A, int i){
return (A[i] == '1' || (A[i] == '2' && A[i+1] <= '6'));
}
int numDecodings(string A) {
int ans = 1;
int nc;
if ((A.length() == 0)||(A[0] == '0')) return 0;
for(int i = 1; i < A.length();i++){
if(A[i] == '0' && validTens(A, i-1) == false) return 0; //invalid string
while(i < A.length() && validTens(A, i-1)) {
if(A[i] == '0'){
//think of '110' or '1210', the last two digits must be together
if(nc > 0) nc--;
}
else nc++;
i++;
}
ans *= ways(nc);
nc = 0;
}
return ans;
}
Java solution with space and time complexity O(n)
public int numDecodings(String s) {
int n = s.length();
if (n > 0 && s.charAt(0) == '0')
return 0;
int[] d = new int[n + 1];
d[0] = 1;
d[1] = s.charAt(0) != '0' ? 1 : 0;
for (int i = 2; i <= n; i++) {
if (s.charAt(i - 1) > '0')
d[i] = d[i] + d[i - 1];
if (s.charAt(i - 2) == '2' && s.charAt(i - 1) < '7')
d[i] = d[i - 2] + d[i];
if (s.charAt(i - 2) == '1' && s.charAt(i - 1) <= '9')
d[i] = d[i - 2] + d[i];
}
return d[n];
}
Here is an O(N) C++ DP implementation.
int numDecodings(string s) {
if(s[0] == '0') return 0; // Invalid Input
int n = s.length();
// dp[i] denotes the number of ways to decode the string of length 0 to i
vector<int> dp(n+1, 0);
// base case : string of 0 or 1 characters will have only 1 way to decode
dp[0] = dp[1] = 1;
for(int i = 2; i <= n; i++) {
// considering the previous number
if(s[i-1] > '0') dp[i] += dp[i-1];
// considering the previous two numbers
if(s[i-2] == '1' || (s[i-2] == '2' && s[i-1] < '7')) dp[i] += dp[i-2];
}
return dp[n];
}
I want to evaluate an expression like -4-12-2*12-3-4*5 given in a String form without using API as I am a beginner and want to grasp the logic.
Given below is my unsuccessful attempt to this problem which, if you may like, ignore and suggest appropriate logic.And of course your codes are also welcome :-)
public class SolveExpression3 {
static String testcase1 = "-4-12-2*12-3-4*5";
public static void main(String args[]){
SolveExpression3 testInstance= new SolveExpression3();
int result = testInstance.solve(testcase1);
System.out.println("Result is : "+result);
}
public int solve(String str){
int sum = 1;
int num1 = 0;
int num2 = 0;
String num = "";
int len = str.length();
System.out.println(str);
for (int i = len-1 ; i >= 0; i--)
{
char ch = str.charAt(i);
if(ch == '*')
{
String s = "";
num1 = num2 = 0;
//to get the number on left of *
for (int j = i; j >= 0; j--)
{
char c = str.charAt(j);
if(c == '+' || c == '-' || j == 1)
{
num1 = stringToInt(s);
s = "";
break;
}
else
{
s = c + s;
}
}
//to get the number on right of *
for (int j = i; j <= len; j++)
{
char c = str.charAt(j);
if(c == '+' || c == '-' || j == len-1)
{
num2 = stringToInt(s);
s = "";
break;
}
else
{
s = c + s;
}
}
sum = sum + num1*num2;
}
else
{
num = ch + num;
}
}
len = str.length();
for (int i = len-1; i >= 0; i--)
{
char ch = str.charAt(i);
if(ch==' ')
{}
else if(ch=='+')
{
sum = sum + stringToInt(num);
num = "";
}
else if(ch=='-')
{
sum = sum - stringToInt(num);
num = "";
}
else
{
num = ch + num;
}
}
return sum;
}
public int stringToInt(String str)
{
int number=0;
for(int i = 0; i < str.length(); i++)
{
int num = str.charAt(i) - 48;
number = number*10+num;
}
return number;
}
}
found=true;
static String testcase1 = "-4-12-2*12-3-4*5";
Pattern SEGMENT_PATTERN = Pattern.compile("(\\d+(\\.\\d+)?|\\D+)");
/*\\d-means digit,
\\.-point,
+-one or more times,
?-optional and
\\D-non digit ch*/
Matcher matcher = SEGMENT_PATTERN.matcher(testcase1);
while (found) {
boolean Found = matcher.find();
String segment = matcher.group();//representing a number or an operator
if (Character.isDigit(segment.toCharArray()[0])) {
//is digit
}
else {
//is operator
}
}
This a a solution using a patter to determine if you have a number or and operator,u just have to adapt it a little to your case to computing the result.
You can add all the matches found to an array list than traverse it and test the operators and computer the result.
It works for floating numbers too,ex:"it matches 5.10".
I would suggest a different logic for your purpose.
Usually the logic behind programs algorithms is not different from the logic that you will apply if you have to do the task by hand.
For an expression like your example you would usually do:
Find all the *
For each * compute the result of the operation
Repeat steps 1 and 2 for + and -
Try to implement a recursive descent parser, a tutorial depicting how a calculator can be implemented (in Python but the same concepts apply to java) can be found here http://blog.erezsh.com/how-to-write-a-calculator-in-70-python-lines-by-writing-a-recursive-descent-parser/
Given a polynomial with a single variable x, and the value of x as input, compute its value. Examples:
eval("-2x^3+10x-4x^2","3")=-60
eval("x^3+x^2+x","6")=258
Description of issue: In this code I break the string into a substring whenever a +/- is encountered and pass the substring to a function which evaluates single term like "-2x^3". So my code for input = "-2x^3+10x-4x^2" calculates till "-2x^3+10x" only and skips "-4x^2" part.
Can anyone please tell me whats wrong here?
public class EvalPolyX2 {
static String testcase1 = "-2x^3+10x-4x^2";
static String testcase2 = "3";
public static void main(String args[]){
EvalPolyX2 testInstance = new EvalPolyX2();
int result = testInstance.eval(testcase1,testcase2);
System.out.println("Result : "+result);
}
public int eval(String str,String valx){
int sum = 0;
String subStr = "";
if(str.charAt(0) == '-')
{
int len = str.length();
for (int i = 0; i < len; i++)
{
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
System.out.println("subStr="+subStr);
sum += evalSubPoly(subStr, valx);
str = str.substring(i);
len = str.length();
i = 0;
}
}
}
else if(str.charAt(0) != '-')
{
str = '+' + str;
int len = str.length();
for (int i = 0; i < len; i++)
{
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
System.out.println("subStr="+subStr);
sum += evalSubPoly(subStr, valx);
str = str.substring(i);
len = str.length();
i=0;
}
}
}
return sum;
}
public int evalSubPoly(String poly,String valx){
int len = poly.length();
String num = "";
String power = "";
int exp = 0, coeff = 0;
for(int i = 0; i < len; i++)
{
if(poly.charAt(i) == 'x')
{
num = poly.substring(0, i);
coeff = Integer.parseInt(num);
}
if(poly.charAt(i) == '^')
{
power = poly.substring(i+1, len);
exp = Integer.parseInt(power);
}
}
if(power.equals(""))
exp = 1;
System.out.println("coeff="+coeff);
int sum = 1;
int x = Integer.parseInt(valx);
for (int i = 0; i < exp; i++)
{
sum = sum*x;
}
System.out.println("sum="+sum);
sum = sum*coeff;
return sum;
}
}
What's wrong with using regex? You can split the polynomial into monomials, evaluate each, and add all of the results.
private static final Pattern monomial = Pattern
.compile("([+-])?(\\d+)?x(?:\\^(\\d+))?");
public static int eval(String str, String valx) {
Matcher m = monomial.matcher(str);
int x = Integer.parseInt(valx);
int total = 0;
while (m.find()) {
String mul = m.group(2);
int value = (mul == null) ? 1 : Integer.parseInt(m.group(2));
String pow = m.group(3);
value *= (pow == null) ? x : (int) Math.pow(x,
Integer.parseInt(pow));
if ("-".equals(m.group(1)))
value = -value;
total += value;
}
return total;
}
System.out.println(eval("-2x^3+10x-4x^2", "3"));
System.out.println(eval("x^3+x^2+x", "6"));
-60
258
This code replacement should help
if(str.charAt(i) == '-' || str.charAt(i) == '+' || i == (len - 1))
{
if(i == len - 1)
{
i++;
}
...
Though there could be better ways, but I only wanted to show a way out here.
The reason is you are looking for + or - as the delimiter.
But the last part of the expression will not end with either of these but just probably EOL
You need to account for the last term (the if-statement will only trigger when a - or + is found, which there isn't at the end).
One easy way to do this is to replace:
for (int i = 0; i < len; i++)
{
if (str.charAt(i) == '-' || str.charAt(i) == '+')
with:
// v one more iteration
for (int i = 0; i <= len; i++)
{
if (i == len || str.charAt(i) == '-' || str.charAt(i) == '+')
// \------/
// extra condition
The above simply goes on for one more iteration and, on that iteration, always goes into the if-statement, causing the last term to be processed.
You can also simplify
if (str.charAt(0) == '-')
{
// common code
}
else if (str.charAt(0) != '-')
{
str = '+' + str;
// common code
}
To:
if (str.charAt(0) != '-')
{
str = '+' + str;
}
// common code
There's also a bug with handling +. I get a NumberFormatException for this. One way to handle it is to ignore the + between the terms (and not adding a + to the start):
if (i != len && str.charAt(i) == '+')
str = str.substring(i+1);
else
str = str.substring(i);
And you might as well make your functions static and call them directly rather than declaring a new instance of your class.
Test.
The simple answer is that when you do this:
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
the effect is that you're setting subStr to text just before the - or +, and evaluating it. But since there's no - or + at the end of the string, there's no way this logic will evaluate the last term of the polynomial, since it only evaluates substrings that are right before a - or +.
P.S. That's just one problem I noticed. I don't know if the rest of the logic is correct.
When you parse the string, you look for +/- and only stop if you find them. This works for the first two terms, but when you get down to "-4x^2" the loop won't stop because there is no +/-. So in addition to the conditions you have, you need to add code so that when the end of the string is reached, what you have left is the last term. So what you want to have is this
if(str.charAt(0) == '-')
{
int len = str.length();
for (int i = 0; i < len; i++)
{
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
System.out.println("subStr="+subStr);
sum += evalSubPoly(subStr, valx);
str = str.substring(i+1);
len = str.length();
i = 0;
}
}
System.out.println("subStr="+str);
sum += evalSubPoly(str, valx);
}
else if(str.charAt(0) != '-')
{
str = '+' + str;
int len = str.length();
for (int i = 0; i < len; i++)
{
if(str.charAt(i) == '-' || str.charAt(i) == '+')
{
subStr = str.substring(0, i);
System.out.println("subStr="+subStr);
sum += evalSubPoly(subStr, valx);
str = str.substring(i+1);
len = str.length();
i=0;
}
}
System.out.println("subStr="+str);
sum += evalSubPoly(str, valx);
}
I will also throw out the disclaimer that there may be more errors, but this is the major one causing your problem.
EDIT: added change to else if statement and added change mentioned in my comment above
With regular expressions, you can get a more simple solution. And, do you want support for simple constants? Try the next:
public class EvalPolyX2 {
public static void main(String args[]) {
System.out.println("Result: " + eval("x^3+x^2+x", 6));
}
public static int eval(String eq, int val) {
int result = 0;
String mons[] = eq.split("(?=[+-])(?!\\B)");
for (String str : mons) {
str = str.replace("+", "");
if (str.contains("x")) {
double a = 1, b = 1;
String[] comps = str.split("x\\^?");
if (comps.length > 0) {
a = comps[0].isEmpty() ? 1 : Integer.parseInt(comps[0]);
}
if (comps.length > 1) {
b = Integer.parseInt(comps[1]);
}
result += a * Math.pow(val, b);
} else {
result += Integer.parseInt(str);
}
}
return result;
}
}