diff --git a/config.json b/config.json index 9a69db8..9008e40 100644 --- a/config.json +++ b/config.json @@ -856,6 +856,14 @@ ], "difficulty": 5 }, + { + "slug": "camicia", + "name": "Camicia", + "uuid": "8a02fe66-fd54-49ab-ae25-1722a1dc1620", + "practices": [], + "prerequisites": [], + "difficulty": 5 + }, { "slug": "change", "name": "Change", diff --git a/exercises/Exercises.slnx b/exercises/Exercises.slnx index 6f3dbc9..e1cc952 100644 --- a/exercises/Exercises.slnx +++ b/exercises/Exercises.slnx @@ -16,6 +16,7 @@ + diff --git a/exercises/practice/camicia/.docs/instructions.md b/exercises/practice/camicia/.docs/instructions.md new file mode 100644 index 0000000..db62fce --- /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 0000000..761d8a8 --- /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/.editorconfig b/exercises/practice/camicia/.editorconfig new file mode 100644 index 0000000..11f55d2 --- /dev/null +++ b/exercises/practice/camicia/.editorconfig @@ -0,0 +1,89 @@ +############################### +# Core EditorConfig Options # +############################### + +; This file is for unifying the coding style for different editors and IDEs. +; More information at: +; https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference?view=vs-2022 +; https://docs.microsoft.com/en-us/visualstudio/ide/create-portable-custom-editor-options?view=vs-2022 + +root = true + +[*] +end_of_line = lf +indent_style = space +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{vbproj,slnx}] +indent_size = 2 + +[*.vb] +indent_size = 4 +charset = utf-8 + +############################### +# .NET Coding Conventions # +############################### + +# Organize imports +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = true + +# Me. preferences +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_event = false:suggestion + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none +dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none +dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:none +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = always:suggestion +dotnet_style_readonly_field = true:suggestion + +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_return = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion + +############################### +# Naming Conventions # +############################### + +# Style Definitions +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + +# Use PascalCase for constant fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.applicable_accessibilities = * +dotnet_naming_symbols.constant_fields.required_modifiers = const + +################################### +# Visual Basic Coding Conventions # +################################### +visual_basic_preferred_modifier_order = Partial, Default, Private, Protected, Public, Friend, NotOverridable, Overridable, MustOverride, Overloads, Overrides, MustInherit, NotInheritable, Static, Shared, Shadows, ReadOnly, WriteOnly, Dim, Const, WithEvents, Widening, Narrowing, Custom, Async:suggestion +visual_basic_style_unused_variable_expression_statement_preference = unused_local_variable:suggestion +visual_basic_style_unused_value_assignment_preference = unused_local_variable:suggestion +visual_basic_style_prefer_isnot_expression = true:suggestion +visual_basic_style_prefer_simplified_object_creation = false:none +dotnet_diagnostic.IDE0090.severity = none diff --git a/exercises/practice/camicia/.meta/Example.vb b/exercises/practice/camicia/.meta/Example.vb new file mode 100644 index 0000000..3663f57 --- /dev/null +++ b/exercises/practice/camicia/.meta/Example.vb @@ -0,0 +1,147 @@ +Public Enum GameStatus + Finished + [Loop] +End Enum + +Public Structure GameResult + Public Sub New(ByVal status As GameStatus, ByVal tricks As Integer, ByVal cards As Integer) + Me.Status = status + Me.Tricks = tricks + Me.Cards = cards + End Sub + + Public ReadOnly Property Status As GameStatus + Public ReadOnly Property Tricks As Integer + Public ReadOnly Property Cards As Integer +End Structure + +Public Module Camicia + Private Enum Player + A + B + End Enum + + Public Function SimulateGame(ByVal playerA As String(), ByVal playerB As String()) As GameResult + Dim handA As New Queue(Of Integer)(playerA.Select(AddressOf CardValue)) + Dim handB As New Queue(Of Integer)(playerB.Select(AddressOf CardValue)) + Dim pile As New List(Of Integer) + Dim seen As New HashSet(Of String) + Dim activePlayer = Player.A + Dim tricks = 0 + Dim cards = 0 + Dim debt = 0 + + While True + If IsRepeatedPosition(pile, handA, handB, activePlayer, seen) Then + Return New GameResult(GameStatus.[Loop], tricks, cards) + End If + + Dim activeHand = HandFor(activePlayer, handA, handB) + Dim otherHand = HandFor(OtherPlayer(activePlayer), handA, handB) + + If activeHand.Count = 0 Then + Return FinishedGame(tricks, cards, pile) + End If + + Dim card = activeHand.Dequeue() + pile.Add(card) + cards += 1 + + If card > 0 Then + debt = card + activePlayer = OtherPlayer(activePlayer) + ElseIf debt > 1 Then + debt -= 1 + ElseIf debt = 1 Then + AwardPile(pile, otherHand) + tricks += 1 + debt = 0 + + If handA.Count = 0 OrElse handB.Count = 0 Then + Return New GameResult(GameStatus.Finished, tricks, cards) + End If + + activePlayer = OtherPlayer(activePlayer) + Else + activePlayer = OtherPlayer(activePlayer) + End If + End While + + Throw New InvalidOperationException("unreachable") + End Function + + Private Function IsRepeatedPosition( + ByVal pile As List(Of Integer), + ByVal handA As Queue(Of Integer), + ByVal handB As Queue(Of Integer), + ByVal activePlayer As Player, + ByVal seen As HashSet(Of String)) As Boolean + + If pile.Count > 0 Then + Return False + End If + + Dim position = PositionKey(handA, handB, activePlayer) + Return Not seen.Add(position) + End Function + + Private Function FinishedGame( + ByVal tricks As Integer, + ByVal cards As Integer, + ByVal pile As List(Of Integer)) As GameResult + + Dim extraTrick = If(pile.Count = 0, 0, 1) + Return New GameResult(GameStatus.Finished, tricks + extraTrick, cards) + End Function + + Private Function HandFor( + ByVal player As Player, + ByVal handA As Queue(Of Integer), + ByVal handB As Queue(Of Integer)) As Queue(Of Integer) + + If player = Player.A Then + Return handA + End If + + Return handB + End Function + + Private Sub AwardPile(ByVal pile As List(Of Integer), ByVal winner As Queue(Of Integer)) + For Each card In pile + winner.Enqueue(card) + Next + + pile.Clear() + End Sub + + Private Function OtherPlayer(ByVal player As Player) As Player + If player = Player.A Then + Return Player.B + End If + + Return Player.A + End Function + + Private Function CardValue(ByVal card As String) As Integer + Select Case card + Case "J" + Return 1 + Case "Q" + Return 2 + Case "K" + Return 3 + Case "A" + Return 4 + Case Else + Return 0 + End Select + End Function + + Private Function PositionKey( + ByVal handA As Queue(Of Integer), + ByVal handB As Queue(Of Integer), + ByVal activePlayer As Player) As String + + Return $"{String.Join(",", handA)}|{String.Join(",", handB)}|{activePlayer}" + End Function +End Module diff --git a/exercises/practice/camicia/.meta/config.json b/exercises/practice/camicia/.meta/config.json new file mode 100644 index 0000000..5993763 --- /dev/null +++ b/exercises/practice/camicia/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "Camicia.vb" + ], + "test": [ + "CamiciaTests.vb" + ], + "example": [ + ".meta/Example.vb" + ] + }, + "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/tests.toml b/exercises/practice/camicia/.meta/tests.toml new file mode 100644 index 0000000..18d3fdd --- /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/Camicia.vb b/exercises/practice/camicia/Camicia.vb new file mode 100644 index 0000000..0b9caf4 --- /dev/null +++ b/exercises/practice/camicia/Camicia.vb @@ -0,0 +1,22 @@ +Public Enum GameStatus + Finished + [Loop] +End Enum + +Public Structure GameResult + Public Sub New(ByVal status As GameStatus, ByVal tricks As Integer, ByVal cards As Integer) + Me.Status = status + Me.Tricks = tricks + Me.Cards = cards + End Sub + + Public ReadOnly Property Status As GameStatus + Public ReadOnly Property Tricks As Integer + Public ReadOnly Property Cards As Integer +End Structure + +Public Module Camicia + Public Function SimulateGame(ByVal playerA As String(), ByVal playerB As String()) As GameResult + Throw New NotImplementedException("You need to implement this function.") + End Function +End Module diff --git a/exercises/practice/camicia/Camicia.vbproj b/exercises/practice/camicia/Camicia.vbproj new file mode 100644 index 0000000..b4587f0 --- /dev/null +++ b/exercises/practice/camicia/Camicia.vbproj @@ -0,0 +1,19 @@ + + + + net10.0 + Exe + true + + + + + + + + + + + + + diff --git a/exercises/practice/camicia/CamiciaTests.vb b/exercises/practice/camicia/CamiciaTests.vb new file mode 100644 index 0000000..3c60218 --- /dev/null +++ b/exercises/practice/camicia/CamiciaTests.vb @@ -0,0 +1,458 @@ +Public Class CamiciaTests + + Public Sub Two_cards_one_trick() + Dim playerA = {"2"} + Dim playerB = {"3"} + Dim status = GameStatus.Finished + Dim tricks = 1 + Dim cards = 2 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Three_cards_one_trick() + Dim playerA = {"2", "4"} + Dim playerB = {"3"} + Dim status = GameStatus.Finished + Dim tricks = 1 + Dim cards = 3 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Four_cards_one_trick() + Dim playerA = {"2", "4"} + Dim playerB = {"3", "5", "6"} + Dim status = GameStatus.Finished + Dim tricks = 1 + Dim cards = 4 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub The_ace_reigns_supreme() + Dim playerA = {"2", "A"} + Dim playerB = {"3", "4", "5", "6", "7"} + Dim status = GameStatus.Finished + Dim tricks = 1 + Dim cards = 7 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub The_king_beats_ace() + Dim playerA = {"2", "A"} + Dim playerB = {"3", "4", "5", "6", "K"} + Dim status = GameStatus.Finished + Dim tricks = 1 + Dim cards = 7 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub The_queen_seduces_the_king() + Dim playerA = {"2", "A", "7", "8", "Q"} + Dim playerB = {"3", "4", "5", "6", "K"} + Dim status = GameStatus.Finished + Dim tricks = 1 + Dim cards = 10 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub The_jack_betrays_the_queen() + Dim playerA = {"2", "A", "7", "8", "Q"} + Dim playerB = {"3", "4", "5", "6", "K", "9", "J"} + Dim status = GameStatus.Finished + Dim tricks = 1 + Dim cards = 12 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub The_Ten_just_wants_to_put_on_a_show() + Dim playerA = {"2", "A", "7", "8", "Q", "10"} + Dim playerB = {"3", "4", "5", "6", "K", "9", "J"} + Dim status = GameStatus.Finished + Dim tricks = 1 + Dim cards = 13 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Simple_loop_with_decks_of_3_cards() + Dim playerA = {"J", "2", "3"} + Dim playerB = {"4", "J", "5"} + Dim status = GameStatus.[Loop] + Dim tricks = 3 + Dim cards = 8 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub The_story_is_starting_to_get_a_bit_complicated() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 1 + Dim cards = 361 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Two_tricks() + Dim playerA = {"J"} + Dim playerB = {"3", "J"} + Dim status = GameStatus.Finished + Dim tricks = 2 + Dim cards = 5 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub More_tricks() + Dim playerA = {"J", "2", "4"} + Dim playerB = {"3", "J", "A"} + Dim status = GameStatus.Finished + Dim tricks = 4 + Dim cards = 12 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Simple_loop_with_decks_of_4_cards() + Dim playerA = {"2", "3", "J", "6"} + Dim playerB = {"K", "5", "J", "7"} + Dim status = GameStatus.[Loop] + Dim tricks = 4 + Dim cards = 16 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Easy_card_combination() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 4 + Dim cards = 40 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Easy_card_combination_inverted_decks() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 4 + Dim cards = 40 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Mirrored_decks() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 4 + Dim cards = 59 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Opposite_decks() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 21 + Dim cards = 151 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Random_decks_1() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 76 + Dim cards = 542 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Random_decks_2() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 42 + Dim cards = 327 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Kleber_1999() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 805 + Dim cards = 5790 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Collins_2006() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 960 + Dim cards = 6913 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Mann_and_Wu_2007() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 1007 + Dim cards = 7157 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Nessler_2012() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 1015 + Dim cards = 7207 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Anderson_2013() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 1016 + Dim cards = 7225 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Rucklidge_2014() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 1122 + Dim cards = 7959 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Nessler_2021() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 1106 + Dim cards = 7972 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Nessler_2022() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.Finished + Dim tricks = 1164 + Dim cards = 8344 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub + + + Public Sub Casella_2024_first_infinite_game_found() + Dim playerA = { + "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"} + Dim playerB = { + "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"} + Dim status = GameStatus.[Loop] + Dim tricks = 66 + Dim cards = 474 + Dim expected = New GameResult(status, tricks, cards) + + Assert.Equal(expected, SimulateGame(playerA, playerB)) + End Sub +End Class diff --git a/exercises/practice/camicia/packages.lock.json b/exercises/practice/camicia/packages.lock.json new file mode 100644 index 0000000..8da1f14 --- /dev/null +++ b/exercises/practice/camicia/packages.lock.json @@ -0,0 +1,168 @@ +{ + "version": 1, + "dependencies": { + "net10.0": { + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[18.3.0, )", + "resolved": "18.3.0", + "contentHash": "xW3kXuWRQtgoxJp4J+gdhHSQyK+6Wb/AZDSd7lMvuMRYlZ1tnpkojyfZlWilB5G4dmZ0Y0ZxU/M23TlubndNkw==", + "dependencies": { + "Microsoft.CodeCoverage": "18.3.0", + "Microsoft.TestPlatform.TestHost": "18.3.0" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[3.1.5, )", + "resolved": "3.1.5", + "contentHash": "tKi7dSTwP4m5m9eXPM2Ime4Kn7xNf4x4zT9sdLO/G4hZVnQCRiMTWoSZqI/pYTVeI27oPPqHBKYI/DjJ9GsYgA==" + }, + "xunit.v3": { + "type": "Direct", + "requested": "[3.2.2, )", + "resolved": "3.2.2", + "contentHash": "L+4/4y0Uqcg8/d6hfnxhnwh4j9FaeULvefTwrk30rr1o4n/vdPfyUQ8k0yzH8VJx7bmFEkDdcRfbtbjEHlaYcA==", + "dependencies": { + "xunit.v3.mtp-v1": "[3.2.2]" + } + }, + "Microsoft.ApplicationInsights": { + "type": "Transitive", + "resolved": "2.23.0", + "contentHash": "nWArUZTdU7iqZLycLKWe0TDms48KKGE6pONH2terYNa8REXiqixrMOkf1sk5DHGMaUTqONU2YkS4SAXBhLStgw==" + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg==" + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "18.3.0", + "contentHash": "23BNy/vziREC20Wwhb50K7+kZe0m07KlLWDQv4qjJ9tt3QjpDpDIqJFrhYHmMEo9xDkuSp55U/8h4bMF7MiB+g==" + }, + "Microsoft.Testing.Extensions.Telemetry": { + "type": "Transitive", + "resolved": "1.9.1", + "contentHash": "No5AudZMmSb+uNXjlgL2y3/stHD2IT4uxqc5yHwkE+/nNux9jbKcaJMvcp9SwgP4DVD8L9/P3OUz8mmmcvEIdQ==", + "dependencies": { + "Microsoft.ApplicationInsights": "2.23.0", + "Microsoft.Testing.Platform": "1.9.1" + } + }, + "Microsoft.Testing.Extensions.TrxReport.Abstractions": { + "type": "Transitive", + "resolved": "1.9.1", + "contentHash": "AL46Xe1WBi85Ntd4mNPvat5ZSsZ2uejiVqoKCypr8J3wK0elA5xJ3AN4G/Q4GIwzUFnggZoH/DBjnr9J18IO/g==", + "dependencies": { + "Microsoft.Testing.Platform": "1.9.1" + } + }, + "Microsoft.Testing.Platform": { + "type": "Transitive", + "resolved": "1.9.1", + "contentHash": "QafNtNSmEI0zazdebnsIkDKmFtTSpmx/5PLOjURWwozcPb3tvRxzosQSL8xwYNM1iPhhKiBksXZyRSE2COisrA==" + }, + "Microsoft.Testing.Platform.MSBuild": { + "type": "Transitive", + "resolved": "1.9.1", + "contentHash": "oTUtyR4X/s9ytuiNA29FGsNCCH0rNmY5Wdm14NCKLjTM1cT9edVSlA+rGS/mVmusPqcP0l/x9qOnMXg16v87RQ==", + "dependencies": { + "Microsoft.Testing.Platform": "1.9.1" + } + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "18.3.0", + "contentHash": "AEIEX2aWdPO9XbtR96eBaJxmXRD9vaI9uQ1T/JbPEKlTAZwYx0ZrMzKyULMdh/HH9Sg03kXCoN7LszQ90o6nPQ==" + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "18.3.0", + "contentHash": "twmsoelXnp1uWMU3VGip9f0Jr1mZ0PZqgJdF35CIrdYgYrkHIJMV1m8uKyhcdjLdsQDESHAgkR7KhS9i1qpJag==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "18.3.0", + "Newtonsoft.Json": "13.0.3" + } + }, + "Microsoft.Win32.Registry": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==" + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, + "xunit.analyzers": { + "type": "Transitive", + "resolved": "1.27.0", + "contentHash": "y/pxIQaLvk/kxAoDkZW9GnHLCEqzwl5TW0vtX3pweyQpjizB9y3DXhb9pkw2dGeUqhLjsxvvJM1k89JowU6z3g==" + }, + "xunit.v3.assert": { + "type": "Transitive", + "resolved": "3.2.2", + "contentHash": "BPciBghgEEaJN/JG00QfCYDfEfnLgQhfnYEy+j1izoeHVNYd5+3Wm8GJ6JgYysOhpBPYGE+sbf75JtrRc7jrdA==" + }, + "xunit.v3.common": { + "type": "Transitive", + "resolved": "3.2.2", + "contentHash": "Hj775PEH6GTbbg0wfKRvG2hNspDCvTH9irXhH4qIWgdrOSV1sQlqPie+DOvFeigsFg2fxSM3ZAaaCDQs+KreFA==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "6.0.0" + } + }, + "xunit.v3.core.mtp-v1": { + "type": "Transitive", + "resolved": "3.2.2", + "contentHash": "Ga5aA2Ca9ktz+5k3g5ukzwfexwoqwDUpV6z7atSEUvqtd6JuybU1XopHqg1oFd78QdTfZgZE9h5sHpO4qYIi5w==", + "dependencies": { + "Microsoft.Testing.Extensions.Telemetry": "1.9.1", + "Microsoft.Testing.Extensions.TrxReport.Abstractions": "1.9.1", + "Microsoft.Testing.Platform": "1.9.1", + "Microsoft.Testing.Platform.MSBuild": "1.9.1", + "xunit.v3.extensibility.core": "[3.2.2]", + "xunit.v3.runner.inproc.console": "[3.2.2]" + } + }, + "xunit.v3.extensibility.core": { + "type": "Transitive", + "resolved": "3.2.2", + "contentHash": "srY8z/oMPvh/t8axtO2DwrHajhFMH7tnqKildvYrVQIfICi8fOn3yIBWkVPAcrKmHMwvXRJ/XsQM3VMR6DOYfQ==", + "dependencies": { + "xunit.v3.common": "[3.2.2]" + } + }, + "xunit.v3.mtp-v1": { + "type": "Transitive", + "resolved": "3.2.2", + "contentHash": "O41aAzYKBT5PWqATa1oEWVNCyEUypFQ4va6K0kz37dduV3EKzXNMaV2UnEhufzU4Cce1I33gg0oldS8tGL5I0A==", + "dependencies": { + "xunit.analyzers": "1.27.0", + "xunit.v3.assert": "[3.2.2]", + "xunit.v3.core.mtp-v1": "[3.2.2]" + } + }, + "xunit.v3.runner.common": { + "type": "Transitive", + "resolved": "3.2.2", + "contentHash": "/hkHkQCzGrugelOAehprm7RIWdsUFVmIVaD6jDH/8DNGCymTlKKPTbGokD5czbAfqfex47mBP0sb0zbHYwrO/g==", + "dependencies": { + "Microsoft.Win32.Registry": "[5.0.0]", + "xunit.v3.common": "[3.2.2]" + } + }, + "xunit.v3.runner.inproc.console": { + "type": "Transitive", + "resolved": "3.2.2", + "contentHash": "ulWOdSvCk+bPXijJZ73bth9NyoOHsAs1ZOvamYbCkD4DNLX/Bd29Ve2ZNUwBbK0MqfIYWXHZViy/HKrdEC/izw==", + "dependencies": { + "xunit.v3.extensibility.core": "[3.2.2]", + "xunit.v3.runner.common": "[3.2.2]" + } + } + } + } +} \ No newline at end of file