New Exercise Proposal: Camicia

I think I’ve found a little gem.
I was playing a popular card game with my grandmother from southern Italy. Her version was slightly different, but the essence was the same. Since I’ve always played this game, I had never thought about the algorithmic problem hidden within it.
I think it would be a good idea to implement it as an exercise in Elixir or even others.
The problem to be solved would be whether the game ends or continues in an infinite loop.

I’m pretty much new to this community, so don’t stone me if it’s a bad idea or if I don’t have a PR ready to show. :slight_smile:

If I had to implement my idea in Elixir, it would already be a challenge for me, let alone creating something for multiple tracks. I have no idea where to start.

Any ideas, advice or criticism are welcome. :relieved:

You’re fine. We generally prefer a forum discussion and approval from the relevant parties before a PR is opened.

Maybe if you gave us some proposed inputs and outputs, that’ll help the discussion. Unless this is an exercise specific to just Elixir, the agreed-upon canonical test data and instructions will go into GitHub - exercism/problem-specifications: Shared metadata for exercism exercises.. Then the 77+ Exercism tracks can implement the exercise using that canonical data if desired. You certainly wouldn’t be expected to implement it yourself for all those tracks.

1 Like

I managed to find the name of the Italian version of the game, Camicia.
(I couldn’t find it using my grandmother’s dialect.)

Depending on the version of the game, you start with either 40 or 52 cards. (beggar-my-neighbour → 52)

Possible inputs and outputs could be those found in the links I mentioned earlier here:

#1 case (First infinite game found)

input1: ---K---Q-KQAJ-----AAJ--J--
input2: ----------Q----KQ-J-----KA
output: {state => loop, cards => 474, tricks => 66}

#2 case (Latest record for the longest game)

input1: ---AJ--Q---------QAKQJJ-QK
input2: -----A----KJ-K--------A---
output: {state => finished, cards => 8344, tricks => 1164}

In this game, the cards are dealt into two equal decks.
The game ends when one of the two players (A & B), represented by input1 and input2, runs out of cards in their deck, resulting in their defeat.
From an algorithmic point of view, we are only interested in the position of the cards A (ace), K (king), Q (queen) and J (jack).

Example Sequence

  • Card 1: Player A plays a 7♠ → (1 card played).
  • Card 2: Player B plays a K♥ (a payment card, opponent must pay 3) → (2 cards played).
  • Card 3: Player A pays with a 4♣ → (3 cards played).
  • Card 4: Player A continues, plays a 9♦ → (4 cards played).
  • Card 5: Player A continues, plays a Q♠ (another payment card!) → (5 cards played). Now Player B must pay 2.
  • Card 6: Player B pays with a 5♦ → (6 cards played).
  • Card 7: Player B pays with a J♣ (another payment card!) → (7 cards played). Now Player A must pay 1.
  • Card 8: Player A pays with a 6♠ → (8 cards played).

Since Player A’s payment was just a normal card (not another payment card), Player B wins the pile and takes all 8 cards → this is 1 trick.
In this sequence, I have also added numbers and symbols, but they are not important for the purposes of the exercise.

Please let me know if you need anything else, I am at your complete disposal. :grin:

1 Like

What exactly would the tests look like?

1 Like

If you want an example of canonical-data.json, here it is:

{
  "exercise": "beggar-my-neighbour",
  "cases": [
    {
      "uuid": "...",
      "description": "Kleber 1999",
      "property": "findEndGame",
      "input": {
        "playerA": "---JQ---K-A----A-J-K---QK-",
        "playerB": "-J-----------AJQA----K---Q"
      },
      "expected": {
        "status": "finished",
        "cards": 5791, 
        "tricks": 805
      }
    },
    {
      "uuid": "...",
      "description": "Collins 2006",
      "property": "findEndGame",
      "input": {
        "playerA": "A-QK------Q----KA-----J---",
        "playerB": "-JAK----A--Q----J---QJ--K-"
      },
      "expected": {
        "status": "finished",
        "cards": 6914, 
        "tricks": 960
      }
    },
    {
      "uuid": "...",
      "description": "Nessler 2022",
      "property": "findEndGame",
      "input": {
        "playerA": "---AJ--Q---------QAKQJJ-QK",
        "playerB": "-----A----KJ-K--------A---"
      },
      "expected": {
        "status": "finished",
        "cards": 8344, 
        "tricks": 1164
      }
    },
    {
      "uuid": "...",
      "description": "Casella 2024",
      "property": "findEndGame",
      "input": {
        "playerA": "---K---Q-KQAJ-----AAJ--J--",
        "playerB": "----------Q----KQ-J-----KA"
      },
      "expected": {
        "status": "loop",
        "cards": 474, 
        "tricks": 66
      }
    }
  ]
}

If you would like an example of a test written in Elixir or another language, I would be happy to write one for you.

For anything else that I am not familiar with, I would appreciate receiving a link to an example that I can use as a reference.

Here is a small Python programme that calculates the results.

