Java: Possible to use a single for-loop instead of two? - java

My code is as below. It first takes input from user and prints it in reverse. I'm new to Java. I achieve this by using two 'for loops' to first iterate through the input and another for-loop to print the numbers in reverse. My question is if there's any way to improve my code - by using just a single loop perhaps? Any suggestion is appreciated. Thank you.
public static void main (String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int arr[] = new int[n];
for (int arr_i = 0; arr_i < n; arr_i++) {
arr[arr_i] = in.nextInt();
}
for (int reverse_i = n-1; reverse_i >= 0; reverse_i--) {
System.out.print(arr[reverse_i]);
if (reverse_i != 0) {
System.out.print(" ");
}
}
}
An example input:
4
1 2 3 4
Expected output:
4 3 2 1

Use a StringBuilder and always insert at 0 index.
See: Oracle » JavaDocs » 1.7 » java.lang.StringBuilder.insert(int, int)
StringBuilder bld = new StringBuilder();
for (int arr_i = 0; arr_i < n; arr_i++) {
int i = in.nextInt();
bld.insert(0, i);
}
System.out.println(bld.toString());

The simplest approach I found is to use String Builder here:
Scanner in = new Scanner(System.in);
StringBuilder stringBuilder = new StringBuilder();
while (in.hasNext()) {
stringBuilder.append(in.next());
if(in.hasNext()) {
stringBuilder.append(" ");
}
}
System.out.print(stringBuilder.reverse());

First, you might reverse your elements as you insert them in the array. Then, assuming you are using Java 8+, you could use an IntStream instead of a loop and print with a basic Collector. Like,
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] arr = new int[n];
IntStream.range(0, n).forEachOrdered(i -> arr[n - i - 1] = in.nextInt());
System.out.println(IntStream.of(arr).mapToObj(String::valueOf)
.collect(Collectors.joining(" ")));

I am not sure about the requirements of your request, but you do not necessarily have to use an array for this. You can concatenate the inputs into a String in reverse order like so.
public static void main(String[] args) {
System in = new Scanner(System.in);
int n = in.nextInt();
String allNumbers = "";
for (int i = 0; i < n; i++) {
int current = in.nextInt();
allNumbers = current + " " + allNumbers;
}
if(allNumbers != ""){
allNumbers = allNumbers.substring(0,allNumbers.length()-1);
}
System.out.println(allNumbers);
}

Java has inbuilt String method for the same. If your input is a String, you can use the below-
String s1 = new String("new");
String s2 = s1.reverse();
System.out.println(s2) // wen

Related

Java Stdin Cannot convert from String[] to String, but inputs are String?

I am doing a programming assignment that takes all of its input from stdin. The first input is an int n to tell you how many strings will follow, and the next n inputs are strings of varying lengths. The goal is to find the longest string(s) and print them.
I thought this was easy, but for the life of me, I cannot get the stdin to work with me. The eclipse arguments entered are (separated by enter):
3
a2
b3c
7
Yet I run the program, and it tells me it cannot convert from String[] to String. I do not understand how any of the above are String[]. The code is below:
import java.util.Scanner;
public class A2P1 {
public static void main(String[] args) {
int size = Integer.parseInt(args[0]);
String[] str = new String[size];
Scanner sc = new Scanner(System.in);
for (int i=0; i < size; i++) {
str[i] = sc.nextLine().split(" "); // The error
//str[i] = sc.next(); This line and the line below throw
//str[i] = sc.nextLine(); no errors, but also gives no output.
}
String[] longest = new String[size];
String[] temp = new String[size];
longest[0] = str[0];
int numToBeat = str[0].length();
int k = 0;
for (int i=0; i < size; i++) {
if (str[i].length() > numToBeat) {
numToBeat = str[i].length();
k = 0;
longest = temp;
longest[k] = str[i];
k++;
}
else if (str[i].length() == numToBeat) {
longest[k] = str[i];
}
}
System.out.println("The longest input strings are:");
for (int i=0; i < k; i++) {
System.out.println(longest[i]);
}
sc.close();
}
}
Tried:
Changing str[i] = sc.nextLine().split(" "); to its other variations in the code
Changing input values
Googling stdin for the last hour trying to find any documentation that helps me
If you are using eclipse arguments separated by enter then your logic is wrong:
according to your logic get 1st element from the eclipse argument like args[0]
another Input is taken from the console.
if you need to take all elements from the eclipse argument follow the below code:
public class A2P1 {
public static void main(String[] args) {
int size = Integer.parseInt(args[0]);
String[] str = new String[size];
int length=0;
String loggestString="";
for (int i=1; i < size; i++) {
str[i] = args[i];
int strLen = str[i].length();
if(strLen>length) {
length=strLen;
loggestString=str[i];
}
}
System.out.println(loggestString);
}
}

