Java program to find the second smallest number in console input - java

I am really trying to grasp this problem but could not continue further without help.
My logic is in order but for some reason it will not execute properly.
On execution I want to enter a line of numbers for example 10 12 5 9 3 and the program should return me the second smallest number.
As I want to control the basics first I am refraining from using any other imported classes except for the two used.
If someone could shed some light on why this does not work I would be very grateful.
package secondSmallest;
import java.util.Scanner;
import java.io.PrintStream;
public class secondSmallest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
PrintStream out = new PrintStream(System.out);
int smallest = 1;
int secsmallest = 0;
int hold = 0;
while(scan.hasNext()); {
hold = scan.nextInt();
if (hold < smallest) {
smallest = secsmallest;
smallest = hold;
} else {
hold = scan.nextInt();
}
out.printf(" %d", secsmallest);
}
}
}

First of all:
My logic is in order but for some reason it will not execute properly.
means that your logic is not in order (unless there is just a typo, or other syntax error, blocking flawless result);
Second:
Scanner#hasNext(), which you have as a while condition:
Returns true if this scanner has another token in its input. This method may block while waiting for input to scan. The scanner does not advance past any input.
and you should, somewhere, somehow, indicate when you want your while loop to end. In your example, your loop is going on infinitely, as it does not have any base case. Even the "Enter" keystroke is a data, and pressing it will keep entering new-line control character;
Third:
You have your smallest initialized as 1, which is not really a clean design to statically assign the constant to the current minimum. Think of a possibility when your input is different;
Fourth:
You are printing the secsmallest inside your while loop, which, I suppose, is not what you meant to do;
Fifth:
By reading in your else block hold = scan.nextInt(); you are effectively ommiting one input, as the moment your while iterates one step forward, you have another hold = scan.nextInt(); and you jump one iteration;
Sixth:
There are many ways to design "find-second-smallest" algorithm (sorting it first and then taking the second element; introducing two pointers; etc.), but if you insist to follow something close to your way, this works as expected:
public class Main {
public static void main(String[] args) {
int[] arr = {10, 12, 5, 9, 32, 5, 123, 4, -34, 12, -534, -53, -1, 432, 53};
int res = secondSmallest(arr);
System.out.println(res);
}
public static int secondSmallest(int[] arr) {
int smallest = arr[0];
int secsmallest = arr[1];
int i = 2;
while (i < arr.length-1) {
int current = arr[i];
if (current < smallest) {
secsmallest = smallest;
smallest = current;
}
else if(current < secsmallest) {
secsmallest = current;
}
i++;
}
return secsmallest;
}
}
Outputting:
-53

Your program should look like this
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
PrintStream out = new PrintStream(System.out);
int smallest = Integer.MAX_VALUE;
int secSmallest = smallest;
int hold = 0;
while (scan.hasNextInt()) {
hold = scan.nextInt();
if (hold < smallest) {
secSmallest = smallest;
smallest = hold;
} else if (hold < secSmallest) secSmallest = hold;
}
out.printf(" %d", secSmallest);
}

Related

Checking if the graph exist (java)

