Skip to content

Commit 8d6c753

Browse files
authored
add camicia (#2811)
1 parent 5527423 commit 8d6c753

File tree

15 files changed

+825
-0
lines changed

15 files changed

+825
-0
lines changed

config.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,16 @@
869869
"integers"
870870
]
871871
},
872+
{
873+
"slug": "camicia",
874+
"name": "Camicia",
875+
"uuid": "96d482ab-effc-4082-b4a8-3165de8ff0eb",
876+
"practices": [],
877+
"prerequisites": [
878+
"arrays"
879+
],
880+
"difficulty": 5
881+
},
872882
{
873883
"slug": "clock",
874884
"name": "Clock",
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Instructions
2+
3+
In this exercise, you will simulate a game very similar to the classic card game **Camicia**.
4+
Your program will receive the initial configuration of two players' decks and must simulate the game until it ends (or detect that it will never end).
5+
6+
## Rules
7+
8+
- The deck is split between **two players**.
9+
The player's cards are read from left to right, where the leftmost card is the top of the deck.
10+
- A round consists of both players playing at least one card.
11+
- Players take turns placing the **top card** of their deck onto a central pile.
12+
- If the card is a **number card** (2-10), play simply passes to the other player.
13+
- If the card is a **payment card**, a penalty must be paid:
14+
- **J** → opponent must pay 1 card
15+
- **Q** → opponent must pay 2 cards
16+
- **K** → opponent must pay 3 cards
17+
- **A** → opponent must pay 4 cards
18+
- If the player paying a penalty reveals another payment card, that player stops paying the penalty.
19+
The other player must then pay a penalty based on the new payment card.
20+
- If the penalty is fully paid without interruption, the player who placed the **last payment card** collects the central pile and places it at the bottom of their deck.
21+
That player then starts the next round.
22+
- If a player runs out of cards and is unable to play a card (either while paying a penalty or when it is their turn), the other player collects the central pile.
23+
- The moment when a player collects cards from the central pile is called a **trick**.
24+
- If a player has all the cards in their possession after a trick, the game **ends**.
25+
- The game **enters a loop** as soon as the decks are identical to what they were earlier during the game, **not** counting number cards!
26+
27+
## Examples
28+
29+
A small example of a match that ends.
30+
31+
| Round | Player A | Player B | Pile | Penalty Due |
32+
| :---- | :----------- | :------------------------- | :------------------------- | :---------- |
33+
| 1 | 2 A 7 8 Q 10 | 3 4 5 6 K 9 J | | - |
34+
| 1 | A 7 8 Q 10 | 3 4 5 6 K 9 J | 2 | - |
35+
| 1 | A 7 8 Q 10 | 4 5 6 K 9 J | 2 3 | - |
36+
| 1 | 7 8 Q 10 | 4 5 6 K 9 J | 2 3 A | Player B: 4 |
37+
| 1 | 7 8 Q 10 | 5 6 K 9 J | 2 3 A 4 | Player B: 3 |
38+
| 1 | 7 8 Q 10 | 6 K 9 J | 2 3 A 4 5 | Player B: 2 |
39+
| 1 | 7 8 Q 10 | K 9 J | 2 3 A 4 5 6 | Player B: 1 |
40+
| 1 | 7 8 Q 10 | 9 J | 2 3 A 4 5 6 K | Player A: 3 |
41+
| 1 | 8 Q 10 | 9 J | 2 3 A 4 5 6 K 7 | Player A: 2 |
42+
| 1 | Q 10 | 9 J | 2 3 A 4 5 6 K 7 8 | Player A: 1 |
43+
| 1 | 10 | 9 J | 2 3 A 4 5 6 K 7 8 Q | Player B: 2 |
44+
| 1 | 10 | J | 2 3 A 4 5 6 K 7 8 Q 9 | Player B: 1 |
45+
| 1 | 10 | - | 2 3 A 4 5 6 K 7 8 Q 9 J | Player A: 1 |
46+
| 1 | - | - | 2 3 A 4 5 6 K 7 8 Q 9 J 10 | - |
47+
| 2 | - | 2 3 A 4 5 6 K 7 8 Q 9 J 10 | - | - |
48+
49+
status: `"finished"`, cards: 13, tricks: 1
50+
51+
This is a small example of a match that loops.
52+
53+
| Round | Player A | Player B | Pile | Penalty Due |
54+
| :---- | :------- | :------- | :---- | :---------- |
55+
| 1 | J 2 3 | 4 J 5 | - | - |
56+
| 1 | 2 3 | 4 J 5 | J | Player B: 1 |
57+
| 1 | 2 3 | J 5 | J 4 | - |
58+
| 2 | 2 3 J 4 | J 5 | - | - |
59+
| 2 | 3 J 4 | J 5 | 2 | - |
60+
| 2 | 3 J 4 | 5 | 2 J | Player A: 1 |
61+
| 2 | J 4 | 5 | 2 J 3 | - |
62+
| 3 | J 4 | 5 2 J 3 | - | - |
63+
| 3 | J 4 | 2 J 3 | 5 | - |
64+
| 3 | 4 | 2 J 3 | 5 J | Player B: 1 |
65+
| 3 | 4 | J 3 | 5 J 2 | - |
66+
| 4 | 4 5 J 2 | J 3 | - | - |
67+
68+
The start of round 4 matches the start of round 2.
69+
Recall, the value of the number cards does not matter.
70+
71+
status: `"loop"`, cards: 8, tricks: 3
72+
73+
## Your Task
74+
75+
- Using the input, simulate the game following the rules above.
76+
- Determine the following information regarding the game:
77+
- **Status**: `"finished"` or `"loop"`
78+
- **Cards**: total number of cards played throughout the game
79+
- **Tricks**: number of times the central pile was collected
80+
81+
```exercism/advanced
82+
For those who want to take on a more exciting challenge, the hunt for other records for the longest game with an end is still open.
83+
There are 653,534,134,886,878,245,000 (approximately 654 quintillion) possibilities, and we haven't calculated them all yet!
84+
```
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Introduction
2+
3+
One rainy afternoon, you sit at the kitchen table playing cards with your grandmother.
4+
The game is her take on [Camicia][bmn].
5+
6+
At first it feels like just another friendly match: cards slapped down, laughter across the table, the occasional victorious grin from Nonna.
7+
But as the game stretches on, something strange happens.
8+
The same cards keep cycling back.
9+
You play card after card, yet the end never seems to come.
10+
11+
You start to wonder.
12+
_Will this game ever finish?
13+
Or could we keep playing forever?_
14+
15+
Later, driven by curiosity, you search online and to your surprise you discover that what happened wasn't just bad luck.
16+
You and your grandmother may have stumbled upon one of the longest possible sequences!
17+
Suddenly, you're hooked.
18+
What began as a casual game has turned into a quest: _how long can such a game really last?_
19+
_Can you find a sequence even longer than the one you played at the kitchen table?_
20+
_Perhaps even long enough to set a new world record?_
21+
22+
And so, armed with nothing but a deck of cards and some algorithmic ingenuity, you decide to investigate...
23+
24+
[bmn]: https://en.wikipedia.org/wiki/Beggar-my-neighbour
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/node_modules
2+
/bin/configlet
3+
/bin/configlet.exe
4+
/package-lock.json
5+
/yarn.lock
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"authors": [
3+
"BNAndras"
4+
],
5+
"files": {
6+
"solution": [
7+
"camicia.js"
8+
],
9+
"test": [
10+
"camicia.spec.js"
11+
],
12+
"example": [
13+
".meta/proof.ci.js"
14+
]
15+
},
16+
"blurb": "Simulate the card game and determine whether the match ends or enters an infinite loop.",
17+
"source": "Beggar-My-Neighbour",
18+
"source_url": "https://www.richardpmann.com/beggar-my-neighbour-records.html",
19+
"custom": {
20+
"version.tests.compatibility": "jest-27",
21+
"flag.tests.task-per-describe": false,
22+
"flag.tests.may-run-long": false,
23+
"flag.tests.includes-optional": false
24+
}
25+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
export const simulateGame = (playerA, playerB) => {
2+
const getCardValue = (card) => {
3+
if (card === 'J') return 1;
4+
if (card === 'Q') return 2;
5+
if (card === 'K') return 3;
6+
if (card === 'A') return 4;
7+
return 0;
8+
};
9+
10+
const handA = playerA.map(getCardValue);
11+
const handB = playerB.map(getCardValue);
12+
let turn = 'A';
13+
let pile = [];
14+
const seen = new Set();
15+
let totalTricks = 0;
16+
let cardsPlayed = 0;
17+
let currentDebt = 0;
18+
19+
while (true) {
20+
if (pile.length === 0) {
21+
const round = JSON.stringify([handA, handB, turn]);
22+
if (seen.has(round)) {
23+
return { status: 'loop', tricks: totalTricks, cards: cardsPlayed };
24+
}
25+
seen.add(round);
26+
}
27+
28+
const activeHand = turn === 'A' ? handA : handB;
29+
const otherHand = turn === 'A' ? handB : handA;
30+
31+
if (activeHand.length === 0) {
32+
const extraTrick = pile.length === 0 ? 0 : 1;
33+
return {
34+
status: 'finished',
35+
tricks: totalTricks + extraTrick,
36+
cards: cardsPlayed,
37+
};
38+
}
39+
40+
const cardVal = activeHand.shift();
41+
pile.push(cardVal);
42+
cardsPlayed += 1;
43+
44+
// payment card so debt is either forgiven for player or assigned to opponent
45+
if (cardVal > 0) {
46+
currentDebt = cardVal;
47+
turn = turn === 'A' ? 'B' : 'A';
48+
} else {
49+
// time to pay up!
50+
if (currentDebt > 0) {
51+
currentDebt -= 1;
52+
if (currentDebt === 0) {
53+
// penalty paid off
54+
otherHand.push(...pile);
55+
pile = [];
56+
totalTricks += 1;
57+
currentDebt = 0;
58+
59+
if (handA.length === 0 || handB.length === 0) {
60+
return {
61+
status: 'finished',
62+
tricks: totalTricks,
63+
cards: cardsPlayed,
64+
};
65+
}
66+
turn = turn === 'A' ? 'B' : 'A';
67+
}
68+
} else {
69+
turn = turn === 'A' ? 'B' : 'A';
70+
}
71+
}
72+
}
73+
};
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[0b7f737c-3ecd-4a55-b34d-e65c62a85c28]
13+
description = "two cards, one trick"
14+
15+
[27c19d75-53a5-48e5-b33b-232c3884d4f3]
16+
description = "three cards, one trick"
17+
18+
[9b02dd49-efaf-4b71-adca-a05c18a7c5b0]
19+
description = "four cards, one trick"
20+
21+
[fa3f4479-466a-4734-a001-ab79bfe27260]
22+
description = "the ace reigns supreme"
23+
24+
[07629689-f589-4f54-a6d1-8ce22776ce72]
25+
description = "the king beats ace"
26+
27+
[54d4a1c5-76fb-4d1e-8358-0e0296ac0601]
28+
description = "the queen seduces the king"
29+
30+
[c875500c-ff3d-47a4-bd1e-b60b90da80aa]
31+
description = "the jack betrays the queen"
32+
33+
[436875da-96ca-4149-be22-0b78173b8125]
34+
description = "the 10 just wants to put on a show"
35+
36+
[5be39bb6-1b34-4ce6-a1cd-0fcc142bb272]
37+
description = "simple loop with decks of 3 cards"
38+
39+
[2795dc21-0a2a-4c38-87c2-5a42e1ff15eb]
40+
description = "the story is starting to get a bit complicated"
41+
42+
[6999dfac-3fdc-41e2-b64b-38f4be228712]
43+
description = "two tricks"
44+
45+
[83dcd4f3-e089-4d54-855a-73f5346543a3]
46+
description = "more tricks"
47+
48+
[3107985a-f43e-486a-9ce8-db51547a9941]
49+
description = "simple loop with decks of 4 cards"
50+
51+
[dca32c31-11ed-49f6-b078-79ab912c1f7b]
52+
description = "easy card combination"
53+
54+
[1f8488d0-48d3-45ae-b819-59cedad0a5f4]
55+
description = "easy card combination, inverted decks"
56+
57+
[98878d35-623a-4d05-b81a-7bdc569eb88d]
58+
description = "mirrored decks"
59+
60+
[3e0ba597-ca10-484b-87a3-31a7df7d6da3]
61+
description = "opposite decks"
62+
63+
[92334ddb-aaa7-47fa-ab36-e928a8a6a67c]
64+
description = "random decks #1"
65+
66+
[30477523-9651-4860-84a3-e1ac461bb7fa]
67+
description = "random decks #2"
68+
69+
[20967de8-9e94-4e0e-9010-14bc1c157432]
70+
description = "Kleber 1999"
71+
72+
[9f2fdfe8-27f3-4323-816d-6bce98a9c6f7]
73+
description = "Collins 2006"
74+
75+
[c90b6f8d-7013-49f3-b5cb-14ea006cca1d]
76+
description = "Mann and Wu 2007"
77+
78+
[a3f1fbc5-1d0b-499a-92a5-22932dfc6bc8]
79+
description = "Nessler 2012"
80+
81+
[9cefb1ba-e6d1-4ab7-9d8f-76d8e0976d5f]
82+
description = "Anderson 2013"
83+
84+
[d37c0318-5be6-48d0-ab72-a7aaaff86179]
85+
description = "Rucklidge 2014"
86+
87+
[4305e479-ba87-432f-8a29-cd2bd75d2f05]
88+
description = "Nessler 2021"
89+
90+
[252f5cc3-b86d-4251-87ce-f920b7a6a559]
91+
description = "Nessler 2022"
92+
93+
[b9efcfa4-842f-4542-8112-8389c714d958]
94+
description = "Casella 2024, first infinite game found"

exercises/practice/camicia/.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
audit=false

exercises/practice/camicia/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021 Exercism
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
presets: [['@exercism/babel-preset-javascript', { corejs: '3.40' }]],
3+
plugins: [],
4+
};

0 commit comments

Comments
 (0)