Given a string, compute recursively (no loops) [closed] - java

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 11 years ago.
Given a string, compute recursively (no loops) the number of times lowercase "hi" appears in the string
countHi("xxhixx") -> 1
countHi("xhixhixx") -> 2
countHi("hi") -> 1
public class Tester {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int count = countHi("xxhixx");
System.out.println("countHi: " + count);
}
public static int countHi(String s) {
if (s.length() == 0) {
return 0;
}
int spot = s.indexOf("hi");
if(spot > 0)
{
String nextString = s.substring(spot + 2);
return 1 + countHi(nextString);
}
return 1;
}
}

Should work with the following code:
public static int countHi(String s) {
return countHi(s, 0);
}
public static int countHi(String s, int pos) {
if (s.length() - pos < 2) {
return 0;
}
int result = 0;
if(s.charAt(pos) == 'h' && s.charAt(pos + 1) == 'i') {
result++;
}
return result + countHi(s, pos + 2);
}

F(x[1...n]) =
if the string starts with "hi" then 1 + F(x[3...n])
else F(x[2...n])

Your recursive function will need a parameter that tells it where in the string to start looking. If the character at that position is 'h', then check whether the one after it is 'i'; if it is, you've found a match.
For the recursive call that checks the remainder of the string, pass the index of the next character if it wasn't 'i', or two characters ahead if it was.
(I'm giving just a description instead of actual code because this looks like a homework question.)

package com.indivunet.utils;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class Tester
{
/**
* #param args
*/
public static void main(String[] args)
{
printCountFor("xxhixx", 1);
printCountFor("", 0);
printCountFor("xxhixxhihi", 3);
printCountFor(null, 0);
}
#Test
public void countHi()
{
assertAndPrint("xxhixx", 1);
assertAndPrint("", 0);
assertAndPrint("xxhixxhihi", 3);
assertAndPrint(null, 0);
}
private void assertAndPrint(String string, int expectedCount)
{
int count = printCountFor(string, expectedCount);
assertEquals(expectedCount, count);
}
private static int printCountFor(String string, int expected)
{
int count = countHi(string);
System.out.println("string: \"" + string + "\" expected: " + expected + " count: " + count);
return count;
}
public static int countHi(String s)
{
if (s == null)
{
return 0;
}
int count = 0;
boolean hiSpotted = true;
while (hiSpotted)
{
int startOfNextHi = s.indexOf("hi");
hiSpotted = startOfNextHi >= 0;
if (!hiSpotted)
{
return count;
}
s = s.substring(startOfNextHi + 2);
count++;
}
return count;
}
}

public static int recCountHi(String str) {
if(str.length() < 2) {
return 0;
}
if(str.substring(0, 2).equals("hi")) {
return 1 + recCountHi(str.substring(1));
}
return recCountHi(str.substring(1));
}

Related

How to substring a String in java when it has Double bytes chracters

I have a string that might contain both Unicode and UTF-8 characters. This makes it difficult when I want to save them to a database that doesn't deal with Unicode characters. The database I am using is PostgreSQL. They might be to big for a certain column this is a simple example for my situation
public static void main(String[] args) {
String test= "İİİİİİİİİİ";
byte[] bytesOrig = null;
bytesOrig = test.getBytes("UTF-8");
System.out.println("bytesOrig="+new String(bytesOrig));
byte[] bytesFive = new byte[5];
System.arraycopy(bytesOrig, 0, bytesFive, 0, 5);
System.out.println("bytes-Five="+new String(bytesFive));
System.out.println("Substring="+test.substring(0,5));
System.out.println("Substring real length=" + test.substring(0,5).getBytes().length);
}
I cant use the String.substring method since it will NOT help me in case of double bytes characters - i have tried working with Bytes-Array copy but it means that the last characters might be deleted.
And this is the Debug info:
bytesOrig=İİİİİİİİİİ
bytes-Five=İİ�
Substring=İİİİİ
Substring real length=10
You can see since I have only part of the Bytes array - I don't want the last character to appear as �
You can try this: the changing places are shows in comment.
public static void main(String[] args) throws UnsupportedEncodingException {
String test= "İİİİİİİİİİ";
System.out.println("test.length() = " + test.length()); // out: 10
byte[] bytesOrig;
bytesOrig = test.getBytes("UTF-8"); // but after get bytes will return 20
System.out.println("bytesOrig.length = " + bytesOrig.length); // it
System.out.println("bytesOrig="+new String(bytesOrig));
byte[] bytesFive = new byte[10]; // 1. so change here to twice
System.arraycopy(bytesOrig, 0, bytesFive, 0, 10); // 2. change here also
System.out.println("bytes-Five="+new String(bytesFive));
System.out.println("Substring="+test.substring(0,5));
System.out.println("Substring real length=" + test.substring(0,5).getBytes().length);
}
And here is the output:
test.length() = 10
bytesOrig.length = 20
bytesOrig=İİİİİİİİİİ
bytes-Five=İİİİİ
Substring=İİİİİ
Substring real length=10
Most of the logic is done at transformOverhead method
according to the value, we will increase i.
public class ZoneTrimTransformer implements ZoneTransformer {
private int maxLength;
public ZoneTrimTransformer(int maxLength) {
this.maxLength = maxLength;
}
#Override
public Object transform(Object value) {
if (value == null) {
return null;
}
else {
String val = value.toString();
if (getDBRequireLength(val) > getJavaLength(val) ){
return transformOverhead(val);
}
else if (val != null && getJavaLength(val) > maxLength) {
// Trim
val = val.substring(0, maxLength);
}
return val;
}
}
public static void main(String[] args) {
System.out.println("1234567".substring(0, 5));
}
public int getJavaLength(String val) {
return val.length();
}
public int getDBRequireLength(String val) {
return val.getBytes().length;
}
private Object transformOverhead(Object s) {
byte[] byeArray = s.toString().getBytes();
if (byeArray.length < maxLength) maxLength = byeArray.length;
int n16 = 0;
int advance = 1;
int i = 0;
while (i < maxLength) {
advance = 1;
if ((byeArray[i] & 0x80) == 0) i += 1;
else if ((byeArray[i] & 0xE0) == 0xC0) i += 2;
else if ((byeArray[i] & 0xF0) == 0xE0) i += 3;
else { i += 4; advance = 2; }
if (i <= maxLength) n16 += advance;
}
return s.toString().substring(0,n16);
}
}
And a test class for it:
#Category(UnitTest.class)
#RunWith(MockitoJUnitRunner.class)
public class ZoneTrimTransformerTest {
#Test
public void testLengths()
{
ZoneTrimTransformer lztr = new ZoneTrimTransformer(5);
assertEquals(lztr.transform("İİİİİİİİİİ"),"İİ");
assertEquals(lztr.getDBRequireLength(lztr.transform("İİİİİİİİİİ").toString()),4);
assertEquals(lztr.getJavaLength(lztr.transform("İİİİİİİİİİ").toString()),2);
assertEquals(lztr.transform("%&*%$^&$$^&$").toString(),"%&*%$");
assertEquals(lztr.getDBRequireLength(("%&*%$^&$$^&$").toString()),12);
assertEquals(lztr.getJavaLength(("%&*%$^&$$^&$").toString()),12);
assertEquals(lztr.transform("媒体アカウント名"),"媒");
assertEquals(lztr.getDBRequireLength(("媒体アカウント名").toString()),24);
assertEquals(lztr.getJavaLength(("媒体アカウント名").toString()),8);
assertEquals(lztr.transform("媒体媒体アカウント名アカウント名"),"媒");
assertEquals(lztr.getDBRequireLength(("媒体媒体アカウント名アカウント名").toString()),48);
assertEquals(lztr.getJavaLength(("媒体媒体アカウント名アカウント名").toString()),16);
assertEquals(lztr.transform("SÄ°STA+UNÄ°VERSAL"),"SÄ°");
assertEquals(lztr.getDBRequireLength(("SÄ°STA+UNÄ°VERSAL").toString()),21);
assertEquals(lztr.getJavaLength(("SÄ°STA+UNÄ°VERSAL").toString()),17);
assertEquals(lztr.transform("1234567890"),"12345");
assertEquals(lztr.getDBRequireLength(("1234567890").toString()),10);
assertEquals(lztr.getJavaLength(("1234567890").toString()),10);
assertEquals(lztr.transform("abcdefghI"),"abcde");
assertEquals(lztr.getDBRequireLength(("abcdefghI").toString()),9);
assertEquals(lztr.getJavaLength(("abcdefghI").toString()),9);
assertEquals(lztr.transform("אהגדהוזחט"),"אה");
assertEquals(lztr.getDBRequireLength(("אהגדהוזחט").toString()),18);
assertEquals(lztr.getJavaLength(("אהגדהוזחט").toString()),9);
assertEquals(lztr.transform("ABAA"),"ABAA");
assertEquals(lztr.getDBRequireLength(("ABAA").toString()),4);
assertEquals(lztr.getJavaLength(("ABAA").toString()),4);
assertEquals(lztr.getDBRequireLength(lztr.transform("ABCE").toString()),4);
assertEquals(lztr.getJavaLength(lztr.transform("ABCE").toString()),4);
}
}

Sequential search does not work as expected

I have written a program which takes the words the user have entered, with a button press, and puts them in an ArrayList. There is also another text field where the user can enter a letter or word, for which the user can search for in the ArrayList with another button press. I'm using a sequential search algorithm to accomplish this, but it does not work as I expect it to; If the searched word is found, the search function should return, and print out in a textArea that the word was found and where in the array it was found. This works, but only for the first search. If the word is not found, the function should print out that the word was not found. This works as I want it to.
The problem is that after I searched for one word, and it displays where in the ArrayList this can be found, nothing happens when I press the button after that, whether the entered letter/word is in the array or not. It's like the string that the text gets stored isn't changing. I don't understand why... Here below is the custom Class of the search function and then my Main class:
public class Search {
static private int i;
static String index;
static boolean found = false;
public static String sequencial (ArrayList<String> list, String user) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals(user)) {
index = "The word " + user + " exist on the place " + i + " in the Arraylist";
found = true;
}
}
if (!found) {
index = "The word " + user + " could not be found";
}
return index;
}
My Main class:
ArrayList<String> list = new ArrayList<String>();
ArrayList<String> s = new ArrayList<String>();
private void btnAddActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
txtaOutput.setText("");
String word = txtfAdd.getText();
list.add(word);
for (int i = 0; i < list.size(); i++) {
txtaOutput.append("" + list.get(i) + "\n");
}
}
private void btnSearchActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String user = txtfSearch.getText();
txtaOutput.setText("");
String index = Search.sequencial(list, user);
txtaOutput.setText("" + index);
}
Any help is appreciated!
The problem is that you declared your found variable as static. When your first word is found, it is set to true, and nothing ever sets it back to false. Instead of making it a static variable, declare it as a local variable inside your sequencial (it's spelled sequential, by the way) function, just before the for-loop.
In fact, all the variables you've declared as static should be made local. Declaring static variables is never a good idea.
As said by other users:
There is the List#indexOf(Object) method. You should use that instead of reinventing the wheel (unless you need to, and in that case you might have a look at the ArrayList implementation). There are also other collections, like HashSet which are more apropiate for looking up, but i guess that is another history.
The scope and the names of the variables (i, index, found) is error-prone. Do other methods or even classes need to have access to those variables? If you need to keep those variables, you might want to choose a visibility (public,protected,private). "index" is a misleading choice of a name for a message.
This would be an slightly simplified/corrected version of your code:
// Ommit those unneeded static variables
public static String sequencial (ArrayList<String> list, String user) {
int indexFound = list.indexOf(user);
if (user >= 0) {
return "The word " + user + " exist on the place " + indexFound + " in the Arraylist";
} else {
return "The word " + user + " could not be found";
}
}
...
private void btnSearchActionPerformed(java.awt.event.ActionEvent evt) {
String user = txtfSearch.getText();
// txtaOutput.setText("");
String seqMessage = sequencial(list, user);
txtaOutput.setText(seqMessage);
}
We use the static properties when you would like to use the constants. You should not use the static properties here. The problem will happen when your found property is changed the first time, it will not be changed again. And from that time, it will always be true. Similar with index property. Here is the code you can fix this:
public class Search {
public static SearchResult sequencial (ArrayList<String> list, String user) {
SearchResult result = null;
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals(user)) {
String index = "The word " + user + " exist on the place " + i + " in the Arraylist";
boolean found = true;
result = new SearchResult(index, found);
break;
}
}
if (result == null) {
String index = "The word " + user + " could not be found";
result = new SearchResult(index);
}
return result;
}
//sample inner class
static class SearchResult {
private String index;
private boolean found;
public SearchResult(String index) {
this.index = index;
}
public SearchResult(String index, boolean found) {
this.index = index;
this.found = found;
}
public String getIndex() {
return index;
}
public void setIndex(String index) {
this.index = index;
}
public boolean isFound() {
return found;
}
public void setFound(boolean found) {
this.found = found;
}
}
}
public class SequencialSearcher {
public static int SequencialSearchInt(int[] inputArray, int key)
{
for(int i=0; i < inputArray.length ; i++)
{
if(inputArray[i] == key)
{
return i;
}
}
return -1;
}
public static int SequencialSearchString(String[] array, String key)
{
for(int i=0; i < array.length ; i++)
{
if(array[i] == key)
{
return i;
}
}
return -1;
}
public static int SequencialSearchFloat(double[] array, double key)
{
for(int i=0; i < array.length ; i++)
{
if(array[i] == key)
{
return i;
}
}
return -1;
}
public static void main (String args[])
{
//select the type of the elements of search
//1 if integers
//2 if float
//3 if string
int x = 3;
int[] array1 = {9, 0, 10, 8, 5, 4, 6, 2, 3};
double[] array2 = {9.0, 0.0, 10.0, 8.0, 5.0, 4.0, 6.0, 2.0, 3.0};
String[] array3 = {"aa","hey", "hello"};
if(x == 1){
//enter the integer you want to search for here below
int requiredValue = 5;
int result = SequencialSearchInt(array1, requiredValue);
if (result != -1)
{
System.out.println("Required Value: "+requiredValue+" found at index: "+result);
}
else
{
System.out.println("Value:"+requiredValue+" not found");
}
}
else if(x == 2)
{
//enter the double you want to search for here below
double requiredValue1 = 5.0;
int result = SequencialSearchFloat(array2, requiredValue1);
if (result != -1)
{
System.out.println("Required Value: "+requiredValue1+" found at index: "+result);
}
else
{
System.out.println("Value:"+requiredValue1+" not found");
}
}
else if(x == 3){
//enter the string you want to search for here below
String requiredValue2 = "hey";
int result = SequencialSearchString(array3, requiredValue2);
if (result != -1)
{
System.out.println("Required Value: "+requiredValue2+" found at index: "+result);
}
else
{
System.out.println("Value:"+requiredValue2+" not found");
}
}
else{
System.out.println("Error. Please select 1,2 and 3 only");
}
}
}