Determine whether there exists a graph with a sequence of degrees of vertices (s = s1, s2...sn).
What is the best and most optimized algorithm for solving this problem.
Input:
the first line contains `t<100` - amount of sequnces.
the second line contains value `n <= 1000000`(length of a sequence).
the third line contains contains `n` non-negative integer numbers. And so on.
Output:
if the graph can exist print "yes" otherwise print "no".
For example:
Input:
3
5
1 2 3 2 1
4
3 3 2 2
3
1 3 2
Output:
No
Yes
Yes
The maximum execution time should be 0.4 second.
Here is my code (If the number of odd vertices is even, then the graph exists):
import java.util.Scanner;
public class Main {
public static final Scanner in = new Scanner(System.in);
public static void isGraph (int []a, int n) {
int k=0;
for(int i=0; i< n; i++) {
if(a[i] %2 != 0) {
k++;
}
}
if(k%2 == 0)
System.out.println("Yes");
else
System.out.println("No");
}
public static void main(String[] args) throws Exception{
double t1 = System.nanoTime();
int n;
int []a;
int t = Integer.parseInt(in.nextLine());
while(t-- > 0) {
n = in.nextInt();
a = new int[n];
for(int i=0; i<n; i++)
a[i] = in.nextInt();
isGraph(a,n);
}
System.out.println(System.nanoTime() - t1);
}
}
But the execution time of this program is more than 0.4 second. I get run time exceeded. How I can optimize code and speed up runtime. May be there is another algorithm to solve this task, please help me.
I think I have a faster way for you. Please verify this. If you are concerned about the final outcome of even/odd, then there seems to be no reason to keep track of the k counter. You can keep a dynamic value of whether the running sequence is even or odd:
public static void isGraph (int []a, int n) {
int k = 0;
for(int i=0; i< n; i++) {
k += a[i] & 1;
}
if(k%2 == 0)
System.out.println("Yes");
else
System.out.println("No");
}
This might help your reading: I have no experience with it however, I got it from a competition website:
Slow way to read:
/** Read count integers using Scanner */
static int scanInteger(int count) {
Scanner scanner = new Scanner(input);
int last = 0;
while (count-- > 0) {
last = scanner.nextInt();
}
return last;
}
Faster way:
static int readIntegers(int count)
throws IOException {
BufferedReader reader = new BufferedReader(
new InputStreamReader(input) );
StringTokenizer tokenizer = new StringTokenizer("");
int last = 0;
while (count-- > 0) {
if (! tokenizer.hasMoreTokens() ) {
tokenizer = new StringTokenizer(reader.readLine());
}
last = Integer.parseInt(tokenizer.nextToken());
}
return last;
}
EDIT: to show how to avoid two phases where Phase 1 is the read loop, and Phase 2 is the algorithm:
public static void main(String[] args) throws Exception{
double t1 = System.nanoTime();
int n;
// int []a; // Not necessary
int t = Integer.parseInt(in.nextLine());
while(t-- > 0) {
n = in.nextInt();
// a = new int[n]; // Not necessary
int k = 0;
int a;
for(int i=0; i<n; i++) {
a = in.nextInt();
k += a & 1;
}
// isGraph(a,n); // Not necessary
if(k % 2 == 0)
System.out.println("Yes");
else
System.out.println("No");
}
System.out.println(System.nanoTime() - t1);
}
May be there is another algorithm to solve this task
That's not the problem (IMO).
Hint 1: since you know the length of the sequence beforehand, you can create the array and parse the sequence faster than this:
a = Arrays.stream(s.split(" ")).mapToInt(Integer::parseInt).toArray();
(Java 8+ streams are elegant, but they are not the fastest way.)
Hint 2: using Scanner is probably faster than reading strings and parsing them.
Hint 3: you could probably avoid creating an array entirely. (It would be poor coding practice IMO ... but if performance is critical ...)

Need help to spot flaws in my java code

I am working on a school assignment and I have the following question:
I am given a number of sticks (with distinct or similar length), and am tasked to find out the minimum number of sticks required to form a longer stick of given length.
For instance,
Given 6 sticks of length 1,1,1,1,1,3 to form a longer stick of length 5, the output would be 3.
NOTE: Sticks cannot be reused.
However, if it is impossible to form the given length, output -1.
For instance,
Given 3 sticks of length 1,2,6, to form a longer stick of length 5, output would be -1.
I have the following code, which have passed all public test cases. However, I failed the private test cases which I cannot figure out my mistake.
Here's my code:
import java.util.*;
class Result {
static int min = 100000;
public static int solve(int pos, int currSum, int len, int numStk) {
// implementation
for (int i=1; i<=Stick.data.length - pos; i++){
if (currSum > len){
continue;
}
else if (currSum < len){
if (pos+i >= Stick.data.length){
break;
}
else{
solve(pos+i,currSum+Stick.data[pos+i], len, numStk+1);
}
}
else if (currSum == len){
if (numStk < min){
min = numStk;
}
}
}
return min;
}
}
class Stick {
static int[] data;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int sticks = sc.nextInt();
data = new int[sticks];
int len = sc.nextInt();
for (int i=0; i<sticks; i++){
data[i] = sc.nextInt();
}
for (int i=0; i<sticks; i++){
Result.solve(i,0,len,1);
}
if (Result.min == 100000){
System.out.println(-1);
} else {
System.out.println(Result.min-1);
}
}
}
Things I notice about your code:
Bug: In main,
Result.solve(i,0,len,1);
assumes that stick i is taken (hence numsticks = 1 in the arguments list), but currSum is given as 0. Shouldn't that be data[i]?
Better code quality: The checks for currSum > len and currSum == len can be done outside the for loop, which is more efficient.

Count how many times an element occurs in an array - Java

