Java Vowel Counter Alternative Method - java

I'm writing a simple vowel-counter and was wondering if there's a cleaner alternative (possibly a loop?) to replace all of the else if's when comparing s to the various vowels.
I can't think of a simple way to do this effectively as the number of each vowel must be shown individually. It would be very simple if it was just a total vowel count.
I'm quite new to Java so I don't know what can be used to clean this up. If this is the best option, then I am contempt -- but I love cleaning up code where it can be!
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int A = 0, E = 0, I = 0, O = 0, U = 0;
System.out.print("Type a single word > ");
String word = input.next();
for (int i = 0; i < word.length(); i++) {
String s = word.substring(i, i + 1);
if (s.equalsIgnoreCase("A")) { A++; }
else if (s.equalsIgnoreCase("E")) { E++; }
else if (s.equalsIgnoreCase("I")) { I++; }
else if (s.equalsIgnoreCase("O")) { O++; }
else if (s.equalsIgnoreCase("U")) { U++; }
}
int total = A + E + I + O + U;
System.out.println("\n'" + word + "' has...\n" + A + " A's\n" + E + " E's\n" + I + " I's\n" + O + " O's\n" + U + " U's\nTotal vowels: " + total + "\n");
input.close();
}
}
Input:
Coding
Output:
'Coding' has...
0 A's
0 E's
1 I's
1 O's
0 U's
Total vowels: 2

Here is a less repetitive way to code it, using an int array for the counts, and a string holding the sequence of vowels.
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Type a single word > ");
String word = input.next();
String vowels = "AEIOU";
int[] counts = new int[vowels.length()];
int total = 0;
for (int i = 0; i < word.length(); i++) {
int index = vowels.indexOf(Character.toUpperCase(word.charAt(i)));
if (index >= 0) {
++counts[index];
++total;
}
}
System.out.printf("%n'%s' has...%n", word);
for (int i = 0; i < counts.length; ++i) {
System.out.printf("%s %s's%n", counts[i], vowels.charAt(i));
}
System.out.printf("Total vowels: %s%n", total);
}
}
Output:
Type a single word > Coding
'Coding' has...
0 A's
0 E's
1 I's
1 O's
0 U's
Total vowels: 2

You could avoid a lot of repetition by using a Map that associates vowels (keys) to their frequencies within the word passed at runtime (values).
It is worth noting that a LinkedHashMap is used in the below example as to preserve the insertion order of keys for printing at the end of the program - as would not be the case with a HashMap.
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// Define Map to map vowels to frequencies
Map<Character, Integer> vowels = new LinkedHashMap<Character, Integer>();
vowels.put('A', 0);
vowels.put('E', 0);
vowels.put('I', 0);
vowels.put('O', 0);
vowels.put('U', 0);
// Get input from user
System.out.print("Type a single word > ");
String word = input.next();
// Iterate across word
for (int i = 0; i < word.length(); i++) {
String c = word.substring(i, i+1); // Get current char
for (Character key : vowels.keySet()) { // Iterate across vowels
if (c.equalsIgnoreCase(key.toString())) {
vowels.put(key, vowels.get(key)+1); // Increment vowel frequency if matched
break; // Break inner loop and move to next char in word
}
}
// Sum total
int total = 0;
for (Character key : vowels.keySet()) {
total += vowels.get(key);
}
// Print results to console
System.out.println("\'" + word + "\'" + " has...");
for (Character key : vowels.keySet()) {
System.out.println(vowels.get(key) + " " + key + "\'s");
}
System.out.println("Total vowels: " + total);
input.close();
}
}
}

Related

How to remove one charachter from a string

