So I have this method to count the letters in a sentence and put them into an int array of size 26:
public void countLetters()
{
String upper = sentence.toUpperCase();
int ascii;
for (int k = 0; k <upper.length(); k++)
{
char ch = upper.charAt(k);
if (Character.isLetter(ch))
{
ascii = (int) ch;
ascii -= 65;
count[ascii] += 1;
}
}
}
The count variable is my array and I have the ASCII values and stuff...
What I don't know how to write is the toString method
These are the Javadocs:
/**
* Returns a String containing the letters in the sentence
* and how many times they occurred.
* #return returns a formatted string with only the letters
* that occurred in the string, each on a separate line.
*/
public String toString()
{
StringBuffer a = new StringBuffer();
for (Integer i : count)
{
a.append(i + " ");
}
return a.toString();
//This is what I have so far, but I need to print them out in a format that looks like this:
I sure hope this WORKS!!!
e's = 2
h's = 2
i's = 2
k's = 1
o's = 2
p's = 1
r's = 2
s's = 3
t's = 1
u's = 1
w's = 1
}
He doesn't want us printing out characters that don't appear in the string. The string in his driver program looks like "Aa678 ,.. zZ"; and in my tester it just prints out 0 0 0... 26 times whereas it should print out A's = 2 and Z's = 2.
the tester program looks like
public class LetterCounterDriver
{
public static void main(String[] args)
{
String s = "Aa678 ,.. zZ";
LetterCounter lc = new LetterCounter(s);
System.out.println(lc);
if (lc.toString().equals("a's = 2\nz's = 2\n"))
System.out.println("Works");
else if (strip(lc.toString()).equals(strip("a's = 2\nz's = 2\n")))
System.out.println("Close to working. Check you spacing and capitalization!");
else
System.out.println("Needs some more work");
}
/**
* Removes:
* space -> 32
* (\t) tab -> 9
* (\n) line feed -> 10
* (\f) form feed -> 12
* (\r) return -> 13
*/
private static String strip(String s)
{
String remove = " \t\n\f\r";
String x = "";
for (int k = 0; k < s.length(); k++)
if (remove.indexOf(s.charAt(k)) == -1)
x += s.charAt(k);
return x.toLowerCase();
}
}
The output says
A's = 2 Z's = 2
Needs some more work
Whereas it should say
Works
UPDATE: Here is the full class. Note that I wrote all of this.
import java.util.Arrays;
public class LetterCounter
{
private String sentence;
private int[] count;
/**
* Creates a LetterCounter object
*/
public LetterCounter(String s)
{
count = new int[26];
sentence = s;
}
/**
* Sets all locations in the letter count array to zero
* #postcondition sets all locations in the letter count array to zero
*/
public void zeroArray()
{
for (int k = 0; k < count.length; k++)
count[k] = 0;
}
/**
* Computes the array containing a count for each letter
* in the sentence
* #postcondition computes the counter array for letters a - z
*/
private void countLetters()
{
String upper = sentence.toUpperCase();
int ascii;
for (int k = 0; k <upper.length(); k++)
{
char ch = upper.charAt(k);
if (Character.isLetter(ch))
{
ascii = (int) ch;
ascii -= 65;
count[ascii] += 1;
}
}
}
/**
* Returns a String containing the letters in the sentence
* and how many times they occurred.
* #return returns a formatted string with only the letters
* that occurred in the string, each on a separate line.
*/
public String toString()
{
countLetters();
StringBuffer a = new StringBuffer();
for (int i = 0; i < count.length; i++)
{
int c = count[i];
if (c > 0)
{
char letter = (char) (i + 'a');
a.append(letter).append("'s = ").append(c).append("\n");
}
}
return a.toString();
}
}
//The output is
//a's = 2
//z's = 2
//Needs more work
I hope this will help you.
String upper = "Aa678 ,.. zZ.qammar".toUpperCase();
//your method then following toString
public String toString(){
StringBuffer a = new StringBuffer();
for (int i = 0; i < count.length; i++)
{
int v = count[i];
if(v > 0){
a.append( (char)(i + 65) + "'s = " + v + ", ");
}
}
return a.toString();
}
Output:
A's = 4, M's = 2, Q's = 1, R's = 1, Z's = 2,
Here this should work for you:
public String toString() {
StringBuffer a = new StringBuffer();
for (int i = 0; i < count.length; i++) {
int c = count[i];
if (c > 0) {
char letter = (char) (i + 'a');
a.append(letter).append("'s = ").append(c).append("\n");
}
}
return a.toString();
}
Here are the things that had to change compared to your original code:
We need to iterate using the index because we need the index to get the letter
The current letter is the value of the index + the value of a since we want lower-case letters
The 's = part and a line break at the end were missing
A check whether the current count is larger than 0 was missing
Hope this helps you.
Related
I have problem with my algorithm, I tried with my sample data noted below. And I don't understand why the result is not what I thought at all. For example when i = 3(n) and j = 2(n). The q should have output 2 but it's equal to 1. I guess the cause could just be that the while loop working was having problems. But I don't know the reason why. Please someone help me! Thank you very much
Running method
public static void compareStringToString(String str1, String str2) {
ArrayList<Integer> numSames = new ArrayList<Integer>();
int p = 0, n; // p - Maximum number of similar characters, n - the number of characters of the longer string
// str1 = "slcnsicnn"
// str2 = "ahnscnn"
int i = 0, j = 0;
if (str1.length() >= str2.length()) {
n = str1.length();
for (i = 0; i < n; i++) {
for (j = 0; j < str2.length(); j++) {
if (str1.charAt(i) == str2.charAt(j)) {
p = 0;
while (str1.charAt(i + p) == str2.charAt(j + p)) {
p++;
if ((i + p < n) || (j + p < str2.length())) {
break;
}
}
numSames.add(p);
}
}
}
System.out.println("The similarity of the two strings is: " + (((float)
Collections.max(numSames)) / n) * 100 + "%");
else {
n = str2.length();
// TODO Same things
}
Running Screen
**
I did as you said. I created a new method to split the work. Indeed, when I did that, my mind became clearer. And more specifically, I was able to run it smoothly without errors. Or maybe there are some more minor bugs that I haven't noticed yet. But it's really great like a little bit of a burden. Once again thank you very much for your kind advice.
**
// Get the number of similar characters after a pair of similar characters of 2 strings
public static int getNumSimilarAfterChar(String str1, String str2, int indexStr1, int indexStr2) {
int numChar = 0; // It's both a count and an index
// Substrings to work with algorithm
String subStr1;
String subStr2;
if (str1.charAt(indexStr1) == str2.charAt(indexStr2)) {
// Cut substring from highlighted part
subStr1 = str1.substring(indexStr1);
subStr2 = str2.substring(indexStr2);
while (subStr1.charAt(numChar) == subStr2.charAt(numChar)) {
numChar++;
if ((numChar >= (subStr1.length() - 1)) || (numChar >= (subStr2.length() - 1))) {
break;
}
}
return numChar + 1;
} else {
return numChar;
}
}
// Given any two strings of characters, compare the match of these two strings
/**
* Compare the match of string 1 vs string 2
*
* #param str1
* #param str2
*/
public static void compareStringToString(String str1, String str2) {
ArrayList<Integer> numSames = new ArrayList<Integer>();
// maxSimilar - maximum number of similar characters, totalLength - the number of characters of longer string
int numSimilar = 0, totalLength;
// slcnsicnn
// ahnscnn
int i = 0, j = 0;
// If string 1 is longer than string 2
if (str1.length() >= str2.length()) {
totalLength = str1.length();
for (i = 0; i < totalLength; i++) {
for (j = 0; j < str2.length(); j++) {
// Browse until you come across two similar characters
if (str1.charAt(i) == str2.charAt(j)) {
numSimilar = MyStrings.getNumSimilarAfterChar(str1, str2, i, j);
numSames.add(numSimilar);
System.out.println(numSames.toString());
}
}
}
// Get the max value in a list of how many identical characters are generated
System.out.println("The similarity of the two strings is: " + (((float) Collections.max(numSames)) / totalLength) * 100 + "%");
} else {
totalLength = str2.length();
// TODO Same things
}
}
public class Hello {
public static void pattern() {
int s1 = 3;
while(s1 >= 1) {
System.out.println("*");
s1--;
}
}
public static void main(String [] args){
pattern();
}
}
Actual output:
*
*
*
Expected output:
* * *
* *
*
I would like to print " * " (like the above-expected output) using while loop. I made a while loop controlling the number of columns. I'm not able to make a while loop to control the rows to output "*" in the same line 3 times (next line 2 times and so on).
With just you one loop and some String.repeat() you can draw your pattern
Repeat the leading space, starting and 0, and one more each round
Repeat the pattern depending ong s1, 3 times, then 2 then 1
public static void pattern() {
int s1 = 3;
int s2 = 0; // space counter
while(s1 >= 1) {
System.out.print(" ".repeat(s2));
System.out.println("* ".repeat(s1).trim()); // trim to remove last space
s1--;
s2++;
}
}
int lines = 0, asterisks = 3;
String whiteSpace = "";
while (lines++ < 3) {
System.out.print(whiteSpace);
for (int i = 0; i < 3; i++) {
if (i <= (asterisks - lines)) {
System.out.print("* ");
}
}
whiteSpace += " ";
System.out.println();
}
For a given positive integer N of not more than 1000000 digits, write the value of the smallest palindrome larger than N to output.
Here is my code:
public class Palin {
public static String reverseString(String s) {
String newS = "";
for(int i = s.length() - 1; i >= 0; i--)
newS += s.charAt(i);
return newS;
}
public static String getPalin(String s) {
int lth = s.length();
String left = "", mid = "", right = "", newS = "";
if(lth % 2 != 0) {
left = s.substring(0, lth / 2);
mid = s.substring(lth / 2, lth / 2 + 1);
right = reverseString(left);
newS = left + mid + right;
if(s.compareTo(newS) < 0) return newS;
else {
int temp = Integer.parseInt(mid);
temp++;
mid = Integer.toString(temp);
newS = left + mid + right;
return newS;
}
}
else {
left = s.substring(0, lth / 2 - 1);
mid = s.substring(lth / 2 - 1, lth / 2);
right = reverseString(left);
newS = left + mid + mid + right;
if(s.compareTo(newS) < 0) return newS;
else {
int temp = Integer.parseInt(mid);
temp++;
mid = Integer.toString(temp);
newS = left + mid + mid + right;
return newS;
}
}
}
public static void main(String[] args) throws java.lang.Exception {
Scanner input = new Scanner(System.in);
//Scanner input = new Scanner(System.in);
int k = input.nextInt();
String[] s = new String[k];
for(int i = 0; i < k; i++) {
s[i] = input.next();
}
for(int i = 0; i < k; i++) {
System.out.println(getPalin(s[i]));
}
}
}
My idea is use a String represent for a number. I divide this String into 2 part, coppy first part and reverse it for second part. I think my solve is correct but it not fast enough. I need a more efficient algorithm.
Thanks
EDITED
Since you said that:
For a given positive integer N of not more than 1000000 digits
My previous solution won't work since I have converted them to int and an int can't accommodate 1000000 digits. Thus I have made a new approach, an approach that doesn't need any String to int conversion.
Refer to the code and comment below for details.
CODE:
package main;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// Scanner input = new Scanner(System.in);
int k = Integer.parseInt(input.nextLine());
String[] s = new String[k];
for (int i = 0; i < k; i++) {
s[i] = input.nextLine();
}
for (int i = 0; i < k; i++) {
System.out.println(getPalin(s[i]));
}
input.close();
}
public static String getPalin(String s) {
// initialize the result to "" since if input is 1 digit, nothing is printed
String result = "";
// if input is greater than 1000000 digits
if (s.length() >= 1000000) {
// return the highest palindrome less than 1000000
result = "999999";
} else if (s.length() > 1) {
// get the middle index of the string
int mid = s.length() % 2 == 0 ? s.length() / 2 : (s.length() / 2) + 1;
// get the left part of the string
String leftPart = getPalindrome(s.substring(0, mid));
if (s.length() % 2 == 0) {
// attach the left part and the reverse left part
result = leftPart + new StringBuilder(leftPart).reverse().toString();
} else {
// attach the left part and the reverse left part excluding the middle digit
result = leftPart
+ new StringBuilder(leftPart.substring(0, leftPart.length() - 1)).reverse().toString();
}
// check if the new result greater than 1000000 digits
if (result.length() >= 1000000) {
// return the highest palindrome less than 1000000
result = "999999";
}
}
return result;
}
public static String getPalindrome(String param) {
String result = "";
// iterate through the string from last index until index 0
for (int i = param.length() - 1; i >= 0; i--) {
// get the char at index i
char c = param.charAt(i);
/*
* increment char since the next palindrome is the current digit + 1. Example:
* User input is 121, then param will be 12 so the next is 13
*/
c++;
/*
* check if the current character is greater than '9', which means it is not a
* digit after incrementing
*/
if (c > '9') {
// set the current char to 0
c = '0';
// check if index is at index 0
if (i - 1 < 0) {
// if at index 0 then add '1' at start
result = '1' + result;
} else {
// if not then append c at result
result = result + c;
}
} else {
// check if index is at index 0
if (i - 1 < 0) {
// if not then prepend c at result
result = c + result;
} else {
// if not then get the rest of param then append c and result
result = param.substring(0, i) + c + result;
}
break;
}
}
return result;
}
}
Im looking for some help on this binary translator problem. The question goes: In this exercise, you’ll write a binary to text translator!
As we’ve seen, every character can be represented by a string of 8 bits, or a byte. For example, the binary string 010000012 has the decimal value of 6510, which maps to the character ‘A’.
So far I have this but the output is: H
CÞ*
NÒ)MØ
Here is my code:
public class Scratchpad extends ConsoleProgram
{
public void run()
{
System.out.println(binaryToText("0100100001001001"));
System.out.println(binaryToText("010000110110111101100100011001010100100001010011"));
System.out.println(binaryToText("010011100110100101100011011001010010000001001010011011110110001000100001"));
}
public String binaryToText(String binary)
{
String s2 = "";
char nextChar;
for(int i = 0; i <= binary.length()-8; i += 9) //this is a little tricky. we want [0, 7], [9, 16], etc (increment index by 9 if bytes are space-delimited)
{
nextChar = (char)Integer.parseInt(binary.substring(i, i+8), 2);
s2 += nextChar;
}
return s2;
}
public int binaryToDecimal(String binaryString)
{
int decimal = 0;
int base = 2;
for (int i = binaryString.length() - 1; i >= 0; i--) {
if (binaryString.charAt(i) == '1')
decimal += Math.pow(base,i);
}
return decimal;
}
}
Here is the solution:
For each string of bits, perform the following:
Create an array of 256 chars, the value of each element is the ASCII value of the index. For example, the value of element 65 is the character 'A'. This is the translationTable referenced below.
If the length of the string of bits is divisible by 8, continue.
If the string of bits contains only digits 0 and 1, continue.
Split the string of bits into smaller strings, each of which is exactly 8 digits in length.
For each 8-bit string, convert from binary to decimal.
Using the translationTable, convert from decimal to the desired ASCII character.
Accumulate the individual characters into a string (perhaps using a StringBuilder).
public class Scratchpad extends ConsoleProgram
{
public String binaryToText(String binary)
{
String s2 = "";
char nextChar;
for(int i = 0; i <= binary.length()-8; i += 8)
{
nextChar = (char)Integer.parseInt(binary.substring(i, i+8), 2);
s2 += nextChar;
}
return s2;
public int binaryToDecimal(String binaryString)
{
int numPlaces = binaryString.length();
int currentExponent = numPlaces - 1;
int decimalValue = 0;
for(int i = 0; i < binaryString.length(); i++)
{
int placeValue = (int) Math.pow(2, currentExponent);
char currentDigit = binaryString.charAt(i);
int digitValue = Character.getNumericValue(currentDigit);
System.out.print(digitValue + " * (" + placeValue + ")");
if(i != binaryString.length() - 1)
{
System.out.print(" + ");
}
decimalValue += digitValue * placeValue;
currentExponent--;
}
System.out.println(" = " + decimalValue);
return decimalValue;
}
}
String s="101010101010";
String sub=""; //substring
int k=2;
package coreJava;
import java.util.Scanner;
public class substring {
public static void main(String args[])
{
String string, sub;
int k, c, i;
Scanner in = new Scanner(System.in);
System.out.println("Enter a string to print it's all substrings");
string = in.nextLine();
i = string.length();
System.out.println("Substrings of \""+string+"\" are :-");
for( c = 0 ; c < i ; c++ )
{
for( k = 1 ; k <= i - c ; k++ )
{
sub = string.substring(c, c+k);
System.out.println(sub);
}
}
}
}
take a binary string s="1010011010"; //etc
take one variable k=2;
take another variable i; //which is the length of the sub string(i>k)
now i want to find sub string of the above string, in such a way that if k=2,the number of 1's in sub string must be 2,if k=3,the number of 1's in substring must be 3 and so on...
Output should be like this:
string s="1010011010"
Enter value of k=2;
Enter length of substring i=3;
substring= 101 110 101 011
Create a "window" the length of your desired substrings which you move along the string, maintaining a count of the number of 1s in your current window. Each iteration you move the window along one, testing the next character outside the current window, the first character in the current window and updating the count accordingly. During each iteration, if your count is equal to the desired length, print the substring from the current window.
public class Substring {
public static void main(String[] args) {
String str = "1010011010";
int k = 2;
int i = 3;
printAllSubstrings(str, i, k);
}
private static void printAllSubstrings(String str, int substringLength, int numberOfOnes) {
// start index of the current window
int startIndex = 0;
// count of 1s in current window
int count = 0;
// count 1s in the first i characters
for (int a = 0; a < substringLength; a++) {
if (str.charAt(a) == '1') {
count++;
}
}
while (startIndex < str.length() - substringLength + 1) {
if (count == numberOfOnes) {
System.out.print(str.substring(startIndex, startIndex + substringLength));
System.out.print(" ");
}
// Test next bit, which will be inside the window next iteration
if (str.length() > startIndex + substringLength && str.charAt(startIndex + substringLength) == '1') {
count ++;
}
// Test the starting bit, which will be outside the window next iteration
if (str.charAt(startIndex) == '1') {
count --;
}
startIndex++;
}
}
}
This outputs:
101 011 110 101
Iterate over the characters and count the number of one's. If the counter reaches the desired number, stop iterating and take the substring from index zero to where you got.
String str = "010101001010";
int count = 0;
int k = 2;
int i = 0;
for (; i < str.length() && count < k; ++i)
{
if (str.charAt(i) == '1') count++;
}
You could use regular expressions:
public class BinaryString {
public static void main(String[] args) {
String binary = "11000001101110";
int count = 3;
String regEx = "1{" + count + "}";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(binary);
if (m.find()) {
int startIndex = m.start();
System.out.println("MATCH (#index " + startIndex + "): "+ m.group());
} else {
System.out.println("NO MATCH!");
}
}
}
OUTPUT
MATCH (#index 10): 111