Duplicate values in a hashSet

I am trying to count the number of combinations of 1, 5, 10 and 25 that sum to n. Given that I don't want any repetitions (like 1+5 = 6 and 5+1 = 6). I am using a hashSet. I implemented a class named ResultSet that saves the number of 1, 5, 10, and 25 in a solution and I overrode the equals method. However, for some reason, my solution hashSet keeps returning duplicate values. Why?
import java.util.HashSet;
public class Solution {
public static void main(String[] args) {
int N = 6;
int combinationsSolution = new Combine(N).getSolution();
System.out.println("N= " + N + " Number of solutions= " + combinationsSolution);
}
}
class Combine {
private int solution;
private int n;
private HashSet<ResultSet> cacheUnordered = new HashSet<ResultSet>();
public Combine(int N) {
this.n = N;
this.solution = solve(n);
}
public int getSolution() {
return solution;
}
public int solve(int N) {
solve(N, 0, 0, 0, 0);
for (ResultSet r:cacheUnordered){
System.out.println(r.toString());
}
return cacheUnordered.size();
}
public void solve(int N, int substracted1, int substracted5, int substracted10, int substracted25) {
if (N == 0) {
cacheUnordered.add(new ResultSet(substracted1, substracted5, substracted10, substracted25));
} else if (N > 0) {
solve(N - 1, substracted1 + 1, substracted5, substracted10, substracted25);
solve(N - 5, substracted1, substracted5 + 1, substracted10, substracted25);
solve(N - 10, substracted1, substracted5, substracted10 + 1, substracted25);
solve(N - 25, substracted1, substracted5, substracted10, substracted25 + 1);
}
}
}
class ResultSet {
private int numberOf1;
private int numberOf5;
private int numberOf10;
private int numberOf25;
public ResultSet(int num1, int num5, int num10, int num25) {
numberOf1 = num1;
numberOf5 = num5;
numberOf10 = num10;
numberOf25 = num25;
}
#Override
public String toString(){
String result;
result = numberOf1 + " " + numberOf5 + " " + numberOf10 + " " + numberOf25;
return result;
}
#Override
public boolean equals(Object r2) {
if (r2 == null) {
return false;
}
if (!(r2 instanceof ResultSet)) {
return false;
}
ResultSet rr = (ResultSet) r2;
if (rr.numberOf1 == this.numberOf1 && rr.numberOf5 == this.numberOf5
&& rr.numberOf10 == this.numberOf10 && rr.numberOf25 == this.numberOf25) {
System.out.println("Comparing " + this.toString() + " to " + rr.toString());
return true;
} else {
return false;
}
}
public int getNum1() {
return numberOf1;
}
public int getNum5() {
return numberOf5;
}
public int getNum10() {
return numberOf10;
}
public int getNum25() {
return numberOf25;
}
}
For your ResultSet class, you defined an equals() method but not a hashCode() method. You need both methods for HashSet to work correctly. Please see this explanation. (It talks about HashMap, but it also applies to HashSet.)
As JavaDoc Clearly Specified
Note that it is generally necessary to override the hashCode method
whenever this method is overridden, so as to maintain the general
contract for the hashCode method, which states that equal objects must
have equal hash codes.
and you have not followed it , that is why you get duplicates ,
Please Read How HashCode and Equals Work it will help you out to understand the above statement better