With the scanner I want to read the index of a char and then remove it from the string. There is only one problem: If the char comes multiple times in the string, .replace() removes all of them.
For example I want to get the index of first 't' from the String "Texty text" and then remove only that 't'. Then I want to get index of second 't' and then remove it.
import java.util.Scanner;
class Main {
public static void main(String[] args) {
String text = "Texty text";
Scanner sc = new Scanner(System.in);
int f = 0;
int x = 0;
while(f<1){
char c = sc.next().charAt(0);
for(int i = 0; i<text.length();i++){
if(text.charAt(i)==c){
System.out.println(x);
x++;
}
else{
x++;
}
}
}
System.out.println(text);
}
}
You could use replaceFirst:
System.out.println(text.replaceFirst("t", ""));
Probably you are looking for something like the following:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
String text = "Texty text";
String copy = text;
Scanner sc = new Scanner(System.in);
while (true) {
text = copy;
System.out.print("Enter a character from '" + text + "': ");
char c = sc.next().charAt(0);
for (int i = 0; i < text.length(); i++) {
if (Character.toUpperCase(text.charAt(i)) == Character.toUpperCase(c)) {
System.out.println(c + " was found at " + i);
text = text.substring(0, i) + "%" + text.substring(i + 1);
System.out.println("After replacing " + c + " with % at " + i + ": " + text);
}
}
}
}
}
A sample run:
Enter a character from 'Texty text': x
x was found at 2
After replacing x with % at 2: Te%ty text
x was found at 8
After replacing x with % at 8: Te%ty te%t
Enter a character from 'Texty text': t
t was found at 0
After replacing t with % at 0: %exty text
t was found at 3
After replacing t with % at 3: %ex%y text
t was found at 6
After replacing t with % at 6: %ex%y %ext
t was found at 9
After replacing t with % at 9: %ex%y %ex%
Enter a character from 'Texty text':
Try using txt.substring(x,y)
x = usually 0 , but x is first start index
y = this is what you want to delete for example for the last word of string write this code:
txt.substring(0, txt.length() - 1)
Since you are specifying indices, it is possible that you may want to replace the second of a particular character. This does just that by ignoring the ones before it. This returns an Optional<String> to encase the result. Exceptions are thrown for appropriate situations.
public static void main(String[] args) {
// Replace the first i
Optional<String> opt = replace("This is a testi", 1, "i", "z");
// Replace the second i (and so on).
System.out.println(opt.get());
opt = replace("This is a testi", 2, "i", "z");
System.out.println(opt.get());
opt = replace("This is a testi", 3, "i", "z");
System.out.println(opt.get());
opt = replace("This is a testi", 4, "i", "z");
System.out.println(opt.get());
}
public static Optional<String> replace(String str, int occurrence, String find, String repl) {
if (occurrence == 0) {
throw new IllegalArgumentException("occurrence <= 0");
}
int i = -1;
String strCopy = str;
while (occurrence-- > 0) {
i = str.indexOf(find, i+1);
if (i < 0) {
throw new IllegalStateException("insufficient occurrences of '" + find + "'");
}
}
str = str.substring(0,i);
return Optional.of(str + strCopy.substring(i).replaceFirst(find, repl));
}

How can I get my for each loop to print once for each number in the array

