diff --git a/config.json b/config.json index 908da5831..df37a59b1 100644 --- a/config.json +++ b/config.json @@ -2714,6 +2714,23 @@ ], "difficulty": 7 }, + { + "slug": "intergalactic-transmission", + "name": "intergalactic-transmission", + "uuid": "845c8cf4-207c-438f-9d18-c5e7875ee729", + "practices": [ + "bit-manipulation" + ], + "prerequisites": [ + "bit-manipulation", + "arrays", + "exceptions", + "integral-numbers", + "for-loops", + "if-statements" + ], + "difficulty": 6 + }, { "slug": "split-second-stopwatch", "name": "Split-Second Stopwatch", diff --git a/exercises/Exercises.sln b/exercises/Exercises.sln index 006267b96..08e9a3d9c 100644 --- a/exercises/Exercises.sln +++ b/exercises/Exercises.sln @@ -357,6 +357,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StateOfTicTacToe", "practic EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BottleSong", "practice\bottle-song\BottleSong.csproj", "{6BD384E6-225E-4F8A-856C-3079957C6E36}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntergalacticTransmission", "practice\intergalactic-transmission\IntergalacticTransmission.csproj", "{E81F1BA3-1F99-4DCB-B875-78D1F4750BD5}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SplitSecondStopwatch", "practice\split-second-stopwatch\SplitSecondStopwatch.csproj", "{0A6CD51A-2120-4A72-A17B-08CCC2E6D365}" EndProject Global @@ -2469,18 +2471,18 @@ Global {6BD384E6-225E-4F8A-856C-3079957C6E36}.Release|x64.Build.0 = Release|Any CPU {6BD384E6-225E-4F8A-856C-3079957C6E36}.Release|x86.ActiveCfg = Release|Any CPU {6BD384E6-225E-4F8A-856C-3079957C6E36}.Release|x86.Build.0 = Release|Any CPU - {DA4856F5-A260-43A0-9C9C-6DD2E2B08692}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DA4856F5-A260-43A0-9C9C-6DD2E2B08692}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DA4856F5-A260-43A0-9C9C-6DD2E2B08692}.Debug|x64.ActiveCfg = Debug|Any CPU - {DA4856F5-A260-43A0-9C9C-6DD2E2B08692}.Debug|x64.Build.0 = Debug|Any CPU - {DA4856F5-A260-43A0-9C9C-6DD2E2B08692}.Debug|x86.ActiveCfg = Debug|Any CPU - {DA4856F5-A260-43A0-9C9C-6DD2E2B08692}.Debug|x86.Build.0 = Debug|Any CPU - {DA4856F5-A260-43A0-9C9C-6DD2E2B08692}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DA4856F5-A260-43A0-9C9C-6DD2E2B08692}.Release|Any CPU.Build.0 = Release|Any CPU - {DA4856F5-A260-43A0-9C9C-6DD2E2B08692}.Release|x64.ActiveCfg = Release|Any CPU - {DA4856F5-A260-43A0-9C9C-6DD2E2B08692}.Release|x64.Build.0 = Release|Any CPU - {DA4856F5-A260-43A0-9C9C-6DD2E2B08692}.Release|x86.ActiveCfg = Release|Any CPU - {DA4856F5-A260-43A0-9C9C-6DD2E2B08692}.Release|x86.Build.0 = Release|Any CPU + {E81F1BA3-1F99-4DCB-B875-78D1F4750BD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E81F1BA3-1F99-4DCB-B875-78D1F4750BD5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E81F1BA3-1F99-4DCB-B875-78D1F4750BD5}.Debug|x64.ActiveCfg = Debug|Any CPU + {E81F1BA3-1F99-4DCB-B875-78D1F4750BD5}.Debug|x64.Build.0 = Debug|Any CPU + {E81F1BA3-1F99-4DCB-B875-78D1F4750BD5}.Debug|x86.ActiveCfg = Debug|Any CPU + {E81F1BA3-1F99-4DCB-B875-78D1F4750BD5}.Debug|x86.Build.0 = Debug|Any CPU + {E81F1BA3-1F99-4DCB-B875-78D1F4750BD5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E81F1BA3-1F99-4DCB-B875-78D1F4750BD5}.Release|Any CPU.Build.0 = Release|Any CPU + {E81F1BA3-1F99-4DCB-B875-78D1F4750BD5}.Release|x64.ActiveCfg = Release|Any CPU + {E81F1BA3-1F99-4DCB-B875-78D1F4750BD5}.Release|x64.Build.0 = Release|Any CPU + {E81F1BA3-1F99-4DCB-B875-78D1F4750BD5}.Release|x86.ActiveCfg = Release|Any CPU + {E81F1BA3-1F99-4DCB-B875-78D1F4750BD5}.Release|x86.Build.0 = Release|Any CPU {0A6CD51A-2120-4A72-A17B-08CCC2E6D365}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0A6CD51A-2120-4A72-A17B-08CCC2E6D365}.Debug|Any CPU.Build.0 = Debug|Any CPU {0A6CD51A-2120-4A72-A17B-08CCC2E6D365}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -2673,9 +2675,8 @@ Global {8E276065-1371-4CFA-BA20-95225EC6AEBC} = {E276EF69-669A-43E0-88AC-8ABB17A9C026} {67E9BAB3-9805-42F1-9298-E9BBB795140E} = {E276EF69-669A-43E0-88AC-8ABB17A9C026} {6BD384E6-225E-4F8A-856C-3079957C6E36} = {E276EF69-669A-43E0-88AC-8ABB17A9C026} - {DA4856F5-A260-43A0-9C9C-6DD2E2B08692} = {E276EF69-669A-43E0-88AC-8ABB17A9C026} - {B587F905-CC4E-0FB1-25B1-84C433FD33E0} = {E276EF69-669A-43E0-88AC-8ABB17A9C026} - {0A6CD51A-2120-4A72-A17B-08CCC2E6D365} = {B587F905-CC4E-0FB1-25B1-84C433FD33E0} + {E81F1BA3-1F99-4DCB-B875-78D1F4750BD5} = {E276EF69-669A-43E0-88AC-8ABB17A9C026} + {0A6CD51A-2120-4A72-A17B-08CCC2E6D365} = {E276EF69-669A-43E0-88AC-8ABB17A9C026} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AB4EA6C9-5461-4024-BDC7-2AE0C3A85CD1} diff --git a/exercises/practice/intergalactic-transmission/.docs/instructions.md b/exercises/practice/intergalactic-transmission/.docs/instructions.md new file mode 100644 index 000000000..63fe661e0 --- /dev/null +++ b/exercises/practice/intergalactic-transmission/.docs/instructions.md @@ -0,0 +1,54 @@ +# Instructions + +Your job is to help implement + +- the transmitter, which calculates the transmission sequence, and +- the receiver, which decodes it. + +A parity bit is simple way of detecting transmission errors. +The transmitters and receivers can only transmit and receive _exactly_ eight bits at a time (including the parity bit). +The parity bit is set so that there is an _even_ number 1s in each transmission and is always the first bit from the right. +So if the receiver receives `11000001`, `01110101` or `01000000` (i.e. a transmission with an odd number of 1 bits), it knows there is an error. + +However, messages are rarely this short, and need to be transmitted in a sequence when they are longer. + +For example, consider the message `11000000 00000001 11000000 11011110` (or `C0 01 C0 DE` in hex). + +Since each transmission contains exactly eight bits, it can only contain seven bits of data and the parity bit. +A parity bit must then be inserted after every seven bits of data: + +```text +11000000 00000001 11000000 11011110 + ↑ ↑ ↑ ↑ (7th bits) +``` + +The transmission sequence for this message looks like this: + +```text +1100000_ 0000000_ 0111000_ 0001101_ 1110 + ↑ ↑ ↑ ↑ (parity bits) +``` + +The data in the first transmission in the sequence (`1100000`) has two 1 bits (an even number), so the parity bit is 0. +The first transmission becomes `11000000` (or `C0` in hex). + +The data in the next transmission (`0000000`) has zero 1 bits (an even number again), so the parity bit is 0 again. +The second transmission thus becomes `00000000` (or `00` in hex). + +The data for the next two transmissions (`0111000` and `0001101`) have three 1 bits. +Their parity bits are set to 1 so that they have an even number of 1 bits in the transmission. +They are transmitted as `01110001` and `00011011` (or `71` and `1B` in hex). + +The last transmission (`1110`) has only four bits of data. +Since exactly eight bits are transmitted at a time and the parity bit is the right most bit, three 0 bits and then the parity bit are added to make up eight bits. +It now looks like this (where `_` is the parity bit): + +```text +1110 000_ + ↑↑↑ (added 0 bits) +``` + +There is an odd number of 1 bits again, so the parity bit is 1. +The last transmission in the sequence becomes `11100001` (or `E1` in hex). + +The entire transmission sequence for this message is `11000000 00000000 01110001 00011011 11100001` (or `C0 00 71 1B E1` in hex). diff --git a/exercises/practice/intergalactic-transmission/.docs/introduction.md b/exercises/practice/intergalactic-transmission/.docs/introduction.md new file mode 100644 index 000000000..f19dffbea --- /dev/null +++ b/exercises/practice/intergalactic-transmission/.docs/introduction.md @@ -0,0 +1,23 @@ +# Introduction + +Trillions upon trillions of messages zip between Earth and neighboring galaxies every millisecond. +But transmitting over such long distances is tricky. +Pesky solar flares, temporal distortions, stray forces, and even the flap of a space butterfly's wing can cause a random bit to change during transmission. + +Now imagine the consequences: + +- Crashing the Intergalactic Share Market when "buy low" turns to "sell now". +- Losing contact with the Kepler Whirl system when "save new worm hole" becomes "cave new worm hole". +- Or plunging the universe into existential horror by replacing a cowboy emoji 🤠 with a clown emoji 🤡. + +Detecting corrupted messages isn't just important — it's critical. +The receiver _must_ know when something has gone wrong before disaster strikes. + +But how? +Scientists and engineers from across the universe have been battling this problem for eons. +Entire cosmic AI superclusters churn through the data. +And then, one day, a legend resurfaces — an ancient, powerful method, whispered in debugging forums, muttered by engineers who've seen too much... + +The Parity Bit! + +A method so simple, so powerful, that it might just save interstellar communication. diff --git a/exercises/practice/intergalactic-transmission/.editorconfig b/exercises/practice/intergalactic-transmission/.editorconfig new file mode 100644 index 000000000..182213a7d --- /dev/null +++ b/exercises/practice/intergalactic-transmission/.editorconfig @@ -0,0 +1,141 @@ +############################### +# 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-2017 +; https://docs.microsoft.com/en-us/visualstudio/ide/create-portable-custom-editor-options?view=vs-2017 + +root = true + +[*] +indent_style = space + +[IntergalacticTransmission.cs] +indent_size = 4 + +############################### +# .NET Coding Conventions # +############################### + +# Organize usings +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = true + +# this. 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 + +############################### +# C# Code Style Rules # +############################### + +# var preferences +csharp_style_var_for_built_in_types = true:none +csharp_style_var_when_type_is_apparent = true:none +csharp_style_var_elsewhere = true:none + +# Expression-bodied members +csharp_style_expression_bodied_methods = true:suggestion +csharp_style_expression_bodied_constructors = true:suggestion +csharp_style_expression_bodied_operators = true:suggestion +csharp_style_expression_bodied_properties = true:suggestion +csharp_style_expression_bodied_indexers = true:suggestion +csharp_style_expression_bodied_accessors = true:suggestion + +# Pattern-matching preferences +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion + +# Null-checking preferences +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion + +# Modifier preferences +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion + +# Expression-level preferences +csharp_prefer_braces = true:none +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion + +############################### +# C# Formatting Rules # +############################### + +# New line preferences +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = false +csharp_new_line_before_members_in_anonymous_types = false +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true diff --git a/exercises/practice/intergalactic-transmission/.meta/Example.cs b/exercises/practice/intergalactic-transmission/.meta/Example.cs new file mode 100644 index 000000000..bf1af354e --- /dev/null +++ b/exercises/practice/intergalactic-transmission/.meta/Example.cs @@ -0,0 +1,91 @@ +public static class IntergalacticTransmission +{ + private const byte InitUpperMask = (byte)0xFE; + + public static byte[] GetTransmitSequence(byte[] message) + { + List transmitSeq = new List(); + byte carry = 0; + byte upperMask = InitUpperMask; + + for (int i = 0; i < message.Length; i++) + { + if (upperMask == 0) + { + // The carry now contains 7 bits. Flush the carry out. + transmitSeq.Add(AddParity(carry)); + carry = 0; + upperMask = 0xFE; + } + + int shiftPlaces = byte.TrailingZeroCount(upperMask); + int current = (carry << (8 - shiftPlaces)) | (message[i] >>> shiftPlaces); + transmitSeq.Add(AddParity((byte)current)); + + // Update parameters for next round. + carry = (byte)(message[i] & (~upperMask)); + + // Shorten the upper mask. + upperMask = (byte)(upperMask << 1); + } + + if (upperMask != InitUpperMask) + { + byte lastGroup = (byte)(carry << byte.PopCount(upperMask)); + // We have left over carry data + transmitSeq.Add(AddParity(lastGroup)); + } + return transmitSeq.ToArray(); + } + + private static byte AddParity(byte source) + { + if (byte.PopCount((byte)(source & 0x7F)) % 2 == 0) + { + return (byte)(source << 1); + } + return (byte)((source << 1) | 1); + } + + public static byte[] DecodeSequence(byte[] receivedSeq) + { + if (receivedSeq.Length == 0) + { + return []; + } + + List decodedMessage = new List(); + byte byteToAdd = 0x00; + byte upperMask = 0xFF; + for (int i = 0; i < receivedSeq.Length; i++) + { + if (upperMask == 0xFF) + { + // We've completed a complete round. + // Current byte too short. + byteToAdd = GetByteData(receivedSeq[i]); + upperMask = 0x80; + continue; + } + + byte currentByteData = GetByteData(receivedSeq[i]); + byte contribution = (byte)(currentByteData >>> byte.TrailingZeroCount(upperMask)); + decodedMessage.Add((byte)(byteToAdd | contribution)); + + // Update parameters for next round + byteToAdd = (byte)((currentByteData & ~(upperMask | 0x01)) << byte.PopCount(upperMask)); + upperMask = (byte)((upperMask >> 1) | 0x80); + } + return decodedMessage.ToArray(); + } + + private static byte GetByteData(byte data) + { + if (byte.PopCount(data) % 2 != 0) + { + throw new ArgumentException("Byte has incorrect parity"); + } + + return (byte)(data & 0xFE); + } +} diff --git a/exercises/practice/intergalactic-transmission/.meta/Generator.tpl b/exercises/practice/intergalactic-transmission/.meta/Generator.tpl new file mode 100644 index 000000000..e8f41982a --- /dev/null +++ b/exercises/practice/intergalactic-transmission/.meta/Generator.tpl @@ -0,0 +1,19 @@ +public class {{ testClass }} +{ + {{- for test in tests }} + [Fact{{ if !for.first }}(Skip = "Remove this Skip property to run this test"){{ end }}] + public void {{ test.testMethod }}() + { + {{- message = string.replace test.input.message "\"" "" }} + {{- if test.property == "transmitSequence" }} + Assert.Equal({{ string.replace test.expected "\"" "" }}, IntergalacticTransmission.GetTransmitSequence({{ message }})); + {{- else if test.property == "decodeMessage" }} + {{- if test.expected.error }} + Assert.Throws(() => IntergalacticTransmission.DecodeSequence({{ message }})); + {{- else }} + Assert.Equal({{ string.replace test.expected "\"" "" }}, IntergalacticTransmission.DecodeSequence({{ message }})); + {{ end -}} + {{ end -}} + } + {{ end -}} +} diff --git a/exercises/practice/intergalactic-transmission/.meta/config.json b/exercises/practice/intergalactic-transmission/.meta/config.json new file mode 100644 index 000000000..f9f6fdd34 --- /dev/null +++ b/exercises/practice/intergalactic-transmission/.meta/config.json @@ -0,0 +1,22 @@ +{ + "authors": [ + "kahgoh" + ], + "files": { + "solution": [ + "IntergalacticTransmission.cs" + ], + "test": [ + "IntergalacticTransmissionTests.cs" + ], + "example": [ + ".meta/Example.cs" + ], + "invalidator": [ + "IntergalacticTransmission.csproj" + ] + }, + "blurb": "Add parity bits to a message for transmission", + "source": "Kah Goh", + "source_url": "https://github.com/exercism/problem-specifications/pull/2543" +} diff --git a/exercises/practice/intergalactic-transmission/.meta/tests.toml b/exercises/practice/intergalactic-transmission/.meta/tests.toml new file mode 100644 index 000000000..37ebc138e --- /dev/null +++ b/exercises/practice/intergalactic-transmission/.meta/tests.toml @@ -0,0 +1,82 @@ +# 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. + +[f99d4046-b429-4582-9324-f0bcac7ab51c] +description = "calculate transmit sequences -> empty message" + +[ee27ea2d-8999-4f23-9275-8f6879545f86] +description = "calculate transmit sequences -> 0x00 is transmitted as 0x0000" + +[97f27f98-8020-402d-be85-f21ba54a6df0] +description = "calculate transmit sequences -> 0x02 is transmitted as 0x0300" + +[24712fb9-0336-4e2f-835e-d2350f29c420] +description = "calculate transmit sequences -> 0x06 is transmitted as 0x0600" + +[7630b5a9-dba1-4178-b2a0-4a376f7414e0] +description = "calculate transmit sequences -> 0x05 is transmitted as 0x0581" + +[ab4fe80b-ef8e-4a99-b4fb-001937af415d] +description = "calculate transmit sequences -> 0x29 is transmitted as 0x2881" + +[4e200d84-593b-4449-b7c0-4de1b6a0955e] +description = "calculate transmit sequences -> 0xc001c0de is transmitted as 0xc000711be1" + +[fbc537e9-6b21-4f4a-8c2b-9cf9b702a9b7] +description = "calculate transmit sequences -> six byte message" + +[d5b75adf-b5fc-4f77-b4ab-77653e30f07c] +description = "calculate transmit sequences -> seven byte message" + +[6d8b297b-da1d-435e-bcd7-55fbb1400e73] +description = "calculate transmit sequences -> eight byte message" + +[54a0642a-d5aa-490c-be89-8e171a0cab6f] +description = "calculate transmit sequences -> twenty byte message" + +[879af739-0094-4736-9127-bd441b1ddbbf] +description = "decode received messages -> zero message" + +[7a89eeef-96c5-4329-a246-ec181a8e959a] +description = "decode received messages -> 0x0300 is decoded to 0x02" + +[3e515af7-8b62-417f-960c-3454bca7f806] +description = "decode received messages -> 0x0581 is decoded to 0x05" + +[a1b4a3f7-9f05-4b7a-b86e-d7c6fc3f16a9] +description = "decode received messages -> 0x2881 is decoded to 0x29" + +[2e99d617-4c91-4ad5-9217-e4b2447d6e4a] +description = "decode received messages -> first byte has wrong parity" + +[507e212d-3dae-42e8-88b4-2223838ff8d2] +description = "decode received messages -> second byte has wrong parity" + +[b985692e-6338-46c7-8cea-bc38996d4dfd] +description = "decode received messages -> 0xcf4b00 is decoded to 0xce94" + +[467549dc-a558-443b-80c5-ff3d4eb305d4] +description = "decode received messages -> six byte message" + +[1f3be5fb-093a-4661-9951-c1c4781c71ea] +description = "decode received messages -> seven byte message" + +[6065b8b3-9dcd-45c9-918c-b427cfdb28c1] +description = "decode received messages -> last byte has wrong parity" + +[98af97b7-9cca-4c4c-9de3-f70e227a4cb1] +description = "decode received messages -> eight byte message" + +[aa7d4785-2bb9-43a4-a38a-203325c464fb] +description = "decode received messages -> twenty byte message" + +[4c86e034-b066-42ac-8497-48f9bc1723c1] +description = "decode received messages -> wrong parity on 16th byte" diff --git a/exercises/practice/intergalactic-transmission/IntergalacticTransmission.cs b/exercises/practice/intergalactic-transmission/IntergalacticTransmission.cs new file mode 100644 index 000000000..5c4612df8 --- /dev/null +++ b/exercises/practice/intergalactic-transmission/IntergalacticTransmission.cs @@ -0,0 +1,12 @@ +public static class IntergalacticTransmission +{ + public static byte[] GetTransmitSequence(byte[] message) + { + throw new NotImplementedException("You need to implement this method."); + } + + public static byte[] DecodeSequence(byte[] receivedSeq) + { + throw new NotImplementedException("You need to implement this method."); + } +} diff --git a/exercises/practice/intergalactic-transmission/IntergalacticTransmission.csproj b/exercises/practice/intergalactic-transmission/IntergalacticTransmission.csproj new file mode 100644 index 000000000..725e436c6 --- /dev/null +++ b/exercises/practice/intergalactic-transmission/IntergalacticTransmission.csproj @@ -0,0 +1,18 @@ + + + net9.0 + Exe + enable + enable + true + + + + + + + + + + + diff --git a/exercises/practice/intergalactic-transmission/IntergalacticTransmissionTests.cs b/exercises/practice/intergalactic-transmission/IntergalacticTransmissionTests.cs new file mode 100644 index 000000000..3081d5c43 --- /dev/null +++ b/exercises/practice/intergalactic-transmission/IntergalacticTransmissionTests.cs @@ -0,0 +1,158 @@ +public class IntergalacticTransmissionTests +{ + [Fact] + public void Calculate_transmit_sequences_empty_message() + { + Assert.Equal([], IntergalacticTransmission.GetTransmitSequence([])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Calculate_transmit_sequences_0x00_is_transmitted_as_0x0000() + { + Assert.Equal([0x00, 0x00], IntergalacticTransmission.GetTransmitSequence([0x00])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Calculate_transmit_sequences_0x02_is_transmitted_as_0x0300() + { + Assert.Equal([0x03, 0x00], IntergalacticTransmission.GetTransmitSequence([0x02])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Calculate_transmit_sequences_0x06_is_transmitted_as_0x0600() + { + Assert.Equal([0x06, 0x00], IntergalacticTransmission.GetTransmitSequence([0x06])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Calculate_transmit_sequences_0x05_is_transmitted_as_0x0581() + { + Assert.Equal([0x05, 0x81], IntergalacticTransmission.GetTransmitSequence([0x05])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Calculate_transmit_sequences_0x29_is_transmitted_as_0x2881() + { + Assert.Equal([0x28, 0x81], IntergalacticTransmission.GetTransmitSequence([0x29])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Calculate_transmit_sequences_0xc001c0de_is_transmitted_as_0xc000711be1() + { + Assert.Equal([0xc0, 0x00, 0x71, 0x1b, 0xe1], IntergalacticTransmission.GetTransmitSequence([0xc0, 0x01, 0xc0, 0xde])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Calculate_transmit_sequences_six_byte_message() + { + Assert.Equal([0x47, 0xb8, 0x99, 0xac, 0x17, 0xa0, 0x84], IntergalacticTransmission.GetTransmitSequence([0x47, 0x72, 0x65, 0x61, 0x74, 0x21])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Calculate_transmit_sequences_seven_byte_message() + { + Assert.Equal([0x47, 0xb8, 0x99, 0xac, 0x17, 0xa0, 0xc5, 0x42], IntergalacticTransmission.GetTransmitSequence([0x47, 0x72, 0x65, 0x61, 0x74, 0x31, 0x21])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Calculate_transmit_sequences_eight_byte_message() + { + Assert.Equal([0xc0, 0x00, 0x44, 0x66, 0x7d, 0x06, 0x78, 0x42, 0x21, 0x81], IntergalacticTransmission.GetTransmitSequence([0xc0, 0x01, 0x13, 0x37, 0xc0, 0xde, 0x21, 0x21])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Calculate_transmit_sequences_twenty_byte_message() + { + Assert.Equal([0x44, 0xbd, 0x18, 0xaf, 0x27, 0x1b, 0xa5, 0xe7, 0x6c, 0x90, 0x1b, 0x2e, 0x33, 0x03, 0x84, 0xee, 0x65, 0xb8, 0xdb, 0xed, 0xd7, 0x28, 0x84], IntergalacticTransmission.GetTransmitSequence([0x45, 0x78, 0x65, 0x72, 0x63, 0x69, 0x73, 0x6d, 0x20, 0x69, 0x73, 0x20, 0x61, 0x77, 0x65, 0x73, 0x6f, 0x6d, 0x65, 0x21])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_empty_message() + { + Assert.Equal([], IntergalacticTransmission.DecodeSequence([])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_zero_message() + { + Assert.Equal([0x00], IntergalacticTransmission.DecodeSequence([0x00, 0x00])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_0x0300_is_decoded_to_0x02() + { + Assert.Equal([0x02], IntergalacticTransmission.DecodeSequence([0x03, 0x00])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_0x0581_is_decoded_to_0x05() + { + Assert.Equal([0x05], IntergalacticTransmission.DecodeSequence([0x05, 0x81])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_0x2881_is_decoded_to_0x29() + { + Assert.Equal([0x29], IntergalacticTransmission.DecodeSequence([0x28, 0x81])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_first_byte_has_wrong_parity() + { + Assert.Throws(() => IntergalacticTransmission.DecodeSequence([0x07, 0x00])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_second_byte_has_wrong_parity() + { + Assert.Throws(() => IntergalacticTransmission.DecodeSequence([0x03, 0x68])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_0xcf4b00_is_decoded_to_0xce94() + { + Assert.Equal([0xce, 0x94], IntergalacticTransmission.DecodeSequence([0xcf, 0x4b, 0x00])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_0xe2566500_is_decoded_to_0xe2ad90() + { + Assert.Equal([0xe2, 0xad, 0x90], IntergalacticTransmission.DecodeSequence([0xe2, 0x56, 0x65, 0x00])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_six_byte_message() + { + Assert.Equal([0x47, 0x72, 0x65, 0x61, 0x74, 0x21], IntergalacticTransmission.DecodeSequence([0x47, 0xb8, 0x99, 0xac, 0x17, 0xa0, 0x84])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_seven_byte_message() + { + Assert.Equal([0x47, 0x72, 0x65, 0x61, 0x74, 0x31, 0x21], IntergalacticTransmission.DecodeSequence([0x47, 0xb8, 0x99, 0xac, 0x17, 0xa0, 0xc5, 0x42])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_last_byte_has_wrong_parity() + { + Assert.Throws(() => IntergalacticTransmission.DecodeSequence([0x47, 0xb8, 0x99, 0xac, 0x17, 0xa0, 0xc5, 0x43])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_eight_byte_message() + { + Assert.Equal([0xc0, 0x01, 0x13, 0x37, 0xc0, 0xde, 0x21, 0x21], IntergalacticTransmission.DecodeSequence([0xc0, 0x00, 0x44, 0x66, 0x7d, 0x06, 0x78, 0x42, 0x21, 0x81])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_twenty_byte_message() + { + Assert.Equal([0x45, 0x78, 0x65, 0x72, 0x63, 0x69, 0x73, 0x6d, 0x20, 0x69, 0x73, 0x20, 0x61, 0x77, 0x65, 0x73, 0x6f, 0x6d, 0x65, 0x21], IntergalacticTransmission.DecodeSequence([0x44, 0xbd, 0x18, 0xaf, 0x27, 0x1b, 0xa5, 0xe7, 0x6c, 0x90, 0x1b, 0x2e, 0x33, 0x03, 0x84, 0xee, 0x65, 0xb8, 0xdb, 0xed, 0xd7, 0x28, 0x84])); + } + + [Fact(Skip = "Remove this Skip property to run this test")] + public void Decode_received_messages_wrong_parity_on_16th_byte() + { + Assert.Throws(() => IntergalacticTransmission.DecodeSequence([0x44, 0xbd, 0x18, 0xaf, 0x27, 0x1b, 0xa5, 0xe7, 0x6c, 0x90, 0x1b, 0x2e, 0x33, 0x03, 0x84, 0xef, 0x65, 0xb8, 0xdb, 0xed, 0xd7, 0x28, 0x84])); + } +} diff --git a/exercises/practice/intergalactic-transmission/packages.lock.json b/exercises/practice/intergalactic-transmission/packages.lock.json new file mode 100644 index 000000000..6b3387771 --- /dev/null +++ b/exercises/practice/intergalactic-transmission/packages.lock.json @@ -0,0 +1,170 @@ +{ + "version": 1, + "dependencies": { + "net9.0": { + "Exercism.Tests.xunit.v3": { + "type": "Direct", + "requested": "[0.1.0-beta1, )", + "resolved": "0.1.0-beta1", + "contentHash": "XjVtQWWxmHDDj7UMdkPKpBFFKnsW0tkBhlyJSfFFh+fWwGemyyJwJYhdsvWhiKKCY7zItB+mI/o0OQtOKQxUhA==", + "dependencies": { + "xunit.v3.extensibility.core": "1.1.0" + } + }, + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[17.12.0, )", + "resolved": "17.12.0", + "contentHash": "kt/PKBZ91rFCWxVIJZSgVLk+YR+4KxTuHf799ho8WNiK5ZQpJNAEZCAWX86vcKrs+DiYjiibpYKdGZP6+/N17w==", + "dependencies": { + "Microsoft.CodeCoverage": "17.12.0", + "Microsoft.TestPlatform.TestHost": "17.12.0" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[3.0.1, )", + "resolved": "3.0.1", + "contentHash": "lbyYtsBxA8Pz8kaf5Xn/Mj1mL9z2nlBWdZhqFaj66nxXBa4JwiTDm4eGcpSMet6du9TOWI6bfha+gQR6+IHawg==" + }, + "xunit.v3": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "1ckSz5GVswlM9TCk5bGdHOjnYwqAWjkeqxckoHawQIA8sTeuN+RCBUypCi5A/Um0XlczRx5TjAK5W6BbN0HLcQ==", + "dependencies": { + "xunit.analyzers": "1.20.0", + "xunit.v3.assert": "[1.1.0]", + "xunit.v3.core": "[1.1.0]" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg==" + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.12.0", + "contentHash": "4svMznBd5JM21JIG2xZKGNanAHNXplxf/kQDFfLHXQ3OnpJkayRK/TjacFjA+EYmoyuNXHo/sOETEfcYtAzIrA==" + }, + "Microsoft.Testing.Extensions.TrxReport.Abstractions": { + "type": "Transitive", + "resolved": "1.5.3", + "contentHash": "h34zKNpGyni66VH738mRHeXSnf3klSShUdavUWNhSfWICUUi5aXeI0LBvoX/ad93N0+9xBDU3Fyi6WfxrwKQGw==", + "dependencies": { + "Microsoft.Testing.Platform": "1.5.3" + } + }, + "Microsoft.Testing.Platform": { + "type": "Transitive", + "resolved": "1.5.3", + "contentHash": "WqJydnJ99dEKtquR9HwINz104ehWJKTXbQQrydGatlLRw14bmsx0pa8+E6KUXMYXZAimN0swWlDmcJGjjW4TIg==" + }, + "Microsoft.Testing.Platform.MSBuild": { + "type": "Transitive", + "resolved": "1.5.3", + "contentHash": "bOtpRMSPeT5YLQo+NNY8EtdNTphAUcmALjW4ABU7P0rb6yR2XAZau3TzNieLmR3lRuwudguWzzBhgcLRXwZh0A==", + "dependencies": { + "Microsoft.Testing.Platform": "1.5.3" + } + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.12.0", + "contentHash": "TDqkTKLfQuAaPcEb3pDDWnh7b3SyZF+/W9OZvWFp6eJCIiiYFdSB6taE2I6tWrFw5ywhzOb6sreoGJTI6m3rSQ==", + "dependencies": { + "System.Reflection.Metadata": "1.6.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.12.0", + "contentHash": "MiPEJQNyADfwZ4pJNpQex+t9/jOClBGMiCiVVFuELCMSX2nmNfvUor3uFVxNNCg30uxDP8JDYfPnMXQzsfzYyg==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.12.0", + "Newtonsoft.Json": "13.0.1" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.6.0", + "contentHash": "OEkbBQoklHngJ8UD8ez2AERSk2g+/qpAaSWWCBFbpH727HxDq5ydVkuncBaKcKfwRqXGWx64dS6G1SUScMsitg==" + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + }, + "xunit.analyzers": { + "type": "Transitive", + "resolved": "1.20.0", + "contentHash": "HElev2E9vFbPxwKRQtpCSSzLOu8M/N9EWBCB37v7SRx6z4Lbj19FxfLEig3v9jiI6s4b0l2uena91nEsTWl9jA==" + }, + "xunit.v3.assert": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "4D+eM08ImfhA+zLbRzi8HA4qsT98zDxgaCD7vCg8yFesokKsgSsqWsAmImHFjVymGVhVS7WFGb19d6v1k9i0xQ==", + "dependencies": { + "System.Collections.Immutable": "8.0.0", + "System.Memory": "4.6.0" + } + }, + "xunit.v3.common": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "Cq55z8pC7fOkfj+3TB/YQ6OW96qWqxKiMd15CtkIl37VtV9EsiUL4B4HsR6VLJCzkk7cBiXQ1ABVIcp3TCm6HQ==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "6.0.0" + } + }, + "xunit.v3.core": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "kXP/1d3jnQ2m4skcdM3gSMmubI6P747D6KVswzeedysgFkLj2xJlfo7p7slsmtEnp8BZb8X6D92Hssd/UtVPMw==", + "dependencies": { + "Microsoft.Testing.Platform.MSBuild": "1.5.3", + "xunit.v3.extensibility.core": "[1.1.0]", + "xunit.v3.runner.inproc.console": "[1.1.0]" + } + }, + "xunit.v3.extensibility.core": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "AeQbbYN001x0c+B9pqwml6jZPovHz8O/sOp7jmrjz90rUzz/QPal12SlHLKYszR44CMnW4MsDam3RYT5pkYUxw==", + "dependencies": { + "xunit.v3.common": "[1.1.0]" + } + }, + "xunit.v3.runner.common": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "Q81J0VPuu8fpF+/1CIjThqKKUjnqh0TQrLlD0iORkF75KdsOV+iGWT8c3AVuY96kDoxXxkTf0ZvJsK6o9osc1A==", + "dependencies": { + "xunit.v3.common": "[1.1.0]" + } + }, + "xunit.v3.runner.inproc.console": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "lX/4TwIJe9ysCd5dqLk/Doq8ieYaZGivgf95xR59wRuSV+nHzHnyhpjXfaPUp8nkncUH1rOmJ85o1KebipisXQ==", + "dependencies": { + "Microsoft.Testing.Extensions.TrxReport.Abstractions": "1.5.3", + "Microsoft.Testing.Platform": "1.5.3", + "xunit.v3.extensibility.core": "[1.1.0]", + "xunit.v3.runner.common": "[1.1.0]" + } + } + } + } +} \ No newline at end of file