I recently made a very simple practice program in Python, that takes user input and rolls dice. The code is:
import random
import sys
import math
def roll(rolls, sides, results):
for rolls in range(1, rolls + 1):
result = random.randrange(1, sides + 1)
print result
results.append(result)
def countf(rolls, sides, results):
i = 1
print "There were", rolls, "rolls."
for sides in range(1, sides + 1):
if results.count(i) != 1:
print "There were", results.count(i), i,"s."
else:
print "There was", results.count(i), i
i = i + 1
if i == sides:
break
rolls = input("How many rolls? ")
sides = input("How many sides of the die? ")
results = []
roll(rolls, sides, results)
countf(rolls, sides, results)
(actually this is part of a larger program, so I had to cut'n'paste bits, and I might have missed something out).
And so I decided to translate that to Java. Notice the algorithm here: get random number, print it, append it to an array, then count the amount of each number in the array at the end, and print out that value. Problem is, I don't know how to do the equivalent of someArray.count(someIndex) in Java syntax. So my Java program looks like this so far:
import java.util.*;
public class Dice {
static Scanner input = new Scanner(System.in);
public static void main(String[] args) {
final static int TIMES_TO_ROLL = getInt("Times to roll?");
Random flip = new Random();
int[] results = new int[TIMES_TO_ROLL];
for (int i = 0; i < TIMES_TO_ROLL; i++) {
int result = flip.nextInt(6);
System.out.println(result);
results[i] = result;
}
}
public static int getInt(String prompt) {
System.out.print(prompt + " ");
int integer = input.nextInt();
input.nextLine();
return integer;
}
}
So can someone help me with the array counting code? I understand that this might not be a defined method, since Python is higher level after all, so I could make my own array counting method, but I was wondering if Java, like Python, has a predefined one.
EDIT: I managed something like this:
public static int arrayCount(int[] array, int item) {
int amt = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] == item) {
amt++;
}
else {
amt = amt;
}
}
return amt;
}
EDIT: Just out of interest, assuming I use Command prompt to run my Java program and Python.exe (command prompt console for Python), which one will be faster (in other words, for the same code, which language has better performance?)?
You could use a HashMap to store the result.
If the new number is not in your map you add it with "1" as initial value.
If it exists your put "+1" to the current map value.
To display the values you just have to iterate on you entries in a for each loop.
The solution is to transform your array to a List and then use the Collections.frequency method:
List<Integer> resultList = Arrays.asList(results);
int freq = Collections.frequency(resultList, 4);
Also you could use ArrayList from the very beginning saving you the transformation:
List<Integer> result = new ArrayList<Integer>();
// add results
int freq = Collections.frequency(result, 4);
See the Collections documentation here
EDIT: If performance is an issue (as suggested in the comments) then maybe you want to use each index of the array as a counter, as follows:
Random flip = new Random(SIDES);
int[] counters = new int[SIDES];
for (int i = 0; i < TIMES_TO_ROLL; i++) {
int result = flip.nextInt;
counters[result] = counters[result]+1;
}
Notice that you no longer need to count at the end since you've already got all the counters in the array and there is no overhead of calculating the hash.
There are a couple libraries that will do this for you:
Google Guava's MultiSet
Apache Common's Bag
But for something so simple, you may consider an extra library a bit excessive.
You can also do this yourself with an int[]. Assuming your dice is using whole numbers, have the number rolled refer to the index into the array, and then increment the value at that index. When you need to retrieve the value for a given number, look up its value by the index.
private static final int NUMBER_DICE_SIDES = 6;
public static void main(String[] args) {
final static int TIMES_TO_ROLL = getInt("Times to roll?");
Random flip = new Random(NUMBER_DICE_SIDES);
int[] results = new int[NUMBER_DICE_SIDES];
for (int i = 0; i < TIMES_TO_ROLL; i++) {
int result = flip.nextInt;
System.out.println(result);
results[result]++;
}
for(int i = 0; i < NUMBER_DICE_SIDES; ++i) {
System.out.println((i+1)+"'s: " + arraysCount(results, i));
}
}
public static int arrayCount(int[] array, int item) {
return array[item];
}
There's a frequency method in collections
int occurrences = Collections.frequency(listObject, searchItem);
Java doc for collections
As far as I am aware, there is no defined method to return the frequency of a particular element in an array. If you were to write a custom method, it would simply be a matter of iterating through the array, checking each value, and if the value matches the element you're after, incrementing a counter.
So something like:
// in this example, we assume myArray is an array of ints
private int count( int[] myArray, int targetValue) {
int counter = 0;
for (int i = 0 ; i < myArray.length; i++ ) {
if (myArray[i] == targetValue) {
counter++;
}
}
return counter;
}
Of course, if you want to find the frequency of all the unique values in your array, this has the potential of being extremely inefficient.
Also, why are you using a 7-sided die? The Random nextInt() will return a number from 0 up to but not including the max. So your die will return values from 0 through 6. For a six-sided die, you'd want a new Random(6); and then increment your roll by one to get a value from one through six: flip.nextInt() +1;.
class FindOccurrence {
public static void main (String[]args) {
int myArray[] = {5, 8, 5, 12, 19, 5, 6, 7, 100, 5, 45, 6, 5, 5, 5};
int numToFind = 5;
int numberOfOccurrence = 0;
for (int i=0; i < myArray.length; i++) {
if (numToFind == myArray[i]) {
numberOfOccurrence++;
}
}
System.out.println("Our number: " + numToFind);
System.out.println("Number of times it appears: " + numberOfOccurrence);
}
}

