Java: Palindrome, not getting biggest number - java

I want to get the largest palindrome number of 3-digit numbers. This is my code:
for (int start = 100; start < 1000; start++) {
for (int start2 = 100; start2 < 1000; start2++) {
int temp = start * start2;
int biggest = 1;
String strTemp = temp + "";
if (strTemp.equals(new StringBuilder(strTemp).reverse().toString())) {
if (temp > biggest) {
biggest = temp;
System.out.println("Original: " + strTemp);
System.out.println("Reverse: " + new StringBuilder(strTemp).reverse().toString());
System.out.println("Siffra: " + start);
System.out.println("Siffra2: " + start2);
}
}
}
In the end, I get 995 x 583 and not 993 x 913, which is the largest one. Why? I have it so the int biggest always chooses the biggest number.

You need to move int biggest = 1; out of both for loops.
If you don't do that at every inner loop you restart the value of biggest.
int biggest = 1;
for (int start = 100; start < 1000; start++) {
for (int start2 = 100; start2 < 1000; start2++) {
int temp = start * start2;
String strTemp = temp + "";
if (strTemp.equals(new StringBuilder(strTemp).reverse().toString())) {
if (temp > biggest) {
biggest = temp;
System.out.println("Original: " + strTemp);
System.out.println("Reverse: " + new StringBuilder(strTemp).reverse().toString());
System.out.println("Siffra: " + start);
System.out.println("Siffra2: " + start2);
}
}
}
With java 8 you can rewrite this code as follow:
// Define what it means palindrome
IntPredicate isPalindrome = n -> new StringBuffer(String.valueOf(n)).reverse().toString().equals(String.valueOf(n));
OptionalInt max =
// Define a stream from 100 to 1000
IntStream.range(100, 1000)
// Map the original stream to a new stream
// Basically for each x of the first stream
// creates a new stream 100-1000 and map each element
// x of the first stream and y of the second stream
// to x * y
.flatMap(x -> IntStream.range(100, 1000).map(y -> x * y))
// Take only palyndrome of x * y
.filter(isPalindrome)
// take the max
.max();
A functional approach is more readable in most cases where you have to loop over n elements and is easier to filter and extract elements without
doing errors.

Move your declaration of biggest outside the loops:
int biggest = 1;
for (int start = 100; start < 1000; start++) {
for (int start2 = 100; start2 < 1000; start2++) {
int temp = start * start2;
String strTemp = temp + "";
if (strTemp.equals(new StringBuilder(strTemp).reverse().toString())) {
if (temp > biggest) {
biggest = temp;
System.out.println("Original: " + strTemp);
System.out.println("Reverse: " + new StringBuilder(strTemp).reverse().toString());
System.out.println("Siffra: " + start);
System.out.println("Siffra2: " + start2);
}
}
}
Output:
....
Original: 906609
Reverse: 906609
Siffra: 913
Siffra2: 993

int biggest = 1;
for (int start = 100; start < 1000; start++) {
for (int start2 = 100; start2 < 1000; start2++) {
int temp = start * start2;
in above you are initializing biggest=1 always. so you not getting proper result. Keep it outside of for loop.

Related

Why does my method increment seemingly automatically?

I have been working through 'Head First Java', and spent an inordinate amount of time on what was seemingly a fairly simple question. And yet, could not for the life of me figure out why the method maybeNew seemingly randomly increments. I spent a good amount of time assuming it was dead code.
Does return 1 also operate as an index increaser in this case?
The code output is 14 1.
The question in the book was to work out what different flow control examples would output given the following code: e.g. having x < 19, and index < 1, for instance. Hence my confusion, given the code:
count = count + m4a[x].maybeNew(x);
Thank you for your patience.
public class Mix4 {
int counter = 0;
public static void main(String[] args) {
int count = 0;
Mix4[] m4a = new Mix4[20];
int x = 0;
while (x < 9) {
m4a[x] = new Mix4();
m4a[x].counter = m4a[x].counter + 1;
count = count + 1;
count = count + m4a[x].maybeNew(x);
x = x + 1; // 1;, 2;
}
System.out.println(count + " " + m4a[1].counter);
}
public int maybeNew(int index) { // index = 0;
if (index < 5) {
Mix4 m4 = new Mix4(); // m4 0 - 4; rn = 1;
m4.counter = m4.counter + 1; // 1.
// System.out.println(index);
return 1;
}
return 0;
}
}
If that may help:
public int maybeNew(int index) { // index = 0;
if (index < 5) {
Mix4 m4 = new Mix4(); // m4 0 - 4; rn = 1;
m4.counter = m4.counter + 1; // 1.
// System.out.println(index);
return 1;
}
return 0;
}
The whole new Mix4() is useless here: that's a dead variable because you don't really do anything with m4.
So maybeNew can be written as:
public int maybeNew(int index) { // index = 0;
if (index < 5) {
return 1;
}
return 0;
}
The whole maybeNew method could also be static (independent of any instance of Mix4):
int count = 0;
Mix4[] m4a = new Mix4[20];
int x = 0;
while (x < 9) {
m4a[x] = new Mix4();
m4a[x].counter = m4a[x].counter + 1;
count = count + 1;
count = count + Mix4.maybeNew(x);
x = x + 1; // 1;, 2;
}
System.out.println(count + " " + m4a[1].counter);
Since the code only ever use m4a[1], the other index are not used; you can move the new Mix4 and further: simplify the loop:
int count = 0;
Mix4[] m4a = new Mix4[20];
m4a[1] = new Mix4();
m4a[1].counter = m4a[1].counter + 1;
int x = 0;
while (x < 9) {
count = count + 1 + Mix4.maybeNew(x);
x = x + 1; // 1;, 2;
}
System.out.println(count + " " + m4a[1].counter);
And finally, remove the array:
int count = 0;
Mix4 m4a = new Mix4();
m4a.counter = m4a.counter + 1;
int x = 0;
while (x < 9) {
count = count + 1 + Mix4.maybeNew(x);
x = x + 1; // 1;, 2;
}
System.out.println(count + " " + m4a.counter);
The loop can then be read:
add one to count 9 times
add result of maybeNew(x):
maybeNew(0) : 1
maybeNew(1) : 1
maybeNew(2) : 1
maybeNew(3) : 1
maybeNew(4) : 1
maybeNew(5) : 0
maybeNew(6) : 0
maybeNew(7) : 0
maybeNew(8) : 0
add 5 to count
= count = 14.

Java: How to add variable in a loop together, multiple times

public class R {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
int trials = Integer.parseInt(args[1]);
int x = 0;
int y = 0;
int j = 0;
int distance = 0;
while (trials>j) {
j = j + 1;
int i = -1;
double counter = 1.0 * distance;
double sum = (distance + counter);
while (i<=n) {
i = i + 1;
if (i == n) {
distance = ((x*x) + (y*y));
}
if (i<n) {
int random = (int )(Math.random() * 4 + 1);
if (random == 1) x = x + 1;
if (random == 2) y = y + 1;
if (random == 3) x = x - 1;
if (random == 4) y = y - 1;
}
}
}
double average= (sum)/(trials);
System.out.println("mean " + "squared " + "distance " + "= " + average);
}
}
Hey guys I'm wondering how it's possible to compute a value within a loop, and then every single time the loop finishes (and the value in computed) to average them together. I can't wrap my head around the concept and I tried doing it in the code above but I can't quite figure it out.
As you can see there are two while loops, and inside one of them a random value (distance) is computed. So essentially I need to average the distances together, but I can't imagine how it's possible to add the distances that are computed each time together into one number. Let's say the loop goes through one time and outputs a singular distance, how would I go about adding a new distance (for the new loop) together with the old one, and then keep doing that for each trial?
You just have to divide the total distance per trials.
public class R {
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
int trials = Integer.parseInt(args[1]);
int x = 0;
int y = 0;
int j = 0;
int distance = 0, distance_total = 0;
while (trials>j) {
j = j + 1;
int i = -1;
distance = 0;
while (i<=n) {
i = i + 1;
if (i == n) {
distance += ((x*x) + (y*y));
}
if (i<n) {
int random = (int )(Math.random() * 4 + 1);
if (random == 1) x = x + 1;
if (random == 2) y = y + 1;
if (random == 3) x = x - 1;
if (random == 4) y = y - 1;
}
}
distance_total += distance;
}
System.out.println(distance_total/j);
}
}

How can I optimize my java implementation of Held-Karp algorithm to shorten the running time?

I use Java implemented Held-KarpTSP algorithm algo to solve a 25 cities TSP problem.
The program passes with 4 cities.
When it runs with 25 cities it won't stop for several hours. I use jVisualVM to see what's the hotspot, after some optimization now it shows
98% of time is in real computing instead in Map.contains or Map.get.
So I'd like to have your advice, and here is the code:
private void solve() throws Exception {
long beginTime = System.currentTimeMillis();
int counter = 0;
List<BitSetEndPointID> previousCosts;
List<BitSetEndPointID> currentCosts;
//maximum number of elements is c(n,[n/2])
//To calculate m-set's costs just need to keep (m-1)set's costs
List<BitSetEndPointID> lastKeys = new ArrayList<BitSetEndPointID>();
int m;
if (totalNodes < 10) {
//for test data, generate them on the fly
SetUtil3.generateMSet(totalNodes);
}
//m=1
BitSet beginSet = new BitSet();
beginSet.set(0);
previousCosts = new ArrayList<BitSetEndPointID>(1);
BitSetEndPointID beginner = new BitSetEndPointID(beginSet, 0);
beginner.setCost(0f);
previousCosts.add(beginner);
//for m=2 to totalNodes
for (m = 2; m <= totalNodes; m++) {// sum(m=2..n 's C(n,m)*(m-1)(m-1)) ==> O(n^2 * 2^n)
//pick m elements from total nodes, the element id is the index of nodeCoordinates
// the first node is always present
BitSet[] msets;
if (totalNodes < 10) {
msets = SetUtil3.msets[m - 1];
} else {
//for real data set, will read from serialized file
msets = SetUtil3.getMsets(totalNodes, m-1);
}
currentCosts = new ArrayList<BitSetEndPointID>(msets.length);
//System.out.println(m + " sets' size: " + msets.size());
for (BitSet mset : msets) { //C(n,m) mset
int[] candidates = allSetBits(mset, m);
//mset is a BitSet which makes sure begin point 0 comes first
//so end point candidate begins with 1. candidate[0] is always begin point 0
for (int i = 1; i < candidates.length; i++) { // m-1 bits are set
//set the new last point as j, j must not be the same as begin point 0
int j = candidates[i];
//middleNodes = mset -{j}
BitSet middleNodes = (BitSet) mset.clone();
middleNodes.clear(j);
//loop through all possible points which are second to the last
//and get min(A[S-{j},k] + k->j), k!=j
float min = Float.MAX_VALUE;
int k;
for (int ki = 0; ki < candidates.length; ki++) {// m-1 calculation
k = candidates[ki];
if (k == j) continue;
float middleCost = 0;
BitSetEndPointID key = new BitSetEndPointID(middleNodes, k);
int index = previousCosts.indexOf(key);
if (index != -1) {
//System.out.println("get value from map in m " + m + " y key " + middleNodes);
middleCost = previousCosts.get(index).getCost();
} else if (k == 0 && !middleNodes.equals(beginSet)) {
continue;
} else {
System.out.println("middleCost not found!");
continue;
// System.exit(-1);
}
float lastCost = distances[k][j];
float cost = middleCost + lastCost;
if (cost < min) {
min = cost;
}
counter++;
if (counter % 500000 == 0) {
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException iex) {
System.out.println("Who dares interrupt my precious sleep?!");
}
}
}
//set the costs for chosen mset and last point j
BitSetEndPointID key = new BitSetEndPointID(mset, j);
key.setCost(min);
currentCosts.add(key);
// System.out.println("===========================================>mset " + mset + " and end at " +
// j + " 's min cost: " + min);
// if (m == totalNodes) {
// lastKeys.add(key);
// }
}
}
previousCosts = currentCosts;
System.out.println("...");
}
calcLastStop(lastKeys, previousCosts);
System.out.println(" cost " + (System.currentTimeMillis() - beginTime) / 60000 + " minutes.");
}
private void calcLastStop(List<BitSetEndPointID> lastKeys, List<BitSetEndPointID> costs) {
//last step, calculate the min(A[S={1..n},k] +k->1)
float finalMinimum = Float.MAX_VALUE;
for (BitSetEndPointID key : costs) {
float middleCost = key.getCost();
Integer endPoint = key.lastPointID;
float lastCost = distances[endPoint][0];
float cost = middleCost + lastCost;
if (cost < finalMinimum) {
finalMinimum = cost;
}
}
System.out.println("final result: " + finalMinimum);
}
You can speed up your code by using arrays of primitives (it's likely to have to better memory layout than a list of objects) and operating on bitmasks directly (without bitsets or other objects). Here is some code (it generates a random graph but you can easily change it so that it reads your graph):
import java.io.*;
import java.util.*;
class Main {
final static float INF = 1e10f;
public static void main(String[] args) {
final int n = 25;
float[][] dist = new float[n][n];
Random random = new Random();
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
dist[i][j] = dist[j][i] = random.nextFloat();
float[][] dp = new float[n][1 << n];
for (int i = 0; i < dp.length; i++)
Arrays.fill(dp[i], INF);
dp[0][1] = 0.0f;
for (int mask = 1; mask < (1 << n); mask++) {
for (int lastNode = 0; lastNode < n; lastNode++) {
if ((mask & (1 << lastNode)) == 0)
continue;
for (int nextNode = 0; nextNode < n; nextNode++) {
if ((mask & (1 << nextNode)) != 0)
continue;
dp[nextNode][mask | (1 << nextNode)] = Math.min(
dp[nextNode][mask | (1 << nextNode)],
dp[lastNode][mask] + dist[lastNode][nextNode]);
}
}
}
double res = INF;
for (int lastNode = 0; lastNode < n; lastNode++)
res = Math.min(res, dist[lastNode][0] + dp[lastNode][(1 << n) - 1]);
System.out.println(res);
}
}
It takes only a couple of minutes to complete on my computer:
time java Main
...
real 2m5.546s
user 2m2.264s
sys 0m1.572s

Trying to convert a String of digits to a array of numbers

I wrote a function that validates credit cards. It usses the last 10 digits of the card number. The card number is stored as a String. I'm trying to figure out how to converts the last 10 digits of the card number into a array numbers. I found some code on stack overflow, but it usses string instad of String. So I get a error when I try to access the string as a arrow
Code:
int[] n = { 0, 0, 0, 8, 2, 9, 8, 7, 0, 1 };
boolean ValidCredt()
{
String strNum = "1230008298701";
int p = strNum.length() - 1;
int pt = 9;
// this is where I'm trying to convert the String into a arrow of
// numbers
for (int i = 0; i < 10; i++)
{
n[pt--] = strNum[p--] - '0'; // get a error for tryinmg to usr
// String as a array
}
// step 1 double every other digit
n[9] = n[9] + n[9];
n[7] = n[7] + n[7];
n[5] = n[5] + n[5];
n[3] = n[3] + n[3];
n[1] = n[1] + n[1];
// Your number is now “0-0-0-16-2-18-8-14-0-2.”
// step 3 add together 2 digy
for (int i = 0; i < n.length; i++)
{
if (n[i] > 9)
{
int low = n[i] % 10;
int hi = n[i] / 10;
n[i] = low + hi;
}
}
// Your number is now “0-0-0-7-2-9-8-5-0-2.”
// step 4
int sum = 0;
for (int i = 0; i < n.length; i++)
sum = sum + n[i];
// step 5
int step5 = sum * 9;
int step5b = 10 - sum % 10;
// step 6
int step6 = sum + step5 % 10;
if (step5 % 10 == 0)
return true;
return false;
}
I'm not sure why have you tried so complicated stuff, but I think this might be useful:
String ccNumber = "1234567890";
char[] characters = ccNumber.toCharArray();
int[] result = new int[characters.length];
int i = 0;
for (char c : characters) {
result[i++] = c - '0';
}
int[] result = new int[string.size()];
for(int i = 0; i < string.size(); i++){
result[i] = string.charAt(i) - '0';
}

Overcoming heap overflow issues

I tried to solve problems from Project Euler. I know my method would work logically (it returns answers to the small scale problem almost instantly). However, it scales horribly. I already attempted changing the .ini file, but to no avail.
Here's my code:
public class Number28 {
static int SIZE = 101; //this should be an odd number, i accidentally posted 100
/**
* #param args
*/
public static void main(String[] args) {
double start = System.currentTimeMillis();
long spiral[][]= spiral(SIZE);
long sum = 0;
for(int i = 0; i < SIZE; i++)
{
sum += spiral[i][i];
sum += spiral[i][SIZE - 1 - i];
}
System.out.println(sum - 1);
double time = System.currentTimeMillis() - start;
System.out.println(time);
}
public static long[][] spiral(int size){
long spiral[][]= new long[size][size];
if(size == 1){
spiral[0][0] = 1;
return spiral;
}
else{
long subspiral[][]= new long[size - 2][size - 2];
subspiral = spiral(size - 2);
for(int r = 0; r < size - 2; r++){
for(int c = 0; c < size - 2; c++){
spiral[r + 1][c + 1] = subspiral[r][c];
}
}
long counter = subspiral[0][size - 3];
for(int r = 1; r < size ; r++){
counter++;
spiral[r][size - 1] = counter;
}
for(int c = size - 2; c >= 0; c--){
counter++;
spiral[size - 1][c] = counter;
}
for(int r = size - 2 ; r >= 0 ; r--){
counter++;
spiral[r][0] = counter;
}
for(int c = 1; c < size ; c++){
counter++;
spiral[0][c] = counter;
}
return spiral;
}
}
}
Here's the edited code, worked like a gem:
public class Number28 {
static int SIZE = 1001;
static long spiral[][]= new long[SIZE][SIZE];
/**
* #param args
*/
public static void main(String[] args) {
double start = System.currentTimeMillis();
long spiral[][]= spiral(SIZE);
long sum = 0;
for(int i = 0; i < SIZE; i++)
{
sum += spiral[i][i];
sum += spiral[i][SIZE - 1 - i];
}
System.out.println(sum - 1);
double time = System.currentTimeMillis() - start;
System.out.println(time);
}
public static long[][] spiral(int size){
if(size == 1){
spiral[SIZE / 2][SIZE / 2] = 1;
return spiral;
}
else{
long subspiral[][]= spiral(size - 2);
int edge = (SIZE - size) / 2;
long counter = subspiral[edge + 1][edge + size - 2];
for(int r = 1; r < size ; r++){
counter++;
spiral[edge + r][edge + size - 1] = counter;
}
for(int c = size - 2; c >= 0; c--){
counter++;
spiral[edge + size - 1][edge + c] = counter;
}
for(int r = size - 2 ; r >= 0 ; r--){
counter++;
spiral[edge + r][edge] = counter;
}
for(int c = 1; c < size ; c++){
counter++;
spiral[edge][edge + c] = counter;
}
return spiral;
}
}
}
As a general piece of Project Euler advice, if your solution doesn't scale, there's almost certainly a better way to solve it. If you've used the same type of solution on an earlier problem you can go through the posts from other users on the earlier question to get ideas for solving the problem in different ways.
Not familiar with the Euler problems, but the horror appears to be your continual allocation and re-allocation of what are basically throwaway intermediate spirals, as you call down recursively to the base case.
Restructure so that you allocate your full spiral up front. Then call your recursive function, passing your full spiral in as a parameter by reference, along with a "level" parameter, which will change with each recursive call. E.g., initial call is with 100x100 spiral and level 100; next (recursive) call is with same spiral, by reference, and level 98. Operations within the function will all be done on the one-and-only-allocated spiral.
In a nutshell: allocate your data structure once, even if you operate on that data structure recursively.
The first problem I saw was a NegativeArraySizeException when running your program with SIZE = 100. I guess this has something to do with how each recursive call is decreasing the size by 2.
I believe that Steven's comment is right on the money. You are allocating the size of the array, them making a recursive call. This causes (SIZE - 1) number of arrays to be allocating, eating up all of your memory. Removing that one line should prevent any memory from being allocated until necessary.
Here is a simplified solution that doesn't store a matrix:
public class P28 {
private final static int N = 1001;
public static void main(String[] args) {
int limit = (N + 1) / 2;
int sum = -3;
int first = 4;
int r = 20;
for (int i = 1; i <= limit; i++) {
sum += first;
first += r;
r += 32;
}
System.out.println(sum);
}
}
Explanation:
Starting from 1 you can see 4 sums:
1 + 3 + 13 + 31 + 57 + ...
1 + 5 + 17 + 37 + 65 + ...
1 + 7 + 21 + 43 + 73 + ...
1 + 9 + 25 + 49 + 81 + ...
1 is added 4 times, this is why the default value for sum is -3.
Let's gather those sums:
4 + 24 + 76 + 160 + 276 + ...
(this is why first is 4 and r is 20 = 24 - 4)
You can observe that r increases by 32 per step ( 24 - 4 = 32 + 76 - 24 = 32 + 32 + 160 - 76 = ... ) and the actual number (first) increases by r.

Categories