The test data should probably include some simple games that do not last very long, if those exist

1 Like

Surely there are matches that last 10 to 20 “tricks” or less. Just think of a deck with only useless cards and a deck with all A,K,Q,J.
I can find even the shortest matches if needed.
Another idea that came to me and @Pul, would be to also implement a test where the input is randomized.

P.s. @Pul has already offered to help me implement the exercise in Elixir

Having some examples in the tests would be helpful :) They don’t need to be the absolute shortest but the earlier tests should probably be a simpler/shorter case or two.

We typically don’t have random values in the unit tests. Randomization and deterministic unit tests are hard to mix easily.

1 Like

OK fine, I will create the other tests tonight to complete the file.

To generate the uuids, how do I do it? Do I have to do it myself or is it an automatic thing that will be added later?

The configlet tool has a uuid command.

1 Like

I have finished writing the tests with the various UUIDs (15 in total).
If anyone wants to double-check with the little Python programme I found, that would be welcome.
(You can never be too sure of your own abilities. :rofl:)

{
  "exercise": "beggar-my-neighbour",
  "cases": [
    {
      "uuid": "dca32c31-11ed-49f6-b078-79ab912c1f7b",
      "description": "easy card combination",
      "property": "findEndGame",
      "input": {
        "playerA": "--------------------------",
        "playerB": "----------AAAAKKKKQQQQJJJJ"
      },
      "expected": {
        "status": "finished",
        "cards": 40, 
        "tricks": 4
      }
    },
    {
      "uuid": "1f8488d0-48d3-45ae-b819-59cedad0a5f4",
      "description": "easy card combination, inverted decks",
      "property": "findEndGame",
      "input": {
        "playerA": "----------AAAAKKKKQQQQJJJJ",
        "playerB": "--------------------------"
      },
      "expected": {
        "status": "finished",
        "cards": 40, 
        "tricks": 4
      }
    },
    {
      "uuid": "98878d35-623a-4d05-b81a-7bdc569eb88d",
      "description": "mirrored decks",
      "property": "findEndGame",
      "input": {
        "playerA": "-A-A-K-K-Q-Q-J-J----------",
        "playerB": "-A-A-K-K-Q-Q-J-J----------"
      },
      "expected": {
        "status": "finished",
        "cards": 59, 
        "tricks": 4
      }
    },
    {
      "uuid": "3e0ba597-ca10-484b-87a3-31a7df7d6da3",
      "description": "opposite decks",
      "property": "findEndGame",
      "input": {
        "playerA": "-A-A-K-K-Q-Q-J-J----------",
        "playerB": "----------J-J-Q-Q-K-K-A-A-"
      },
      "expected": {
        "status": "finished",
        "cards": 151, 
        "tricks": 21
      }
    },
    {
      "uuid": "92334ddb-aaa7-47fa-ab36-e928a8a6a67c",
      "description": "random decks #1",
      "property": "findEndGame",
      "input": {
        "playerA": "K---J----AK---J-J---------",
        "playerB": "--KAQ-A-Q-----Q-K--A-Q-J--"
      },
      "expected": {
        "status": "finished",
        "cards": 542, 
        "tricks": 76
      }
    },
    {
      "uuid": "30477523-9651-4860-84a3-e1ac461bb7fa",
      "description": "random decks #2",
      "property": "findEndGame",
      "input": {
        "playerA": "-A---QJ-----KA--K---K---K-",
        "playerB": "----QJA------JA-Q-JQ------"
      },
      "expected": {
        "status": "finished",
        "cards": 327, 
        "tricks": 42
      }
    },
    {
      "uuid": "20967de8-9e94-4e0e-9010-14bc1c157432",
      "description": "Kleber 1999",
      "property": "findEndGame",
      "input": {
        "playerA": "---JQ---K-A----A-J-K---QK-",
        "playerB": "-J-----------AJQA----K---Q"
      },
      "expected": {
        "status": "finished",
        "cards": 5790, 
        "tricks": 805
      }
    },
    {
      "uuid": "9f2fdfe8-27f3-4323-816d-6bce98a9c6f7",
      "description": "Collins 2006",
      "property": "findEndGame",
      "input": {
        "playerA": "A-QK------Q----KA-----J---",
        "playerB": "-JAK----A--Q----J---QJ--K-"
      },
      "expected": {
        "status": "finished",
        "cards": 6913, 
        "tricks": 960
      }
    },
    {
      "uuid": "c90b6f8d-7013-49f3-b5cb-14ea006cca1d",
      "description": "Mann and Wu 2007",
      "property": "findEndGame",
      "input": {
        "playerA": "K-KK----K-A-----JAA--Q--J-",
        "playerB": "---Q---Q-J-----J------AQ--"
      },
      "expected": {
        "status": "finished",
        "cards": 7157, 
        "tricks": 1007
      }
    },
    {
      "uuid": "a3f1fbc5-1d0b-499a-92a5-22932dfc6bc8",
      "description": "Nessler 2012",
      "property": "findEndGame",
      "input": {
        "playerA": "----Q------A--K--A-A--QJK-",
        "playerB": "-Q--J--J---QK---K----JA---"
      },
      "expected": {
        "status": "finished",
        "cards": 7207, 
        "tricks": 1015
      }
    },
    {
      "uuid": "9cefb1ba-e6d1-4ab7-9d8f-76d8e0976d5f",
      "description": "Anderson 2013",
      "property": "findEndGame",
      "input": {
        "playerA": "--A-Q--J--J---Q--AJ-K---K-",
        "playerB": "-J-------Q------A--A--QKK-"
      },
      "expected": {
        "status": "finished",
        "cards": 7225, 
        "tricks": 1016
      }
    },
    {
      "uuid": "d37c0318-5be6-48d0-ab72-a7aaaff86179",
      "description": "Rucklidge 2014",
      "property": "findEndGame",
      "input": {
        "playerA": "-J------Q------AAA-----QQ-",
        "playerB": "K----JA-----------KQ-K-JJK"
      },
      "expected": {
        "status": "finished",
        "cards": 7959,
        "tricks": 1122
      }
    },
    {
      "uuid": "4305e479-ba87-432f-8a29-cd2bd75d2f05",
      "description": "Nessler 2021",
      "property": "findEndGame",
      "input": {
        "playerA": "----K---A--Q-A--JJA------J",
        "playerB": "-----KK---------A-JK-Q-Q-Q"
      },
      "expected": {
        "status": "finished",
        "cards": 7972, 
        "tricks": 1106
      }
    },
    {
      "uuid": "252f5cc3-b86d-4251-87ce-f920b7a6a559",
      "description": "Nessler 2022",
      "property": "findEndGame",
      "input": {
        "playerA": "---AJ--Q---------QAKQJJ-QK",
        "playerB": "-----A----KJ-K--------A---"
      },
      "expected": {
        "status": "finished",
        "cards": 8344, 
        "tricks": 1164
      }
    },
    {
      "uuid": "b9efcfa4-842f-4542-8112-8389c714d958",
      "description": "Casella 2024, first infinite game found",
      "property": "findEndGame",
      "input": {
        "playerA": "---K---Q-KQAJ-----AAJ--J--",
        "playerB": "----------Q----KQ-J-----KA"
      },
      "expected": {
        "status": "loop",
        "cards": 474, 
        "tricks": 66
      }
    }
  ]
}

