diff --git a/exercises/practice/clock/.meta/Example.roc b/exercises/practice/clock/.meta/Example.roc index acdd522f..a400ee04 100644 --- a/exercises/practice/clock/.meta/Example.roc +++ b/exercises/practice/clock/.meta/Example.roc @@ -1,5 +1,5 @@ Clock :: { hour : U8, minute : U8 }.{ - create : { hour : I64, minute : I64 } -> Clock + create : { hour : I64 ?? 0, minute : I64 ?? 0 } -> Clock create = |{ hour, minute }| { hour24 = (hour % 24 + minute // 60) % 24 minute60 = minute % 60 @@ -20,14 +20,14 @@ Clock :: { hour : U8, minute : U8 }.{ "${zero_padded(hour)}:${zero_padded(minute)}" } - add : Clock, { hour : I64, minute : I64 } -> Clock + add : Clock, { hour : I64 ?? 0, minute : I64 ?? 0 } -> Clock add = |clock, { hour, minute }| { total_hour = clock.hour.to_i64() + (hour % 24 + minute // 60) total_minute = clock.minute.to_i64() + minute % 60 create({ hour: total_hour, minute: total_minute }) } - subtract : Clock, { hour : I64, minute : I64 } -> Clock + subtract : Clock, { hour : I64 ?? 0, minute : I64 ?? 0 } -> Clock subtract = |clock, { hour, minute }| { clock.add({ hour: -(hour % 24 + minute // 60), minute: -(minute % 60) }) } diff --git a/exercises/practice/clock/.meta/plugins.py b/exercises/practice/clock/.meta/plugins.py index ff8f8f05..7852c6f3 100644 --- a/exercises/practice/clock/.meta/plugins.py +++ b/exercises/practice/clock/.meta/plugins.py @@ -1,4 +1,9 @@ def to_hour_minute_record(input): hour = input.get("hour", 0) minute = input.get("minute", 0) - return f'{{hour: {hour}, minute: {minute}}}' \ No newline at end of file + fields = [] + if hour != 0: + fields.append(f"hour: {hour}") + if minute != 0: + fields.append(f"minute: {minute}") + return "{ " + ", ".join(fields) + " }" if fields else "{}" diff --git a/exercises/practice/clock/.meta/template.j2 b/exercises/practice/clock/.meta/template.j2 index 90b02c56..b9a3fadd 100644 --- a/exercises/practice/clock/.meta/template.j2 +++ b/exercises/practice/clock/.meta/template.j2 @@ -17,7 +17,7 @@ expect { {%- elif case["property"] in ["add", "subtract"] %} expect { clock = create({{ plugins.to_hour_minute_record(case["input"]) }}) - result = clock.{{ case["property"] | to_snake }}({ hour: 0, minute: {{ case["input"]["value"] }} }).to_str() + result = clock.{{ case["property"] | to_snake }}({ minute: {{ case["input"]["value"] }} }).to_str() expected = {{ case["expected"] | to_roc }} result == expected } diff --git a/exercises/practice/clock/Clock.roc b/exercises/practice/clock/Clock.roc index 48e440b1..4ec59248 100644 --- a/exercises/practice/clock/Clock.roc +++ b/exercises/practice/clock/Clock.roc @@ -1,5 +1,5 @@ Clock :: { hour : U8, minute : U8 }.{ - create : { hour : I64, minute : I64 } -> Clock + create : { hour : I64 ?? 0, minute : I64 ?? 0 } -> Clock create = |{ hour, minute }| { crash "Please implement the 'create' function" } @@ -9,12 +9,12 @@ Clock :: { hour : U8, minute : U8 }.{ crash "Please implement the 'to_str' function" } - add : Clock, { hour : I64, minute : I64 } -> Clock + add : Clock, { hour : I64 ?? 0, minute : I64 ?? 0 } -> Clock add = |clock, { hour, minute }| { crash "Please implement the 'add' function" } - subtract : Clock, { hour : I64, minute : I64 } -> Clock + subtract : Clock, { hour : I64 ?? 0, minute : I64 ?? 0 } -> Clock subtract = |clock, { hour, minute }| { crash "Please implement the 'subtract' function" } diff --git a/exercises/practice/clock/clock-test.roc b/exercises/practice/clock/clock-test.roc index 7a364e53..297d720a 100644 --- a/exercises/practice/clock/clock-test.roc +++ b/exercises/practice/clock/clock-test.roc @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/clock/canonical-data.json -# File last updated on 2026-08-01 +# File last updated on 2026-08-18 import Clock exposing [create, add, subtract, to_str] @@ -10,7 +10,7 @@ import Clock exposing [create, add, subtract, to_str] # on the hour expect { - clock = create({ hour: 8, minute: 0 }) + clock = create({ hour: 8 }) result = clock.to_str() expected = "08:00" result == expected @@ -26,7 +26,7 @@ expect { # midnight is zero hours expect { - clock = create({ hour: 24, minute: 0 }) + clock = create({ hour: 24 }) result = clock.to_str() expected = "00:00" result == expected @@ -34,7 +34,7 @@ expect { # hour rolls over expect { - clock = create({ hour: 25, minute: 0 }) + clock = create({ hour: 25 }) result = clock.to_str() expected = "01:00" result == expected @@ -42,7 +42,7 @@ expect { # hour rolls over continuously expect { - clock = create({ hour: 100, minute: 0 }) + clock = create({ hour: 100 }) result = clock.to_str() expected = "04:00" result == expected @@ -58,7 +58,7 @@ expect { # minutes roll over expect { - clock = create({ hour: 0, minute: 160 }) + clock = create({ minute: 160 }) result = clock.to_str() expected = "02:40" result == expected @@ -66,7 +66,7 @@ expect { # minutes roll over continuously expect { - clock = create({ hour: 0, minute: 1723 }) + clock = create({ minute: 1723 }) result = clock.to_str() expected = "04:43" result == expected @@ -106,7 +106,7 @@ expect { # negative hour rolls over expect { - clock = create({ hour: -25, minute: 0 }) + clock = create({ hour: -25 }) result = clock.to_str() expected = "23:00" result == expected @@ -114,7 +114,7 @@ expect { # negative hour rolls over continuously expect { - clock = create({ hour: -91, minute: 0 }) + clock = create({ hour: -91 }) result = clock.to_str() expected = "05:00" result == expected @@ -174,8 +174,8 @@ expect { # add minutes expect { - clock = create({ hour: 10, minute: 0 }) - result = clock.add({ hour: 0, minute: 3 }).to_str() + clock = create({ hour: 10 }) + result = clock.add({ minute: 3 }).to_str() expected = "10:03" result == expected } @@ -183,31 +183,31 @@ expect { # add no minutes expect { clock = create({ hour: 6, minute: 41 }) - result = clock.add({ hour: 0, minute: 0 }).to_str() + result = clock.add({ minute: 0 }).to_str() expected = "06:41" result == expected } # add to next hour expect { - clock = create({ hour: 0, minute: 45 }) - result = clock.add({ hour: 0, minute: 40 }).to_str() + clock = create({ minute: 45 }) + result = clock.add({ minute: 40 }).to_str() expected = "01:25" result == expected } # add more than one hour expect { - clock = create({ hour: 10, minute: 0 }) - result = clock.add({ hour: 0, minute: 61 }).to_str() + clock = create({ hour: 10 }) + result = clock.add({ minute: 61 }).to_str() expected = "11:01" result == expected } # add more than two hours with carry expect { - clock = create({ hour: 0, minute: 45 }) - result = clock.add({ hour: 0, minute: 160 }).to_str() + clock = create({ minute: 45 }) + result = clock.add({ minute: 160 }).to_str() expected = "03:25" result == expected } @@ -215,7 +215,7 @@ expect { # add across midnight expect { clock = create({ hour: 23, minute: 59 }) - result = clock.add({ hour: 0, minute: 2 }).to_str() + result = clock.add({ minute: 2 }).to_str() expected = "00:01" result == expected } @@ -223,7 +223,7 @@ expect { # add more than one day (1500 min = 25 hrs) expect { clock = create({ hour: 5, minute: 32 }) - result = clock.add({ hour: 0, minute: 1500 }).to_str() + result = clock.add({ minute: 1500 }).to_str() expected = "06:32" result == expected } @@ -231,7 +231,7 @@ expect { # add more than two days expect { clock = create({ hour: 1, minute: 1 }) - result = clock.add({ hour: 0, minute: 3500 }).to_str() + result = clock.add({ minute: 3500 }).to_str() expected = "11:21" result == expected } @@ -243,7 +243,7 @@ expect { # subtract minutes expect { clock = create({ hour: 10, minute: 3 }) - result = clock.subtract({ hour: 0, minute: 3 }).to_str() + result = clock.subtract({ minute: 3 }).to_str() expected = "10:00" result == expected } @@ -251,7 +251,7 @@ expect { # subtract to previous hour expect { clock = create({ hour: 10, minute: 3 }) - result = clock.subtract({ hour: 0, minute: 30 }).to_str() + result = clock.subtract({ minute: 30 }).to_str() expected = "09:33" result == expected } @@ -259,23 +259,23 @@ expect { # subtract more than an hour expect { clock = create({ hour: 10, minute: 3 }) - result = clock.subtract({ hour: 0, minute: 70 }).to_str() + result = clock.subtract({ minute: 70 }).to_str() expected = "08:53" result == expected } # subtract across midnight expect { - clock = create({ hour: 0, minute: 3 }) - result = clock.subtract({ hour: 0, minute: 4 }).to_str() + clock = create({ minute: 3 }) + result = clock.subtract({ minute: 4 }).to_str() expected = "23:59" result == expected } # subtract more than two hours expect { - clock = create({ hour: 0, minute: 0 }) - result = clock.subtract({ hour: 0, minute: 160 }).to_str() + clock = create({}) + result = clock.subtract({ minute: 160 }).to_str() expected = "21:20" result == expected } @@ -283,7 +283,7 @@ expect { # subtract more than two hours with borrow expect { clock = create({ hour: 6, minute: 15 }) - result = clock.subtract({ hour: 0, minute: 160 }).to_str() + result = clock.subtract({ minute: 160 }).to_str() expected = "03:35" result == expected } @@ -291,7 +291,7 @@ expect { # subtract more than one day (1500 min = 25 hrs) expect { clock = create({ hour: 5, minute: 32 }) - result = clock.subtract({ hour: 0, minute: 1500 }).to_str() + result = clock.subtract({ minute: 1500 }).to_str() expected = "04:32" result == expected } @@ -299,7 +299,7 @@ expect { # subtract more than two days expect { clock = create({ hour: 2, minute: 20 }) - result = clock.subtract({ hour: 0, minute: 3000 }).to_str() + result = clock.subtract({ minute: 3000 }).to_str() expected = "00:20" result == expected } @@ -366,8 +366,8 @@ expect { # clocks with minute overflow expect { - clock1 = create({ hour: 0, minute: 1 }) - clock2 = create({ hour: 0, minute: 1441 }) + clock1 = create({ minute: 1 }) + clock2 = create({ minute: 1441 }) clock1 == clock2 } @@ -415,8 +415,8 @@ expect { # full clock and zeroed clock expect { - clock1 = create({ hour: 24, minute: 0 }) - clock2 = create({ hour: 0, minute: 0 }) + clock1 = create({ hour: 24 }) + clock2 = create({}) clock1 == clock2 } @@ -443,7 +443,7 @@ expect { # Can add max I64 values to a clock expect { clock = create({ hour: 23, minute: 59 }) - result = clock.add({ hour: 0, minute: 9223372036854775807 }).to_str() + result = clock.add({ minute: 9223372036854775807 }).to_str() expected = "18:06" result == expected } @@ -451,7 +451,7 @@ expect { # Can add min I64 values to a clock expect { clock = create({ hour: 23, minute: 59 }) - result = clock.add({ hour: 0, minute: -9223372036854775808 }).to_str() + result = clock.add({ minute: -9223372036854775808 }).to_str() expected = "05:51" result == expected } @@ -459,7 +459,7 @@ expect { # Can subtract max I64 values from a clock expect { clock = create({ hour: 23, minute: 59 }) - result = clock.subtract({ hour: 0, minute: 9223372036854775807 }).to_str() + result = clock.subtract({ minute: 9223372036854775807 }).to_str() expected = "05:52" result == expected } @@ -467,7 +467,7 @@ expect { # Can subtract min I64 values from a clock expect { clock = create({ hour: 23, minute: 59 }) - result = clock.subtract({ hour: 0, minute: -9223372036854775808 }).to_str() + result = clock.subtract({ minute: -9223372036854775808 }).to_str() expected = "18:07" result == expected } diff --git a/exercises/practice/killer-sudoku-helper/.meta/Example.roc b/exercises/practice/killer-sudoku-helper/.meta/Example.roc index 93301294..6833c77e 100644 --- a/exercises/practice/killer-sudoku-helper/.meta/Example.roc +++ b/exercises/practice/killer-sudoku-helper/.meta/Example.roc @@ -1,7 +1,7 @@ KillerSudokuHelper :: {}.{ Combination : List(U8) - combinations : { sum : U8, size : U8, exclude : List(U8) } -> List(Combination) + combinations : { sum : U8, size : U8, exclude : List(U8) ?? [] } -> List(Combination) combinations = |{ sum, size, exclude }| { help = |target, digits| { if target == 0 { diff --git a/exercises/practice/killer-sudoku-helper/.meta/template.j2 b/exercises/practice/killer-sudoku-helper/.meta/template.j2 index 068045d8..b7030e07 100644 --- a/exercises/practice/killer-sudoku-helper/.meta/template.j2 +++ b/exercises/practice/killer-sudoku-helper/.meta/template.j2 @@ -5,7 +5,7 @@ import {{ exercise | to_pascal }} exposing [combinations] {% macro to_cage(cage) -%} -{ sum: {{ cage["sum"] }}, size: {{ cage["size"] }}, exclude: {{ cage["exclude"] | to_roc }} } +{ sum: {{ cage["sum"] }}, size: {{ cage["size"] }}{% if cage["exclude"] %}, exclude: {{ cage["exclude"] | to_roc }}{% endif %} } {%- endmacro %} {% for supercase in cases %} diff --git a/exercises/practice/killer-sudoku-helper/KillerSudokuHelper.roc b/exercises/practice/killer-sudoku-helper/KillerSudokuHelper.roc index be7f7c12..3954827c 100644 --- a/exercises/practice/killer-sudoku-helper/KillerSudokuHelper.roc +++ b/exercises/practice/killer-sudoku-helper/KillerSudokuHelper.roc @@ -1,7 +1,7 @@ KillerSudokuHelper :: {}.{ Combination : List(U8) - combinations : { sum : U8, size : U8, exclude : List(U8) } -> List(Combination) + combinations : { sum : U8, size : U8, exclude : List(U8) ?? [] } -> List(Combination) combinations = |{ sum, size, exclude }| { crash "Please implement the 'combinations' function" } diff --git a/exercises/practice/killer-sudoku-helper/killer-sudoku-helper-test.roc b/exercises/practice/killer-sudoku-helper/killer-sudoku-helper-test.roc index 10b26cb5..e79f7c0c 100644 --- a/exercises/practice/killer-sudoku-helper/killer-sudoku-helper-test.roc +++ b/exercises/practice/killer-sudoku-helper/killer-sudoku-helper-test.roc @@ -1,79 +1,79 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/killer-sudoku-helper/canonical-data.json -# File last updated on 2026-08-01 +# File last updated on 2026-08-18 import KillerSudokuHelper exposing [combinations] ## Trivial 1-digit cages # 1 expect { - result = combinations({ sum: 1, size: 1, exclude: [] }) + result = combinations({ sum: 1, size: 1 }) result == [[1]] } # 2 expect { - result = combinations({ sum: 2, size: 1, exclude: [] }) + result = combinations({ sum: 2, size: 1 }) result == [[2]] } # 3 expect { - result = combinations({ sum: 3, size: 1, exclude: [] }) + result = combinations({ sum: 3, size: 1 }) result == [[3]] } # 4 expect { - result = combinations({ sum: 4, size: 1, exclude: [] }) + result = combinations({ sum: 4, size: 1 }) result == [[4]] } # 5 expect { - result = combinations({ sum: 5, size: 1, exclude: [] }) + result = combinations({ sum: 5, size: 1 }) result == [[5]] } # 6 expect { - result = combinations({ sum: 6, size: 1, exclude: [] }) + result = combinations({ sum: 6, size: 1 }) result == [[6]] } # 7 expect { - result = combinations({ sum: 7, size: 1, exclude: [] }) + result = combinations({ sum: 7, size: 1 }) result == [[7]] } # 8 expect { - result = combinations({ sum: 8, size: 1, exclude: [] }) + result = combinations({ sum: 8, size: 1 }) result == [[8]] } # 9 expect { - result = combinations({ sum: 9, size: 1, exclude: [] }) + result = combinations({ sum: 9, size: 1 }) result == [[9]] } ## Cage with sum 45 contains all digits 1:9 expect { - result = combinations({ sum: 45, size: 9, exclude: [] }) + result = combinations({ sum: 45, size: 9 }) result == [[1, 2, 3, 4, 5, 6, 7, 8, 9]] } ## Cage with only 1 possible combination expect { - result = combinations({ sum: 7, size: 3, exclude: [] }) + result = combinations({ sum: 7, size: 3 }) result == [[1, 2, 4]] } ## Cage with several combinations expect { - result = combinations({ sum: 10, size: 2, exclude: [] }) + result = combinations({ sum: 10, size: 2 }) result == [[1, 9], [2, 8], [3, 7], [4, 6]] } diff --git a/exercises/practice/rest-api/.meta/Example.roc b/exercises/practice/rest-api/.meta/Example.roc index aab15f00..0ba79469 100644 --- a/exercises/practice/rest-api/.meta/Example.roc +++ b/exercises/practice/rest-api/.meta/Example.roc @@ -10,10 +10,15 @@ RestApi :: {}.{ Loan : { lender : Str, borrower : Str, amount : Dec } - get : Database, { url : Str, payload : Str } -> Try(Str, [Http404(Str), Http422(Str)]) + get : Database, { url : Str, payload ?: Str } -> Try(Str, [Http404(Str), Http422(Str)]) get = |database, { url, payload }| { match url { - "/users" | "/users/" => (database |> get_users(payload)).map_err(|_| Http422(payload)) + "/users" | "/users/" => { + match payload { + Ok(request_payload) => (database |> get_users(request_payload)).map_err(|_| Http422(request_payload)) + Err(MissingField) => Ok(users_to_json(database.users)) + } + } bad_url => Err(Http404(bad_url)) } } @@ -36,14 +41,8 @@ RestApi :: {}.{ get_users : RestApi.Database, Str -> Try(Str, [InvalidJson]) get_users = |database, payload| { - users = - if payload == "" { - database.users - } else { - names = get_user_names(payload)? - database.users - .keep_if(|user| names.contains(user.name)) - } + names = get_user_names(payload)? + users = database.users.keep_if(|user| names.contains(user.name)) Ok(users_to_json(users)) } @@ -91,8 +90,8 @@ add_user = |_database, payload| { add_loan : RestApi.Database, Str -> Try(Str, [NotFound, InvalidJson]) add_loan = |database, payload| { loan = parse_json_loan(payload)? - lender = database -> get_user(loan.lender)? - borrower = database -> get_user(loan.borrower)? + lender = database |> get_user(loan.lender)? + borrower = database |> get_user(loan.borrower)? updated_lender = lender |> update_lender(borrower.name, loan.amount) updated_borrower = borrower |> update_lender(lender.name, -loan.amount) Ok(users_to_json([updated_lender, updated_borrower])) diff --git a/exercises/practice/rest-api/.meta/template.j2 b/exercises/practice/rest-api/.meta/template.j2 index a445f181..5bd288f5 100644 --- a/exercises/practice/rest-api/.meta/template.j2 +++ b/exercises/practice/rest-api/.meta/template.j2 @@ -33,11 +33,9 @@ expect { ] } result_json = database |> {{ case["property"] | to_snake }}({ - url: {{ case["input"]["url"] | to_roc }}, + url: {{ case["input"]["url"] | to_roc }} {%- if case["input"].get("payload", {}) != {} %} - payload: {{ case["input"]["payload"] | tojson | to_roc }} - {%- else %} - payload: "" + , payload: {{ case["input"]["payload"] | tojson | to_roc }} {%- endif %} })? expected_json = {{ case["expected"] | tojson | to_roc }} diff --git a/exercises/practice/rest-api/RestApi.roc b/exercises/practice/rest-api/RestApi.roc index d5142fad..10d3515f 100644 --- a/exercises/practice/rest-api/RestApi.roc +++ b/exercises/practice/rest-api/RestApi.roc @@ -8,7 +8,7 @@ RestApi :: {}.{ Database : { users : List(User) } - get : Database, { url : Str, payload : Str } -> Try(Str, _) + get : Database, { url : Str, payload ?: Str } -> Try(Str, _) get = |database, { url, payload }| { crash "Please implement the 'get' function" } diff --git a/exercises/practice/rest-api/rest-api-test.roc b/exercises/practice/rest-api/rest-api-test.roc index 7053fdd2..abf29246 100644 --- a/exercises/practice/rest-api/rest-api-test.roc +++ b/exercises/practice/rest-api/rest-api-test.roc @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/rest-api/canonical-data.json -# File last updated on 2026-08-15 +# File last updated on 2026-08-18 import RestApi exposing [get, post] @@ -12,7 +12,7 @@ import RestApi exposing [get, post] expect { database = { users: [] } result_json = database - |> get({ url: "/users", payload: "" })? + |> get({ url: "/users" })? expected_json = "{\"users\": []}" result_json |> is_equivalent_to(expected_json)? } diff --git a/exercises/practice/robot-simulator/.meta/Example.roc b/exercises/practice/robot-simulator/.meta/Example.roc index 570529b1..082804a4 100644 --- a/exercises/practice/robot-simulator/.meta/Example.roc +++ b/exercises/practice/robot-simulator/.meta/Example.roc @@ -2,6 +2,11 @@ RobotSimulator :: {}.{ Direction : [North, East, South, West] Robot : { x : I64, y : I64, direction : Direction } + create : { x : I64 ?? 0, y : I64 ?? 0, direction : Direction ?? North } -> Robot + create = |{ x, y, direction }| { + { x, y, direction } + } + move : Robot, Str -> Robot move = |robot, instructions| { instructions diff --git a/exercises/practice/robot-simulator/.meta/plugins.py b/exercises/practice/robot-simulator/.meta/plugins.py index 2615ad25..b110bb96 100644 --- a/exercises/practice/robot-simulator/.meta/plugins.py +++ b/exercises/practice/robot-simulator/.meta/plugins.py @@ -1,5 +1,12 @@ -def to_robot(robot): +def to_robot(robot, with_defaults): x = robot["position"]["x"] y = robot["position"]["y"] direction = robot["direction"] - return f"{{x : {x}, y : {y}, direction : {direction.capitalize()}}}" + fields = [] + if x != 0 or not with_defaults: + fields.append(f"x: {x}") + if y != 0 or not with_defaults: + fields.append(f"y: {y}") + if direction != "north" or not with_defaults: + fields.append(f"direction: {direction.capitalize()}") + return "{" + ", ".join(fields) + "}" diff --git a/exercises/practice/robot-simulator/.meta/template.j2 b/exercises/practice/robot-simulator/.meta/template.j2 index eac820c5..a9952405 100644 --- a/exercises/practice/robot-simulator/.meta/template.j2 +++ b/exercises/practice/robot-simulator/.meta/template.j2 @@ -2,7 +2,7 @@ {{ macros.canonical_ref() }} {{ macros.header() }} -import {{ exercise | to_pascal }} exposing [move] +import {{ exercise | to_pascal }} exposing [create, move] {% for supercase in cases %} ## @@ -12,9 +12,13 @@ import {{ exercise | to_pascal }} exposing [move] {% for case in supercase["cases"] -%} # {{ case["description"] }} expect { - robot = {{ plugins.to_robot(case["input"]) }} - result = robot|>move({{ case["input"]["instructions"] | to_roc }}) - result == {{ plugins.to_robot(case["expected"]) }} + {%- if case["input"]["instructions"] %} + robot = create({{ plugins.to_robot(case["input"], with_defaults=True) }}) + result = robot |> move({{ case["input"]["instructions"] | to_roc }}) + {%- else %} + result = create({{ plugins.to_robot(case["input"], with_defaults=True) }}) + {%- endif %} + result == {{ plugins.to_robot(case["expected"], with_defaults=False) }} } {% endfor %} diff --git a/exercises/practice/robot-simulator/.meta/tests.toml b/exercises/practice/robot-simulator/.meta/tests.toml index f2e52b19..16da03d4 100644 --- a/exercises/practice/robot-simulator/.meta/tests.toml +++ b/exercises/practice/robot-simulator/.meta/tests.toml @@ -11,11 +11,9 @@ [c557c16d-26c1-4e06-827c-f6602cd0785c] description = "Create robot -> at origin facing north" -include = false [bf0dffce-f11c-4cdb-8a5e-2c89d8a5a67d] description = "Create robot -> at negative position facing south" -include = false [8cbd0086-6392-4680-b9b9-73cf491e67e5] description = "Rotating clockwise -> changes north to east" diff --git a/exercises/practice/robot-simulator/RobotSimulator.roc b/exercises/practice/robot-simulator/RobotSimulator.roc index 0933626b..ef62152d 100644 --- a/exercises/practice/robot-simulator/RobotSimulator.roc +++ b/exercises/practice/robot-simulator/RobotSimulator.roc @@ -2,6 +2,11 @@ RobotSimulator :: {}.{ Direction : [North, East, South, West] Robot : { x : I64, y : I64, direction : Direction } + create : { x : I64 ?? 0, y : I64 ?? 0, direction : Direction ?? North } -> Robot + create = |{ x, y, direction }| { + crash "Please implement the 'create' function" + } + move : Robot, Str -> Robot move = |robot, instructions| { crash "Please implement the 'move' function" diff --git a/exercises/practice/robot-simulator/robot-simulator-test.roc b/exercises/practice/robot-simulator/robot-simulator-test.roc index f6a1b917..25107fe8 100644 --- a/exercises/practice/robot-simulator/robot-simulator-test.roc +++ b/exercises/practice/robot-simulator/robot-simulator-test.roc @@ -1,8 +1,24 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/robot-simulator/canonical-data.json -# File last updated on 2026-08-01 +# File last updated on 2026-08-17 -import RobotSimulator exposing [move] +import RobotSimulator exposing [create, move] + +## +## Create robot +## + +# at origin facing north +expect { + result = create({}) + result == { x: 0, y: 0, direction: North } +} + +# at negative position facing south +expect { + result = create({ x: -1, y: -1, direction: South }) + result == { x: -1, y: -1, direction: South } +} ## ## Rotating clockwise @@ -10,28 +26,28 @@ import RobotSimulator exposing [move] # changes north to east expect { - robot = { x: 0, y: 0, direction: North } + robot = create({}) result = robot |> move("R") result == { x: 0, y: 0, direction: East } } # changes east to south expect { - robot = { x: 0, y: 0, direction: East } + robot = create({ direction: East }) result = robot |> move("R") result == { x: 0, y: 0, direction: South } } # changes south to west expect { - robot = { x: 0, y: 0, direction: South } + robot = create({ direction: South }) result = robot |> move("R") result == { x: 0, y: 0, direction: West } } # changes west to north expect { - robot = { x: 0, y: 0, direction: West } + robot = create({ direction: West }) result = robot |> move("R") result == { x: 0, y: 0, direction: North } } @@ -42,28 +58,28 @@ expect { # changes north to west expect { - robot = { x: 0, y: 0, direction: North } + robot = create({}) result = robot |> move("L") result == { x: 0, y: 0, direction: West } } # changes west to south expect { - robot = { x: 0, y: 0, direction: West } + robot = create({ direction: West }) result = robot |> move("L") result == { x: 0, y: 0, direction: South } } # changes south to east expect { - robot = { x: 0, y: 0, direction: South } + robot = create({ direction: South }) result = robot |> move("L") result == { x: 0, y: 0, direction: East } } # changes east to north expect { - robot = { x: 0, y: 0, direction: East } + robot = create({ direction: East }) result = robot |> move("L") result == { x: 0, y: 0, direction: North } } @@ -74,28 +90,28 @@ expect { # facing north increments Y expect { - robot = { x: 0, y: 0, direction: North } + robot = create({}) result = robot |> move("A") result == { x: 0, y: 1, direction: North } } # facing south decrements Y expect { - robot = { x: 0, y: 0, direction: South } + robot = create({ direction: South }) result = robot |> move("A") result == { x: 0, y: -1, direction: South } } # facing east increments X expect { - robot = { x: 0, y: 0, direction: East } + robot = create({ direction: East }) result = robot |> move("A") result == { x: 1, y: 0, direction: East } } # facing west decrements X expect { - robot = { x: 0, y: 0, direction: West } + robot = create({ direction: West }) result = robot |> move("A") result == { x: -1, y: 0, direction: West } } @@ -106,28 +122,28 @@ expect { # moving east and north from README expect { - robot = { x: 7, y: 3, direction: North } + robot = create({ x: 7, y: 3 }) result = robot |> move("RAALAL") result == { x: 9, y: 4, direction: West } } # moving west and north expect { - robot = { x: 0, y: 0, direction: North } + robot = create({}) result = robot |> move("LAAARALA") result == { x: -4, y: 1, direction: West } } # moving west and south expect { - robot = { x: 2, y: -7, direction: East } + robot = create({ x: 2, y: -7, direction: East }) result = robot |> move("RRAAAAALA") result == { x: -3, y: -8, direction: South } } # moving east and north expect { - robot = { x: 8, y: 4, direction: South } + robot = create({ x: 8, y: 4, direction: South }) result = robot |> move("LAAARRRALLLL") result == { x: 11, y: 5, direction: North } }