I previously posted a Reservoir-Sampling program, which was basically a test version of this one. This is an assignment. In the code below, I use RunTimeException
to control when scanner finishes reading data. Reasons for this being:
- I cannot use any other library than java.lang.
- I cannot use Scanner, either. We have been provided a StdIn class which has a static
scanner.next()
method only for reading strings.
Note: All the code is inside main()
because that is how the API demands it.
Can someone review my code, and possibly tell if there's some way I can improve this?
import java.io.BufferedInputStream;
import java.util.Scanner;
public class Subset {
public static void main(String[] args) {
int k = Integer.parseInt(args[0]);
String[] arr = new String[k];
int i = 0;
String str;
while((str=stdin.readString())!=null && i < arr.length){
arr[i++] = str;
// System.out.println(str);
}
try{
for(; (str=stdin.readString())!=null; i++){
int r = (int)(Math.random()*(i + 1));
if(r < k){
arr[r] = str;
//System.out.println(str);
}
}
}catch(RuntimeException e){ // do nothing }
for(String s : arr){
System.out.print(s + " ");
}
System.out.println("\n");
}
}
class stdin{
private stdin(){}
private static Scanner sc = new Scanner(new BufferedInputStream(System.in));
public static String readString(){
return sc.next();
}
}
Command line input: echo A B C D E F G H I J | java Subset 3
Output: A F C
To clear out confusion, I am posting what the API and the instructor demands:
Subset client. Write a client program Subset.java that takes a command-line integer k,
reads in a sequence of N strings from standard input using StdIn.readString(),
and prints out exactly k of them, uniformly at random. Each item from the sequence can be printed out at most once.
You may assume that k = 0 and no greater than the number of string on standard input.
% echo A B C D E F G H I | java Subset 3 % echo AA BB BB BB BB BB CC CC | java Subset 8
C BB
G AA
A BB
CC
% echo A B C D E F G H I | java Subset 3 BB
E BB
F CC
G BB
Your client should use only constant space plus one object either of type Deque or of type RandomizedQueue;
use generics properly to avoid casting and compiler warnings. It should also use time and space proportional to
at most N in the worst case, where N is the number of strings on standard input.
(For an extra challenge, use space proportional to k.) It should have the following API.
public class Subset {
public static void main(String[] args)
}
stdin
is nothing to do with your solution maybe delete it and define the interface you have been given. A few easy things to tidy up though are the naming, there is no limit of characters - i, r, k, s do not convey enough information. Making it clear regarding the unusual reuse ofi
. Using awhile
loop in the second instance once we've discovered thati
is being weirdly used. Are you just picking a random sample of 3 from stdin? \$\endgroup\$Unusual termination of stream
to System.out I guess) and returns null to terminate your loop in the manner intended. \$\endgroup\$