Find test-case for which code does't work

I submitted one code in code chef but it's giving wrong answer even if it's correct
can anybody help me to identify that please.
I have tried so many inputs and calculated manually and they are correct so why they gave me wrong answer.
so,anybody who can find the TEST Case which give incorrect output by this code ?.
Here is Problem definition.
import java.util.Scanner;
import java.lang.Math;
class Codechef {
static int get(int n,int i,int digit)
{
int p;
p=(int)Math.pow(10,i-1);
n=n/p;
return n%10;
}
static boolean check_pal(int n)
{
int digit;
digit=(int) (Math.log10(n)+1);
int a=0,b=0,i,j,p;
int sum=0;
for(i=1,j=digit-1 ; i<=digit ; i++,j-- )
{
a=get(n,i,digit);
sum+=a*Math.pow(10,j);
}
if(sum==n)
return true;
else
return false;
}
static int reverse(int n)
{
int digit;
digit=(int) (Math.log10(n)+1);
int a=0,b=0,i,j,p;
int sum=0;
for(i=1,j=digit-1 ; i<=digit ; i++,j-- )
{
a=get(n,i,digit);
sum+=a*Math.pow(10,j);
}
return n+sum;
}
public static void main(String[] args) {
try{
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
if(n<10 || n>999){
System.out.println("NONE");
return;
}
boolean c;
for(int i=1 ; i<=100 ; i++)
{
c=check_pal(n);
if(c==true)
{
System.out.println(n);
return;
}
n=reverse(n);
}
System.out.println("NONE");
}
catch(Exception e)
{
System.out.println("NONE");
}
}
}
Here is one more output.
for 99 it gives 99 and which is correct as it's palindrome.
For 89 (or 98 for that matter), your code returns "NONE", although you reach the answer 8813200023188 after only 24 steps.
Another case is that for 177 and 276 you should get 8836886388 instead of NONE
I didn't debug your code, I just wrote a program that does the same, and compared the output my program gave to the one your program gave. Since you just requested a testcase, that should suffice :) My gutfeeling is that you overflow... an int is not large enough to hold the answer in all cases.
Happy bughunting.
Edit (on Request) with my code.
I didn't change your code, except that I extracted your logic into a getResult(integer) methode so that I could bypass the scanning of the input and simply return a string as result. It prints out all the differences between our versions. I used BigInteger as the type to hold my results.
public class Main {
public static void main(String[] args) {
Main m = new Main();
for (int i=10; i < 1000; i++) {
String myResult = null;
String hisResult = null;
try {
myResult = m.getResultAsString(i);
} catch (Exception e){
System.out.println("Your code threw an exception for " + i);
}
try{
hisResult = Codechef.getResult(i);
} catch (Exception e){
System.out.println("His code threw an exception for " + i);
}
if (myResult != null && hisResult != null && ! myResult.equals(hisResult)) {
System.out.println("For " + i + " you have " + myResult + " but he has " + hisResult);
}
}
}
public String getResultAsString(int inputNumber) {
BigInteger res = getResultAsBigInteger(new BigInteger(""+inputNumber));
if (res != null) {
return res.toString();
} else {
return "NONE";
}
}
public BigInteger getResultAsBigInteger(BigInteger inputNumber) {
int numberOfSteps = 0;
BigInteger currentValue = inputNumber;
while (numberOfSteps < 101 && ! isPalindrome(currentValue)) {
numberOfSteps++;
currentValue = currentValue.add(reverseDigits(currentValue));
}
return numberOfSteps < 101 ? currentValue : null;
}
public boolean isPalindrome(BigInteger number) {
return number.equals(reverseDigits(number));
}
public BigInteger reverseDigits(BigInteger input) {
String inputString = input.toString();
String output = "";
for (int i = inputString.length() - 1; i >= 0; i--)
{
output += inputString.charAt(i);
}
return new BigInteger(output);
}
}
There is an overflow error in your code.
for input 89 it's not working as #Yves V. said
Suggestion is to use BigInteger class of lang.Match it will be useful to eliminate this overflow error.

