Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions exercises/practice/clock/.meta/Example.roc
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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) })
}
Expand Down
7 changes: 6 additions & 1 deletion exercises/practice/clock/.meta/plugins.py
Original file line number Diff line number Diff line change
@@ -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}}}'
fields = []
if hour != 0:
fields.append(f"hour: {hour}")
if minute != 0:
fields.append(f"minute: {minute}")
return "{ " + ", ".join(fields) + " }" if fields else "{}"
2 changes: 1 addition & 1 deletion exercises/practice/clock/.meta/template.j2
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
6 changes: 3 additions & 3 deletions exercises/practice/clock/Clock.roc
Original file line number Diff line number Diff line change
@@ -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"
}
Expand All @@ -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"
}
Expand Down
78 changes: 39 additions & 39 deletions exercises/practice/clock/clock-test.roc
Original file line number Diff line number Diff line change
@@ -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]

Expand All @@ -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
Expand All @@ -26,23 +26,23 @@ 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
}

# hour rolls over
expect {
clock = create({ hour: 25, minute: 0 })
clock = create({ hour: 25 })
result = clock.to_str()
expected = "01:00"
result == expected
}

# hour rolls over continuously
expect {
clock = create({ hour: 100, minute: 0 })
clock = create({ hour: 100 })
result = clock.to_str()
expected = "04:00"
result == expected
Expand All @@ -58,15 +58,15 @@ expect {

# minutes roll over
expect {
clock = create({ hour: 0, minute: 160 })
clock = create({ minute: 160 })
result = clock.to_str()
expected = "02:40"
result == expected
}

# minutes roll over continuously
expect {
clock = create({ hour: 0, minute: 1723 })
clock = create({ minute: 1723 })
result = clock.to_str()
expected = "04:43"
result == expected
Expand Down Expand Up @@ -106,15 +106,15 @@ 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
}

# 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
Expand Down Expand Up @@ -174,64 +174,64 @@ 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
}

# 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
}

# 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
}

# 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
}

# 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
}
Expand All @@ -243,63 +243,63 @@ 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
}

# 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
}

# 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
}

# 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
}

# 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
}

# 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
}
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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
}

Expand All @@ -443,31 +443,31 @@ 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
}

# 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
}

# 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
}

# 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
}
Expand Down
2 changes: 1 addition & 1 deletion exercises/practice/killer-sudoku-helper/.meta/Example.roc
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion exercises/practice/killer-sudoku-helper/.meta/template.j2
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
Expand Down
Original file line number Diff line number Diff line change
@@ -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"
}
Expand Down
Loading