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.
Related
Hello so am trying to create a 2D array of int with random number of rows and columns and a random starting and ending points using java to apply the A* algorithm on it.
When i add {S} and {E} to define the tow points and print it there are numbers outside of the 2D array printed.
`Random rand = new Random();
int min = 2, max = 10;
// a random number of rows and columns
int a = (int)(Math.random() * (max - min + 1)) + min;
// the location of the starting point.
int row_start = rand.nextInt(a);
int col_start = rand.nextInt(a);
// the location of the ending point.
int row_end = rand.nextInt(a);
int col_end = rand.nextInt(a);
int [][] M = new int [a][a];
public void create() {
//empty: 0; grass: 1; sand: 2; water: 3; wall: 4.
for (int i = 0; i < a; i++) {
for (int j = 0; j < a; j++) {
M[i][j] = rand.nextInt(5);
}
}
for (int i = 0; i < a; i++) {
for (int j = 0; j < a; j++) {
System.out.print(" " +M[i][j] + "\t");
if(row_start == i && col_start == j) {
System.out.print("{S}" + "\t");
}
if(row_end == i && col_end == j) {
System.out.print("{E}" + "\t");
}
}
System.out.print("\n");
}
}`
the output looks like this:
1 0 4 0
2 {S} 1 2 2
4 4 {E} 0 3
2 0 3 3
the 2 and 3 shouldn't appear there.
The problem is that you always print m[i][j].
What you need is to only print m[i][j] when i and j are not S and E positions. When i and j are S and E positions, print S or E. Otherwise, print m[i][j].
if(row_start == i && col_start == j) {
System.out.print("{S}" + "\t");
} else if(row_end == i && col_end == j) {
System.out.print("{E}" + "\t");
} else {
System.out.print(" " +M[i][j] + "\t");
}
I am having some trouble with writing a method that when prompted with a number returns how many times each value is repeated. For example, if the number 7846597 is entered the method would return:
0 - 0
1 - 0
2 - 0
3 - 0
4 - 1
5 - 1
6 - 1
7 - 2
8 - 1
9 - 1
I know this would be most easily done with a loop, but I am not sure how to write the actual code. I also know that I need to convert the number value I get as an input into a string so I can use char methods.
This is my attempt:
public double countOccurences(int num)
{
String str = num + "";
int goneThrough = 0;
int count0 = 0;
int count1 = 0;
int count2 = 0;
int count3 = 0;
int count4 = 0;
int count5 = 0;
int count6 = 0;
int count7 = 0;
int count8 = 0;
int count9 = 0;
while(goneThrough <= str.length())
{
int value = 0;
if(value >= 10){
value = value * 0;
}
if(str.charAt(0) == 0)
count0++;
if(str.charAt(0) = 1)
count1++;
}
return count0;
return count1;
return count2;
return count3;
return count4;
return count5;
return count6;
return count7;
return count8;
return count9;
}
countOccurences(int num) should return the number of occurrences of each digit as int[10].
static int[] countOccurences(int num) {
int[] result = new int[10];
for ( ; num > 0; num /= 10)
++result[num % 10];
return result;
}
public static void main(String[] args) {
int input = 7846597;
int[] output = countOccurences(input);
for (int i = 0; i < 10; ++i)
System.out.println(i + " - " + output[i]);
}
output:
0 - 0
1 - 0
2 - 0
3 - 0
4 - 1
5 - 1
6 - 1
7 - 2
8 - 1
9 - 1
This is my code where I used HashTable and stored number as string and count as value. This is optimized code where time complexity is O(n).
// code
import java.util.*;
class Main {
public static void main(String args[]) {
String number = "7846597";
Hashtable<String, Integer> result = new Hashtable<String, Integer>();
for(int i=0; i<number.length(); i++){
String current = "" + number.charAt(i);
if(result.contains(current)) {
int val = result.get(current);
result.put(current, ++val);
} else {
result.put(current, 1);
}
}
System.out.print(result);
}
}
Using int array of size 10 and increment value at index that maps to digit of 0-9.
public static void digitFrequencies(int number) {
int[] arr = new int[10];
for (char ch : String.valueOf(number).toCharArray()) {
int digit = Character.digit(ch, 10);
arr[digit] = arr[digit] + 1;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(i + " - " + arr[i] + " ");
}
}
Here is my mess of a code. I have to write a program that inputs a positive integer greater than 3. Validate that the integer is in fact greater than 3. Then print all possible pairs of positive integers great than whose product is less than or equal to the number entered.
ex. If 24 is the input.
It would print:
4 = 2 x 2
6 = 2 x 3
8 = 2 x 4
10 = 2 x 5
12 = 2 x 6
14 = 2 x 7
16 = 2 x 8....
9 = 3 x 3
12 = 3 x 4..
24 = 3 x 8...
all the way to
24 = 4 x 6
import java.util.Scanner;
public class Factors {
public static void main(String[] args) {
// Define Variables
Scanner input = new Scanner(System.in);
int i = 0;
int j = 0;
int k = 2;
int product = 0;
// Ask for input/loop
while (i < 3) {
System.out.println("Please enter an integer greater than 3");
i = input.nextInt();
}
while (product < i) {
if (product == i) { j++; k = 2;
for (j = 2; product < i; k++) {
product = j * k;
System.out.println(product + " = " + j + " x " + k);
if (product == i) { j++; k = 2;
}
}
}
}
}
}
public class Factors {
public static void main(String[] args) {
// Define Variables
Scanner input = new Scanner(System.in);
int i = 0;
int product = 0;
// Ask for input/loop
while (i < 3) {
System.out.println("Please enter an integer greater than 3");
i = input.nextInt();
}
for (int j = 2; j < i / 2; j++) {
for (int k = 2; k < i / 2; k++) {
if (j <= k && j * k <= i)
System.out.println(j * k + " = " + j + "*" + k);
}
}
// while (product < i) {
// if (product == i) {
// j++;
// k = 2;
// for (j = 2; product < i; k++) {
// product = j * k;
// System.out.println(product + " = " + j + " x " + k);
// if (product == i) {
// j++;
// k = 2;
// }
// }
// }
// }
}
}
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
I want to take the array of random values I've generated and print the aforementioned array with parentheses outside the longest run of the same number.
For example, if the array was [0,1,1,1,2,4,7,4] I'd like to receive 0(111)2474 as an output.
This is my code thus far.
import java.util.Random;
import java.util.Arrays;
/**
* Write a description of class ArrayRunner1 here.
*
* #author Ibrahim Khan
* #version (a version number or a date)
*/
public class ArrayRunner1 {
/**
* This method will generate my random numbers for my array.
* #param min minimum random value wanted
* #param max maximum random value wanted
* #return randomNum a random number between 1 and 6 inclusive
*/
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
public static void main(String[] args) {
System.out.println("\f");
//Part 1 - Generate a random array of length 40 with random 1-6 inclusive
int[] array1 = new int[40];
for (int i = 0; i < array1.length; i++) {
array1[i] = randInt(1, 6);
}
System.out.println(Arrays.toString(array1));
//Counts and RETURN: reports how many times each number is present
int counter1 = 0;
int counter2 = 0;
int counter3 = 0;
int counter4 = 0;
int counter5 = 0;
int counter6 = 0;
for (int i = 0; i < array1.length; i++) {
if (array1[i] == 1) {
counter1++;
}
if (array1[i] == 2) {
counter2++;
}
if (array1[i] == 3) {
counter3++;
}
if (array1[i] == 4) {
counter4++;
}
if (array1[i] == 5) {
counter5++;
}
if (array1[i] == 6) {
counter6++;
}
}
System.out.println("There are " + counter1 + " ones.");
System.out.println("There are " + counter2 + " twos.");
System.out.println("There are " + counter3 + " threes.");
System.out.println("There are " + counter4 + " fours.");
System.out.println("There are " + counter5 + " fives.");
System.out.println("There are " + counter6 + " sixes.");
//Counts the longest run of the same number. A run continues only when consecutive numbers have the same value.
//RETURN: The repeated number and the length of the run is then printed
int counter = 1;
int runMax = 1;
int runMin = 0;
int variableNum = 0;
int startCounter = 0;
int endCounter = 0;
for (int i = 0; i < array1.length - 1; i++) {
if (array1[i] == array1[i + 1]) {
counter++;
if (counter >= runMax {
runMax = counter;
runMin = i - counter + 1;
variableNum = array1[i];
startCounter = i - counter + 2;
endCounter = i + counter - 1;
}
} else {
counter = 1;
}
}
System.out.println("The longest run is " + runMax + " times and the number is " + variableNum + ". ");
System.out.println("The run starts at " + startCounter + " and ends at " + endCounter);
//Prints the array with parentheses outside the longest run, if there is more than one max run, use the last one.
}
}
try this code:
import java.util.Arrays;
import java.util.Random;
public class Snippet {
/**
* This method will generate my random numbers for my array.
*
* #param min
* minimum random value wanted
* #param max
* maximum random value wanted
* #return randomNum a random number between 1 and 6 inclusive
*/
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
public static void main(String[] args) {
System.out.println("\f");
// Part 1 - Generate a random array of length 40 with random 1-6
// inclusive
int[] array1 = new int[40];
for (int i = 0; i < array1.length; i++) {
array1[i] = randInt(1, 6);
}
System.out.println(Arrays.toString(array1));
// Counts and RETURN: reports how many times each number is present
int counter1 = 0;
int counter2 = 0;
int counter3 = 0;
int counter4 = 0;
int counter5 = 0;
int counter6 = 0;
for (int i = 0; i < array1.length; i++) {
if (array1[i] == 1) {
counter1++;
}
if (array1[i] == 2) {
counter2++;
}
if (array1[i] == 3) {
counter3++;
}
if (array1[i] == 4) {
counter4++;
}
if (array1[i] == 5) {
counter5++;
}
if (array1[i] == 6) {
counter6++;
}
}
System.out.println("There are " + counter1 + " ones.");
System.out.println("There are " + counter2 + " twos.");
System.out.println("There are " + counter3 + " threes.");
System.out.println("There are " + counter4 + " fours.");
System.out.println("There are " + counter5 + " fives.");
System.out.println("There are " + counter6 + " sixes.");
// Counts the longest run of the same number. A run continues only when
// consecutive numbers have the same value.
// RETURN: The repeated number and the length of the run is then printed
int counter = 1;
int runMax = 0;
int runMin = 0;
int variableNum = 0;
int startCounter = 0;
int endCounter = 0;
for (int i = 0; i < array1.length - 1; i++) {
if (array1[i] == array1[i + 1]) {
counter++;
if (counter >= runMax) {
runMax = counter;
startCounter = i - counter +2;
// runMin = i-counter+1;
variableNum = array1[i];
endCounter = i+1;
}
} else {
counter = 1;
}
}
System.out.println("The longest run is " + runMax
+ " times and the number is " + variableNum + ". ");
System.out.println("The run starts at " + startCounter
+ " and ends at " + endCounter);
for (int i = 0; i < array1.length; i++) {
if (i==startCounter) {
System.out.print("(");
}
System.out.print(array1[i]);
if (i==endCounter) {
System.out.print(")");
}
}
System.out.println();
// Prints the array with parentheses outside the longest run, if there
// is more than one max run, use the last one.
}
}
Okay. I think I have this. The first answer was close, but if you run the program a few times, you discover issues. There is a logic error somewhere in your above code, but I have a work around. I think it is how you get the endCounter. It seems to count odd. But I got the program to work as far as I can tell. Try this out. I have run it several times and it seems consistent.
import java.util.Random;
import java.util.Arrays;
/**
* Write a description of class ArrayRunner1 here.
*
* #author Ibrahim Khan
* #version (a version number or a date)
*/
public class ArrayRunner1 {
/**
* This method will generate my random numbers for my array.
* #param min minimum random value wanted
* #param max maximum random value wanted
* #return randomNum a random number between 1 and 6 inclusive
*/
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
public static void main(String[] args) {
System.out.println("\f");
//Part 1 - Generate a random array of length 40 with random 1-6 inclusive
int[] array1 = new int[40];
for (int i = 0; i < array1.length; i++) {
array1[i] = randInt(1, 6);
}
System.out.println(Arrays.toString(array1));
//Counts and RETURN: reports how many times each number is present
int counter1 = 0;
int counter2 = 0;
int counter3 = 0;
int counter4 = 0;
int counter5 = 0;
int counter6 = 0;
for (int i = 0; i < array1.length; i++) {
if (array1[i] == 1) {
counter1++;
}
if (array1[i] == 2) {
counter2++;
}
if (array1[i] == 3) {
counter3++;
}
if (array1[i] == 4) {
counter4++;
}
if (array1[i] == 5) {
counter5++;
}
if (array1[i] == 6) {
counter6++;
}
}
System.out.println("There are " + counter1 + " ones.");
System.out.println("There are " + counter2 + " twos.");
System.out.println("There are " + counter3 + " threes.");
System.out.println("There are " + counter4 + " fours.");
System.out.println("There are " + counter5 + " fives.");
System.out.println("There are " + counter6 + " sixes.");
//Counts the longest run of the same number. A run continues only when consecutive numbers have the same value.
//RETURN: The repeated number and the length of the run is then printed
int counter = 1;
int runMax = 1;
int runMin = 0;
int variableNum = 0;
int startCounter = 0;
int endCounter = 0;
for (int i = 0; i < array1.length - 1; i++) {
if (array1[i] == array1[i + 1]) {
counter++;
if (counter >= runMax ){
runMax = counter;
runMin = i - counter ;// was plus one I cahnged this.
variableNum = array1[i];
startCounter = i - counter + 2;
endCounter = i + counter -1;
}
} else {
counter = 1;
}
}
System.out.println("The longest run is " + runMax + " times and the number is " + variableNum + ". ");
System.out.println("The run starts at " + startCounter + " and ends at " + endCounter);
//Prints the array with parentheses outside the longest run, if there is more than one max run, use the last one.
String output = "";// added this
for(int x = 0; x < array1.length; x++)
{
if( x == startCounter)
{
output += "("+array1[x];
}
else if( x == startCounter + runMax )
{
else if( x == startCounter + runMax )
{
if(x == array1.length-1)
{
output += ")";
}
else
{
output += ")"+array1[x];
}
}
else
{
output += array1[x];
}
}
System.out.print("\n"+output);
}
}
Here's a shorter, more generic solution. This method takes any array of ints and prints parenthesis around the longest run of numbers. If there are two runs of the same lengths it prints it around the first one.
public String makeString(int[] ints) {
if (ints.length == 0) return ""; // Quit early if there's nothing to do.
// Initialize variables.
int lastNumber = ints[0];
// We keep track of the all time best run. Defaults to first int found.
int bestStart = 0;
int bestRun = 1;
// ... as well as the current run.
int currentStart = 0;
int currentRun = 1;
String s = ""+ints[0];
// Starting from the second int, we check if the current run is continuing.
for (int i = 1; i < ints.length; i++) {
int current = ints[i];
// If the current run continues, we update currentStart/currentRun, else we reset it.
if (current == lastNumber) {
currentRun++;
} else {
currentStart = i;
currentRun = 1;
}
// Now we check if the currentRun is better than the best.
// If so, we update bestStart/bestRun.
if (currentRun > bestRun) {
bestStart = currentStart;
bestRun = currentRun;
}
lastNumber = current;
s += current;
}
// Now that we've found it, we insert parenthesis aaaaaaand we're done!
return s.substring(0, bestStart)
+"("+s.substring(bestStart, bestStart+bestRun)+")"
+s.substring(bestStart+bestRun);
}