Uva's 3n+1 problem

I'm solving Uva's 3n+1 problem and I don't get why the judge is rejecting my answer. The time limit hasn't been exceeded and the all test cases I've tried have run correctly so far.
import java.io.*;
public class NewClass{
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
int maxCounter= 0;
int input;
int lowerBound;
int upperBound;
int counter;
int numberOfCycles;
int maxCycles= 0;
int lowerInt;
BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
String line = consoleInput.readLine();
String [] splitted = line.split(" ");
lowerBound = Integer.parseInt(splitted[0]);
upperBound = Integer.parseInt(splitted[1]);
int [] recentlyused = new int[1000001];
if (lowerBound > upperBound )
{
int h = upperBound;
upperBound = lowerBound;
lowerBound = h;
}
lowerInt = lowerBound;
while (lowerBound <= upperBound)
{
counter = lowerBound;
numberOfCycles = 0;
if (recentlyused[counter] == 0)
{
while ( counter != 1 )
{
if (recentlyused[counter] != 0)
{
numberOfCycles = recentlyused[counter] + numberOfCycles;
counter = 1;
}
else
{
if (counter % 2 == 0)
{
counter = counter /2;
}
else
{
counter = 3*counter + 1;
}
numberOfCycles++;
}
}
}
else
{
numberOfCycles = recentlyused[counter] + numberOfCycles;
counter = 1;
}
recentlyused[lowerBound] = numberOfCycles;
if (numberOfCycles > maxCycles)
{
maxCycles = numberOfCycles;
}
lowerBound++;
}
System.out.println(lowerInt +" "+ upperBound+ " "+ (maxCycles+1));
}
}
Are you making sure to accept the entire input? It looks like your program terminates after reading only one line, and then processing one line. You need to be able to accept the entire sample input at once.
I faced the same problem. The following changes worked for me:
Changed the class name to Main.
Removed the public modifier from the class name.
The following code gave a compilation error:
public class Optimal_Parking_11364 {
public static void main(String[] args) {
...
}
}
Whereas after the changes, the following code was accepted:
class Main {
public static void main(String[] args) {
...
}
}
This was a very very simple program. Hopefully, the same trick will also work for more complex programs.
If I understand correctly you are using a memoizing approach. You create a table where you store full results for all the elements you have already calculated so that you do not need to re-calculate results that you already know (calculated before).
The approach itself is not wrong, but there are a couple of things you must take into account. First, the input consists of a list of pairs, you are only processing the first pair. Then, you must take care of your memoizing table limits. You are assuming that all numbers you will hit fall in the range [1...1000001), but that is not true. For the input number 999999 (first odd number below the upper limit) the first operation will turn it into 3*n+1, which is way beyond the upper limit of the memoization table.
Some other things you may want to consider are halving the memoization table and only memorize odd numbers, since you can implement the divide by two operation almost free with bit operations (and checking for even-ness is also just one bit operation).
Did you make sure that the output was in the same order specified in the input. I see where you are swapping the input if the first input was higher than the second, but you also need to make sure that you don't alter the order it appears in the input when you print the results out.
ex.
Input
10 1
Output
10 1 20
If possible Please use this Java specification : to read input lines
http://online-judge.uva.es/problemset/data/p100.java.html
I think the most important thing in UVA judge is 1) Get the output Exactly same , No Extra Lines at the end or anywhere . 2) I am assuming , Never throw exception just return or break with No output for Outside boundary parameters.
3)Output is case sensitive 4)Output Parameters should Maintain Space as shown in problem
One possible solution based on above patterns is here
https://gist.github.com/4676999
/*
Problem URL: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=36
Home>Online Judge > submission Specifications
Sample code to read input is from : http://online-judge.uva.es/problemset/data/p100.java.html
Runtime : 1.068
*/
import java.io.*;
import java.util.*;
class Main
{
static String ReadLn (int maxLg) // utility function to read from stdin
{
byte lin[] = new byte [maxLg];
int lg = 0, car = -1;
String line = "";
try
{
while (lg < maxLg)
{
car = System.in.read();
if ((car < 0) || (car == '\n')) break;
lin [lg++] += car;
}
}
catch (IOException e)
{
return (null);
}
if ((car < 0) && (lg == 0)) return (null); // eof
return (new String (lin, 0, lg));
}
public static void main (String args[]) // entry point from OS
{
Main myWork = new Main(); // create a dinamic instance
myWork.Begin(); // the true entry point
}
void Begin()
{
String input;
StringTokenizer idata;
int a, b,max;
while ((input = Main.ReadLn (255)) != null)
{
idata = new StringTokenizer (input);
a = Integer.parseInt (idata.nextToken());
b = Integer.parseInt (idata.nextToken());
if (a<b){
max=work(a,b);
}else{
max=work(b,a);
}
System.out.println (a + " " + b + " " +max);
}
}
int work( int a , int b){
int max=0;
for ( int i=a;i<=b;i++){
int temp=process(i);
if (temp>max) max=temp;
}
return max;
}
int process (long n){
int count=1;
while(n!=1){
count++;
if (n%2==1){
n=n*3+1;
}else{
n=n>>1;
}
}
return count;
}
}
Please consider that the integers i and j must appear in the output in the same order in which they appeared in the input, so for:
10 1
You should print
10 1 20
package pandarium.java.preparing2topcoder;/*
* Main.java
* java program model for www.programming-challenges.com
*/
import java.io.*;
import java.util.*;
class Main implements Runnable{
static String ReadLn(int maxLg){ // utility function to read from stdin,
// Provided by Programming-challenges, edit for style only
byte lin[] = new byte [maxLg];
int lg = 0, car = -1;
String line = "";
try
{
while (lg < maxLg)
{
car = System.in.read();
if ((car < 0) || (car == '\n')) break;
lin [lg++] += car;
}
}
catch (IOException e)
{
return (null);
}
if ((car < 0) && (lg == 0)) return (null); // eof
return (new String (lin, 0, lg));
}
public static void main(String args[]) // entry point from OS
{
Main myWork = new Main(); // Construct the bootloader
myWork.run(); // execute
}
public void run() {
new myStuff().run();
}
}
class myStuff implements Runnable{
private String input;
private StringTokenizer idata;
private List<Integer> maxes;
public void run(){
String input;
StringTokenizer idata;
int a, b,max=Integer.MIN_VALUE;
while ((input = Main.ReadLn (255)) != null)
{
max=Integer.MIN_VALUE;
maxes=new ArrayList<Integer>();
idata = new StringTokenizer (input);
a = Integer.parseInt (idata.nextToken());
b = Integer.parseInt (idata.nextToken());
System.out.println(a + " " + b + " "+max);
}
}
private static int getCyclesCount(long counter){
int cyclesCount=0;
while (counter!=1)
{
if(counter%2==0)
counter=counter>>1;
else
counter=counter*3+1;
cyclesCount++;
}
cyclesCount++;
return cyclesCount;
}
// You can insert more classes here if you want.
}
This solution gets accepted within 0.5s. I had to remove the package modifier.
import java.util.*;
public class Main {
static Map<Integer, Integer> map = new HashMap<>();
private static int f(int N) {
if (N == 1) {
return 1;
}
if (map.containsKey(N)) {
return map.get(N);
}
if (N % 2 == 0) {
N >>= 1;
map.put(N, f(N));
return 1 + map.get(N);
} else {
N = 3*N + 1;
map.put(N, f(N) );
return 1 + map.get(N);
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
try {
while(scanner.hasNextLine()) {
int i = scanner.nextInt();
int j = scanner.nextInt();
int maxx = 0;
if (i <= j) {
for(int m = i; m <= j; m++) {
maxx = Math.max(Main.f(m), maxx);
}
} else {
for(int m = j; m <= i; m++) {
maxx = Math.max(Main.f(m), maxx);
}
}
System.out.println(i + " " + j + " " + maxx);
}
System.exit(0);
} catch (Exception e) {
}
}
}

Categories

Resources