Returning different return value - java

When i have a problem with the code im writing, i usually handle it like a story. Each command is a sentence in a story. The sentences needs to make sense in order for the story to be complete/right.
So im learning java from scratch now with the MOOC course at Helsinki University. I got somewhat stuck at exercise 68. The program is suppose to compare integer values of a list(array) together with user input. What i programmed is a method that return true if the user input number is already on the list, and false if its not.
What I said about story at the start: The commented out code is my initial code. This did not past the last test but in my head both the commented out code and the other code say basically the same
Error message (from last test):
"Answer wrong when parameter was list [0, 7, 9, -1, 13, 8, -1] and value 8 expected: false but was: true"
public static boolean moreThanOnce(ArrayList<Integer> list, int searched)
// if (list.size()==1) {return false;}
//
// for (int i = 0; i < list.size();i++ ){
// if (list.contains(searched))
//
// {
//
// return true; }
//
// }
//return false;
//
int counter = 0;
for (int num : list) {
if (searched == num) {
counter++;
}
}
if (counter >= 2){
return true;
} else {
return false;
}
}
I understand that there is something wrong, just cant seem to figure it out. Do you see why the last code would be accepted, but not the first (commented out one) ?
If any use, the rest of the code (not my work) is this:
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(3);
list.add(2);
list.add(7);
list.add(2);
System.out.println("Type a number: ");
int number = Integer.parseInt(reader.nextLine());
if (moreThanOnce(list, number)) {
System.out.println(number + " appears more than once.");
} else {
System.out.println(number + " does not appear more than once. ");
}
}
}

Code that is commented out guaranties only that if true there is at least one of occurance in array, maybe there are more but not guaranted. If function returns false thes may be 1 or no occurance.
Reason: If arrary os bigger than 1 it does not mean that there are 2 or more occurances of value you search for.
Posible solution: Add counter like uncommented code.

Your first algorithm has a few flaws, first you test for a length of one explicitly. Not null, and not an empty List. Second, you should prefer the List interface to the ArrayList explicit type. And finally, you need to consider the sublist offset by one of the current position when you call contains (clearly the list contains at least the current value).
I think you wanted something like
public static boolean moreThanOnce(List<Integer> list, int searched) {
if (list == null || list.size() < 2) {
return false;
}
int len = list.size();
for (int i = 0; i < len - 1; i++) {
if (list.get(i).equals(searched)
&& list.subList(i + 1, list.size()).contains(searched)) {
return true;
}
}
return false;
}
And, we can express that as generic method. Like,
public static <T> boolean moreThanOnce(List<T> list, T searched) {
if (list == null || list.size() < 2) {
return false;
}
int len = list.size();
for (int i = 0; i < len - 1; i++) {
if (list.get(i).equals(searched)
&& list.subList(i + 1, list.size()).contains(searched)) {
return true;
}
}
return false;
}
or, if you're using Java 8+, use a Stream and filter and then count like
public static <T> boolean moreThanOnce(List<T> list, T searched) {
if (list == null || list.size() < 2) {
return false;
}
return list.stream().filter(v -> v.equals(searched)).count() > 1;
}

Related

Can't find the problem with my solution to leetcode problem