Unique characters from string

I am trying to print all the unique characters from a string but I am not getting proper output. Also, I want to check if someone enters integer in string, I want to print Invalid String. How can I achieve this?
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char[] ch = new char[20];
System.out.println("Enter the sentence:");
String sent = sc.nextLine().replaceAll(" ", "");
int count = 0;
for (int i = 0; i < sent.length(); i++) {
int j = (sent.length() - 1);
count = 0;
while (j > i) {
if (sent.charAt(j) == sent.charAt(i)) {
sent = deleteCharAt(sent, i);
sent = deleteCharAt(sent, j - 1);
break;
}
j--;
}
}
for (int i = 0; i < sent.length(); i++) {
System.out.println(sent.charAt(i));
}
}
private static String deleteCharAt(String strValue, int index) {
return strValue.substring(0, index) + strValue.substring(index + 1);
}
Enter the sentence:
java is good object oriented programming language
a
v
i
s
o
d
b
c
r
e
e
d
p
g
m
m
n
l
u
You are probably going to want to use a Set. These data structures are like Lists, except:
They do not have an ordering (meaning you cant call set.get(3))
They do not allow duplicates
You can think of them as a Map without any values.
If you have a String and you want to get all the unique chars from it. The steps are as follows:
String string = "hello"; // 4 unique characters
Set<Character> uniqueChars = new HashSet<>(); // create an empty set to put the unique chars into
// split into char[]
char[] chars = string.toCharArray();
Arrays.stream(chars).forEach(c -> {
// the following code will be run once for every char in the array
uniqueChars.add(c);
// adding the same char twice does not insert it twice
});
This can be written more concisely as:
String string = "hello";
Set<Character> uniqueChars = new HashSet<>();
Arrays.stream(string.toCharArray()).forEach(uniqueChars::add); // using a Java 8 method reference
If you want to reject any char that is a numerical digit, you can use the following line:
boolean containsDigit = Arrays.stream(string.toCharArray())
.filter(Character::isDigit) // filter out all the non digit characters
.findAny() // check if there are any remaining
.isPresent();
It would be more efficient and easier to read code to use a HashSet:
HashSet<Character> h = new HashSet<Character>();
for (int i = 0; i <= (sent.length() - 1); i++)
h.add(sent.charAt(i));
Iterator<Character> i = h.iterator();
while (i.hasNext())
System.out.println(i.next());
To avoid duplicate you can use a Set: is a collection that doesn't allow duplicates. You have to use a specific implementation of that interface, such as HashSet. You can do something like this:
public class UniqueChar {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the sentence:");
String withoutSpaces = sc.nextLine();
withoutSpaces = "asc34csf"; // mock example
Set<Character> goodChars = new HashSet<>();
String sent = withoutSpaces.replaceAll(" ", "");
int count = 0;
for (int i = 0; i < sent.length(); i++) {
char currChar = sent.charAt(i);
// do not add a character if is a digit
if(Character.isDigit(currChar))
System.out.println("Digit!");
else
goodChars.add(currChar); // add a character only if not present
}
String output = "";
for (Character character : goodChars) {
output += character; // concat in a single output string
}
System.out.println(output);
}
So you simply jump characters that are digits, if it's a character it'll be added to the collection (and the Set manages internally the fact that if it's a duplicate, it will not be added), then concat the elements of the Set in a single String.
You can find more information about HashSet in the Java documentation.
You can write your code something like this:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] alpha = new int[26];
System.out.println("Enter the sentence:");
String sent = sc.nextLine().replaceAll(" ", "");
for (int i = 0; i < sent.length(); i++) {
int temp = sent[i] - 'a';
if (temp >= 0 && temp <= 25) {
alpha[temp] = 1;
} else {
System.out.println("Invalid String");
return;
}
}
for (int i = 0; i < 26; i++) {
if (alpha[i] == 1)
System.out.println((char) (i + 'a'));
}
}
This uses an array of length 26 as the workaround if you don't want to use any SET like data structure.
This code can bring you problem if your sentence have capital letters as well. You can avoid that problem by using toLowercase like function just before the loop.

