java application converting to junit testing - java

I have this java program:
public class countOccurances {
public void countOccurancesInString(String str){
char[] c = str.toCharArray();//in order to convert the string into a char array that will help us handle the string easily
int loopCount=0;
int count=0;//this variable will count every occurance of every character
int len=str.length();
if(len>1000){
System.out.println("String size is bigger than 1000 characters which is illegal, program will terminate..." );
System.exit(0);
}
for(int i=0;i<len;i++){
boolean flag =true;
for(int k=0;k<i;k++){
if(c[i]==(str.charAt(k)))
flag=false;
}
if(flag){ //after we notice that we have several occurences of the character we want to count it
for(int j=0;j<len;j++){
if(c[i]==str.charAt(j))
count++;
}
System.out.print("'" + c[i] + "'" + ":" + (count) + ",");
count=0;
loopCount=0;
}
}
}
}
And I want to convert it to junit testing which will provide me the option to test several unit test cases that will tell me if different values will pass or fail the program and I am struggling doing it.
any ideas?

OK, first things first: Java class names should usually start with a capital letter, and method names with lower case. With that out of the way:
Outputting to System.out isn't a very clean way to wite a method. This is referred to as a side effect - that is, you call the method, it does "something" and returns. It's also arguably a violation of the Single Responsibility Principle. It's doing two things: working out your answer and deciding how to display it. This limits the method's usefulness to your one application (spitting it out to the console) but not alternatives (e.g. outputting it to a web page, filtering it for a specific character, or - and this is where we come in - testing it).
It is possible to test this code, by redirecting System.out and using a mocking framework such as Mockito:
#Test
public void testCountOccurrences() {
PrintStream mockSystemOut = Mockito.mock(PrintStream.class);
System.setOut(mockSystemOut);
new CountOccurrences().countOccurences("AABBCCD");
Mockito.verify(mockSystemOut).print("'A':2,");
Mockito.verify(mockSystemOut).print("'B':2,");
Mockito.verify(mockSystemOut).print("'C':1,");
}
But you're starting from shaky ground: get your method signature right first. What you probably want is a Map<Character, Integer> - that is, a set of pairs of characters with their counts. That gives the caller much more flexibility about how it uses the information:
public Map<Character, Integer> countOccurrences(String str) { ... }
Then, at the point you call the code, you can choose to output that information to the console if you wish (in fact, most Map implementations have a built-in toString() method which will probably give you what you want - it's not precisely the same output, but may work for what you want to achieve).
For your implementation, create a HashMap<Character, Integer>:
Map<Character, Integer> result = new HashMap<Character, Integer>();
Add your pairs to it rather than outputting to the console:
result.put(c[i], count);
And return the result at the end. Then your test looks like this:
#Test
public void testCountOccurrences() {
Map<Character, Integer> expected = new HashMap<Character, Integer>();
expected.put("A", 2);
expected.put("B", 2);
expected.put("C", 1);
assertEquals(
expected,
new CountOccurrences().countOccurences("AABBCCD");
);
}
One final thought: adhere to the principles of Test Driven Development - write your tests before you code it!

Related

Leetcode: My solution works for Individual test cases but not for All test cases together

This is Leetcode question no: 940. Distinct Subsequences II
My code is using Recursion to fetch the subsequences. And I am using an external HashSet to keep count of the unique subsets. The reason I am subtracting one from the size is to incorporate for the empty string because as per the solution we are not supposed to include the empty string. When I run the code for individual test cases, it runs fine. But when the test cases are run together consecutively, my solution is deemed wrong. Can anybody point me in the direction as to where I could be going wrong in my code? Is it to do with the Set usage or the recursion code itself? I am aware that this problem can be solved using Dynamic Programming(which I am yet to tackle), but I just wanted to know if there is a solution possible through Recursion ??
Please refer attached images for solution and test cases runs:
Code that I have written on Leet code
The individual test cases that I have run on Leetcode
The joint test cases run by Leetcode
Code:
class Solution {
static Set<String> myset = new HashSet<String>(0);
public int distinctSubseqII(String s) {
int i=0;
String curr="";
subsets(s, curr, i);
int val = myset.size()-1;
return val;
}
public static void subsets(String str,String curr,int i){
if(i==str.length()){
//System.out.println(curr);
myset.add(curr);
return;
}
subsets(str, curr, i+1);
subsets(str, curr+str.charAt(i), i+1);
}
}
Looking at your code, I can see that the static variable is the problem. The contents of that Set carry over from one call of distinctSubseqII to the next. That means that the size of the Set will be wrong ... for the second and all later calls.
Cutting to the chase ...
You need to do the recursion in a helper function.
In your example, it might look like this.
public class Solution {
public int distinctSubseqII(String s) {
Set<String> myset = new HashSet<String>(0);
return recursive(s, mySet);
}
// Helper function
private int recursive(String s, Set<String> mySet) {
...
// call 'recursive' ... recursively
...
}
}
The "helper function" is a common pattern for recursive solutions.

Multiple string replacement in a single string generating all possible combinations

I'm trying to replace multiple words in a string with multiple other words. The string is
I have sample {url} with time to {live}
Here the possible values for {url} are
point1
point2
Possible values for {live} are
10
20
The four possible answers are
I have sample point1 with time to 10
I have sample point1 with time to 20
I have sample point2 with time to 10
I have sample point2 with time to 20
This can also increase to three.
I have {sample} {url} with time to {live}
What would be best data structures and good approach to solve this problem ?
You can do it something like:
public static void main(String[] args) {
String inputStr = "I have {sample} {url} with time to {live}";
Map<String, List<String>> replacers = new HashMap<String, List<String>>(){{
put("{sample}", Arrays.asList("point1", "point2"));
put("{live}", Arrays.asList("10", "20"));
put("{url}", Arrays.asList("url1", "url2", "url3"));
}};
for (String variant : stringGenerator(inputStr, replacers)) {
System.out.println(variant);
}
}
public static List<String> stringGenerator(String template, Map<String, List<String>> replacers) {
List<String> out = Arrays.asList(template);
for (Map.Entry<String, List<String>> replacerEntry : replacers.entrySet()) {
List<String> tempOut = new ArrayList<>(out.size()*replacerEntry.getValue().size());
for (String replacerValue : replacerEntry.getValue()) {
for (String variant : out) {
tempOut.add(variant.replace(replacerEntry.getKey(), replacerValue));
}
}
out = tempOut;
}
return out;
}
also you can try make similar solution with recursion
You can use a template string and print the combinations using System.out.format method like below:
public class Combinations {
public static void main(String[] args) {
String template = "I have sample %s with time to %d%n"; //<-- 2 arguments case
String[] points = {"point1", "point2"};
int[] lives = {10, 20};
for (String point : points) {
for (int live : lives) {
System.out.format(template, point, live);
}
}
}
}
The code solves the 2 argument case but it can be easily extended to the 3 cases substituting the sample word with another %s in the template and a triple loop.
I'm using the simplest array structures, it is up to you decide which structure is the more adapt for your code.
Unless you want the hardcoded solution with simple nested loops shown in Dariosicily's answer, you will need to store "replacee-replacements" pairings, for example the string {url} paired with a list of strings point1 and point2. A simple class can do that, like
class StringListPair{
public final String s;
public final List<String> l;
public StringListPair(String s,List<String> l){
this.s=s;
this.l=l;
}
}
and then a list of replacements can be initialized as
List<StringListPair> mappings=Arrays.asList(
new StringListPair("{url}",Arrays.asList("point1","point2")),
new StringListPair("{live}",Arrays.asList("10","20","30")));
(If someone wants to totally avoid having a helper class, these are all strings, so a List<List<String>> can do the job too, having "{url}","point1","point2" lists inside, just then we would have to fight with indexing the inner lists everywhere)
Then two common approaches pop into my mind: a recursive one, generating all possible combinations in a single run, and a direct-indexing one, numbering all combinations and generating any of them directly upon request. Recursion is simpler to come up with, and it has no significant drawbacks if all the combinations are needed anyway. The direct approach generates a single combination at a time, so if many combinations are not going to be used, it can spare a lot of memory and runtime (for example if someone would need a single randomly selected combination only, out of millions perhaps).
Recursion will be, well, recursive, having a completed combination generated in its deepest level, thus it needs the following:
the list of combinations (because it will be extended deep inside the call-chain)
the mappings
the candidate it is working on at the moment
something to track what label it is supposed to replace a the moment.
Then two things remain: recursion has to stop (when no further labels remain for replacement in the current candidate, it is added to the list), or it has to replace the current label with something, and proceed to the next level.
In code it can look like this:
static void recursive(List<String> result,List<StringListPair> mappings,String sofar,int partindex) {
if(partindex>=mappings.size()) {
result.add(sofar);
return;
}
StringListPair p=mappings.get(partindex);
for(String item:p.l)
recursive(result,mappings,sofar.replace(p.s,item),partindex+1);
}
level is tracked by a simple number, partindex, current candidate is called sofar (from "so far"). When the index is not referring to an existing element in mappings, the candidate is complete. Otherwise it loops through the "current" mapping, and calling itself with every replacement, well, recursively.
Wrapper function to creata and return an actual list:
static List<String> userecursive(List<StringListPair> mappings,String base){
List<String> result=new ArrayList<>();
recursive(result, mappings, base, 0);
return result;
}
The direct-indexing variant uses some maths. We have 2*3 combinations in the example, numbered from 0...5. If we say that these numbers are built from i=0..1 and j=0..2, the expression for that could be index=i+j*2. This can be reversed using modulo and division operations, like for the last index index=5: i=5%2=1, j=5//2=2. Where % is the modulo operator, and // is integer division. The method works higher "dimensions" too, just then it would apply modulo at every step, and update index itself with the division as the actual code does:
static String direct(List<StringListPair> mappings,String base,int index) {
for(StringListPair p:mappings) {
base=base.replace(p.s,p.l.get(index % p.l.size())); // modulo "trick" for current label
index /= p.l.size(); // integer division throws away processed label
}
return base;
}
Wrapper function (it has a loop to calculate "2*3" at the beginning, and collects combinations in a list):
static List<String> usedirect(List<StringListPair> mappings,String base){
int total=1;
for(StringListPair p:mappings)
total*=p.l.size();
List<String> result=new ArrayList<>();
for(int i=0;i<total;i++)
result.add(direct(mappings,base,i));
return result;
}
Complete code and demo is on Ideone

Combine all values per key after accumulating data from all nodes using CombineFn

I want to iterate through values of KV pCollection on perKey basis. I used below code to combine using custom class,
PCollection<KV<String, String>> combinesAttributes =
valExtract.get(extAttUsers).apply(Combine.<String, String>perKey(
new CombineAttributes()));
And below is my custom combine class,
public static class CombineAttributes implements SerializableFunction<Iterable<String>, String> {
#Override
public String apply(Iterable<String> input) {...}..}
This was working fine for small inputs but for large inputs the combine was not as expected. The output had combined only few values for a key, others were missing. I was assuming that the output had only combined data from one node.
The documentation in https://cloud.google.com/dataflow/model/combine mentions to use CombineFn in order to combine full collection-of-values per key in all nodes.
But when I changed the custom combine function as below, I am getting following error,
incompatible types: CombineAttributes cannot be converted to com.google.cloud.dataflow.sdk.transforms.SerializableFunction<java.lang.Iterable<java.lang.String>,java.lang.String>
Combine function
public static class CombineAttributes extends CombineFn<Iterable<String>, CombineAttributes.Accum, String> {
public static class Accum {
List<String> inputList = new ArrayList<String>();
}
public Accum createAccumulator() { return new Accum(); }
public Accum addInput(Accum accum, Iterable<String> input) {
for (String item : input) {
accum.inputList.add(item);
}
return accum;
}
public Accum mergeAccumulators(Iterable<Accum> accums) {
Accum merged = createAccumulator();
for (Accum accum : accums) {
for (String item : accum.inputList) {
merged.inputList.add(item);
}
}
return merged;
}
public String extractOutput(Accum accum) {
return "";
}
}
There was no sample code available for combine perKey extending CombineFn. Please let me know what is wrong with the code above.
If you just want to iterate through all the values you can use GroupByKey to turn a PCollection<KV<K, V>> into PCollection<KV<K, Iterable<V>>. Then you can write a DoFn that processes each element of that, and inside iterate over the Iterable<V>.
Note that you'll only receive all values associated with a key in the same window. If you're using the default global window, that will be all values.
Combine and CombineFn are most useful when you want to combine all the values into a smaller output. For instance, if you want to take the sum or mean of all the values it will be more efficient to do so using Sum.perKey() or Mean.perKey(). The efficiency comes from being able to pass around (and merge) accumulators. In the case of Sum, this corresponds to a partial sum.
As an example, say the pipeline runs on two machines. The first machine processes KV<user1, attr1a>, KV<user1, attr1b>, KV<user2, attr2a> and the second machine processes KV<user1, attr1c>, KV<user2, attr2b>.
The CombineAttributes (either way it was implemented) would first be invoked on each machine. So it could combine [attr1a, attr1b] into a single string or accumulator (say attr1a+attr1b). Then it would run on the other machine to combine [attr1c] to attr1c. Then it would merge all of these partial results to get a final accumulator -- attr1a+attr1b+attr1c. In the case of the original implementation, that would be the final answer. In the latter, extractOutput would be called on this accumulator.

How can I use functional programming to do string manipulation?

I'm writing a function where I'm essentially doing the same thing over and over. I have the function listed below
public String buildGarmentsString(List<Garment> garments)
{
StringBuilder garmentString = new StringBuilder(10000);
for(int i=0;i<4;i++)
{
garmentString.append(this.garmentProductId(i,garments.get(i).getProductId()));
garmentString.append(this.garmentColor(i,garments.get(i).getColor()));
for(int j=0;j<garments.get(i).getSizes().size();j++)
{
//check xxsml
if(garments.get(i).getSizes().get(j).getXxsml() >0)
{
garmentString.append(this.garmentSizes(i, Size.xxsml(),garments.get(i).getSizes().get(j).getXxsml()));
}
//check xsml
if(garments.get(i).getSizes().get(j).getXsml() > 0)
{
garmentString.append(this.garmentSizes(i,Size.xsml(),garments.get(i).getSizes().get(j).getXsml()));
}
//check sml
if(garments.get(i).getSizes().get(j).getSml() > 0)
{
garmentString.append(this.garmentSizes(i,Size.sml(),garments.get(i).getSizes().get(j).getSml()));
}
//check med
if(garments.get(i).getSizes().get(j).getMed() > 0)
{
garmentString.append(this.garmentSizes(i,Size.med(),garments.get(i).getSizes().get(j).getMed()));
}
//check lrg
if(garments.get(i).getSizes().get(j).getLrg() > 0)
{
garmentString.append(this.garmentSizes(i,Size.lrg(),garments.get(i).getSizes().get(j).getLrg()));
}
//check xlrg
if(garments.get(i).getSizes().get(j).getXlg() > 0)
{
garmentString.append(this.garmentSizes(i,Size.xlg(),garments.get(i).getSizes().get(j).getXlg()));
}
//check xxlrg
if(garments.get(i).getSizes().get(j).getXxl() >0)
{
garmentString.append(this.garmentSizes(i,Size.xxlg(),garments.get(i).getSizes().get(j).getXxl()));
}
//check xxxlrg
if(garments.get(i).getSizes().get(j).getXxxl() >0)
{
garmentString.append(this.garmentSizes(i,Size.xxxlg(),garments.get(i).getSizes().get(j).getXxxl()));
}
}
}
}
This is my garmentSizes function:
public String garmentSizes(int garmentNumber, String size,int numberToSend)
{
String garmentSizes = "&garment["+garmentNumber+"][sizes]["+size+"]="+numberToSend;
return garmentSizes;
}
I'm trying to figure out how I can get this done with a lot less code. I've read that with functional programming you can do things like pass in functions to parameters to other functions. After doing some reading online, I think I want to do something like this but I'm not sure how or what the best approach would be.
I have done some reading here on stack overflow and I've seen people mention using either the Command pattern or FunctionalJava or LambdaJ for trying to approximate this feature in Java. I've read over the documentation for the two libraries and read the Wikipedia Article on the Command Pattern, but I'm still not sure how I would use any of those to solve my particular problem. Can somebody explain this to me? As somebody that has never done any functional programming this is a bit confusing.
You could use local variables to decrease the amount of repetition. Say bySize = garments.get(i).getSizes().get(j) for example.
instead of size.getXxsml(), size.getXsml() etc. you could use an enum for sizes and loop on sizes.
The whole thing would then look like:
for(int j=0;j<garments.get(i).getSizes().size();j++) {
bySize = garments.get(i).getSizes().get(j);
for (Size s : Size.values()) {
if (bySize.get(s) > 0) {
garmentString.append(garmentSizes(i, s, bySize.get(s)));
}
}
}
The bySize.get(s) method could be implemented either with a switch that directs to the right method or directly in the enum and you could get rid of the getXsml etc. methods.
The only thing which differs between all your checks is this:
getXxsml/xxsml, getXsml/xsml, getSml/sml, etc.
If you could pass these values (as strings) to some upper-level method, and if
that upper-level method could eval i.e. execute these strings, then you can just
have an array of these values and pass that array to that upper-level method.
In Java, you can do something similar with reflection.
All these checks could indeed be simplified to much less
code through the use of reflection.
Look at:
java.lang.Class
java.lang.reflect.Method
java.lang.reflect.Field
java.lang.reflect.Constructor
and you will see what I mean.
From your code it appears that some Class has the following methods:
xxsml(), xsml(), sml(), med(), ..., xxxlg()
to get the amounts (?) available for each size.
You can design your data better, like this:
Have a "Size" type, that enumerates all sizes (could be Enum or some class with attribute String key)
Have a method that returns a List of all known sizes.
replace the above methods with amountFor(Size) This could be backed by a Map<Size, Integer>
For backward compatibility, you could rewrite the old methods along the lines:
int xxsml() {
return amountFor(Size.XXSML); // assuming you have a singleton instance
// for each well known size
}
Of course, in getGarmentString, you would then loop through the List of all known sizes:
for (Size sz : Size.getAllKnownSizes()) {
if (garments.get(i).getSizes().get(j).amountFor(sz) > 0) {
... do whatever must be done here
}
}

Switch or if statements in writing an interpreter in java

Current assignment needs me to write a program to read a file with instructions in a very tiny and basic programming language (behaves a little like FORTRAN) and execute those instructions. Basically it's a simple interpreter for the language I guess. It's completely linear, with statements all being defined in sequence and it only has String and integer variables. There are 8 keywords and 4 arithmetic operators I would need to find and define if they exist within the source file, and each line must start off with one of the reserved words.
A program in this language might look something like this:
#COMMENTS
LET.... (declares variables with values)
INTEGER myINT
STRING myString
CALCULATE...
PRINT
PRINTLN
END
Can I use a switch block instead of if-loops to find and then execute all these? My concern is that switches don't work with Strings in Java 6, which is what I'm supposed to be using, but I don't see how to easily assign various int values so the switch block would work. Thanks in advance for any suggestions and advice!
If your language is so simple that every statement begins in its own line and is identified by one word only, then (as Gray pointed out in another comment) you can split the words in each line, then compare the first word against a map. However, I would suggest, instead of mapping the words to ints and then doing one big switch, to map them into objects instead, like this (suggested by Dave Newton):
interface Directive {
public void execute(String line);
}
class LetDirective implements Directive {
public void execute(String line) { ...handle LET directive here... }
}
...define other directives in the same way...
Then define the map:
private Map<String, Directive> directives = new HashMap<String, Directive>();
directives.put("LET", new LetDirective());
...
Then in your parsing method:
int firstSpace = line.indexOf(' ');
String command = line;
if (firstSpace > 0)
command = line.substring(0, firstSpace);
Directive directive = directives.get(command.toUpperCase());
if (directive != null)
directive.execute(line);
else
...show some error...
Each directive would have to parse the rest of the line on its own and handle it correctly inside its execute() method.
The benefit of this over a switch is that you can handle a larger amount of commands without ending up with one gigantic method, but instead with one smaller method per each command.
If you are talking about converting strings to integers then you could do it with an Java enumerated type:
private enum ReservedWord {
LET,
...
}
// skip blank lines and comments
String[] tokens = codeLine.split(" ");
ReservedWord keyword;
try {
keyword = ReservedWord.valueOf(tokens[0]);
} catch (IllegalArgumentException e) {
// spit out nice syntax error message
}
You could also put the processing of the line inside of the enum as a method if you'd like. You could also do it with a Map:
private final Map<String, Integer> reservedWords = new HashMap<String, Integer>();
private final int RESERVED_WORD_LET 1
...
{
reservedWords.put("LET", RESERVED_WORD_LET);
...
}
// skip blank lines and comments
String[] tokens = codeLine.split(" ");
Integer value = reservedWords.get(tokens[0]);
if (value == null) // handle error... ;
switch (value) {
case 1:
// LET
...
}

Categories

Resources