I am trying the ransom note challenge:
Given two strings ransomNote and magazine, return true if ransomNote can be constructed by using the letters from magazine and false otherwise.
Each letter in magazine can only be used once in ransomNote.
Example 1:
Input: ransomNote = "a", magazine = "b"
Output: false
Example 2:
Input: ransomNote = "aa", magazine = "ab"
Output: false
Example 3:
Input: ransomNote = "aa", magazine = "aab"
Output: true
here is my solution:
public static boolean canConstruct(String ransomNote, String magazine) {
ArrayList<Character> ransomChar = new ArrayList<Character>();
ArrayList<Character> magazineChar = new ArrayList<Character>();
if (ransomNote.length() == 1 && magazine.length() == 1) {
if (ransomNote.equals(magazine)) {
return true;
}
return false;
}
else if (ransomNote.length() == 1 && magazine.length() > 1) {
for (int i = 0; i < magazine.length(); i++) {
if (magazine.charAt(i) == ransomNote.charAt(0)) {
return true;
}
}
return false;
}
else if (ransomNote.length() > 1 && magazine.length() > 1) {
for (int i = 0; i < ransomNote.length(); i++) {
ransomChar.add(ransomNote.charAt(i));
}
for (int i = 0; i < magazine.length(); i++) {
magazineChar.add(magazine.charAt(i));
}
while (ransomChar.size() > 1) {
for (int i = 0; i < ransomChar.size(); i++) {
boolean flag = false;
for (int j = 0; j < magazineChar.size(); j++) {
if (ransomChar.get(i).equals(magazineChar.get(j))) {
ransomChar.remove(i);
magazineChar.remove(j);
flag = true;
}
else if (ransomChar.isEmpty()) {
return true;
}
}
if (!flag) {
return false;
}
}
}
if (ransomChar.size() == 1 && magazineChar.size() == 1) {
if (ransomChar.equals(magazineChar)) {
return true;
}
return false;
}
else if (ransomChar.size() == 1 && magazineChar.size() > 1) {
for (int i = 0; i < magazineChar.size(); i++) {
if (ransomChar.get(0).equals(magazineChar.get(i))) {
return true;
}
}
return false;
}
}
return false;
}
I am passing most test cases but it throws an error at input:
"bg"
"efjbdfbdgfjhhaiigfhbaejahgfbbgbjagbddfgdiaigdadhcfcj"
It throws error:
java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
at line: if (ransomChar.get(i).equals(magazineChar.get(j)))
Here's a simple way to attack your problem by building a set of candidate characters from magazine. Once you've done that, you just iterate over the ransomNote, checking the set for each character. If you find it, you remove it from the set. If you don't, then you return false. If you make it all the way through, you return true. You need to use a MultiSet because you need to be able to represent multiple copies of the same character in the magazine.
Here's how to do that:
public static boolean canConstruct(String ransomNote, String magazine) {
MultiSet<Character> magazineChars = new HashMultiSet<>();
for (int i = 0; i < magazine.length(); i++)
magazineChars.add(magazine.charAt(i));
for (int i = 0 ; i < ransomNote.length(); i++) {
Character c = ransomNote.charAt(i);
if (magazineChars.contains(c))
magazineChars.remove(c);
else
return false;
}
return true;
}
On each iteration of this loop:
for (int i = 0; i < ransomChar.size(); i++) {
boolean flag = false;
for (int j = 0; j < magazineChar.size(); j++) {
if (ransomChar.get(i).equals(magazineChar.get(j))) {
ransomChar.remove(i);
magazineChar.remove(j);
flag = true;
}
else if (ransomChar.isEmpty()) {
return true;
}
}
if (!flag) {
return false;
}
}
, you know that i is initially less than ransomChar.size(), so that it is safe to perform ransomChar.get(i).
However, the inner loop may remove one (or more!) elements of ransomChar, after which it may no longer be true that i is less than ransomChar.size(). The inner loop continues to iterate, and as a result, it can attempt to retrieve an element of ransomChar that does not exist.
Honestly, the code overall is a mess. Other than this specific issue,
I see no need why you need special cases for all the variations on sizes of note and magazine. I think you might write better code for this if you devoted some effort to designing an approach that just works correctly for all cases.
you are not making good use of the available features of the classes you are using
you are not making good use of general Java language features that would be applicable.
For example, I might write that particular loop as:
for (Character c : ransomChar) {
if (!magazineChar.remove(c)) {
return false;
}
}
return true;
And that's before we come to the fact that you've chosen a suboptimal algorithm. Its execution time will scale as note size * magazine size, whereas there are alternatives that will scale as note size + magazine size, instead. That may in fact be important, because choice of an efficient algorithm is one thing that the test cases for coding challenges such as this often try to detect.
Please find small and simple solution with Time complexity O(n) and Space complexity O(256) or O(1)
int[] count = new int[256];
for (char c : magazine.toCharArray()) {
count[c]++;
}
for (char c : ransomNote.toCharArray()) {
if (count[c]-- == 0) return false;
}
return true;
Result
#Harsh so you are trying to access the element of ransomChar which do not even exists. look at the lines
if (ransomChar.get(i).equals(magazineChar.get(j))) {
ransomChar.remove(i);
magazineChar.remove(j);
flag = true;
}
you are removing the elements from the lists and and every time you remove the elements from the list their indexing changes and and when it rechecks the condition the list is already empty after several iteration. Hence giving the run time error. to avoid this you should check whether the list is empty or not , first (you are checking it after).