What is the next step?

1 Like
  1. Maintainer consensus that this exercise would add value to the problem spec. (I’m not sure if this blocks on approval from Erik and/or Jeremy or not).
  2. A proposed story and instructions (introduction.md and instructions.md), with concensus/approval from a quorum (3) of maintainers.
  3. A PR to push add the already-agreed upon exercise to the problem spec.

Based on the test data, I think this would make an exercise that is interesting and different enough from all the existing exercises so I’m in favor of adding this!

I’m on the fence on the exercise name; we may want a more upbeat name here.

1 Like

I’m very happy that you like my proposal.
I’ll eagerly await confirmation from a maintainer.

We’ll definitely find a better name.
It’s funny how the hardest thing in IT is always naming things :rofl: :rofl: :rofl:.

Same concern. Camicia would work since if we did something generic like Card Game, that might conflict with a similarly named concept exercise. Some tracks like Javascript do have card-related concept exercises.

2 Likes

It is a variant on the game of War, and so that is the upbeat name, others include jewels such as Strip Jack Naked and Beat your Neighbor. I think the name is probably the upbeatest of most that I have heard, if “upbeatest” is a word, and it is admittedly your request of an “upbeat” name reminding me of the pretty harsh names and nature of the game names.

This might be the choice of names that beats the other choices. :slight_smile:

2 Likes

That’s nice, it would be a great tribute to my grandmother, but it would be a variant of a variant.

I prefer War, simple, short and striking as soon as you see it.
Then we could use a green plastic soldier, like the ones in Toy Story, as the image. That would be magnificent. :wink:

It would be nice to involve the community when these decisions need to be made, with a poll or perhaps an Instagram story. (In this case, Twitter, because I don’t see any link for Instagram.)

We also need to change the Twitter logo to the X logo when someone has time.

I like Camicia

but it would be a variant of a variant.

Not a blocker. The instructions and especially the tests are the specification, not the exercise name.

1 Like

Exercism uses this forum and Discord as it’s primary social platforms. This thread is community involvement. Everyone on this thread is a community member. No Exercism staff has gotten involved yet.

ok, fair enough.

It’s not that long ago that we moved from Minesweeper to Flower Field, so Camicia would be my choice of a name. At least no violence in the headline.

I don’t know if the problem itself helps making progress in a programming language, as it looks like a really hard exercise for Exercism - like zebra. There is little or no help to develop the algorithm given by the tests - the essence of TDD is to make incremental test driven steps towards a solution. And you actually have to know a language very well already to come up with a solution.

3 Likes