Need help in clarifying Gotta Snatch them all exercise

Hi, I am trying to solve the Gotta Snatch 'Em All
exercise in Java: Gotta Snatch 'Em All in Java on Exercism

The third task asks us to implement the canTrade() cards function. One of the test cases says that if my collection of cards is a subset of my friend’s, I can trade(how?). The other test case says that if my friend’s collection is a subset of my cards, I can’t trade(this makes sense).

 @Test
    @Tag("task:3")
    @DisplayName("canTrade returns true when my collection is a non-empty subset of their collection")
    void testCanTradeMyCollectionSubsetOfTheirCollection() {
        Set<String> myCollection = new HashSet<>(Set.of("Gyros", "Garilord"));
        Set<String> theirCollection = new HashSet<>(Set.of("Garilord", "Veevee", "Gyros"));
        assertThat(GottaSnatchEmAll.canTrade(myCollection, theirCollection)).isTrue();
    }

    @Test
    @Tag("task:3")
    @DisplayName("canTrade returns false when their collection is a non-empty subset of my collection")
    void testCanTradeTheirCollectionSubsetOfMyCollection() {
        Set<String> myCollection = new HashSet<>(Set.of("Garilord", "Veevee", "Gyros"));
        Set<String> theirCollection = new HashSet<>(Set.of("Gyros", "Garilord"));
        assertThat(GottaSnatchEmAll.canTrade(myCollection, theirCollection)).isFalse();
    }

Does this have something to do with the snatch part in the exercise title? Meaning the “trade” in which only one side(myself) benefits is allowed as well

Hey, thanks for the feedback!

While designing the exercise, we discussed this case and concluded that the trade has to be “worth it” for you. One scenario I can think of is that your friend is trying to help you out in growing your collection, so they accept a card they might already have in exchange for one of their cards which you don’t have yet.

Does that make sense?

Hi @sanderploegsma, thanks for clarifying! I understand that doing it this way makes this case consistent with the instructions. But is there a particular reason why the instructions are like this?

Usually, a trade will have people wanting the same thing and so there is a negotiation, etc. If I don’t want a duplicate card, my friend may not want it either. Plus, as this exercise focuses on sets, this special test case doesn’t teach me anything unique about sets.

Having said that, I guess I am fixating on a small detail. As the title says “Gotta snatch 'em all”, then doing it this way makes sense. Thanks!

The exercise is designed to teach the Java Set API as well as some concepts from set theory. Specifically:

  • The canTrade method covers the concept of set difference and how it can be achieved in Java using the removeAll method.
  • The commonCards method covers the concept of set intersection and how it can be achieved in Java using the retainAll method.
  • The allCards method covers the concept of set union and how it can be achieved in Java using the addAll method.

This special test case should make it explicit that the difference between to sets is asymmetric: A \ B contains all items of A that are not in B, while B \ A contains all items of B that are not in A.

I had a hard time understanding this was the desired behavior based on the instructions.

Not every trade is worth doing, or can be done at all. You cannot trade a card you don’t have, and you shouldn’t trade a card for one that you already have.

Implement the canTrade method, that takes your current collection and the collection of one of your friends. It should return a boolean indicating whether a trade is possible, following the rules above.

Set<String> myCollection = Set.of("Newthree");
Set<String> theirCollection = Set.of("Scientuna");
GottaSnatchEmAll.canTrade(myCollection, theirCollection);
// => true

In the example, your collection is not a subset of their collection yet the result is true. Should it be false if you’re supposed to check for subsets? Or am I still not understanding the task correctly?

The task is not about subsets, it’s about set difference. Their collection contains a card that your collection doesn’t have, so it’s worth trading according to the instructions.

@IsaacG given my explanation above about the intended design of this exercise, do you have suggestions on how we can improve the exercise instructions to remove some ambiguity?

Just to confirm I’m understanding correctly, the function should return true when their collection has a card my collection does not have and both collections are not empty. Is that correct?

I’m having a hard time understanding what “You cannot trade a card you don’t have” is supposed to mean in the instructions.

Yes, the exercise teaches us a lot of things about sets. My point was about the particular test implying that trade that benefits one party is allowed. I guess it is a small detail but needs explanation.

I get your point about the asymmetric difference.

I also agree with @IsaacG about the instructions not being clear:

“Not every trade is worth doing or can be done at all. You cannot trade a card you don’t have”

When and how can a learner attempt to make this kind of trade? I don’t think this clause is needed.

The above can be replaced by:

You shouldn’t trade a card for one that you already have. Although, as your friend is trying to help you out, they might accept a card they already have in exchange for giving you one of their cards which you don’t have yet.

@sanderploegsma, this is what you explained to me above. I suggest we add this to the instructions.

I’m having a hard time understanding the requirements from this block of text.

Let’s say, I have cards {A, B, C}, and my friend has {A, B}, so this trade is not beneficial to me as I already have cards A & B. Hence, this trade is not allowed.

But let’s reverse the scenario where my friend has {A, B, C} and I have {A, B}. In this case, my friend can give me a C in exchange for me giving them an A or B, although they already have whichever card I give them.

Do you guys think we should give an example in the description to make it more clear?

This example implies you need to check for a superset.

I think the requirement here is that their hand has a card not in your hand and that your hand is not empty. Though I’m not certain about this.

Yes, you are right—their hand needs to have a card I don’t have. The example shows that if that condition is not satisfied, the trade doesn’t happen.

Maybe the instructions should read, “You should make a trade when you have any cards and their collection contains cards your collection does not.” I think that succinctly and clearly expresses the requirements. Thoughts?

Yes, this looks fine. But we don’t need the “when you have any cards”. That’s obvious, right? When either party has 0 cards, nothing will be exchanged. I guess most students will not falter in this condition.

You should make a trade when their collection contains cards your collection does not

I guess that should be enough. What do you think?
@IsaacG @sanderploegsma

If this seems okay, I can raise a PR.

Thanks!

No. It’s not obvious. I wouldn’t assume anything is obvious. I would think it’s obvious no one would accept a trade of A for A+B but this exercise isn’t about what people would normally accept. If A for A+B is accepted, then I would think nothing for B is the same.

That makes sense.

That is indeed what is expected for this exercise.

So, let’s define your collection of cards as A and your friend’s collection as B. The implementation needs to check that these two conditions are met:

  • A != {}
  • B \ A != {}

Here, \ means the asymmetric difference between B and A: all items in B that are not in A.


Given this discussion though, I am wondering whether it’s necessary to simplify this task and change the requirement to “When trading with friends, you should only trade if both you and your friend have a card the other doesn’t have”. My guess is that this is less ambiguous, while still covering the concept of set difference.

This basically comes down to calculating the symmetric difference between sets, and the implementation should check that:

  • A \ B != {}
  • B \ A != {}

@IsaacG @kshekabhi what do you think?

1 Like

That depends entirely on what concepts you want to cover/teach. I believe the instructions can be written in a way that is clear regardless of which concept you want to teach here.

“You should make a trade when you have any cards and their collection contains cards your collection does not.” seems to cover the existing requirements pretty well. If the instructions are changed to something similar, I think the exercise does not need to change.

If you think it would be better to change what concept(s) are covered, that’s completely reasonable, too!

1 Like

Yes, I think this is less ambiguous. Let me know if you want help in making this change. Thanks!

@manumafe98 @kahgoh what do you think?