I keep getting a missing return statement?

In my code I'm trying to go through the arraylist and see if theres any reoccurring numbers. I keep getting an error saying i have a missing return statement. Is my code correct and how do I fix this problem.
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(3);
list.add(2);
list.add(7);
list.add(2);
System.out.println("Type a number: ");
int number = Integer.parseInt(in.nextLine());
if (moreThanOnce(list,number)) {
System.out.println(number + " appears more than once");
}
else
System.out.println(number + " number does not appear more than once");
}
public static boolean moreThanOnce(ArrayList<Integer> list , int number) {
int count = 0;
for (int i = 1; i < list.size(); i ++ ) {
if (list.get(i) == number) {
count ++;
if (count > 1) {
return true;
}
else
return false;
}
}
Just remove the else part and move the "return false" outside the for loop in your moreThanOnce method
Change to:
public static boolean moreThanOnce(ArrayList<Integer> list , int number) {
int count = 0;
for (int i = 1; i < list.size(); i ++ ) {
if (list.get(i) == number) {
count ++;
if (count > 1) {
return true;
}
}
}
return false;
}
This guarantees that a return statement (false) is sent back if either there is not a recurring number that's equal to number and if it never enters the for-loop as well. It will return true if the conditions you put is met.
public static boolean moreThanOnce(ArrayList<Integer> list , int number) {
int count = 0;
for (int i = 1; i < list.size(); i ++ ) {
if (list.get(i) == number) {
count ++;
if (count > 1) {
return true;
}
else //delete this line
return false; // delete this line
}
}
return false;//add return here
}
To solve the error, it only needs a return outside the for loop.
And I think you should delete else logic, that makes the method cannot find the number which appears more than one time correctly.
You are missing a return statement in the case of the for loop not being executed in the moreThanOnce method.
You're missing a closing brace "}" for moreThanOnce(). It has four open braces, but only three closing braces.
Most code-oriented editors will match braces for you, and help track down imbalanced braces (and parens, etc.) Figure out how to do that in your editor, as that's something you'll need throughout your programming career.

How to print out the index of a boolean array?

I'm trying to get all of the indexes of a Boolean array to be printed out where its element is true. The end goal is to be able to find a prime number of the indexes (where I change each index number that isn't prime to false in the array) then print out only what is left of the prime numbers of the indexes of the array.
The very first step I'm just trying to do is at least to get some integer index to print out, but nothing seems to be working and I don't know what is wrong.
public class PriNum{
private boolean[] array;
public PriNum(int max){
if (max > 2){ //I don't have any problems with this if statement
throw new IllegalArgumentException();
}
else{
array = new boolean[max];
for(int i = 0; i < max; i++){
if(i == 0 || i == 1){ //Automatically makes 0 and 1 false
//because they are not prime
array[i] = false;
}
else{
array[i] = true;
}
}
toString(); //I know for sure the code gets to here
//because it prints out a string I have
// there, but not the index
}
}
public String toString(){
String s = "test"; //this only prints test so I can see if
//the code gets here, otherwise it would just be ""
for (int i = 0; i < array.length; i++){
if(array[i] == true){
s = s + i; //Initially I tried to have the indexes returned
//to be printed and separated by a comma,
//but nothing comes out at all, save for "test"
}
}
return s;
}
}
EDIT: Included is the driver class that's requesting the print of the class PriNum
class Driver{
public static void main(String [] args){
PriNum theprime = null;
try{
theprime = new PriNum(50);
}
catch (IllegalArgumentException oops){
System.out.println("Max must be at least 2.");
}
System.out.println(theprime);
}
}
I tried running this, and the first change that needs to happen is to set this argument:
if(max < 2)
Then, if I'm reading this correctly: 0 and 1 are false. Every index after that is true. The output is fine as I see it. Just all the numbers crunched as a continuous list.
To get a better output, put a space between indexes:
if(array[i] == true){
s = s + " " + i;
}
You may even just output to screen directly as
if(array[i])
System.out.print( i );
numbers is initialized without declaration, array is declared but not initialized anywhere in your code. You have also a syntax error after array[i] = true, should be curly brace...

Check if every elements in array is of same value