assignment:
Write a program that reads in integers between 1 and 100 from the user and counts the
occurrences of each number. The user input ends when they enter a 0.
You must use an enhanced for-loop to solve this problem.
If a number occurs more than 1 time use the plural word “times” instead of “time”. Do not display numbers that were not entered.
I know and understand why my code's current output below appears with duplicates. The print logic is inside the for-each loop code block. If I close the code block I am no longer able to use the variables I initialized inside the loop. I have tried everything I can think of. Any suggestions would be appreciated
current output:
- 1 occurs 1 time,
- 1 occurs 2 times
- 2 occurs 1 time
- 2 occurs 2 times
- 3 occurs 1 time
- 3 occurs 2 times
needed output:
- 1 occurs 2 times
- 2 occurs 2 times
- 3 occurs 2 times
package com.company;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int[] numbers = new int[10];
System.out.print("Enter Integers:");
for (int i = 0; i < numbers.length; i++) {
numbers[i] = in.nextInt();
if (numbers[i] == 0) {
break;
}
}
enhancedLoop(numbers);
}
private static void enhancedLoop(int[] numbers) {
int[] counts = new int[101];
for (int value : numbers) {
counts[value]++;
if (value > 0)
if (counts[value]> 1)
System.out.println(value + " occurs " + counts[value]+ " times");
else
System.out.println(value + " occurs " + counts[value] + " time");
}
}
Variables are only available in the block in which they are declared. Move the output after the for loop and iterate over counts to display the values:
for (int i = 0, c = counts.length; i < c; ++i) {
if (counts[i] > 0) {
if (counts[i] > 1) {
System.out.println(value + " occurs " + counts[i]+ " times");
} else {
System.out.println(value + " occurs " + counts[i]+ " time");
}
}
}
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int[] numbers = new int[10];
System.out.print("Enter Integers:");
for (int i = 0; i < numbers.length; i++) {
numbers[i] = in.nextInt();
if (numbers[i] == 0) {
break;
}
}
enhancedLoop(numbers);
}
private static void enhancedLoop(int[] numbers) {
int[] counts = new int[101];
for (int value : numbers) {
counts[value]++;
if (value > 0)
if (counts[value]> 1)
System.out.println(value + " occurs " + counts[value]+ " times");
else
System.out.println(value + " occurs " + counts[value] + " time");
}
}
You can do this effectively using the below steps:
(1) Identify the unique numbers first
(2) Find the number of times each unique number occurs
So, you need to change your enhancedLoop(int[] numbers) method as shown below to achieve the result:
private static void enhancedLoop(int[] numbers) {
//convert the array to a list to make computations easier by using streams
List<Integer> numbersList = Arrays.stream(numbers).boxed().collect(Collectors.toList());
//Get the unique numbers in the list
List<Integer> uniqueNumbers = numbersList.stream().distinct().collect(Collectors.toList());
//Now find out number of times each each unique number occured
for(int number : uniqueNumbers) {
long times = numbersList.stream().filter(num -> num == number).count();
System.out.println(number+" occurs "+times);
}
}
lets try to do this without lamdas, using simply a hashmap instead of arrays
import java.util.Scanner;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
HashMap<Integer, Integer> numbers = new HashMap<Integer, Integer>();
int tmp=0;
System.out.print("Enter Integers:");
//read a maximum of 10 int
for (int i = 0; i < 10; i++) {
tmp = in.nextInt();
//if we read a 0 we quit
if (tmp == 0) {
break;
}
//if we already saw the number we up the counter
if(numbers.containsKey(tmp)){
numbers.put(tmp, numbers.get(tmp)+1);
}else{
//otherwise we just add the new int
numbers.put(tmp, 1);
}
}
//call the print loop
enhancedLoop(numbers);
}
private static void enhancedLoop(HashMap<Integer, Integer> numbers) {
//you print what you counted
for(Map.Entry<Integer, Integer> entry : numbers.entrySet()) {
System.out.print(entry.getKey() + " occurs " + entry.getValue() + " time");
if (entry.getValue()>1)
System.out.print("s");
System.out.println("");
}
}

Concat String in a for loop

I'm trying to create a program that takes each number typed in by the user and sort them out as even, odd and the number zero values.
The result should look like something like this:
User Input: 14005
Output:
Even Numbers: 4
Odd Numbers: 1, 5
Zero's: 0, 0
This is the code I've written, I thought of using string concatination in order to add a new value each time the loop checks for the next character, don't know whether I'm thinking right or not though, would appriciate if someone could tell me where I'm thinking in the wrong way.
package com.craydesign;
import javax.swing.JOptionPane;
public class Main {
public static void main(String[] args) {
String number = JOptionPane.showInputDialog("Please enter a number: ");
String evenNumbers = "";
String oddNumbers = "";
String numberZero = "";
for(int i = 0; i < number.length(); i++) {
if(number.charAt(i) % 2 == 0) {
evenNumbers.concat(Integer.toString(i) + ", ");
} else if(number.charAt(i) % 2 != 0) {
oddNumbers.concat(Integer.toString(i) + ", ");
} else if (number.charAt(i) == 0){
numberZero.concat(Integer.toString(i) + ", ");
}
}
JOptionPane.showMessageDialog(null, "Even numbers: " + evenNumbers + "\n" + "Odd numbers: " + oddNumbers + "\n" + "Zero's: " + numberZero);
}
}
use Character.getNumericValue() instead of charAt(i)
public static void main(String[] args) throws IOException
{
String number = JOptionPane.showInputDialog("Please enter a number: ");
StringBuffer evenNumbers = new StringBuffer();
StringBuffer oddNumbers =new StringBuffer();
StringBuffer numberZero =new StringBuffer();
for(int i = 0; i < number.length(); i++) {
int value=Character.getNumericValue(number.charAt(i));
if(value!=0 && value % 2 == 0) {
evenNumbers.append(value).append(',');
} else if(value % 2 != 0) {
oddNumbers.append(value).append(',');
} else if (value == 0){
numberZero.append(value).append(',');
}
}
JOptionPane.showMessageDialog(null, "Even numbers: " + evenNumbers + "\n" + "Odd numbers: " + oddNumbers + "\n" + "Zero's: " + numberZero);
}
EDIT:(displaying numbers in sorted order)
String evenNo[]=evenNumbers.toString().split(",");
String oddNo[]=oddNumbers.toString().split(",");
Arrays.sort(evenNo);
Arrays.sort(oddNo);
JOptionPane.showMessageDialog(null, "Even numbers: " + Arrays.toString(evenNo) + "\n" + "Odd numbers: " + Arrays.toString(oddNo) + "\n" + "Zero's: " + Arrays.toString(numberZero.toString().substring(0,
numberZero.length()-1).split(",")));
You are using String for output and appending the output in the string.
Its a bad idea. as String class is immutable so if you do change anything in String it will create a new Object in memory.
So your solution will take extra memory.
Accroding to me you can solve this problem in two ways
Use StringBuffer class instead of String class for appending
Use ArrayList to Store your result. and iterate over the arraylist and show the output as you want.
Thanks,
Aman

