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.
+
+
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