Basically what I want to do is to check on each element in an array of int, if all elements are of the same value.
I create int array as below to pass to the method for comparing each array element, it return boolean true even tough the elements are not all the same values.
Int[] denominator = {3,3,4,3};
boolean compare;
compare = bruteforce(denominator);
public static boolean bruteforce(int[] input) {
int compare =0;
int count =0;
for (int i = 0; i < input.length; i++) {
compare = input[i];
while(count<input.length){
if(input[i+1]==compare){
return true;
}
i++;
count++;
}//end while
}//end for
return false;
}//end method
I suppose the method above will loop for and keep compare for each element of the array.
When I print out the output, it showed that it only loop once, the return the boolean as true.
I really lost the clue what could be wrong in my code.
Perhaps I just overlook of some silly mistakes.
Try,
Integer[] array = {12,12,12,12};
Set<Integer> set = new HashSet<Integer>(Arrays.asList(array));
System.out.println(set.size()==1?"Contents of Array are Same":"Contents of Array are NOT same");
Explanation:
Add the array to a set and check the size os set , if it is 1 the contents are same else not.
You only need one loop and should return false as quickly as possible where applicable (i.e. when you encounter an element that doesn't match the first).
You also need to account for the edge cases that the input array is null or has one element.
Try something like this, which I minimally adapted from the code you provided...
public class BruteForceTest {
public static boolean bruteforce(int[] input) {
// NOTE: Cover the edge cases that the input array is null or has one element.
if (input == null || input.length == 1)
return true; // NOTE: Returning true for null is debatable, but I leave that to you.
int compare = input[0]; // NOTE: Compare to the first element of the input array.
// NOTE: Check from the second element through the end of the input array.
for (int i = 1; i < input.length; i++) {
if (input[i] != compare)
return false;
}
return true;
}
public static void main(String[] args) {
int[] denominator = {3,3,4,3};
boolean compare = bruteforce(denominator);
// FORNOW: console output to see where the first check landed
System.out.print("{3,3,4,3}:\t");
if (compare)
System.out.println("Yup!");
else
System.out.println("Nope!");
// NOTE: a second array to check - that we expect to return true
int[] denominator2 = {2,2};
boolean compare2 = bruteforce(denominator2);
System.out.print("{2,2}:\t\t");
if (compare2)
System.out.println("Yup!");
else
System.out.println("Nope!");
/*
* NOTE: edge cases to account for as noted below
*/
// array with one element
int[] denominator3 = {2};
System.out.print("{2}:\t\t");
if (bruteforce(denominator3))
System.out.println("Yup!");
else
System.out.println("Nope!");
// null array
System.out.print("null:\t\t");
if (bruteforce(null))
System.out.println("Yup!");
else
System.out.println("Nope!");
}
}
...and outputs:
{3,3,4,3}: Nope!
{2,2}: Yup!
{2}: Yup!
null: Yup!
If an array elements are equal you only need to compare the first element with the rest so a better solution to your problem is the following:
public static boolean bruteforce(int[] input) {
for(int i = 1; i < input.length; i++) {
if(input[0] != input[i]) return false;
}
return true;
}
You don't need more than one loop for this trivial algorithm. hope this helps.
If all elements are the same value, why not use only one for loop to test the next value in the array? If it is not, return false.
If you want to check if all elements are of same value then you can do it in a simpler way,
int arr = {3,4,5,6};
int value = arr[0];
flag notEqual = false;
for(int i=1;i < arr.length; i++){
if(!arr[i] == value){
notEqual = true;
break;
}
}
if(notEqual){
System.out.println("All values not same");
}else{
System.out.println("All values same);
}
Right now, you are not checking if "all the elements are of the same value". You are ending the function and returning true whenever (the first time) two elements are equal to each other.
Why not set the boolean value to true and return false whenever you have two elements that are not equal to each other? That way you can keep most of what you have already.
if(input[i+1]!=compare) return false;
public class Answer {
public static void main(String[] args)
{
boolean compare = false;
int count = 0;
int[] denominator = { 3, 3, 4, 3 };
for (int i = 0; i < denominator.length; i++)
{
if(denominator[0] != denominator[i])
{
count++;
}
}
if(count > 0)
{
compare = false;
} else
{
compare = true;
}
System.out.println(compare);
}
}
One mistake that I noticed right of the bat was that you declared your array as Int[], which is not a java keyword it is in fact int[]. This code checks your array and returns false if the array possesses values that are not equal to each other. If the array possesses values that are equal to each other the program returns true.
If you're interested in testing array equality (as opposed to writing out this test yourself), then you can use Arrays.equals(theArray, theOtherArray).

List collections interface in java

Please find below a function in my code:
private static List<String> formCrfLinesWithMentionClass(int begin, int end, String id,
List<String> mList, int mListPos, List<String> crf) {
List<String> crfLines = crf;
int yes = 0;
mListPosChanged = mListPos;
//--------------------------------------------------------------------------
for (int crfLinesMainIter = begin; crfLinesMainIter < end; ) {
System.out.println(crfLines.get(crfLinesMainIter));
//---------------------------------------------------------------------------
//the total number of attributes without orthographic features
//in a crfLine excluding the class attribute is 98
if (!crfLines.get(crfLinesMainIter).equals("") && crfLines.get(crfLinesMainIter).split("\\s").length == 98) {
//in mList parenthesis are represented by the symbol
//in crfLines parenthesis are represented by -LRB- or -RRB-
//we make a check to ensure the equality is preserved
if(val.equals(crfLines.get(crfLinesMainIter).split("\\s")[0])) {
yes = checkForConsecutivePresence(crfLinesMainIter, mList, mListPos, id, crfLines);
if (yes > 0) {
mListPosChanged += yes;
System.out.println("formCrfLinesWithMentionClass: "+mListPosChanged);
for (int crfLinesMentionIter = crfLinesMainIter;
crfLinesMentionIter < crfLinesMainIter + yes;
crfLinesMentionIter++) {
String valString = "";
if (crfLinesMentionIter == crfLinesMainIter) {
valString += crfLines.get(crfLinesMentionIter);
valString += " B";
crfLines.add(crfLinesMentionIter, valString);
}
else {
valString += crfLines.get(crfLinesMentionIter);
valString += " I";
crfLines.add(crfLinesMentionIter, valString);
}
}
crfLinesMainIter += yes;
}
else {
++crfLinesMainIter;
}
}
else {
++crfLinesMainIter;
}
}
else {
++crfLinesMainIter;
}
}
return crfLines;
}
The problem I face is as follows:
crfLines is a List collections interface.
When the for loop (between //-----) starts out, the crfLines.get(crfLinesMainIter) works fine. But once, it enters into the if and other processing is carried out on it, even though "crfLinesMainIter" changes the crfLines.get(crfLinesMainIter) seems to get a certain previous value. It does not retrieve the actual value at the index. Has anyone faced such a scenario? Would anyone be able to tell me why this occurs?
My actual question is, when does it occur that even though the indexes might be different a list.get() function still retrieves a value from before which was at another index?
For example:
List crfLines = new LinkedList<>();
if crfLinesMainIter = 2
crfLines.get(crfLinesMainIter) brings me a value say 20 and this value 20 satisfies the if loop condition. So then further processing happens. Now when the for loop executes the values of crfLinesMainIter changes to say 5. In this case, crfLines.get(5) should actually bring me a different value, but it still brings me the previous value 20.
(Not an answer.)
Reworked (more or less) for some modicum of readability:
private static List<String> formCrfLinesWithMentionClass(int begin, int end, String id, List<String> mList, int mListPos, List<String> crf) {
List<String> crfLines = crf;
mListPosChanged = mListPos;
int i = begin;
while (i < end) {
if (crfLines.get(i).equals("") || (crfLines.get(i).split("\\s").length != 98)) {
++i;
continue;
}
if (!val.equals(crfLines.get(i).split("\\s")[0])) {
++i;
continue;
}
int yes = checkForConsecutivePresence(i, mList, mListPos, id, crfLines);
if (yes <= 0) {
++i;
continue;
}
mListPosChanged += yes;
for (int j = i; j < i + yes; j++) {
String valString = crfLines.get(j);
valString += (j == i) ? " B" : " I";
crfLines.add(j, valString);
}
i += yes;
}
return crfLines;
}
What is mListPostChanged? I find it confusing that it's being set to the value of a parameter named mListPos--it makes me think the m prefix is meaningless.
What is val in the line containing the split?

Categories