Letter to Numeric Phone Number Java - java

I have the following problem:
Today, everyone comes up with some clever phrase so you can remember
their phone number. You have been given the task to decipher these
phrases and find out what numbers you need to dial in order to contact
these places.
Description: You input will be series of letters, numbers and dashes. You will need to determine the number that the input sequence
represents in regular three - dash- four format (see example output).
You will also need to determine if the resulting number is a valid
number (seven digits) or if there is a number in the input at all.
Input: All letters will be in uppercase. The input string may be up to 25 characters long.
Output: A single line of output is all that is needed either printing the phone number, if the number is not a valid number or if
there is no number at all.
Translation Key ABC = 2 DEF = 3 GHI = 4 JKL = 5 MNO = 6 PRS = 7 TUV = 8 WXY = 9 Numbers will be as themselves and ignore all Q, Z
and dashes. Example Input: ITS-EASY Example Output : 487-3279
Example Input: ---2---3---TS-4 Example Output : Not a valid number.
Example Input: QZ---I-M-A-TEST Example Output : 462-8378 Example
Input: ---------- Example Output : No phone number.
I'm having trouble separating the dashes and unnecessary letters from the actual phrase that translates to the phone number. This is my program so far:
public static void main(String[] args) {
String cleverPhrase = getCleverPhrase("Input the phrase you use to remember a specific phone number (Max 25 characters allowed): ");
checkPhrase(cleverPhrase);
}
public static String getCleverPhrase(String prompt) {
String input;
System.out.print(prompt);
input = console.nextLine();
return input;
}
public static String checkPhrase(String cleverPhrase) {
int len = cleverPhrase.length();
String output = "";
do {
for(int i = 0; i <= len; i++) {
char current = cleverPhrase.charAt(i);
if (Character.isLetter(current)) {
String newCurrent = Character.toString(current);
if (newCurrent.equals('Q') || newCurrent.equals('Z')) {
}
}
}
} while ()
}
As you can see, I haven't made much progress. I don't know how to get the program to pick out the unnecessary letters and dashes and return just the letters that form the number. Could someone help me?

Check the following code..
public static String checkPhrase(String cleverPhrase) {
int len = cleverPhrase.length();
String output = "";
for (int i = 0; i <= len; i++) {
char current = cleverPhrase.charAt(i);
if (Character.isLetter(current)) {
if (current == 'A' || current == 'B' || current == 'C') {
output += "2";
} else if (current == 'D' || current == 'E' || current == 'F') {
output += "3";
} else if (...) {
....
}
}
if(output.length()==3){
output += "-";
}
}
if(output.isEmpty()){
output = "No phone number";
}else if(output.length()!=8){
output = "Not a valid number";
}
return output;
}
You can extend else-if for all other combinations of numbers. You don't have to check for invalid characters like - or Q or Z. The output variable will be get edited if it goes inside a if statement.