Java: Most Efficient Way to Get Input Integer Array

I'm working on a problem that requires me to store a very large amount of integers into an integer array. The input is formatted so that one line displays the amount of integers and the next displays all of the values meant to be stored. Ex:
3
12 45 67
In the problem there is closer to 100,000 integers to be stored. Currently I am using this method of storing the integers:
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] iVau = new int[n];
String[] temp = scanner.nextLine().split(" ");
for(int i = 0; i < n; i++) {
iVau[i] = Integer.parseInt(temp[i]);
}
This works fine, however the problem I am solving has a strict time limit and my current solution is exceeding it. I know that there is a more efficient way to store this input using buffered readers and input streams, but I don't know how to do it, can someone please show me.
The way you are using Scanner makes your program save a String containing the whole numbers at once, in memory. With 100000 numbers in the 2nd line of your input, it is not so efficient, you could read numbers one after the other without keeping the previous one in memory. So, this way, avoiding using Scanner.readLine() should make your program run faster. You will not have to read the whole line one time, and read a 2nd time this String to parse the integers from it: you will do both of these operations only once.
Here is an example. The method testing() does not use any Scanner. The method testing2() is the one you provided. The file tst.txt contains 100000 numbers. The output from this program, on my Mac Mini (Intel Core i5#2.6GHz) is:
duration without reading one line at a time, without using a Scanner instance: 140 ms
duration when reading one line at a time with a Scanner instance: 198 ms
As you can see, not using Scanner makes your program 41% faster (integer part of (198-140)/140*100 equals 41).
package test1;
import java.io.*;
import java.util.*;
public class Test {
// Read and parse an Int from the stream: 2 operations at once
private static int readInt(InputStreamReader ir) throws IOException {
StringBuffer str = new StringBuffer();
int c;
do { c = ir.read(); } while (c < '0' || c > '9');
do {
str.append(Character.toString((char) c));
c = ir.read();
} while (!(c < '0' || c > '9'));
return Integer.parseInt(str.toString());
}
// Parsing the input step by step
private static void testing(File f) throws IOException {
InputStreamReader ir = new InputStreamReader(new BufferedInputStream(new FileInputStream(f)));
int n = readInt(ir);
int [] iVau = new int[n];
for (int i = 0; i < n; i++) iVau[i] = readInt(ir);
ir.close();
}
// Your code
private static void testing2(File f) throws IOException {
Scanner scanner = new Scanner(f);
int n = scanner.nextInt();
int[] iVau = new int[n];
scanner.nextLine();
String[] temp = scanner.nextLine().split(" ");
for(int i = 0; i < n; i++)
iVau[i] = Integer.parseInt(temp[i]);
scanner.close();
}
// Compare durations
public static void main(String[] args) throws IOException {
File f = new File("/tmp/tst.txt");
// My proposal
long t = System.currentTimeMillis();
testing(f);
System.out.println("duration without reading one line at a time, without using a Scanner instance: " + (System.currentTimeMillis() - t) + " ms");
// Your code
t = System.currentTimeMillis();
testing2(f);
System.out.println("duration when reading one line at a time with a Scanner instance: " + (System.currentTimeMillis() - t) + " ms");
}
}
NOTE: creating the input file is done this way, with bash or zsh:
echo 100000 > /tmp/tst.txt
for i in {1..100000}
do
echo -n $i" " >> /tmp/tst.txt
done
I believe this is what you're looking for. A BufferedReader can only read a line at a time, so it is necessary to split the line and cast Strings to ints.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
int n = Integer.parseInt(br.readLine());
int[] arr = new int[n];
String[] line = br.readLine().split(" ");
for (int i = 0; i < n; i++) {
arr[i] = Integer.parseInt(line[i]);
}
} catch (IOException e) {
e.getStackTrace();
}
Just a thought, String.split returns an array of Strings. You say the input can be around 100,000 values. So in order to split the array in this way, String.split must be iterating through each element. Now in parsing the new array of strings to Integers you have iterated through the collection twice. You could do this in one iteration with a few small tweaks.
Scanner scanner = new Scanner(System.in);
String tmp = scanner.nextLine();
scanner = new Scanner(tmp);
for(int i = 0; scanner.hasNextInt(); i++) {
arr[i] = scanner.nextInt();
}
The reason for linking the scanner to a String instead of leaving it on System.in is so that it ends properly. It doesn't open System.in for user input on the last token. I believe in big O notation this is the difference between O(n) and O(2n) where the original snippet is O(2n)
I am not quite sure why OP has to use Integer.parseInt(s) here since Scanner can just do the parsing directly by new Scanner(File source).
Here is a demo/test for this idea:
public class NextInt {
public static void main(String... args) {
prepareInputFile(1000, 500); // create 1_000 arrays which each contains 500 numbers;
Timer.timer(() -> readFromFile(), 20, "NextInt"); // read from the file 20 times using Scanner.nextInt();
Timer.timer(() -> readTest(), 20, "Split"); // read from the file 20 times using split() and Integer.parseInt();
}
private static void readTest() {
Path inputPath = Paths.get(Paths.get("").toAbsolutePath().toString().concat("/src/main/java/io/input.txt"));
try (Scanner scanner = new Scanner(new File(inputPath.toString()))) {
int n = Integer.valueOf(scanner.nextLine());
int[] iVau = new int[n];
String[] temp = scanner.nextLine().split(" ");
for (int i = 0; i < n; i++) {
iVau[i] = Integer.parseInt(temp[i]);
}
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
private static void readFromFile() {
Path inputPath = Paths.get(Paths.get("").toAbsolutePath().toString().concat("/src/main/java/io/input.txt"));
try (Scanner scanner = new Scanner(new File(inputPath.toString()))) {
while (scanner.hasNextInt()) {
int arrSize = scanner.nextInt();
int[] arr = new int[arrSize];
for (int i = 0; i < arrSize; ++i) {
arr[i] = scanner.nextInt();
}
// System.out.println(Arrays.toString(arr));
}
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
private static void prepareInputFile(int arrCount, int arrSize) {
Path outputPath = Paths.get(Paths.get("").toAbsolutePath().toString().concat("/src/main/java/io/input.txt"));
List<String> lines = new ArrayList<>();
for (int i = 0; i < arrCount; ++i) {
int[] arr = new int[arrSize];
for (int j = 0; j < arrSize; ++j) {
arr[j] = new Random().nextInt();
}
lines.add(String.valueOf(arrSize));
lines.add(Arrays.stream(arr).mapToObj(String::valueOf).collect(Collectors.joining(" ")));
}
try {
Files.write(outputPath, lines);
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
}
Locally tested it with 1_000 arrays while each array has 500 numbers, reading all the elements cost about: 340ms using Scanner.nextInt() while OP's method about 1.5ms.
NextInt: LongSummaryStatistics{count=20, sum=6793762162, min=315793916, average=339688108.100000, max=618922475}
Split: LongSummaryStatistics{count=20, sum=26073528, min=740860, average=1303676.400000, max=5724370}
So I really have doubt the issue lies in the input reading.
Since in your case you are aware of the total count of elements all that you have to do is to read X integers from the second line. Here is an example:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int count = in.nextInt();
int array[] = new int[count];
for (int i = 0; i < count; i++) {
array[i] = in.nextInt();
}
}
If this is not fast enough, which I doubt, then you could switch to the use of a BufferedReader as follows:
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int count = Integer.parseInt(in.readLine());
int array[] = new int[count];
for (int i = 0; i < count; i++) {
int nextInteger = 0;
int nextChar = in.read();
do {
nextInteger = nextInteger * 10 + (nextChar - '0');
nextChar = in.read();
} while (nextChar != -1 && nextChar != (int)' ');
array[i] = nextInteger;
}
}
In your case the input will be aways valid so this means that each of the integers will be separated by a single whitespace and the input will end up with EoF character.
If both are still slow enough for you then you could keep looking for more articles about Reading Integers in Java, Competative programming like this one: https://www.geeksforgeeks.org/fast-io-in-java-in-competitive-programming/
Still my favorite language when it comes to competitions will always be C :) Good luck and enjoy!

How can i print my array using Arrays.toString(reverse) without[]

how can i print the result without brackets
public class Solution {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] arr = new int[n];
for(int i=0; i < n; i++){
arr[i] = in.nextInt();
}
int[] reverse =new int[n];
for (int i = 0; i < reverse.length; i++) {
reverse[i]=arr[arr.length-1-i];
}
in.close();
}
}
In java8, you can conveniently do any kind of String output using join, there you will have to do some manual reversing though:
String output = String.join(", ", arr);
You can't change the implementation of Arrays.toString() so you can't print your array like that.
Although, you can assign it to an string variable and then manipulate that string as you desire.
String str = Arrays.toString(reverse);
str = str.substring(1, str.length() - 1);

Java String Bubble Sorting

I need help sorting this array in alphabetical order using the bubble sort algorithm.
My code is:
public class Strings
{
public static void main(String[] args)
{
Scanner reader = new Scanner(System.in);
String tempStr;
System.out.print("Enter the strings > ");
String s1 = new String(reader.nextLine());
String[] t1 = s1.split(", ");
for (int t=0; t<t1.length-1; t++)
{
for (int i = 0; i<t1.length -1; i++)
{
if(t1[i+1].compareTo(t1[1+1])>0)
{
tempStr = t1[i];
t1[i] = t1[i+1];
t1[i+1] = tempStr;
}
}
}
for(int i=0;i<t1.length;i++)
{
System.out.println(t1[i]);
}
}
}
The code compiles, but it does not sort alphabetical. Please help me.
You have three errors in your code.
The first error is in the inner for loop, in the place where you do the check statement, it should be i < t1.length - t -1 not i < t1.length -1. You subtract t because you do not want to loop through the whole array again, only the first part of it.
The second and third errors are in the if statement. You need to turn the greater than symbol into a lesser than symbol, because the way you have the compareTo method set up, it will return a negative number.
The other error in this line is that in the compareTo parameter you put 1 + 1 it actually should be just i, because you want one less than the object it is comparing to.
The fixed working code is below (Comments are what you originally had):
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
String tempStr;
System.out.print("Enter the strings > ");
String s1 = new String(reader.nextLine());
String[] t1 = s1.split(", ");
for (int t = 0; t < t1.length - 1; t++) {
for (int i= 0; i < t1.length - t -1; i++) {
if(t1[i+1].compareTo(t1[i])<0) {
tempStr = t1[i];
t1[i] = t1[i + 1];
t1[i + 1] = tempStr;
}
}
}
for (int i = 0; i < t1.length; i++) {
System.out.println(t1[i]);
}
}
please change
String[] t1 = s1.split(", ");
to
String[] t1 = s1.split("");
This will solve the issue.

Categories