As part of a homework assignment, we are supposed to create an array that will resize itself if the user attempts to input more data to a new index that is out of bounds. We are not allowed to use any libraries like hashsets, arraylists, etc. My code works, however, the length of the array always ends up being one larger than what is required. I know the problem lies in the nature of the while loop because it will grow and then add, but I don't know how I would fix it.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Scanner;
public class DynamicArray
{
public static void main(String[] args)
{
Scanner kb = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
System.out.print("Enter a desired length for an array: ");
String[] x = new String[kb.nextInt()];
int index = 0;
System.out.print("Enter as many Strings as desired, separated by a new line. Type in \"end\" to print out the contents of the array.");
String input = kb.nextLine();
while(!input.equalsIgnoreCase("end"))
{
if (index < x.length)
{
x[index] = input;
}
else
{
String[] temp = new String[x.length + 1];
for (int i = 0; i < x.length; ++i)
{
temp[i] = x[i];
}
temp[index] = input;
x = temp;
}
++index;
input = kb.nextLine();
}
for (int i = 0; i < x.length; ++i)
{
System.out.println(x[i]);
}
System.out.println(x.length);
}
}
I know the problem lies in the nature of the while loop because it will grow and then add […]
Not at all. The problem lies in the way Scanner.nextInt() and Scanner.nextLine() work. Scanner.nextInt() will read in an integer, but will not swallow the newline after the integer. So the first thing Scanner.nextLine() sees is that newline, and it thinks it sees an empty line, which is what it returns. So x[0] is a the empty string.
You can see this a bit more clearly if you change this:
System.out.println(x[i]);
to this:
System.out.println(i + ": " + x[i]);
because then you'll see that the first thing it prints is 0:.
By the way, your approach in general is very inefficient, since it requires creating many more arrays than are actually needed. Instead of increasing the size of the array by one, it's much more efficient to double the size of the array, and keep track of its length separately (rather than using x.length). (Admittedly, in your case, efficiency is probably a non-issue, since you're taking input from the user, and there's no way that the user will type in elements anywhere near as fast as Java can copy the array; but in general, that's the best way to design a dynamically-resizeable array.)
Related
I recently got into Java Programming (Maybe it's already getting too hard for me), and I'm doing some exercises daily to practise. One of the challenges I need to do, is to search an Element (int), and if it's in the Array, the Index should be displayed (All index's should be displayed if Element duplicates found in Array).
Here's the code I have so far!
import java.util.ArrayList;
import java.util.Scanner;
public class IndexOf {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayList<Integer> list = new ArrayList<>();
while (true) {
int input = Integer.valueOf(scanner.nextLine());
if (input == -1) {
break;
}
list.add(input);
}
System.out.println("");
// implement here finding the indices of a number
System.out.println("Search for?");
int arraySize = list.size();
int numToSearch = Integer.valueOf(scanner.nextLine());
for(int i = 0; i <arraySize-1; i++){
int pos = list.indexOf(numToSearch);
if(list.indexOf(i)==pos){
System.out.print(numToSearch+" is at Index: "+pos);
}
}
}
}
So far I've managed to get it to print the Index of the Element I search for, but it only does it for the first correct Index it finds.
Sorry for the clunky code, haven't yet learnt much in terms of neat code!
In the last loop, you were checking the equality between the index of numToSearch in list and the index of 0...arraySize-2 in list. Unless I am understanding the question incorrectly, the correct approach should be checking the equality of each array member and numToSearch. Then print out the string with the current index you are at.
This could be represented like this:
for (int i = 0; i < arraySize; i++) {
if (list.get(i) == numToSearch) {
System.out.println(numToSearch + " is at Index: " + i);
}
}
I know similar questions have been asked. I've read through them and have developed what I thought was a reasonable solution to my problem. However, when I run the code it does not perform as I think it should. I'm obviously missing something here.
I need to read in a string (a propositional logic statement) and determine how many variables it has. My thought process is: convert the string to a charArray and compare the elements. If a certain element is a letter AND is not equal to another element in the array, it is a new variable, thus adding to the variable count, and also needs to be stored in a separate array for later use.
public class PropLogic {
public static void main(String[] args) {
Scanner stdin = new Scanner(System.in);
String statement;
int numOfVariables = 0;
System.out.println("Enter your propositional statement:");
statement = stdin.nextLine();
char[] charStatement = statement.toCharArray();
char[] variables;
variables = new char[25];
// Counts number of variables in statement
for (int i = 0; i < statement.length(); i++){
for(int j = i + 1; j < statement.length(); j++){
if(Character.isLetter(charStatement[i]) && (charStatement[i] !=
charStatement[j])){
variables[i] = charStatement[i];
numOfVariables++;
}
}
}
System.out.println("The number of variables is " + numOfVariables);
System.out.println("The variables are " + new String(variables));
}}
With input "hello" I get output of 9 variables and that the variables are "hell" when I want to be getting 4 variables that are "hello".
Why don't you use a Set. A set has the property that you can enter the same object only once into it. Here is one version:
Set<Character> set = new LinkedHashSet<>();
for(int i = 0; i< statement.length(); i++) {
set.add(statement.charAt(i));
}
System.out.println("The number of variables is " + set.size());
System.out.println("The variables are ");
set.forEach(System.out::println);
You don't need to use char array since String has the methods CharAt() and contains().
Then you have to run through your String. When you find a new letter (which mean this letter is not in the already found array), you put it in the already found array and you increment your counter. (note that the counter is useless since it as the same value as the length of the already found array). You should obtain something like this :
String statement = stdin.nextLine();
String variables = ""; //empty String
//Go through the whole String statement
for (int i = 0; i < statement.length(); i++){
//Check if this letter was not already found and it's a letter
if(!variables.contains(statement.charAt(i)) && Character.isLetter(statement.charAt(i)) ){
//Add this letter to the found ones
variables.concat(String.valueOf(statement.charAt(i)));
}
}
System.out.println("The number of variables is " + variables.length());
System.out.println("The variables are " + variables);
I see two problems:
Problem 1. Think about what happens, for example, with the "h" of "hello." You compare it, in turn, to "e", "l", "l", and "o", and for each of them, you add a new variable. What you want is to add a new variable only if ALL of the future letters are not equal to the "h." This is why you are getting 9 variables total: you add one for each of the following comparisons:
(h, e), (h, l), (h, l), (h, o)
(e, l), (e, l), (e, o)
(l, o)
(l, o)
This is also why you are getting "hell" as your final variables array. The o is never compared to anything, so never gets added to the array.
What you really want to do is go through the entire rest of the string, and check if anything is equal to the current letter. You can do this with a boolean flag. Here is pseudocode:
for i = 0 to len(charArray):
isNewVariable = isLetter(charArray[i])
for j = i+1 to len(charArray):
if charArray[i] == charArray[j]:
isNewVariable = false
if isNewVariable:
Add charArray[i] to variables
Problem 2. You are filling in the wrong index of your variables array. You want to fill in variables[numOfVariables], not variables[i]. Let's say the first and seventh letters are variables; then you want variables[0] and variables[1] to be set to the two variables, not variables[0] and variables[6], which is what your current code does.
Hope this helps! If you fix these two errors, your code will work; however, as other answers point out, this general strategy is not the best for this specific task. Incrementally adding to an array (like variables) is best done with an ArrayList; even better, a Set is exactly suited for the task of finding just the unique elements of an array.
what is happening here is, check if char exists in temp string with 'temp.indexOf(char)', it returns 1 if it exists at an index of that string and 0 otherwise.
so if 0, then add and loop to next char.
public static void main( String[] args ){
Scanner stdin = new Scanner(System.in);
String statement;
int numOfVariables = 0;
System.out.println("Enter your propositional statement:");
statement = stdin.nextLine();
char[] charStatement = statement.toCharArray();
char[] variables;
variables = new char[25];
String temp = "";
for (int i = 0; i < statement.length(); i++){
char current = statement.charAt(i);
if (temp.indexOf(current) < 0){
temp = temp + current;
}
}
System.out.println("The number of variables is " + temp.length());
System.out.println("The variables are " + temp);
}
A key to success in writing good programs is to make sure it has as few lines of code as possible and it doesn't repeat an operation that it has already performed or that is not even needed.
If you think about your problem statement, basically, all you need to do is extract letters from a given input string and remove duplicates. With advance programming languages like Java, String operations shouldn't take more than a couple of lines of codes. If it is more than 2 lines, in most cases, it has a lot of boiler plate code.
See if the following line of code meets your objective.
Set<String> variables = Arrays.stream(statement.split("")).filter(str -> Character.isLetter(str.charAt(0))).collect(Collectors.toSet());
If you are OK with not insisting on char[] variables and use List<Character> instead, this does the job
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class PropLogic {
public static List<Character> parseVariables(char[] input) {
List<Character> candidates = new ArrayList<>();
for (int i = 0; i < input.length; i++){
Character c = input[i];
if( Character.isLetter(c) && !candidates.contains(c)) {
candidates.add(c);
}
}
return candidates;
}
public static void main(String[] args) {
Scanner stdin = new Scanner(System.in);
System.out.println("Enter your propositional statement:");
char[] charStatement = stdin.nextLine().toCharArray();
List<Character> variables = parseVariables(charStatement);
System.out.println("The number of variables is " + variables.size());
System.out.println("The variables are " + variables);
}
}
Sample output:
Enter your propositional statement:
hello1
The number of variables is 4
The variables are [h, e, l, o]
Here's a 1-liner:
String[] variables = statement.replaceAll("[^a-z]|(.)(?=.*\\1)", "").split("(?<=.)");
This uses regex to remove (by replacing with a blank) all non-lowercase letters OR all letters that are repeated later on (ie remove dupes).
Then it splits after each letter giving you the final array of unique letters from the input.
Note that this creates a String[] rather than a char[], which you can just as easily use. If you really want a char[], you can do this:
String[] variables = statement.replaceAll("[^a-z]", "").chars()
.distinct().mapToObject(c -> (char)c).toArray();
I am learning about arrays and I did quiet a few experiments, most of them went well, however now I'm stuck.
What I want to archive is, find if an specific value (String, int or whatever), exists inside an Array and if it does, use that value for something i.e the code below which I basically count how many times that value was present inside the array:
package arraysOnly;
import java.util.*;
public class ArrayContainsString
{
public static void main(String[]args)
{
Scanner sc = new Scanner(System.in);
int arraySize = 0;
int wordCount = 0;
System.out.println("How many words are you gonna type?: ");
arraySize = sc.nextInt();
String[] words = new String[arraySize]; // Simple array, the size of which will be decided from the user-input
for(int count = 0; count < arraySize; count++)
{
System.out.println("Enter your " + (count+1) + ": ");
words[count] = sc.next();
}
//Basically this is the part I'm having troubles
if(in_array("ubt", $words)
{
wordCount++;
}
}
}
I know about this,
if(Arrays.asList(words).contains("ubt"));
which basically converts the array into an List / ArrayList or whatever, however I want to treat this as an array only if possible.
An array is the wrong data structure; a Set is the weapon of choice:
Set<String> words = new HashSet<>()
for (int count = 0; count < arraySize; count++) {
System.out.println("Enter your " + (count+1) + ": ");
words.add(sc.next());
}
if (words.contains("ubt"))
wordCount++;
}
The contains() method of a HashSet completes in constant time not matter how large the set is. Although performance is irrelevant for small input sizes like this usage, it's good to get in the habit of choosing the right tools for the job. It also makes your code cleaner.
Generally speaking, don't use arrays unless you absolutely have to; they are only rarely used in commercial code.
The simple solution
public static boolean contains(String toFind, String[] strings) {
for (String str : strings) {
if (str.equals(toFind)) return true;
}
return false;
}
EDIT:
To increase it after the user inputs a word, use this in the loop:
System.out.println("Enter your " + (count+1) + ": ");
words[count] = sc.next();
if (words[count].equals("ubt")) wordCount++;
You can just iterate over array
for (String str : array){
if(str.equals("ubt")){
wordCount++;
}
}
Edit:
It's just equivalent to a normal for loop
for(int i=0; i<array.length; i++) {
if(array[i].equals("ubt")){
wordCount++;
}
}
I'm trying to make a "for" loop in which it asks the user to input 10 numbers and then only print the positives.
Having trouble controlling the amount of inputs. I keep getting infinite inputs until I add a negative number.
import java.util.Scanner;
public class ej1 {
public static void main(String args[]) {
int x;
for (x = 1; x >= 0; ) {
Scanner input = new Scanner(System.in);
System.out.print("Type a number: ");
x = input.nextInt();
}
}
}
From a syntax point of view, you've got several problems with this code.
The statement for (x = 1; x >= 0; ) will always loop, since x will always be larger than 0, specifically because you're not introducing any kind of condition in which you decrement x.
You're redeclaring the scanner over and over again. You should only declare it once, outside of the loop. You can reuse it as many times as you need.
You're going to want to use nextLine() after nextInt() to avoid some weird issues with the scanner.
Alternatively, you could use nextLine() and parse the line with Integer.parseInt.
That said, there are several ways to control this. Using a for loop is one approach, but things get finicky if you want to be sure that you only ever print out ten positive numbers, regardless of how many negative numbers are entered. With that, I propose using a while loop instead:
int i = 0;
Scanner scanner = new Scanner(System.in);
while(i < 10) {
System.out.print("Enter a value: ");
int value = scanner.nextInt();
scanner.nextLine();
if (value > 0) {
System.out.println("\nPositive value: " + value);
i++;
}
}
If you need to only enter in ten values, then move the increment statement outside of the if statement.
i++;
if (value > 0) {
System.out.println("\nPositive value: " + value);
}
As a hint: if you wanted to store the positive values for later reference, then you would have to use some sort of data structure to hold them in - like an array.
int[] positiveValues = new int[10];
You'd only ever add values to this particular array if the value read in was positive, and you could print them at the end all at once:
// at the top, import java.util.Arrays
System.out.println(Arrays.toString(positiveValues));
...or with a loop:
for(int i = 0; i < positiveValues.length; i++) {
System.out.println(positiveValues[i]);
}
Scanner scan = new Scanner(System.in);
int input=-1;
for(int i=0;i<10;i++)
{
input = sc.nextInt();
if(input>0)
System.out.println(input);
}
Sorry if this is an obvious problem.
I'm trying to read integers from users and store them in an array.
The thing is that I want to use arraylist, because the size of the input is not for sure
If I know the size then I know a way to do that, which is
class Test1
{
public static void main(String[] args)
{
Scanner reader = new Scanner(System.in);
System.out.println("Please input your numbers");
int num; // integer will be stored in this variable
ArrayList<Integer> List = new ArrayList<Integer>();
// for example if I know the size of the input is 5,
// then I read one single number and put it into the arraylist.
for (int i = 0; i <= 4; i++)
{
num = reader.nextInt();
List.add(num);
}
System.out.println(List);
}
}
How to do this if I don't know the size?
Except for reading one number in each loop, is there any better way to do that?
Can I use BufferedReader instead of Scanner?
Thanks a lot for any help!
You could change this
for (int i = 0; i <= 4; i++)
{
num = reader.nextInt();
List.add(num);
}
to use Scanner.hasNextInt() with something like
while (reader.hasNextInt())
{
num = reader.nextInt();
List.add(num);
}
You cannot instanciate an array if you do not know its size.
Therefore your approach is the correct one: start with an ArrayList and when done adding to it, you can convert it to an array.
You can use the hasNextInt() in a while loop to keep going until there are no more numbers to read.
while (reader.hasNextInt()) {
List.add(reader.nextInt());
}