This method will be very handy in your case. Thanks to that you can replace this
if (current == 'A' || current == 'B' || current == 'C')
...
} else if (current == 'D' || current == 'E' || current == 'F') {
...
with this
StringUtils.replaceChars(input, "ABCDEF", "222333")
You can also get rid of all non-numbers simply by output.replaceAll( "[^\\d]", "" ). At the end, you can add the dash in a specific position and check if the number is valid.

To strip out the unwanted characters in your string, have a look at String.replaceAll

Related

Password Checking, Verification and Requirements

I have a problem that requires at least 2 uppercase letters, at least 2 lowercase letters and 2 digits.
Here is the exact problem:
Write an application that prompts the user for a password that contains at least two uppercase letters, at least two lowercase letters, and at least two digits. After a password is entered, display a message indicating whether the user was successful or the reason the user was not successful.
For example, if the user enters "Password" your program should output:
Your password was invalid for the following reasons:
uppercase letters
digits
If a user enters "P4SSw0rd", your program should output:
valid password
Here is my coding so far, I am having the problem of including output lines. For example, if someone doesn't have 2 capital letters AND doesn't have 2 letters. When writing 1 letter, it doesn't include both failures in the output.
import java.util.Scanner;
public class ValidatePassword {
public static void main(String[] args) {
String inputPassword;
Scanner input = new Scanner(System.in);
System.out.print("Password: ");
inputPassword = input.next();
System.out.println(PassCheck(inputPassword));
System.out.println("");
}
public static String PassCheck(String Password) {
String result = "Valid Password";
int length = 0;
int numCount = 0;
int capCount = 0;
for (int x = 0; x < Password.length(); x++) {
if ((Password.charAt(x) >= 47 && Password.charAt(x) <= 58) || (Password.charAt(x) >= 64 && Password.charAt(x) <= 91) ||
(Password.charAt(x) >= 97 && Password.charAt(x) <= 122)) {
} else {
result = "Password Contains Invalid Character!";
}
if ((Password.charAt(x) > 47 && Password.charAt(x) < 58)) {
numCount++;
}
if ((Password.charAt(x) > 64 && Password.charAt(x) < 91)) {
capCount++;
}
length = (x + 1);
}
if (numCount < 2) {
result = "Not Enough Numbers in Password!";
}
if (capCount < 2) {
result = "Not Enough Capital Letters in Password!";
}
if (length < 2) {
result = "Password is Too Short!";
}
return (result);
}
}
If I understand correctly what you want to do is when you enter e.g "Password" you don't have 2 capital letters and 2 digits so your output should looks like:
"Not Enough Numbers in Password! Not Enough Capital Letters in Password!".
I suggest 2 solutions:
If you want to add one String to another use + because you overwrite first result value with another. But this is not best solution because every time you add value to String you create new String on String pool. More information here:
https://stackoverflow.com/a/1553110/6003541
result += "Password is Too Short!";
or
result = result + "Password is Too Short!";
I suggest to use StringBuilder. Use method "append" to add your result and at the end return toString() value of StringBuilder object.
StringBuilder sb = new StringBuilder();
if (numCount < 2) {
sb.append("Not Enough Numbers in Password!");
sb.append(System.getProperty("line.separator"));
}
if (capCount < 2) {
sb.append("Not Enough Capital Letters in Password!");
sb.append(System.getProperty("line.separator"));
}
if (length < 2) {
sb.append("Password is Too Short!");
}
return sb.toString();

Why is the program throwing this error??: Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 36

In this assignment you will write a Tweet Tester.
Twitter allows users to send messages of 140 characters or less. Users direct tweets to specific users by using #mentions and label tweets by using #hashtags. Users may also "retweet" tweets from other users.
For this lab you will ask the user to enter a potential tweet. First you will check to see if it is a valid tweet by checking that the length is less than or equal to 140 characters.
If the tweet is too long print out the number of characters over 140.
If the tweet is valid print Length Correct, then count the number of #mentions and #hashtags and determine whether the tweet is a retweet using the following rules:
Every mention will start with the '#' character and have at least one non-space or non-tab character following it.
All hashtags will start with the '#' character and have at least one non-space or non-tab character following it.
The tweet is a retweet if it contains the string "RT:" anywhere in the text of the tweet. Twitter ignores case, so "RT:", "rt:" and any other possible capitalizations are counted as the same set of characters and all indicate a retweet. You do not need to check for any characters following the "RT:" string.
Remember that the escape sequence, '\t', can be used to check for a tab character.
Sample Run 1:
Please enter a tweet:
RT: This is a #long tweet. An extra long #link. So, when #you write your code it should ignore all of the #hashtags and #mentions since it is too long. It should also ignore retweet strings.
Excess Characters: 50
Sample Run 2:
Please enter a tweet:
This #tweet is #short and has several #hashtags. RT: And it is a retweet.
Length Correct
Number of Mentions: 0
Number of Hashtags: 3
The input was a retweet.
Sample Run 2:
Please enter a tweet:
This #tweet is #short and has #hashtags and #mentions #
Length Correct
Number of Mentions: 2
Number of Hashtags: 2
The input was not a retweet.
import java.util.Scanner;
import java.lang.Math;
public class Main{
public static void main(String[] args)
{
Scanner scan = new Scanner (System.in);
int h = 0;
int m = 0;
int count = 0;
char letter;
boolean r = false;
String tweet;
System.out.println("Please enter a tweet:");
tweet = scan.nextLine();
int length = tweet.length();
if (length <= 140)
{
while (count <= length)
{
letter = tweet.charAt(count);
if (letter == '#' &&
tweet.charAt(letter+1) != ' ')
{
h++;
}
if (letter == '#' &&
tweet.charAt(letter+1) != ' ')
{
m++;
}
if ((letter == 'r' || letter == 'R') &&
(tweet.charAt(letter + 1) == 't' || tweet.charAt(letter + 1) == 'T'))
{
r = true;
}
count ++;
}
System.out.println("Length Correct");
System.out.println("Number of Mentions: " + (m));
System.out.println("Number of Hashtags: " + (h));
if (r == true)
{
System.out.println("The input was a retweet.");
}
else if (r==false)
{
System.out.println("The input was not a retweet.");
}
}
if (length > 140)
{
System.out.println("Excess Characters: " + (length - 140));
}
}
}
Below is the cause of issue.
while (count <= length) {
and below is the fix
while (count < length) {

Java Binary search tree implementation

import java.util.Scanner;
import java.util.Stack;
public class Stack_1 {
public static void main(String[] args) {
String val;
Scanner input = new Scanner(System.in);
System.out.println("Enter Text: ");
val = input.nextLine();
push(val);
}
public static void push(String str) {
Stack<Character> stk = new Stack<Character>();
for (int i = 0; i < str.length(); i++) {
stk.push(str.charAt(i));
}
System.out.println(stk);
String reverseString = "";
String original = "";
int length = original.length();
for (int i = length - 1; i >= 0; i--)
reverseString = reverseString + original.toUpperCase().charAt(i);
if (original.toUpperCase().equals(stk))
System.out.println("The string is a palindrome.");
else if (reverseString.toUpperCase().equals(stk))
System.out.println("The string is not a palindrome.");
}
}
Can anyone help me out. I didn't know where I went wrong. The question was to create a stack (Character), and display the text where it is a palindrome or not. The user had to enter input.
P.S This was one of my lab test.
If I followed the code correctly, the problem appears to be that the OP is comparing a String object (either original or reverseString) to Stack<Character> object.
So, the probable failure is the incorrect attempted comparison of a String object to a Stack object.
I think there is a 2nd failure in the if/else if logic given that an example input of "cool" is not a palindrome, but no output is produced in such a case.
EDIT: while the OP code does attempt to adjust for the case of the entered data (not given in the question as to whether that is a requirement or not), it does not account for spaces or other punctuation. According to the entry on Wikipedia about Palindromes, punctuation is also usually ignored. Again, whether being concerned about spaces, periods, dashes, etc. was part of the exercise is not defined in the question. The question is a bit under specified in terms of full requirements.
I would think a solution using a stack would take a String, push it by character to a Stack (probably correcting for case and stripping out all punctuation at that time), and then do a comparison by popping from the Stack. I think the OP code is missing part of the requirement in using a Stack.
Example code to have only characters on the Stack. There are other approaches, of course:
// push by character onto the stack; use only
// characters, and convert to lower case
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if ( (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ) {
stk.push(Character.toLowerCase(c));
}
}
Example to remove all non characters from a check String:
// convert out comparison String to lower case and remove
// all non letters
String chk = str.toLowerCase().replaceAll("[^a-z]", "");
Example loop to use the Stack to check against the String:
// assume we have a palindrome
boolean palindrome = true;
// counter across the String
int i = 0;
// loop while there is more on the stack and we haven't
// failed our test
while (! stk.isEmpty() && palindrome) {
Character c = stk.pop();
palindrome = (c == chk.charAt(i++));
}
Sample Test Data:
cool is a palindrome: false
mom is a palindrome: true
Never odd or even is a palindrome: true
A man, a plan, a canal - Panama! is a palindrome: true

Check if input is one single letter (Java)

In my program, I get a user input (String):
ex:
String input = in.nextline();
I want to check (with an if-function) if the user/string has the following:
contains a letter (a-z / A-Z)
only contains one letter (A is valid, AA/AB/LWA is invalid)
so what goes on x/x2?
if(input.equals(x) && input.equals(x2){
//...
}
You can use a simple regex for that:
String input = in.nextline():
if (input.matches("[A-Za-z]{1}")) {
//valid input
}
else {
//invalid input
}
A solution that doesn't involve regular expressions (and, as such, can be easier understood) is simply:
check that the length of the String is 1, using String.length().
check that the first character is between 'a' and 'z' or between 'A' and 'Z', using String.charAt(index) and doing integer comparison on the ASCII value of the characters. This can be also simplified by lowercasing the character and checking that it is between 'a' and 'z' only.
A sample code would be:
private static boolean isValid(String str) {
if (str.length() != 1) return false;
char c = Character.toLowerCase(str.charAt(0));
return c >= 'a' && c <= 'z';
}
And you would use it like
String input = in.nextline();
if (isValid(input)) {
// do something wonderful
}
Using a regex should do the work:
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
if (input.matches("[A-z]")) {
System.out.println("Valid input");
}
else {
System.out.println("Wrong input");
}

Converting roman numerals to arabic

I'm new to Java and I need to write a program that converts roman numerals to arabic numbers.
I cannot use some functions because I'm not allowed to change the begging neither the end of the given code. I need to do everything inside the the public static void main function.
I started to search on Google and started to code. From now, I can convert only "one-letter" numerals (as X, I, V...) to arabic numbers but I cannot do this to more than elaborated numerals (XI, CCC, IX, IV...).
Can someone help me? I'm really new to Java. It's my first program language and I'm struggling to understand it.
Here is my code:
import java.util.Scanner;
class Roman {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int[] numbers = {1000, 500, 100, 50, 10, 5, 1 };
String symbols = "MDCLXVI";
/*******************************************
* Complete your program
*******************************************/
System.out.print("Enter a roman numeral");
final int MAX = 3999;
Scanner keyb = new Scanner(System.in);
String roman = keyb.next();
roman=roman.toUpperCase();
if(roman.matches(".*[0-9].*") || !roman.matches("[M|D|C|L|X|V|I]*")){
System.out.println("Impossible to convert. Wrong roman numeral");
}
int i = 0; //position in the string romain
int arabic = 0; // Arabic numeral equivalent of the part of the string that
// has been converted so far
int number;
while (i < roman.length()){
char letter = roman.charAt(i); // letter at the current position in the string
if (letter == 'I'){
number = 1;
} else if (letter == 'V'){
number = 5;
} else if (letter == 'X'){
number = 10;
} else if (letter == 'L'){
number = 50;
} else if (letter == 'C'){
number = 100;
} else if (letter == 'D'){
number = 500;
} else if (letter == 'M'){
number = 1000;
} else {
number = -1;
}
i++; // Move on to next position in the string
if (i==roman.length()){
// There is no letter in the string following the one we have just processed.
// So just add the number corresponding to the single letter to arabic.
arabic += number;
} else {
// Look at the next letter in the string. If it has a larger Roman numeral
// equivalent than number, then the two letters are counted together as
// a Roman numeral with value (nextNumber - number).
number = roman.charAt(i);
int nextNumber = number;
if(nextNumber > number){
// Combine the two letters to get one value, and move on to next position in string.
arabic += (nextNumber - number);
i++;
} else {
// Don't combine the letters. Just add the value of the one letter onto the number.
arabic += number;
}
}
System.out.println(number);
} // end while
/*******************************************
* Do not change after this line.
*******************************************/
}
}
I would suggest using an enumeration for your individual roman numerals. That makes the code nicely encapsulated.
public enum Roman {
I(1), V(5), X(10), L(50), C(100), D(500), M(1000);
private final int value;
private Roman(int value) {
this.value = value;
}
public int toInt() {
return value;
}
}
Converting a single roman numeral to an integer becomes trivial. For example:
Roman.valueOf("X").toInt();
The only complex bit is coping with "IX" and "XC" type of values. The easy way to identify these is that they are the only time when the numerals are not in descending order of value. Checking for this can be added as methods to the enum itself (to continue encapsulation):
public enum Roman {
public boolean shouldCombine(Roman next) {
return this.value < next.value;
}
public int toInt(Roman next) {
return next.value - this.value;
}
}
Now putting it all together:
List<Roman> romans = new ArrayList<>();
input.chars().mapToObj(Character::valueOf)
.map(Roman::valueOf).forEach(romans::add);
int value = 0;
while (!romans.isEmpty()) {
Roman current = romans.remove(0);
if (!romans.isEmpty() && current.shouldCombine(romans.get(0))
value += current.toInt(romans.remove(0));
else
value += current.ToInt();
}
The first part of this code uses Java 8 features to convert the string to roman numerals. Let me know if you find that confusing and I'll convert it to traditional iteration.
Here is one way to do it:
import java.util.Scanner;
class Roman {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int[] numbers = { 1000, 500, 100, 50, 10, 5, 1 };
String symbols = "MDCLXVI";
/*******************************************
* Complete your program
*******************************************/
System.out.print("Enter a roman numeral: ");
final int MAX = 3999;
Scanner keyb = new Scanner(System.in);
String roman = keyb.next();
keyb.close(); // don't want a resource leak
roman = roman.toUpperCase();
if (roman.matches(".*[0-9].*") || !roman.matches("[M|D|C|L|X|V|I]*")) {
System.out.println("Impossible to convert. Wrong roman numeral");
}
int i = 0; // position in the Roman string
int current = 0; // the current Roman numeral character to Arabic
// conversion
int previous = 0; // start previous at zero, that way when
// current is greater than previous in the first
// run, nothing will be subtracted from current
int arabic = 0; // Arabic numeral equivalent of the part of the string
// that has been converted so far
while (i < roman.length()) {
char letter = roman.charAt(i); // letter at the current position in
// the string
// switch statement is easier to read than if - else if - else
switch (letter) {
case ('I'):
current = 1;
break;
case ('V'):
current = 5;
break;
case ('X'):
current = 10;
break;
case ('L'):
current = 50;
break;
case ('C'):
current = 100;
break;
case ('D'):
current = 500;
break;
case ('M'):
current = 1000;
break;
}
if (current > previous) {
// subtract previous * 2 because previous was added to arabic
// once already
arabic += current - (previous * 2);
} else {
// if current is less than or equal to previous then add it to
// arabic
arabic += current;
}
previous = current; // set previous equal to current to check
// for less-than on next iteration
i += 1; // move on to next position in the string
} // end while
// print the Arabic conversion after the loop is done
System.out.println("Arabic: " + arabic);
/*******************************************
* Do not change after this line.
*******************************************/
}
}
In your code, the conditionals after i++ are not necessary since the while(i < roman.length()) conditional stops the loop once i >= roman.length().
Yet another way to do it: switch out the while loop with a for loop and a nested for loop. The outer for loop iterates over each character in the Roman numeral string. The inner for loop iterates over each character in the symbols string. If there is a match between the Roman numeral character and the symbols character, then current is set to the corresponding index in numbers and the inner loop breaks.
for(int i = 0; i < roman.length(); i++) {
for(int s = 0; s < symbols.length(); s++) {
if(roman.charAt(i) == symbols.charAt(s)) {
current = numbers[s];
break;
}
}
if (current > previous) {
// subtract previous * 2 because previous was added to arabic
// once already
arabic += current - (previous * 2);
} else {
// if current is less than or equal to previous then add it to
// arabic
arabic += current;
}
previous = current; // set previous equal to current to check
// for less-than on next iteration
}
This is "one look ahead" in Formal Languages. The only way to solve this problem is to compare position 0 to the next char. If value is less than, value is substracted from the acccumulator, if >=, it is added.

Categories

Resources