From f25e3d9483f216d52987d6f55e837df8a422c398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20B=20Nagy?= <20251272+BNAndras@users.noreply.github.com> Date: Mon, 26 Jan 2026 23:17:06 -0800 Subject: [PATCH] Add `camicia` --- config.json | 8 + .../practice/camicia/.docs/instructions.md | 84 ++++++++ .../practice/camicia/.docs/introduction.md | 24 +++ exercises/practice/camicia/.meta/config.json | 22 ++ .../practice/camicia/.meta/lib/example.dart | 73 +++++++ exercises/practice/camicia/.meta/tests.toml | 94 ++++++++ .../practice/camicia/analysis_options.yaml | 18 ++ exercises/practice/camicia/lib/camicia.dart | 3 + exercises/practice/camicia/pubspec.yaml | 5 + .../practice/camicia/test/camicia_test.dart | 202 ++++++++++++++++++ 10 files changed, 533 insertions(+) create mode 100644 exercises/practice/camicia/.docs/instructions.md create mode 100644 exercises/practice/camicia/.docs/introduction.md create mode 100644 exercises/practice/camicia/.meta/config.json create mode 100644 exercises/practice/camicia/.meta/lib/example.dart create mode 100644 exercises/practice/camicia/.meta/tests.toml create mode 100644 exercises/practice/camicia/analysis_options.yaml create mode 100644 exercises/practice/camicia/lib/camicia.dart create mode 100644 exercises/practice/camicia/pubspec.yaml create mode 100644 exercises/practice/camicia/test/camicia_test.dart diff --git a/config.json b/config.json index 11ef48a8..bd3a1380 100644 --- a/config.json +++ b/config.json @@ -930,6 +930,14 @@ "practices": [], "prerequisites": [], "difficulty": 4 + }, + { + "slug": "camicia", + "name": "Camicia", + "uuid": "b3de907d-4704-4d57-977d-cbbf970f9e49", + "practices": [], + "prerequisites": [], + "difficulty": 5 } ] }, diff --git a/exercises/practice/camicia/.docs/instructions.md b/exercises/practice/camicia/.docs/instructions.md new file mode 100644 index 00000000..db62fcef --- /dev/null +++ b/exercises/practice/camicia/.docs/instructions.md @@ -0,0 +1,84 @@ +# Instructions + +In this exercise, you will simulate a game very similar to the classic card game **Camicia**. +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). + +## Rules + +- The deck is split between **two players**. + The player's cards are read from left to right, where the leftmost card is the top of the deck. +- A round consists of both players playing at least one card. +- Players take turns placing the **top card** of their deck onto a central pile. +- If the card is a **number card** (2-10), play simply passes to the other player. +- If the card is a **payment card**, a penalty must be paid: + - **J** → opponent must pay 1 card + - **Q** → opponent must pay 2 cards + - **K** → opponent must pay 3 cards + - **A** → opponent must pay 4 cards +- If the player paying a penalty reveals another payment card, that player stops paying the penalty. + The other player must then pay a penalty based on the new payment card. +- 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. + That player then starts the next round. +- 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. +- The moment when a player collects cards from the central pile is called a **trick**. +- If a player has all the cards in their possession after a trick, the game **ends**. +- The game **enters a loop** as soon as the decks are identical to what they were earlier during the game, **not** counting number cards! + +## Examples + +A small example of a match that ends. + +| Round | Player A | Player B | Pile | Penalty Due | +| :---- | :----------- | :------------------------- | :------------------------- | :---------- | +| 1 | 2 A 7 8 Q 10 | 3 4 5 6 K 9 J | | - | +| 1 | A 7 8 Q 10 | 3 4 5 6 K 9 J | 2 | - | +| 1 | A 7 8 Q 10 | 4 5 6 K 9 J | 2 3 | - | +| 1 | 7 8 Q 10 | 4 5 6 K 9 J | 2 3 A | Player B: 4 | +| 1 | 7 8 Q 10 | 5 6 K 9 J | 2 3 A 4 | Player B: 3 | +| 1 | 7 8 Q 10 | 6 K 9 J | 2 3 A 4 5 | Player B: 2 | +| 1 | 7 8 Q 10 | K 9 J | 2 3 A 4 5 6 | Player B: 1 | +| 1 | 7 8 Q 10 | 9 J | 2 3 A 4 5 6 K | Player A: 3 | +| 1 | 8 Q 10 | 9 J | 2 3 A 4 5 6 K 7 | Player A: 2 | +| 1 | Q 10 | 9 J | 2 3 A 4 5 6 K 7 8 | Player A: 1 | +| 1 | 10 | 9 J | 2 3 A 4 5 6 K 7 8 Q | Player B: 2 | +| 1 | 10 | J | 2 3 A 4 5 6 K 7 8 Q 9 | Player B: 1 | +| 1 | 10 | - | 2 3 A 4 5 6 K 7 8 Q 9 J | Player A: 1 | +| 1 | - | - | 2 3 A 4 5 6 K 7 8 Q 9 J 10 | - | +| 2 | - | 2 3 A 4 5 6 K 7 8 Q 9 J 10 | - | - | + +status: `"finished"`, cards: 13, tricks: 1 + +This is a small example of a match that loops. + +| Round | Player A | Player B | Pile | Penalty Due | +| :---- | :------- | :------- | :---- | :---------- | +| 1 | J 2 3 | 4 J 5 | - | - | +| 1 | 2 3 | 4 J 5 | J | Player B: 1 | +| 1 | 2 3 | J 5 | J 4 | - | +| 2 | 2 3 J 4 | J 5 | - | - | +| 2 | 3 J 4 | J 5 | 2 | - | +| 2 | 3 J 4 | 5 | 2 J | Player A: 1 | +| 2 | J 4 | 5 | 2 J 3 | - | +| 3 | J 4 | 5 2 J 3 | - | - | +| 3 | J 4 | 2 J 3 | 5 | - | +| 3 | 4 | 2 J 3 | 5 J | Player B: 1 | +| 3 | 4 | J 3 | 5 J 2 | - | +| 4 | 4 5 J 2 | J 3 | - | - | + +The start of round 4 matches the start of round 2. +Recall, the value of the number cards does not matter. + +status: `"loop"`, cards: 8, tricks: 3 + +## Your Task + +- Using the input, simulate the game following the rules above. +- Determine the following information regarding the game: + - **Status**: `"finished"` or `"loop"` + - **Cards**: total number of cards played throughout the game + - **Tricks**: number of times the central pile was collected + +~~~~exercism/advanced +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. +There are 653,534,134,886,878,245,000 (approximately 654 quintillion) possibilities, and we haven't calculated them all yet! +~~~~ diff --git a/exercises/practice/camicia/.docs/introduction.md b/exercises/practice/camicia/.docs/introduction.md new file mode 100644 index 00000000..761d8a82 --- /dev/null +++ b/exercises/practice/camicia/.docs/introduction.md @@ -0,0 +1,24 @@ +# Introduction + +One rainy afternoon, you sit at the kitchen table playing cards with your grandmother. +The game is her take on [Camicia][bmn]. + +At first it feels like just another friendly match: cards slapped down, laughter across the table, the occasional victorious grin from Nonna. +But as the game stretches on, something strange happens. +The same cards keep cycling back. +You play card after card, yet the end never seems to come. + +You start to wonder. +_Will this game ever finish? +Or could we keep playing forever?_ + +Later, driven by curiosity, you search online and to your surprise you discover that what happened wasn't just bad luck. +You and your grandmother may have stumbled upon one of the longest possible sequences! +Suddenly, you're hooked. +What began as a casual game has turned into a quest: _how long can such a game really last?_ +_Can you find a sequence even longer than the one you played at the kitchen table?_ +_Perhaps even long enough to set a new world record?_ + +And so, armed with nothing but a deck of cards and some algorithmic ingenuity, you decide to investigate... + +[bmn]: https://en.wikipedia.org/wiki/Beggar-my-neighbour diff --git a/exercises/practice/camicia/.meta/config.json b/exercises/practice/camicia/.meta/config.json new file mode 100644 index 00000000..55c1d303 --- /dev/null +++ b/exercises/practice/camicia/.meta/config.json @@ -0,0 +1,22 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "lib/camicia.dart" + ], + "test": [ + "test/camicia_test.dart" + ], + "example": [ + ".meta/lib/example.dart" + ], + "invalidator": [ + "pubspec.yaml" + ] + }, + "blurb": "Simulate the card game and determine whether the match ends or enters an infinite loop.", + "source": "Beggar-My-Neighbour", + "source_url": "https://www.richardpmann.com/beggar-my-neighbour-records.html" +} diff --git a/exercises/practice/camicia/.meta/lib/example.dart b/exercises/practice/camicia/.meta/lib/example.dart new file mode 100644 index 00000000..52a8fb7d --- /dev/null +++ b/exercises/practice/camicia/.meta/lib/example.dart @@ -0,0 +1,73 @@ +class Camicia { + Map simulateGame(List playerA, List playerB) { + int val(String card) { + switch (card) { + case 'J': + return 1; + case 'Q': + return 2; + case 'K': + return 3; + case 'A': + return 4; + default: + return 0; + } + } + + final List handA = playerA.map(val).toList(); + final List handB = playerB.map(val).toList(); + + final List pile = []; + final Set seen = {}; + + String turn = 'A'; + int tricks = 0; + int cardsPlayed = 0; + int currentDebt = 0; + + while (true) { + if (pile.isEmpty) { + final key = '${handA.join(',')}|${handB.join(',')}|$turn'; + if (seen.contains(key)) { + return {'status': 'loop', 'tricks': tricks, 'cards': cardsPlayed}; + } + seen.add(key); + } + + final activeHand = turn == 'A' ? handA : handB; + final otherHand = turn == 'A' ? handB : handA; + + if (activeHand.isEmpty) { + final extraTrick = pile.isEmpty ? 0 : 1; + return {'status': 'finished', 'tricks': tricks + extraTrick, 'cards': cardsPlayed}; + } + + final currentCard = activeHand.removeAt(0); + pile.add(currentCard); + cardsPlayed += 1; + + if (currentCard > 0) { + currentDebt = currentCard; + turn = turn == 'A' ? 'B' : 'A'; + } else { + if (currentDebt > 0) { + currentDebt -= 1; + if (currentDebt == 0) { + otherHand.addAll(pile); + pile.clear(); + tricks += 1; + currentDebt = 0; + + if (handA.isEmpty || handB.isEmpty) { + return {'status': 'finished', 'tricks': tricks, 'cards': cardsPlayed}; + } + turn = turn == 'A' ? 'B' : 'A'; + } + } else { + turn = turn == 'A' ? 'B' : 'A'; + } + } + } + } +} diff --git a/exercises/practice/camicia/.meta/tests.toml b/exercises/practice/camicia/.meta/tests.toml new file mode 100644 index 00000000..18d3fdd9 --- /dev/null +++ b/exercises/practice/camicia/.meta/tests.toml @@ -0,0 +1,94 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[0b7f737c-3ecd-4a55-b34d-e65c62a85c28] +description = "two cards, one trick" + +[27c19d75-53a5-48e5-b33b-232c3884d4f3] +description = "three cards, one trick" + +[9b02dd49-efaf-4b71-adca-a05c18a7c5b0] +description = "four cards, one trick" + +[fa3f4479-466a-4734-a001-ab79bfe27260] +description = "the ace reigns supreme" + +[07629689-f589-4f54-a6d1-8ce22776ce72] +description = "the king beats ace" + +[54d4a1c5-76fb-4d1e-8358-0e0296ac0601] +description = "the queen seduces the king" + +[c875500c-ff3d-47a4-bd1e-b60b90da80aa] +description = "the jack betrays the queen" + +[436875da-96ca-4149-be22-0b78173b8125] +description = "the 10 just wants to put on a show" + +[5be39bb6-1b34-4ce6-a1cd-0fcc142bb272] +description = "simple loop with decks of 3 cards" + +[2795dc21-0a2a-4c38-87c2-5a42e1ff15eb] +description = "the story is starting to get a bit complicated" + +[6999dfac-3fdc-41e2-b64b-38f4be228712] +description = "two tricks" + +[83dcd4f3-e089-4d54-855a-73f5346543a3] +description = "more tricks" + +[3107985a-f43e-486a-9ce8-db51547a9941] +description = "simple loop with decks of 4 cards" + +[dca32c31-11ed-49f6-b078-79ab912c1f7b] +description = "easy card combination" + +[1f8488d0-48d3-45ae-b819-59cedad0a5f4] +description = "easy card combination, inverted decks" + +[98878d35-623a-4d05-b81a-7bdc569eb88d] +description = "mirrored decks" + +[3e0ba597-ca10-484b-87a3-31a7df7d6da3] +description = "opposite decks" + +[92334ddb-aaa7-47fa-ab36-e928a8a6a67c] +description = "random decks #1" + +[30477523-9651-4860-84a3-e1ac461bb7fa] +description = "random decks #2" + +[20967de8-9e94-4e0e-9010-14bc1c157432] +description = "Kleber 1999" + +[9f2fdfe8-27f3-4323-816d-6bce98a9c6f7] +description = "Collins 2006" + +[c90b6f8d-7013-49f3-b5cb-14ea006cca1d] +description = "Mann and Wu 2007" + +[a3f1fbc5-1d0b-499a-92a5-22932dfc6bc8] +description = "Nessler 2012" + +[9cefb1ba-e6d1-4ab7-9d8f-76d8e0976d5f] +description = "Anderson 2013" + +[d37c0318-5be6-48d0-ab72-a7aaaff86179] +description = "Rucklidge 2014" + +[4305e479-ba87-432f-8a29-cd2bd75d2f05] +description = "Nessler 2021" + +[252f5cc3-b86d-4251-87ce-f920b7a6a559] +description = "Nessler 2022" + +[b9efcfa4-842f-4542-8112-8389c714d958] +description = "Casella 2024, first infinite game found" diff --git a/exercises/practice/camicia/analysis_options.yaml b/exercises/practice/camicia/analysis_options.yaml new file mode 100644 index 00000000..c06363d6 --- /dev/null +++ b/exercises/practice/camicia/analysis_options.yaml @@ -0,0 +1,18 @@ +analyzer: + strong-mode: + implicit-casts: false + implicit-dynamic: false + errors: + unused_element: error + unused_import: error + unused_local_variable: error + dead_code: error + +linter: + rules: + # Error Rules + - avoid_relative_lib_imports + - avoid_types_as_parameter_names + - literal_only_boolean_expressions + - no_adjacent_strings_in_list + - valid_regexps diff --git a/exercises/practice/camicia/lib/camicia.dart b/exercises/practice/camicia/lib/camicia.dart new file mode 100644 index 00000000..415ef153 --- /dev/null +++ b/exercises/practice/camicia/lib/camicia.dart @@ -0,0 +1,3 @@ +class Camicia { + // Put your code here +} diff --git a/exercises/practice/camicia/pubspec.yaml b/exercises/practice/camicia/pubspec.yaml new file mode 100644 index 00000000..f315b7c0 --- /dev/null +++ b/exercises/practice/camicia/pubspec.yaml @@ -0,0 +1,5 @@ +name: 'camicia' +environment: + sdk: '>=2.18.0 <3.0.0' +dev_dependencies: + test: '<2.0.0' diff --git a/exercises/practice/camicia/test/camicia_test.dart b/exercises/practice/camicia/test/camicia_test.dart new file mode 100644 index 00000000..6f33b622 --- /dev/null +++ b/exercises/practice/camicia/test/camicia_test.dart @@ -0,0 +1,202 @@ +import 'package:camicia/camicia.dart'; +import 'package:test/test.dart'; + +void main() { + final camicia = Camicia(); + List deck(String s) => s.split(' '); + + group('Camicia', () { + test('two cards, one trick', () { + final result = camicia.simulateGame(deck('2'), deck('3')); + expect(result, equals({'status': 'finished', 'cards': 2, 'tricks': 1})); + }, skip: false); + + test('three cards, one trick', () { + final result = camicia.simulateGame(deck('2 4'), deck('3')); + expect(result, equals({'status': 'finished', 'cards': 3, 'tricks': 1})); + }, skip: true); + + test('four cards, one trick', () { + final result = camicia.simulateGame(deck('2 4'), deck('3 5 6')); + expect(result, equals({'status': 'finished', 'cards': 4, 'tricks': 1})); + }, skip: true); + + test('the ace reigns supreme', () { + final result = camicia.simulateGame(deck('2 A'), deck('3 4 5 6 7')); + expect(result, equals({'status': 'finished', 'cards': 7, 'tricks': 1})); + }, skip: true); + + test('the king beats ace', () { + final result = camicia.simulateGame(deck('2 A'), deck('3 4 5 6 K')); + expect(result, equals({'status': 'finished', 'cards': 7, 'tricks': 1})); + }, skip: true); + + test('the queen seduces the king', () { + final result = camicia.simulateGame(deck('2 A 7 8 Q'), deck('3 4 5 6 K')); + expect(result, equals({'status': 'finished', 'cards': 10, 'tricks': 1})); + }, skip: true); + + test('the jack betrays the queen', () { + final result = camicia.simulateGame(deck('2 A 7 8 Q'), deck('3 4 5 6 K 9 J')); + expect(result, equals({'status': 'finished', 'cards': 12, 'tricks': 1})); + }, skip: true); + + test('the 10 just wants to put on a show', () { + final result = camicia.simulateGame( + deck('2 A 7 8 Q 10'), + deck('3 4 5 6 K 9 J'), + ); + expect(result, equals({'status': 'finished', 'cards': 13, 'tricks': 1})); + }, skip: true); + + test('simple loop with decks of 3 cards', () { + final result = camicia.simulateGame(deck('J 2 3'), deck('4 J 5')); + expect(result, equals({'status': 'loop', 'cards': 8, 'tricks': 3})); + }, skip: true); + + test('the story is starting to get a bit complicated', () { + final result = camicia.simulateGame( + deck( + '2 6 6 J 4 K Q 10 K J Q 2 3 K 5 6 Q Q A A 6 9 K A 8 K 2 A 9 A Q 4 K K K 3 5 K 8 Q 3 Q 7 J K J 9 J 3 3 K K Q A K 7 10 A Q 7 10 J 4 5 J 9 10 Q J J K 6 10 J 6 Q J 5 J Q Q 8 3 8 A 2 6 9 K 7 J K K 8 K Q 6 10 J 10 J Q J 10 3 8 K A 6 9 K 2 A A 10 J 6 A 4 J A J J 6 2 J 3 K 2 5 9 J 9 6 K A 5 Q J 2 Q K A 3 K J K 2 5 6 Q J Q Q J 2 J 9 Q 7 7 A Q 7 Q J K J A 7 7 8 Q 10 J 10 J J 9 2 A 2'), + deck( + '7 2 10 K 8 2 J 9 A 5 6 J Q 6 K 6 5 A 4 Q 7 J 7 10 2 Q 8 2 2 K J A 5 5 A 4 Q 6 Q K 10 8 Q 2 10 J A Q 8 Q Q J J A A 9 10 J K 4 Q 10 10 J K 10 2 J 7 A K K J A J 10 8 K A 7 Q Q J 3 Q 4 A 3 A Q Q Q 5 4 K J 10 A Q J 6 J A 10 A 5 8 3 K 5 9 Q 8 7 7 J 7 Q Q Q A 7 8 9 A Q A K 8 A A J 8 4 8 K J A 10 Q 8 J 8 6 10 Q J J A A J 5 Q 6 J K Q 8 K 4 Q Q 6 J K 4 7 J J 9 9 A Q Q K A 6 5 K'), + ); + expect(result, equals({'status': 'finished', 'cards': 361, 'tricks': 1})); + }, skip: true); + + test('two tricks', () { + final result = camicia.simulateGame(deck('J'), deck('3 J')); + expect(result, equals({'status': 'finished', 'cards': 5, 'tricks': 2})); + }, skip: true); + + test('more tricks', () { + final result = camicia.simulateGame(deck('J 2 4'), deck('3 J A')); + expect(result, equals({'status': 'finished', 'cards': 12, 'tricks': 4})); + }, skip: true); + + test('simple loop with decks of 4 cards', () { + final result = camicia.simulateGame(deck('2 3 J 6'), deck('K 5 J 7')); + expect(result, equals({'status': 'loop', 'cards': 16, 'tricks': 4})); + }, skip: true); + + test('easy card combination', () { + final result = camicia.simulateGame( + deck('4 8 7 5 4 10 3 9 7 3 10 10 6 8 2 8 5 4 5 9 6 5 2 8 10 9'), + deck('6 9 4 7 2 2 3 6 7 3 A A A A K K K K Q Q Q Q J J J J'), + ); + expect(result, equals({'status': 'finished', 'cards': 40, 'tricks': 4})); + }, skip: true); + + test('easy card combination, inverted decks', () { + final result = camicia.simulateGame( + deck('3 3 5 7 3 2 10 7 6 7 A A A A K K K K Q Q Q Q J J J J'), + deck('5 10 8 2 6 7 2 4 9 2 6 10 10 5 4 8 4 8 6 9 8 5 9 3 4 9'), + ); + expect(result, equals({'status': 'finished', 'cards': 40, 'tricks': 4})); + }, skip: true); + + test('mirrored decks', () { + final result = camicia.simulateGame( + deck('2 A 3 A 3 K 4 K 2 Q 2 Q 10 J 5 J 6 10 2 9 10 7 3 9 6 9'), + deck('6 A 4 A 7 K 4 K 7 Q 7 Q 5 J 8 J 4 5 8 9 10 6 8 3 8 5'), + ); + expect(result, equals({'status': 'finished', 'cards': 59, 'tricks': 4})); + }, skip: true); + + test('opposite decks', () { + final result = camicia.simulateGame( + deck('4 A 9 A 4 K 9 K 6 Q 8 Q 8 J 10 J 9 8 4 6 3 6 5 2 4 3'), + deck('10 7 3 2 9 2 7 8 7 5 J 7 J 10 Q 10 Q 3 K 5 K 6 A 2 A 5'), + ); + expect(result, equals({'status': 'finished', 'cards': 151, 'tricks': 21})); + }, skip: true); + + test('random decks #1', () { + final result = camicia.simulateGame( + deck('K 10 9 8 J 8 6 9 7 A K 5 4 4 J 5 J 4 3 5 8 6 7 7 4 9'), + deck('6 3 K A Q 10 A 2 Q 8 2 10 10 2 Q 3 K 9 7 A 3 Q 5 J 2 6'), + ); + expect(result, equals({'status': 'finished', 'cards': 542, 'tricks': 76})); + }, skip: true); + + test('random decks #2', () { + final result = camicia.simulateGame( + deck('8 A 4 8 5 Q J 2 6 2 9 7 K A 8 10 K 8 10 9 K 6 7 3 K 9'), + deck('10 5 2 6 Q J A 9 5 5 3 7 3 J A 2 Q 3 J Q 4 10 4 7 4 6'), + ); + expect(result, equals({'status': 'finished', 'cards': 327, 'tricks': 42})); + }, skip: true); + + test('Kleber 1999', () { + final result = camicia.simulateGame( + deck('4 8 9 J Q 8 5 5 K 2 A 9 8 5 10 A 4 J 3 K 6 9 2 Q K 7'), + deck('10 J 3 2 4 10 4 7 5 3 6 6 7 A J Q A 7 2 10 3 K 9 6 8 Q'), + ); + expect(result, equals({'status': 'finished', 'cards': 5790, 'tricks': 805})); + }, skip: true); + + test('Collins 2006', () { + final result = camicia.simulateGame( + deck('A 8 Q K 9 10 3 7 4 2 Q 3 2 10 9 K A 8 7 7 4 5 J 9 2 10'), + deck('4 J A K 8 5 6 6 A 6 5 Q 4 6 10 8 J 2 5 7 Q J 3 3 K 9'), + ); + expect(result, equals({'status': 'finished', 'cards': 6913, 'tricks': 960})); + }, skip: true); + + test('Mann and Wu 2007', () { + final result = camicia.simulateGame( + deck('K 2 K K 3 3 6 10 K 6 A 2 5 5 7 9 J A A 3 4 Q 4 8 J 6'), + deck('4 5 2 Q 7 9 9 Q 7 J 9 8 10 3 10 J 4 10 8 6 8 7 A Q 5 2'), + ); + expect(result, equals({'status': 'finished', 'cards': 7157, 'tricks': 1007})); + }, skip: true); + + test('Nessler 2012', () { + final result = camicia.simulateGame( + deck('10 3 6 7 Q 2 9 8 2 8 4 A 10 6 K 2 10 A 5 A 2 4 Q J K 4'), + deck('10 Q 4 6 J 9 3 J 9 3 3 Q K 5 9 5 K 6 5 7 8 J A 7 8 7'), + ); + expect(result, equals({'status': 'finished', 'cards': 7207, 'tricks': 1015})); + }, skip: true); + + test('Anderson 2013', () { + final result = camicia.simulateGame( + deck('6 7 A 3 Q 3 5 J 3 2 J 7 4 5 Q 10 5 A J 2 K 8 9 9 K 3'), + deck('4 J 6 9 8 5 10 7 9 Q 2 7 10 8 4 10 A 6 4 A 6 8 Q K K 2'), + ); + expect(result, equals({'status': 'finished', 'cards': 7225, 'tricks': 1016})); + }, skip: true); + + test('Rucklidge 2014', () { + final result = camicia.simulateGame( + deck('8 J 2 9 4 4 5 8 Q 3 9 3 6 2 8 A A A 9 4 7 2 5 Q Q 3'), + deck('K 7 10 6 3 J A 7 6 5 5 8 10 9 10 4 2 7 K Q 10 K 6 J J K'), + ); + expect(result, equals({'status': 'finished', 'cards': 7959, 'tricks': 1122})); + }, skip: true); + + test('Nessler 2021', () { + final result = camicia.simulateGame( + deck('7 2 3 4 K 9 6 10 A 8 9 Q 7 A 4 8 J J A 4 3 2 5 6 6 J'), + deck('3 10 8 9 8 K K 2 5 5 7 6 4 3 5 7 A 9 J K 2 Q 10 Q 10 Q'), + ); + expect(result, equals({'status': 'finished', 'cards': 7972, 'tricks': 1106})); + }, skip: true); + + test('Nessler 2022', () { + final result = camicia.simulateGame( + deck('2 10 10 A J 3 8 Q 2 5 5 5 9 2 4 3 10 Q A K Q J J 9 Q K'), + deck('10 7 6 3 6 A 8 9 4 3 K J 6 K 4 9 7 8 5 7 8 2 A 7 4 6'), + ); + expect(result, equals({'status': 'finished', 'cards': 8344, 'tricks': 1164})); + }, skip: true); + + test('Casella 2024, first infinite game found', () { + final result = camicia.simulateGame( + deck('2 8 4 K 5 2 3 Q 6 K Q A J 3 5 9 8 3 A A J 4 4 J 7 5'), + deck('7 7 8 6 10 10 6 10 7 2 Q 6 3 2 4 K Q 10 J 5 9 8 9 9 K A'), + ); + expect(result, equals({'status': 'loop', 'cards': 474, 'tricks': 66})); + }, skip: true); + }); +}