How to record array of ints, and print frequency of duplicates

Note: Just a practice problem, not for marks.
This is a practice problem given in a first year Java course:
Design and implement an application that reads an arbitrary number of integers, by the user, that are in the range 0 to 50 inclusive, and counts how many occurrences of each are entered. After all the input has been processed, print all of the values (with the number of occurrences) that were entered one or more times.
In addition, write a method that returns no value which would compute the average of the occurrences of all numbers entered by the user.
This is what I have (I have skipped the "average occurrence" part until I clean this up):
import java.util.Scanner;
public class Main
{
public static Scanner scan = new Scanner(System.in);
public static int[] userIntegers() // this method will build the array of integers, stopping when an out-of-range input is given
{
System.out.println("Enter the number of integers to be recorded: ");
int numInts = scan.nextInt();
int[] userArray = new int[numInts];
int i = 0;
while(i < numInts)
{
System.out.println("Enter an integer between 1-50 inclusive: ");
int userInteger = scan.nextInt();
if(isValidInteger(userInteger))
{
userArray[i] = userInteger;
i++;
}
else if(isValidInteger(userInteger) == false)
{
System.out.println("Try again.");
}
}
return userArray;
}
public static void occurrenceOutput(int[] input) // this method will print the occurrence data for a given array
{
int[] occurrenceArray = new int[51];
int j = 0;
while(j < 51) // iterates through all integers from 0 to 50, while the integer in the array is equal to integer j, the corresponding occurance array element increments.
{
for(int eachInteger : input)
{
occurrenceArray[j] = (eachInteger == j)? occurrenceArray[j]+=1: occurrenceArray[j];
}
j++;
}
int k = 0;
for(int eachOccurrence : occurrenceArray) // as long as there is more than one occurrence, the information will be printed.
{
if(eachOccurrence > 1)
{
System.out.println("The integer " + k + " occurrs " + eachOccurrence + " times.");
}
k++;
}
}
public static boolean isValidInteger(int userInput) // checks if a user input is between 0-50 inclusive
{
boolean validInt = (51 >= userInput && userInput >= 0)? true: false;
return validInt;
}
public static void main(String[] args)
{
occurrenceOutput(userIntegers());
}
}
Can someone point me in a more elegant direction?
EDIT: Thanks for the help! This is where I am at now:
import java.util.Scanner;
public class simpleHist
{
public static void main(String[] args)
{
getUserInputAndPrint();
getIntFreqAndPrint(intArray, numberOfInts);
}
private static int numberOfInts;
private static int[] intArray;
private static int[] intFreqArray = new int[51];
public static void getUserInputAndPrint()
{
// The user is prompted to choose the number of integers to enter:
Scanner input = new Scanner(System.in);
System.out.println("Enter the number of Integers: ");
numberOfInts = input.nextInt();
// The array is filled withchInteger = integer; integers ranging from 0-50:
intArray = new int[numberOfInts];
int integer = 0;
int i = 0;
while(i < intArray.length)
{
System.out.println("Enter integer value(s): ");
integer = input.nextInt();
if(integer > 50 || integer < 0)
{
System.out.println("Invalid input. Integer(s) must be between 0-50 (inclusive).");
}
else
{
intArray[i] = integer;
i++;
}
}
// Here the number of integers, as well as all the integers entered are printed:
System.out.println("Integers: " + numberOfInts);
int j = 0;
for(int eachInteger : intArray)
{
System.out.println("Index[" + j + "] : " + eachInteger);
j++;
}
}
public static void getIntFreqAndPrint(int[] intArray, int numberOfInts)
{
// Frequency of each integer is assigned to its corresponding index of intFreqArray:
for(int eachInt : intArray)
{
intFreqArray[eachInt]++;
}
// Average frequency is calculated:
int totalOccurrences = 0;
for(int eachFreq : intFreqArray)
{
totalOccurrences += eachFreq;
}
double averageFrequency = totalOccurrences / numberOfInts;
// Integers occurring more than once are printed:
for(int k = 0; k < intFreqArray.length; k++)
{
if(intFreqArray[k] > 1)
{
System.out.println("Integer " + k + " occurs " + intFreqArray[k] + " times.");
}
}
// Average occurrence of integers entered is printed:
System.out.println("The average occurrence for integers entered is " + averageFrequency);
}
}
You are actually looking for a histogram. You can implement it by using a Map<Integer,Integer>, or since the range of elements is limited to 0-50, you can use an array with 51 elements [0-50], and increase histogram[i] when you read i.
Bonus: understanding this idea, and you have understood the basics of count-sort
To calculate occurences, you can do something like this:
for(int eachInteger : input) {
occurrenceArray[eachInteger]++;
}
This will replace your while loop.

