diff --git a/config.json b/config.json index 9008e40..64b2d8f 100644 --- a/config.json +++ b/config.json @@ -1230,6 +1230,14 @@ ], "difficulty": 5 }, + { + "slug": "prism", + "name": "Prism", + "uuid": "366fef41-bf62-4314-a6f5-bba9eacd82a0", + "practices": [], + "prerequisites": [], + "difficulty": 5 + }, { "slug": "pythagorean-triplet", "name": "Pythagorean Triplet", diff --git a/exercises/Exercises.slnx b/exercises/Exercises.slnx index e1cc952..299f9e4 100644 --- a/exercises/Exercises.slnx +++ b/exercises/Exercises.slnx @@ -64,6 +64,7 @@ + diff --git a/exercises/practice/prism/.docs/instructions.md b/exercises/practice/prism/.docs/instructions.md new file mode 100644 index 0000000..13cefae --- /dev/null +++ b/exercises/practice/prism/.docs/instructions.md @@ -0,0 +1,38 @@ +# Instructions + +Before activating the laser array, you must predict the exact order in which crystals will be hit, identified by their sample IDs. + +## Example Test Case + +Consider this crystal array configuration: + +```json +{ + "start": { "x": 0, "y": 0, "angle": 0 }, + "prisms": [ + { "id": 1, "x": 10, "y": 10, "angle": -90 }, + { "id": 2, "x": 10, "y": 0, "angle": 90 }, + { "id": 3, "x": 30, "y": 10, "angle": 45 }, + { "id": 4, "x": 20, "y": 0, "angle": 0 } + ] +} +``` + +## What's Happening + +The laser starts at the origin `(0, 0)` and fires horizontally to the right at angle 0°. +Here's the step-by-step beam path: + +**Step 1**: The beam travels along the x-axis (y = 0) and first encounters **Crystal #2** at position `(10, 0)`. +This crystal has a refraction angle of 90°, which means it bends the beam perpendicular to its current path. +The beam, originally traveling at 0°, is now redirected to 90° (straight up). + +**Step 2**: The beam now travels vertically upward from position `(10, 0)` and strikes **Crystal #1** at position `(10, 10)`. +This crystal has a refraction angle of -90°, bending the beam by -90° relative to its current direction. +The beam was traveling at 90°, so after refraction it's now at 0° (90° + (-90°) = 0°), traveling horizontally to the right again. + +**Step 3**: From position `(10, 10)`, the beam travels horizontally and encounters **Crystal #3** at position `(30, 10)`. +This crystal refracts the beam by 45°, changing its direction to 45°. +The beam continues into empty space beyond the array. + +!["A graph showing the path of a laser beam refracted through three prisms."](https://assets.exercism.org/images/exercises/prism/laser_path-light.svg) diff --git a/exercises/practice/prism/.docs/introduction.md b/exercises/practice/prism/.docs/introduction.md new file mode 100644 index 0000000..bfa7ed7 --- /dev/null +++ b/exercises/practice/prism/.docs/introduction.md @@ -0,0 +1,5 @@ +# Introduction + +You're a researcher at **PRISM** (Precariously Redirected Illumination Safety Management), working with a precision laser calibration system that tests experimental crystal prisms. +These crystals are being developed for next-generation optical computers, and each one has unique refractive properties based on its molecular structure. +The lab's laser system can damage crystals if they receive unexpected illumination, so precise path prediction is critical. diff --git a/exercises/practice/prism/.editorconfig b/exercises/practice/prism/.editorconfig new file mode 100644 index 0000000..11f55d2 --- /dev/null +++ b/exercises/practice/prism/.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/prism/.meta/Example.vb b/exercises/practice/prism/.meta/Example.vb new file mode 100644 index 0000000..c6086c1 --- /dev/null +++ b/exercises/practice/prism/.meta/Example.vb @@ -0,0 +1,99 @@ +Public Structure LaserInfo + Public Sub New(ByVal x As Double, ByVal y As Double, ByVal angle As Double) + Me.X = x + Me.Y = y + Me.Angle = angle + End Sub + + Public ReadOnly Property X As Double + Public ReadOnly Property Y As Double + Public ReadOnly Property Angle As Double +End Structure + +Public Structure PrismInfo + Public Sub New(ByVal id As Integer, ByVal x As Double, ByVal y As Double, ByVal angle As Double) + Me.Id = id + Me.X = x + Me.Y = y + Me.Angle = angle + End Sub + + Public ReadOnly Property Id As Integer + Public ReadOnly Property X As Double + Public ReadOnly Property Y As Double + Public ReadOnly Property Angle As Double +End Structure + +Public Module Prism + Private Const Epsilon = 0.000001 + + Public Function FindSequence(ByVal laser As LaserInfo, ByVal prisms As PrismInfo()) As Integer() + Dim x = laser.X + Dim y = laser.Y + Dim angle = laser.Angle + Dim sequence As New List(Of Integer) + + While True + Dim prism = FindNextPrism(x, y, angle, prisms) + If Not prism.HasValue Then + Return sequence.ToArray() + End If + + Dim hit = prism.Value + sequence.Add(hit.Id) + x = hit.X + y = hit.Y + angle = (angle + hit.Angle) Mod 360.0 + End While + + Throw New InvalidOperationException("unreachable") + End Function + + Private Function FindNextPrism( + ByVal x As Double, + ByVal y As Double, + ByVal angle As Double, + ByVal prisms As PrismInfo()) As PrismInfo? + + Dim radians = DegreesToRadians(angle) + Dim directionX = Math.Cos(radians) + Dim directionY = Math.Sin(radians) + Dim nearest As PrismInfo? = Nothing + Dim nearestDistance = Double.PositiveInfinity + + For Each prism In prisms + Dim dx = prism.X - x + Dim dy = prism.Y - y + Dim distance = dx * directionX + dy * directionY + + If distance > Epsilon AndAlso + IsOnRay(dx, dy, directionX, directionY, distance) AndAlso + distance < nearestDistance Then + + nearest = prism + nearestDistance = distance + End If + Next + + Return nearest + End Function + + Private Function IsOnRay( + ByVal dx As Double, + ByVal dy As Double, + ByVal directionX As Double, + ByVal directionY As Double, + ByVal distance As Double) As Boolean + + Dim offsetX = dx - distance * directionX + Dim offsetY = dy - distance * directionY + Dim offsetSquared = offsetX * offsetX + offsetY * offsetY + Dim tolerance = Epsilon * Math.Max(1.0, distance * distance) + + Return offsetSquared < tolerance + End Function + + Private Function DegreesToRadians(ByVal degrees As Double) As Double + Return degrees * Math.PI / 180.0 + End Function +End Module diff --git a/exercises/practice/prism/.meta/config.json b/exercises/practice/prism/.meta/config.json new file mode 100644 index 0000000..222f0e0 --- /dev/null +++ b/exercises/practice/prism/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "Prism.vb" + ], + "test": [ + "PrismTests.vb" + ], + "example": [ + ".meta/Example.vb" + ] + }, + "blurb": "Calculate the path of a laser through refractive prisms.", + "source": "FraSanga", + "source_url": "https://github.com/exercism/problem-specifications/pull/2625" +} diff --git a/exercises/practice/prism/.meta/tests.toml b/exercises/practice/prism/.meta/tests.toml new file mode 100644 index 0000000..b002223 --- /dev/null +++ b/exercises/practice/prism/.meta/tests.toml @@ -0,0 +1,52 @@ +# 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. + +[ec65d3b3-f7bf-4015-8156-0609c141c4c4] +description = "zero prisms" + +[ec0ca17c-0c5f-44fb-89ba-b76395bdaf1c] +description = "one prism one hit" + +[0db955f2-0a27-4c82-ba67-197bd6202069] +description = "one prism zero hits" + +[8d92485b-ebc0-4ee9-9b88-cdddb16b52da] +description = "going up zero hits" + +[78295b3c-7438-492d-8010-9c63f5c223d7] +description = "going down zero hits" + +[acc723ea-597b-4a50-8d1b-b980fe867d4c] +description = "going left zero hits" + +[3f19b9df-9eaa-4f18-a2db-76132f466d17] +description = "negative angle" + +[96dacffb-d821-4cdf-aed8-f152ce063195] +description = "large angle" + +[513a7caa-957f-4c5d-9820-076842de113c] +description = "upward refraction two hits" + +[d452b7c7-9761-4ea9-81a9-2de1d73eb9ef] +description = "downward refraction two hits" + +[be1a2167-bf4c-4834-acc9-e4d68e1a0203] +description = "same prism twice" + +[df5a60dd-7c7d-4937-ac4f-c832dae79e2e] +description = "simple path" + +[8d9a3cc8-e846-4a3b-a137-4bfc4aa70bd1] +description = "multiple prisms floating point precision" + +[e077fc91-4e4a-46b3-a0f5-0ba00321da56] +description = "complex path with multiple prisms floating point precision" diff --git a/exercises/practice/prism/Prism.vb b/exercises/practice/prism/Prism.vb new file mode 100644 index 0000000..c3b0009 --- /dev/null +++ b/exercises/practice/prism/Prism.vb @@ -0,0 +1,31 @@ +Public Structure LaserInfo + Public Sub New(ByVal x As Double, ByVal y As Double, ByVal angle As Double) + Me.X = x + Me.Y = y + Me.Angle = angle + End Sub + + Public ReadOnly Property X As Double + Public ReadOnly Property Y As Double + Public ReadOnly Property Angle As Double +End Structure + +Public Structure PrismInfo + Public Sub New(ByVal id As Integer, ByVal x As Double, ByVal y As Double, ByVal angle As Double) + Me.Id = id + Me.X = x + Me.Y = y + Me.Angle = angle + End Sub + + Public ReadOnly Property Id As Integer + Public ReadOnly Property X As Double + Public ReadOnly Property Y As Double + Public ReadOnly Property Angle As Double +End Structure + +Public Module Prism + Public Function FindSequence(ByVal laser As LaserInfo, ByVal prisms As PrismInfo()) As Integer() + Throw New NotImplementedException("You need to implement this function.") + End Function +End Module diff --git a/exercises/practice/prism/Prism.vbproj b/exercises/practice/prism/Prism.vbproj new file mode 100644 index 0000000..b4587f0 --- /dev/null +++ b/exercises/practice/prism/Prism.vbproj @@ -0,0 +1,19 @@ + + + + net10.0 + Exe + true + + + + + + + + + + + + + diff --git a/exercises/practice/prism/PrismTests.vb b/exercises/practice/prism/PrismTests.vb new file mode 100644 index 0000000..bf9b946 --- /dev/null +++ b/exercises/practice/prism/PrismTests.vb @@ -0,0 +1,261 @@ +Public Class PrismTests + + Public Sub Zero_Prisms() + Dim laser = New LaserInfo(0.0, 0.0, 0.0) + Dim prisms = Array.Empty(Of PrismInfo)() + + Assert.Empty(FindSequence(laser, prisms)) + End Sub + + + Public Sub One_Prism_One_Hit() + Dim laser = New LaserInfo(0.0, 0.0, 0.0) + Dim prisms = {New PrismInfo(1, 10.0, 0.0, 0.0)} + Dim expected = {1} + + Assert.Equal(expected, FindSequence(laser, prisms)) + End Sub + + + Public Sub One_Prism_Zero_Hits() + Dim laser = New LaserInfo(0.0, 0.0, 0.0) + Dim prisms = {New PrismInfo(1, -10.0, 0.0, 0.0)} + Assert.Empty(FindSequence(laser, prisms)) + End Sub + + + Public Sub Going_Up_Zero_Hits() + Dim laser = New LaserInfo(0.0, 0.0, 90.0) + Dim prisms = { + New PrismInfo(3, 0.0, -10.0, 0.0), + New PrismInfo(1, -10.0, 0.0, 0.0), + New PrismInfo(2, 10.0, 0.0, 0.0)} + Assert.Empty(FindSequence(laser, prisms)) + End Sub + + + Public Sub Going_Down_Zero_Hits() + Dim laser = New LaserInfo(0.0, 0.0, -90.0) + Dim prisms = { + New PrismInfo(1, 10.0, 0.0, 0.0), + New PrismInfo(2, 0.0, 10.0, 0.0), + New PrismInfo(3, -10.0, 0.0, 0.0)} + Assert.Empty(FindSequence(laser, prisms)) + End Sub + + + Public Sub Going_Left_Zero_Hits() + Dim laser = New LaserInfo(0.0, 0.0, 180.0) + Dim prisms = { + New PrismInfo(2, 0.0, 10.0, 0.0), + New PrismInfo(3, 10.0, 0.0, 0.0), + New PrismInfo(1, 0.0, -10.0, 0.0)} + Assert.Empty(FindSequence(laser, prisms)) + End Sub + + + Public Sub Negative_Angle() + Dim laser = New LaserInfo(0.0, 0.0, -180.0) + Dim prisms = { + New PrismInfo(1, 0.0, -10.0, 0.0), + New PrismInfo(2, 0.0, 10.0, 0.0), + New PrismInfo(3, 10.0, 0.0, 0.0)} + Assert.Empty(FindSequence(laser, prisms)) + End Sub + + + Public Sub Large_Angle() + Dim laser = New LaserInfo(0.0, 0.0, 2340.0) + Dim prisms = {New PrismInfo(1, 10.0, 0.0, 0.0)} + Assert.Empty(FindSequence(laser, prisms)) + End Sub + + + Public Sub Upward_Refraction_Two_Hits() + Dim laser = New LaserInfo(0.0, 0.0, 0.0) + Dim prisms = { + New PrismInfo(1, 10.0, 10.0, 0.0), + New PrismInfo(2, 10.0, 0.0, 90.0)} + Dim expected = {2, 1} + + Assert.Equal(expected, FindSequence(laser, prisms)) + End Sub + + + Public Sub Downward_Refraction_Two_Hits() + Dim laser = New LaserInfo(0.0, 0.0, 0.0) + Dim prisms = { + New PrismInfo(1, 10.0, 0.0, -90.0), + New PrismInfo(2, 10.0, -10.0, 0.0)} + Dim expected = {1, 2} + + Assert.Equal(expected, FindSequence(laser, prisms)) + End Sub + + + Public Sub Same_Prism_Twice() + Dim laser = New LaserInfo(0.0, 0.0, 0.0) + Dim prisms = { + New PrismInfo(2, 10.0, 0.0, 0.0), + New PrismInfo(1, 20.0, 0.0, -180.0)} + Dim expected = {2, 1, 2} + + Assert.Equal(expected, FindSequence(laser, prisms)) + End Sub + + + Public Sub Simple_Path() + Dim laser = New LaserInfo(0.0, 0.0, 0.0) + Dim prisms = { + New PrismInfo(3, 30.0, 10.0, 45.0), + New PrismInfo(1, 10.0, 10.0, -90.0), + New PrismInfo(2, 10.0, 0.0, 90.0), + New PrismInfo(4, 20.0, 0.0, 0.0)} + Dim expected = {2, 1, 3} + + Assert.Equal(expected, FindSequence(laser, prisms)) + End Sub + + + Public Sub Multiple_Prisms_Floating_Point_Precision() + Dim laser = New LaserInfo(0.0, 0.0, -6.429) + Dim prisms = { + New PrismInfo(26, 5.8, 73.4, 6.555), + New PrismInfo(24, 36.2, 65.2, -0.304), + New PrismInfo(20, 20.4, 82.8, 45.17), + New PrismInfo(31, -20.2, 48.8, 30.615), + New PrismInfo(30, 24.0, 0.6, 28.771), + New PrismInfo(29, 31.4, 79.4, 61.327), + New PrismInfo(28, 36.4, 31.4, -18.157), + New PrismInfo(22, 47.0, 57.8, 54.745), + New PrismInfo(38, 36.4, 79.2, 49.05), + New PrismInfo(10, 37.8, 55.2, 11.978), + New PrismInfo(18, -26.0, 42.6, 22.661), + New PrismInfo(25, 38.8, 76.2, 51.958), + New PrismInfo(2, 0.0, 42.4, -21.817), + New PrismInfo(35, 21.4, 44.8, -171.579), + New PrismInfo(7, 14.2, -1.6, 19.081), + New PrismInfo(33, 11.2, 44.4, -165.941), + New PrismInfo(11, 15.4, 82.6, 66.262), + New PrismInfo(16, 30.8, 6.6, 35.852), + New PrismInfo(15, -3.0, 79.2, 53.782), + New PrismInfo(4, 29.0, 75.4, 17.016), + New PrismInfo(23, 41.6, 59.8, 70.763), + New PrismInfo(8, -10.0, 15.8, -9.24), + New PrismInfo(13, 48.6, 51.8, 45.812), + New PrismInfo(1, 13.2, 77.0, 17.937), + New PrismInfo(34, -8.8, 36.8, -4.199), + New PrismInfo(21, 24.4, 75.8, 20.783), + New PrismInfo(17, -4.4, 74.6, 24.709), + New PrismInfo(9, 30.8, 41.8, -165.413), + New PrismInfo(32, 4.2, 78.6, 40.892), + New PrismInfo(37, -15.8, 47.0, 33.29), + New PrismInfo(6, 1.0, 80.6, 51.295), + New PrismInfo(36, -27.0, 47.8, 92.52), + New PrismInfo(14, -2.0, 34.4, -52.001), + New PrismInfo(5, 23.2, 80.2, 31.866), + New PrismInfo(27, -5.6, 32.8, -75.303), + New PrismInfo(12, -1.0, 0.2, 0.0), + New PrismInfo(3, -6.6, 3.2, 46.72), + New PrismInfo(19, -13.8, 24.2, -9.205)} + Dim expected = { + 7, 30, 16, 28, 13, 22, 23, 10, 9, 24, 25, 38, + 29, 4, 35, 21, 5, 20, 11, 1, 33, 26, 32, 6, + 15, 17, 2, 14, 27, 34, 37, 31, 36, 18, 19, 8, + 3, 12} + + Assert.Equal(expected, FindSequence(laser, prisms)) + End Sub + + + Public Sub Complex_Path_With_Multiple_Prisms_Floating_Point_Precision() + Dim laser = New LaserInfo(0.0, 0.0, 0.0) + Dim prisms = { + New PrismInfo(46, 37.4, 20.6, -88.332), + New PrismInfo(72, -24.2, 23.4, -90.774), + New PrismInfo(25, 78.6, 7.8, 98.562), + New PrismInfo(60, -58.8, 31.6, 115.56), + New PrismInfo(22, 75.2, 28.0, 63.515), + New PrismInfo(2, 89.8, 27.8, 91.176), + New PrismInfo(23, 9.8, 30.8, 30.829), + New PrismInfo(69, 22.8, 20.6, -88.315), + New PrismInfo(44, -0.8, 15.6, -116.565), + New PrismInfo(36, -24.2, 8.2, -90.0), + New PrismInfo(53, -1.2, 0.0, 0.0), + New PrismInfo(52, 14.2, 24.0, -143.896), + New PrismInfo(5, -65.2, 21.6, 93.128), + New PrismInfo(66, 5.4, 15.6, 31.608), + New PrismInfo(51, -72.6, 21.0, -100.976), + New PrismInfo(65, 48.0, 10.2, 87.455), + New PrismInfo(21, -41.8, 0.0, 68.352), + New PrismInfo(18, -46.2, 19.2, -128.362), + New PrismInfo(10, 74.4, 0.4, 90.939), + New PrismInfo(15, 67.6, 0.4, 84.958), + New PrismInfo(35, 14.8, -0.4, 89.176), + New PrismInfo(1, 83.0, 0.2, 89.105), + New PrismInfo(68, 14.6, 28.0, -29.867), + New PrismInfo(67, 79.8, 18.6, -136.643), + New PrismInfo(38, 53.0, 14.6, -90.848), + New PrismInfo(31, -58.0, 6.6, -61.837), + New PrismInfo(74, -30.8, 0.4, 85.966), + New PrismInfo(48, -4.6, 10.0, -161.222), + New PrismInfo(12, 59.0, 5.0, -91.164), + New PrismInfo(33, -16.4, 18.4, 90.734), + New PrismInfo(4, 82.6, 27.6, 71.127), + New PrismInfo(75, -10.2, 30.6, -1.108), + New PrismInfo(28, 38.0, 0.0, 86.863), + New PrismInfo(11, 64.4, -0.2, 92.353), + New PrismInfo(9, -51.4, 31.6, 67.249), + New PrismInfo(26, -39.8, 30.8, 61.113), + New PrismInfo(30, -34.2, 0.6, 111.33), + New PrismInfo(56, -51.0, 0.2, 70.445), + New PrismInfo(41, -12.0, 0.0, 91.219), + New PrismInfo(24, 63.8, 14.4, 86.586), + New PrismInfo(70, -72.8, 13.4, -87.238), + New PrismInfo(3, 22.4, 7.0, -91.685), + New PrismInfo(13, 34.4, 7.0, 90.0), + New PrismInfo(16, -47.4, 11.4, -136.02), + New PrismInfo(6, 90.0, 0.2, 90.415), + New PrismInfo(54, 44.0, 27.8, 85.969), + New PrismInfo(32, -9.0, 0.0, 91.615), + New PrismInfo(8, -31.6, 30.8, 0.535), + New PrismInfo(39, -12.0, 8.2, 90.0), + New PrismInfo(14, -79.6, 32.4, 92.342), + New PrismInfo(42, 65.8, 20.8, -85.867), + New PrismInfo(40, -65.0, 14.0, 87.109), + New PrismInfo(45, 10.6, 18.8, 23.697), + New PrismInfo(71, -24.2, 18.6, -88.531), + New PrismInfo(7, -72.6, 6.4, -89.148), + New PrismInfo(62, -32.0, 24.8, -140.8), + New PrismInfo(49, 34.4, -0.2, 89.415), + New PrismInfo(63, 74.2, 12.6, -138.429), + New PrismInfo(59, 82.8, 13.0, -140.177), + New PrismInfo(34, -9.4, 23.2, -88.238), + New PrismInfo(76, -57.6, 0.0, 1.2), + New PrismInfo(43, 7.0, 0.0, 116.565), + New PrismInfo(20, 45.8, -0.2, 1.469), + New PrismInfo(37, -16.6, 13.2, 84.785), + New PrismInfo(58, -79.0, -0.2, 89.481), + New PrismInfo(50, -24.2, 12.8, -86.987), + New PrismInfo(64, 59.2, 10.2, -92.203), + New PrismInfo(61, -72.0, 26.4, -83.66), + New PrismInfo(47, 45.4, 5.8, -82.992), + New PrismInfo(17, -52.2, 17.8, -52.938), + New PrismInfo(57, -61.8, 32.0, 84.627), + New PrismInfo(29, 47.2, 28.2, 92.954), + New PrismInfo(27, -4.6, 0.2, 87.397), + New PrismInfo(55, -61.4, 26.4, 94.086), + New PrismInfo(73, -40.4, 13.4, -62.229), + New PrismInfo(19, 53.2, 20.6, -87.181)} + Dim expected = { + 43, 44, 66, 45, 52, 35, 49, 13, 3, 69, 46, 28, + 20, 11, 24, 38, 19, 42, 15, 10, 63, 25, 59, 1, + 6, 2, 4, 67, 22, 29, 65, 64, 12, 47, 54, 68, + 23, 75, 8, 26, 18, 9, 60, 17, 31, 7, 70, 40, + 5, 51, 61, 55, 57, 14, 58, 76, 56, 16, 21, 30, + 73, 62, 74, 41, 39, 36, 50, 37, 33, 71, 72, 34, + 32, 27, 48, 53} + + Assert.Equal(expected, FindSequence(laser, prisms)) + End Sub +End Class diff --git a/exercises/practice/prism/packages.lock.json b/exercises/practice/prism/packages.lock.json new file mode 100644 index 0000000..8da1f14 --- /dev/null +++ b/exercises/practice/prism/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