I struggle with very strange behaviour while trying to compare two ints but first things first. Here is my method inside the class:
public class CollectionsTutorial {
private Collection<String> collection = null;
public CollectionsTutorial() {
this.collection = new ArrayList<String>();
for(int i=0;i<100000;i++) {
collection.add("item_"+((i+1)%10000));
}
}
public Set<String> getSet(){
HashSet<String> set = new HashSet<String>(10000);
for(String item: this.collection) {
if (!set.contains(item)) {
set.add(item);
}
}
return set;
}
public TreeSet<String> getEvery3ElementAsSortedSet(){
TreeSet<String> tree = new TreeSet<String>();
int counter = 0;
for(String item : this.collection) {
if (counter%2==0) {
tree.add(item);
counter = -1;
}
counter++;
}
return tree;
}
}
The whole class doesn't really matter here - it only holds ArrayList<String>. I need to return every 3rd element in a tree and everything goes well until it's time to compare current counter value. It returns true everytime. I'm sure of it becouse while testing it's adding to the Tree every single element of collection. I've tried using compareTo(), equalsTo(), valueOf() and intValue() but nothing helps.
EDIT.
I've change code to the class view - maybe something else is cousing the error?
Here is test i'm trying to pass
public class CollectionsTutorialTest {
#Test
public void GetEvery3ElementTest() {
CollectionsTutorial testObj = new CollectionsTutorial();
TreeSet<String> tree = new TreeSet<String>();
tree.addAll(testObj.getSet() );
assertEquals(false, tree.contains("item_2"));
}
}
"I need to return every 3rd element in a tree..." this description screams for the modulo % operator.
If you want to enter an if-condition on every 3rd iteration then you can check this with the following condition: counter % 3 == 0. You don't need to subtract anything at all.
How does % work?
Put simply: The modulo operator returns the result of a division.
Example:
5 / 3 = 1 with remain 2
5 % 3 = 2
9 / 3 = 3 with remain 0
9 % 3 = 0
Note:
if (counter % 2 == 0) {
tree.add(item);
counter = -1;
}
counter++;
You use counter % 2 == 0. This will return true for the second element. Afterwards you set counter = -1 because you intend to get every 3rd element. However, this does not work.
Here's the reason why:
System.out.println(0 % 1); // 0 % 1 = 0
System.out.println(0 % 2); // 0 % 2 = 0
System.out.println(0 % 3); // 0 % 3 = 0
System.out.println(0 % 4); // 0 % 4 = 0
As you can see, every time your counter reaches the value 0 the if-condition will result in true regardless of the divisor. That's why you use % 3.
the list is created by:
for(int i=0;i<100_000;i++) {
collection.add("item_"+((i+1)%10_000));
}
resulting in:
collection[0] = item_1
collection[1] = item_2
collection[2] = item_3
collection[3] = item_4
...
collection[9_998] = item_9999
collection[9_999] = item_0 // (9_999+1) % 10_000 is 0
collection[10_000] = item_1 // (10_000+1) % 10_000 is 1
collection[10_001] = item_2
collection[10_002] = item_3
collection[10_003] = item_4
...
collection[19_998] = item_9999 // (19_998+1) % 10_000 is 9_999
collection[19_999] = item_0 // (19_999+1) % 10_000 is 0
collection[20_000] = item_1
collection[20_001] = item_2
collection[20_002] = item_3
collection[20_003] = item_4
...
above is NOT code
now note that 20_001 % 3 is 0 - so the third item_2 will be picked; same true for 50_001 % 3 and 80_001 % 3. So, actually that item is added 3 times to the tree (since it is a Set, only one instance is kept). At the end, one version of each item will be present in the result. Similar to counter%3 == 1 or counter%3 == 2 (basically the first code version posted in question.)
Lesson: checking that item_2 is present or not, does NOT check if the condition "returns true everytime".
Better test:
...
int index = 0; // DEBUG
for(String item : this.collection) {
if (counter%2==0) {
System.out.println(index); // DEBUG
tree.add(item);
counter = -1;
}
index += 1; // DEBUG
...
above is not the full code, just showing idea for testing
Bonus:
a Set does not save duplicates ("A collection that contains no duplicate elements"), in below snippet:
if (!set.contains(item)) {
set.add(item);
}
the if is not necessary - this is already checked by add()
Related
I have to tell the minimum number of times string A needs to be repeated so that string B becomes a substring of A.
My answer is wrong for some test cases like
A = "abc"
B = "cabcabca"
My output is coming 3..it should be 4.
My code is-
class Solution {
public int repeatedStringMatch(String A, String B) {
int count = 0;
while (A.length() <= 1000) {
if (A.indexOf(B) != -1)
return (count + 1);
else
A = A + A;
count++;
}
return -1;
}
}
The problem is because of A=A+A; as it makes A as abcabc after the first iteration, abcabcabcabc after the second iteration, abcabcabcabcabcabcabcabc after the third iteration and so on i.e. instead of getting appended, the string is getting doubled in each iteration.
It is like you have been given a task to add 2 to itself in each iteration i.e. after the first iteration, it should become 2 + 2 = 4, after the second iteration, it should become 4 + 2 = 6, after the third iteration it should become 6 + 2 = 8 and so on.
Whereas the way you have done, it will become 2 + 2 = 4 after the first iteration, 4 + 4 = 8 after the second iteration, 8 + 8 = 16 after the third iteration and so on.
As a side note, you should avoid using string concatenation in a loop. You should also follow Java naming convention e.g. the variable name A should be a.
Do it as follows:
public class Main {
public static void main(String[] args) {
// Test
System.out.println(repeatedStringMatch("abc", "cabcabca"));
}
static int repeatedStringMatch(String a, String b) {
int count = 1;
StringBuilder sb = new StringBuilder(a);
while (sb.length() <= 1000) {
if (sb.indexOf(b) != -1) {
return count;
} else {
sb.append(a);
count++;
}
}
return -1;
}
}
Output:
4
we have an array of ratings, we have to find the max rating in such a away that we cannot skip 1 or more consecutive rating in an arrray
Example-1: {9,-1,-3,-4,-5} output = 9 + -1 + -4 = 4
Explanation: I took 9 the we have to took -1 or -3 we cannot jump to -4 directly as we cannot skip 1 or more consecutive number.
Example-2: {-1,-2,-3,-4,-5} output = -2 + -4 = -6
Example-3: {-3,2,-4,-1,-2,5} output = 2 + -1 + 5 = 6
Example-4: {9,-1,-3,4,5} output = 9 + -1 + 4 + 5 = 17
I tried below code but it is working in case of example: 2,3,4 but not for example 1 similarly failing for other scenario.
static int maximizeRatings(int[] ratings) {
int current = 0;
boolean result = false;
for(int j=0; j<ratings.length;j++){
if(ratings[j]<0){
result = true;
}else{
result = false;
}
}
if(result){
return allnegatine(ratings);
}
for(int i=0; i<ratings.length;i++){
if(i == ratings.length-1){
if(ratings[i] > 0)
current += ratings[i];
}else{
if(ratings[i] >0 && ratings[i+1]>0){
current = ratings[i]+ratings[i+1];
i++;
}
if(ratings[i] > ratings[i+1]){
current += ratings[i];
}else{
current += ratings[i+1];
i++;
}
}
}
return current;
}
private static int allnegatine(int[] ratings) {
int current =0;
for(int i=0; i<ratings.length;i++){
if(ratings.length%2==0){
if(i%2 == 0)
current += ratings[i];
}else{
if(i%2!=0)
current += ratings[i];
}
}
return current;
}
not getting excepted out for some scenarios like example 1 I am getting -6 instead of 4, I am trying to get proper code which will pass all scenarios. Thank you
This is a dynamic programming problem.
Let dp[i] be the max ratings which can be achieved considering only the part of the array that starts at zero, ends at i, and includes ratings[i].
dp[0]=ratings[0]
dp[1]=max(ratings[1],ratings[0]+ratings[1])
dp[i]=max(dp[i-1],dp[i-2])+ratings[i]
Answer: max(dp[n-1],dp[n-2]) where n is the size of the ratings array.
Also you can chose to do away with dp array and maintain 2 variables for dp[i-1] and dp[i-2].
this is typical recursion problem (as long as the input array is reasonably long). You should go thru items and try all possible combinations and then pick the best one.
Because it looks like typical school work I am not sure if I should paste my solution. You should figure it out yourself or at least understand what's going on to be able to implement it yourself next time.
public class RatingService {
public int calculate(List<Integer> input) {
return recursion(input, true, 0);
}
private int recursion(List<Integer> sublist, boolean canSkip, int sum) {
if (sublist.isEmpty()) {
return sum;
}
int skippedSum = Integer.MIN_VALUE;
int notSkippedSum;
Integer integer = sublist.get(0);
if (canSkip) {
skippedSum = recursion(sublist.subList(1, sublist.size()), false, sum);
}
notSkippedSum = recursion(sublist.subList(1, sublist.size()), true, integer + sum);
return skippedSum > notSkippedSum ? skippedSum : notSkippedSum;
}
}
I think you are doing the mistake while checking for all negative numbers in for loop. If the last element in the array is negative then the 'result' variable will be true means that all array is negative but actually its not.
You have to replace the for loop by :
for(int j=0;j<ratings.length;j++){
if(ratings[j]<0){
result=true;
}
else{
result = false;
break;
}
}
It will break the for loop at the index where it founds any positive number i-e: all elements of array are not negative.
Suppose I have one list which always has the count of even number. Now I want to segregate the list with different group indexes with below conditions,
1) First element (1st element) with one index (EX: 1)
2) Next two elements with same index (Ex: 2nd, 3rd element with index 2,
4th and 5th element with index 3)
3) Last element(6th element) with index 4
I tried with nested for loops to achieve the same, but didn't get the expected output.
Any help is appreciated.
Sample Input:
[2,3,53,52,33,12,44,66]
Sample Output:
2 - 1
3 - 2
53 - 2
52 - 3
33 - 3
12 - 4
44 - 4
66 - 5
I have implemented this using the two additional variables z and count, I am
incrementing z only if the count%2 is 0, and at-last we need to check if the
size-1 is equal to the i variable for the third condition.
Also, for the first condition I am printing the arraylist value at first index and z variable value at i iff the i counter value is 0.
Please see the below code that I have simulated for your input list that I
have added manually ! Please use the link to test :
http://rextester.com/ESYF23501
import javafx.collections.ArrayChangeListener;
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> a= new ArrayList<Integer>();
a.add(2);
a.add(3);
a.add(53);
a.add(52);
a.add(33);
a.add(12);
a.add(44);
a.add(66);
int i = 0;
int z = 2;
//Count to group the middle number by checking its value with respect to mod 2
int count = 0;
for(i = 0; i < a.size(); i++)
{
if(i == 0 )
{
z = i+1;
System.out.println(""+a.get(i)+" " + "" +z+"" );
}
if(i > 0 && i != (a.size() -1))
{
//Increament z if the count is even so that we print the group for two times
if(count%2 == 0)
{
z++;
}
System.out.println(""+a.get(i)+"" +" "+ ""+z+"" );
count ++;
}
if(i == a.size() -1 )
{
z++;
System.out.println(""+a.get(i)+"" +" "+ ""+z+"" );
}
}
}
}
This should work correctly if I understood your question right:
System.out.println(elements.get(0) + " - 1"); // Prints the first number, which has the value of 1
int value = 2; // Value corresponding to the number
for (int i = 1; i < elements.size(); i++) { // Loops through the list starting at second element (index of 1)
System.out.println(elements.get(i) + " - " + value); // Prints the number and the value
if (i % 2 == 0) value++; // Increases the value every two loops
}
It starts by printing out the first number and 1, which as you described always corresponds to each other. Then it loops through the list of numbers starting at the second number (i = 1), and prints out each number and the corresponding value. The value increases every two loops, which is every time the loop number is divisible by 2 (i % 2).
The puzzle is to obtain the minimum number of steps it takes to make a number 1. Allowed operations are
1. You can subtract 1 from the number
2. You can divide the number by 2 if it is divisible by 2.
3. You can divide the number by 3 if it is divisible by 3.
At the end, you need to make the number 1 by performing the above operations. I am trying to obtain a solution that gives me the minimum number of the above operations required to make the number 1.
My code (in Java) is as follows.
public int minStepsBottomUp(int n) {
int[] memoArray = new int[n+1];
memoArray[0] = 0;
memoArray[1] = 0;
for(int i=2;i<=n;++i){
int r = 1 + memoArray[i-1];
if(n % 2 == 0) {
r = Math.min(r, 1+memoArray[n/2]);
}
if(n % 3 == 0) {
r = Math.min(r, 1+memoArray[n/3]);
}
memoArray[i] = r;
}
return memoArray[n];
}
But I get some ambiguous results.Example - if the number is 5, I get the minimun number of steps required as 4. Actually it should be 3. Can someone please explain where I have gone wrong?
I suggest reversing the problem: starting from 1 we should reach n by using three kinds of operations:
add 1
multiply by 2
multiply by 3
For instance for 5 we'll have 3 operations (multiply by 3, add 1, add 1):
1 -> 3 -> 4 -> 5
So far so good, now we have standard dynamic programming problem; C# implementation:
private static int Best(int value) {
if (value <= 0)
return -1; // or throw ArgumentOutOfRangeException
else if (value == 1)
return 0;
Dictionary<int, int> best = new Dictionary<int, int>() { {1, 0} };
List<int> agenda = new List<int>() { 1 };
for (int step = 1; ; ++step)
for (int i = agenda.Count - 1; i >= 0; --i) {
int item = agenda[i];
agenda.RemoveAt(i);
int[] next = new int[] { item + 1, item * 2, item * 3 };
foreach (int v in next) {
if (v == value)
return step;
if (!best.ContainsKey(v)) {
best.Add(v, step);
agenda.Add(v);
}
}
}
}
Tests:
// 3
Console.WriteLine(Best(5));
// 3
Console.WriteLine(Best(10));
// 7
Console.WriteLine(Best(100));
// 19
Console.WriteLine(Best(1000000));
Inside your loop, you are using n instead of i.
For instance, n % 2 == 0 should be i % 2 == 0
If the number is 5 you can get 1 by doing:
int x = 5 - 1;
x = x - 1;
x= x / 3;
I am trying to sort a list using Collections.sort() and noticing notice all the members are being sorted:
Here is my input, a print out of the .compareTo() insides, and the output:
5 4 3 2 1 // Original
me = 4: o = 5 // A printout at each entry into .compareTo()
me = 3: o = 4
me = 3: o = 5
me = 2: o = 5
me = 2: o = 3
me = 1: o = 3
me = 1: o = 2
4 5 3 2 1 // Final output (1 should be at the beginning though)
My rules for sorting are:
1<4
3<2
4<5
My implementation is:
List<Task> tasks = new TaskList();
Task.create(tasks); // creates a list 5 4 3 2 1
while (scan.hasNext()) {
String line = scan.next();
Task.rules.add(line); // address the rules such as "1<4"
}
System.out.println(tasks);
Collections.sort(tasks);
And the compareTo() implementation:
#Override
public int compareTo(Object arg0) {
int me = id;
int o = ((Task) arg0).id;
System.out.println("me = " + me + ": o = " + o);
for (String s : rules) { // rules is an array of strings "1<4" etc
int left = Integer.valueOf(s.substring(0, 1));
int right = Integer.valueOf(s.substring(2));
char op = s.charAt(1);
boolean meLeft = left == me;
boolean oLeft = left == o;
boolean meRight = right == me;
boolean oRight = right == o;
if (meLeft && oRight) {
if (op == '<') { // me < other
return -1;
} else
return 1;
} else if (oLeft && meRight) {
if (op == '<') {// other < me
return 1;
} else {
return -1;
}
}
}
return 0;
}
As you can see from the "me = M, o = O" at the top, the Collections.sort() is not iterating through all the members of the list!
I would expect the following to show for each member "me" all the other members "o" to be compared, so I'd expected that list at the top of this question to be much longer! I believe its size should be N^2...
Your compareTo method breaks the contract for that method in two ways.
1) Transitivity says that if x.compareTo(y) > 0 and y.compareTo(z) > 0 then x.compareTo(z) > 0. Your method breaks this because 5 > 4 and 4 > 1, but 5>1 is not one of your rules.
2) compareTo must also meet the condition that if x.compareTo(y) == 0 then sgn(x.compareTo(z)) == sgn(y.compareTo(z)) for all z. Your method breaks this because 5.compareTo(1) == 0, whereas 5.compareTo(4) and 1.compareTo(4) have opposite signs.
If you don't meet the contract for compareTo, the results of sort are unpredictable. However in your case, we can see what's going on. 4, 5, 3, 2, 1 is in order because 4 < 5 = 3 < 2 = 1. (I am using = to mean the compareTo method returns 0). There are no > signs in that chain, so there is no reason to continue sorting.
If you want 1 to come to the front, in addition to making your compareTo method meet the two conditions above, you will have to add at least one rule involving something from [1, 4, 5] and something from [2, 3]. As long as there is no such rule, there is no reason for the 1 at the end to move past the 2 and the 3.