Printing Two Dimensional Array in Special Format

I am working in a small task that allow the user to enter the regions of any country and store them in one array. Also, each time he enters a region, the system will ask him to enter the neighbours of that entered region and store these neighbours.
I did the whole task but I have a small problem:
I could not be able to print each region and its neighbours like the following format:
Region A: neighbour1 neighbour2
Region B: neighbour1 neighbour2
For example, let us take USA map. I want to print the result as following:
Washington D.C: Texas, Florida, Oregon
and so on.
My code is:
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
public class Test7{public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
System.out.print("Please enter the number of regions: ");
int REGION_COUNT = kb.nextInt();
String[] regionNames = new String[REGION_COUNT];
String[][] regions = new String[REGION_COUNT][2];
for (int r = 0; r < regions.length; r++) {
System.out.print("Please enter the name of region #" + (r + 1)
+ ": ");
regionNames[r] = kb.next();
System.out
.print("How many neighbors for region #" + (r + 1) + ": ");
if (kb.hasNextInt()) {
int size = kb.nextInt();
regions[r] = new String[size];
for (int n = 0; n < size; n++) {
System.out.print("Please enter the neighbour #" + (n)
+ ": ");
regions[r][n] = kb.next();
}
} else
System.exit(0);
}
for (int i = 0; i < REGION_COUNT; i++) {
System.out.print(regionNames[i] +": ");
for (int k = 0; k < 2; k++) {
System.out.print(regions[i][k]+", ");
}
System.out.println();
}
}
}
The code works fine but the problem is with printing the result only.
Also, I should use the 2 dimensional array.
As I see it, you think your problem is dealing with a jagged 2-D array. I think your problem is that you're using arrays of strings in the first place. I'd suggest using a class to model your regions and their neighbors rather than an array of strings.
public class Region
{
private String Name;
public void setName( String name ) {
this.Name = name;
}
public String getName() {
return this.Name;
}
private ArrayList<Region> Neighbors;
public void addNeighbor( Region neighbor ) {
...
}
public ArrayList<Region> getNeighbors()
{
...
}
}
Then keep a hash of the known regions, creating new ones as necessary, and use those to populate a region's neighbors as needed. Then you can iterate over the regions in your hash and, for each region, iterate over its neighbors.
This is what you want:
for (int i = 0; i < region.length; i++){
StringBuilder sb = new StringBuilder();
sb.append(region[i] + ": ");
for (int i2 = 0; i2 < neighbor.length; i2++){
if (i2 != 0 && i2 != neighbor.length-1){
sb.append(", " + neighbor[i2]);
}else{
sb.append(neighbor); //it still need a validation of an array of 2 Strings
}
}
System.out.println(sb.toString());
}

Categories

Resources