Optimize Code for longest common sequence

I was trying to solve this practice problem, it is also quoted below.
The Chef is planning a buffet for the DirectiPlex inauguration party,
and everyone is invited. On their way in, each guest picks up a sheet
of paper containing a random number (this number may be repeated). The
guests then sit down on a round table with their friends.
The Chef now decides that he would like to play a game. He asks you to pick a random person from your table and have them read their
number out loud. Then, moving clockwise around the table, each person
will read out their number. The goal is to find that set of numbers
which forms an increasing subsequence. All people owning these
numbers will be eligible for a lucky draw! One of the software
developers is very excited about this prospect, and wants to maximize
the number of people who are eligible for the lucky draw. So, he
decides to write a program that decides who should read their number
first so as to maximize the number of people that are eligible for the
lucky draw. Can you beat him to it?
Input The first line contains t, the number of test cases (about 15). Then t test cases follow. Each test case consists of two
lines:
The first line contains a number N, the number of guests invited to
the party.
The second line contains N numbers a1, a2, ..., an separated by
spaces, which are the numbers written on the sheets of paper in
clockwise order.
Output For each test case, print a line containing a single number which is the maximum number of guests that can be eligible for
participating the the lucky draw.
Here's the solution that I have come up with
// http://www.codechef.com/problems/D2/
import java.io.*;
import java.util.*;
public class D2
{
public static void main(String [] args)
throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int numTestCases = Integer.parseInt(br.readLine());
for(int _t=0; _t<numTestCases; ++_t)
{
int N = Integer.parseInt(br.readLine());
StringTokenizer strtok = new StringTokenizer(br.readLine());
int [] originalArray = new int[N*2];
for(int i=0; i<N; ++i)
{
//this concatenates the array with itself at the time of reading the input itself
originalArray[i] = originalArray[N+i] = Integer.parseInt(strtok.nextToken());
}
//Now we calculate the length of the longest increasing sequence
int maxWinners = new LongestIncreasingSequence(originalArray).lengthOfLongestIncreasingSequence();
System.out.println(maxWinners);
}
}
}
class LongestIncreasingSequence
{
private int [] array;
private int [] longest;
private int subsequence_size;
public LongestIncreasingSequence(int [] A)
{
array = A;
longest = new int[array.length / 2];
longest[0] = array[0];
subsequence_size = 1;
}
public int lengthOfLongestIncreasingSequence()
{
for(int i=1; i<array.length; ++i)
{
if(array[i] < longest[0])
{
longest[0] = array[i];
}
else if(array[i] > longest[subsequence_size - 1])
{
longest[subsequence_size++] = array[i];
}
else
{
//Make the replacement with binary search
longest[getReplacementIndex(array[i])] = array[i];
}
}
return subsequence_size;
}
//Method to find the correct index using binary search
private int getReplacementIndex(int elem)
{
int left, right, mid;
left = 0; right = subsequence_size - 1;
while(right - left > 1)
{
mid = 1 + (right - left) / 2;
if(array[mid] >= elem)
{
if(mid != right) right = mid;
else --right;
}
else
{
left = mid;
}
}
return right;
}
}
The complexity is O(n(log(n)) I'm finding the Longest Increasing Sequence by concatenating the array with itself.
This however doesn't pass the time requirement, can someone help me speed up this implementation.
I would not do N rotations, but instead determine the longest (cyclic) run in one go. It is certainly doable, you just have to take care warping around at the end of the array.

recursion resulting in extra unwanted data

I'm writing a module to handle dice rolling. Given x die of y sides, I'm trying to come up with a list of all potential roll combinations.
This code assumes 3 die, each with 3 sides labeled 1, 2, and 3. (I realize I'm using "magic numbers" but this is just an attempt to simplify and get the base code working.)
int[] set = { 1, 1, 1 };
list = diceroll.recurse(0,0, list, set);
...
public ArrayList<Integer> recurse(int index, int i, ArrayList<Integer> list, int[] set){
if(index < 3){
// System.out.print("\n(looping on "+index+")\n");
for(int k=1;k<=3;k++){
// System.out.print("setting i"+index+" to "+k+" ");
set[index] = k;
dump(set);
recurse(index+1, i, list, set);
}
}
return list;
}
(dump() is a simple method to just display the contents of list[]. The variable i is not used at the moment.)
What I'm attempting to do is increment a list[index] by one, stepping through the entire length of the list and incrementing as I go.
This is my "best attempt" code. Here is the output:
Bold output is what I'm looking for. I can't figure out how to get rid of the rest. (This is assuming three dice, each with 3 sides. Using recursion so I can scale it up to any x dice with y sides.)
[1][1][1] [1][1][1]
[1][1][1] [1][1][2] [1][1][3] [1][2][3]
[1][2][1] [1][2][2] [1][2][3] [1][3][3]
[1][3][1] [1][3][2] [1][3][3] [2][3][3] [2][1][3]
[2][1][1] [2][1][2] [2][1][3] [2][2][3]
[2][2][1] [2][2][2] [2][2][3] [2][3][3]
[2][3][1] [2][3][2] [2][3][3] [3][3][3] [3][1][3]
[3][1][1] [3][1][2] [3][1][3] [3][2][3]
[3][2][1] [3][2][2] [3][2][3] [3][3][3]
[3][3][1] [3][3][2] [3][3][3]
I apologize for the formatting, best I could come up with.
Any help would be greatly appreciated. (This method was actually stemmed to use the data for something quite trivial, but has turned into a personal challenge. :)
edit: If there is another approach to solving this problem I'd be all ears, but I'd also like to solve my current problem and successfully use recursion for something useful.
edit2:
Running code including the "easy fix." Beware unused variables and weird hacks, I haven't cleaned it up yet.
package code.testing;
import java.util.ArrayList;
public class CodeTesting {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
int[] set = { 1, 1, 1 };
list = recurse(0,0, list, set);
}
public static ArrayList<Integer> recurse(int index, int i, ArrayList<Integer> list, int[] set){
if(index < 3){
// System.out.print("\n(looping on "+index+")\n");
for(int k=1;k<=3;k++){
// System.out.print("setting i"+index+" to "+k+" ");
set[index] = k;
if (index==2){
dump(set);
}
recurse(index+1, i, list, set);
}
}
return list;
}
static void dump(int[] arr) {
for (int s : arr) {
System.out.format("[%s]", s);
}
System.out.println();
}
}
I'm sorry I had to rewrite the code, but it's pretty much the same algorithm as yours with some corrections:
public class DiceRolls {
static void recurse(int diceNumber, int[] values, final int MAX) {
if (diceNumber == values.length) {
System.out.println(java.util.Arrays.toString(values));
} else {
for (int v = 1; v <= MAX; v++) {
values[diceNumber] = v;
recurse(diceNumber + 1, values, MAX);
}
}
}
public static void main(String[] args) {
recurse(0, new int[3], 4);
}
}
This is a standard tuplet recursive generator. If you want to add all the int[] into a List, then make sure to add(values.clone()) so they are independent int[] objects.
But what's with the extra output?
The problem is that you were dumping prematurely, before you're done throwing all the dices. In pseudocode, this is what you're doing:
if we're not done yet
trying all possibilities for this dice
dump result so far // premature dumping!
recurse for next dice
An easy fix to your code is to do the following:
if we're not done yet
trying all possibilities for this dice
recurse for next dice
else, we're done, so
dump result // timely!
So back to the Java implementation, the fix is merely moving dump(set); to an else case for the if (index < 3) statement.
Call dump() only when index == 2.
Incidentally, i and list seem unused. And the verb is "recur". :)
Here is a non-recursive alternative. Change the two constants to calculate all combinations for different dices and different numbers of dice.
package utils;
public class Dice {
private static int FACES = 3;
private static int NUMBER_OF_DICE = 3;
public static void main(String[] args) {
int start = createPair(1);
int end = createPair(FACES);
for (int i = start; i <= end; i++) {
String combination = Integer.toString(i, FACES+1);
if (combination.indexOf('0') < 0)
System.out.println(combination);
}
}
private static int createPair(int number) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < NUMBER_OF_DICE; i++) {
sb.append(number);
}
return Integer.parseInt(sb.toString(), FACES+1);
}
}

Categories