Skip to content

Commit 9443eb1

Browse files
authored
Add camicia (#4075)
* add `camicia` * Conditionally format long inputs * Add prerequisites
1 parent 39e917c commit 9443eb1

File tree

9 files changed

+587
-0
lines changed

9 files changed

+587
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1738,6 +1738,14 @@
17381738
],
17391739
"difficulty": 5
17401740
},
1741+
{
1742+
"slug": "camicia",
1743+
"name": "Camicia",
1744+
"uuid": "ec314b34-2ee3-4eec-9a97-aece9e5fd6c2",
1745+
"practices": [],
1746+
"prerequisites": ["lists", "sets", "strings"],
1747+
"difficulty": 5
1748+
},
17411749
{
17421750
"slug": "rational-numbers",
17431751
"name": "Rational Numbers",
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: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"BNAndras"
4+
],
5+
"files": {
6+
"solution": [
7+
"camicia.py"
8+
],
9+
"test": [
10+
"camicia_test.py"
11+
],
12+
"example": [
13+
".meta/example.py"
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+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
def simulate_game(player_a, player_b):
2+
hand_a = list(map(get_value, player_a))
3+
hand_b = list(map(get_value, player_b))
4+
turn = "A"
5+
pile = []
6+
seen = set()
7+
total_tricks = 0
8+
cards_played = 0
9+
current_debt = 0
10+
11+
while True:
12+
if not pile:
13+
state = (tuple(hand_a), tuple(hand_b), turn)
14+
if state in seen:
15+
return {
16+
"status": "loop",
17+
"tricks": total_tricks,
18+
"cards": cards_played
19+
}
20+
seen.add(state)
21+
22+
active_hand = hand_a if turn == "A" else hand_b
23+
other_hand = hand_b if turn == "A" else hand_a
24+
25+
if not active_hand:
26+
extra_trick = 0 if not pile else 1
27+
return {
28+
"status": "finished",
29+
"tricks": total_tricks + extra_trick,
30+
"cards": cards_played,
31+
}
32+
33+
card_val = active_hand.pop(0)
34+
pile.append(card_val)
35+
cards_played += 1
36+
37+
if card_val > 0:
38+
current_debt = card_val
39+
turn = "B" if turn == "A" else "A"
40+
else:
41+
if current_debt > 0:
42+
current_debt -= 1
43+
if not current_debt:
44+
other_hand.extend(pile)
45+
pile = []
46+
total_tricks += 1
47+
current_debt = 0
48+
49+
if not hand_a or not hand_b:
50+
return {
51+
"status": "finished",
52+
"tricks": total_tricks,
53+
"cards": cards_played
54+
}
55+
56+
turn = "B" if turn == "A" else "A"
57+
else:
58+
turn = "B" if turn == "A" else "A"
59+
60+
61+
def get_value(card):
62+
if card == "J":
63+
return 1
64+
if card == "Q":
65+
return 2
66+
if card == "K":
67+
return 3
68+
if card == "A":
69+
return 4
70+
return 0
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{%- import "generator_macros.j2" as macros with context -%}
2+
{{ macros.canonical_ref() }}
3+
4+
{{ macros.header() }}
5+
6+
class {{ exercise | camel_case }}Test(unittest.TestCase):
7+
{% for case in cases -%}
8+
def test_{{ case["description"] | to_snake }}(self):
9+
{%- if case["input"]["playerA"]|length > 10 or case["input"]["playerB"]|length > 10 %}
10+
# fmt: off
11+
player_a = {{ case["input"]["playerA"] }}
12+
player_b = {{ case["input"]["playerB"] }}
13+
# fmt: on
14+
{%- else %}
15+
player_a = {{ case["input"]["playerA"] }}
16+
player_b = {{ case["input"]["playerB"] }}
17+
{%- endif %}
18+
self.assertEqual(simulate_game(player_a, player_b), {{ case["expected"] }})
19+
{% endfor -%}
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"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def simulate_game(player_a, player_b):
2+
pass

0 commit comments

Comments
 (0)