Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,14 @@
],
"difficulty": 4
},
{
"slug": "rectangles",
"name": "Rectangles",
"uuid": "6284512a-b40a-4e81-8d4f-712d729cc419",
"practices": [],
"prerequisites": [],
"difficulty": 4
},
{
"slug": "killer-sudoku-helper",
"name": "Killer Sudoku Helper",
Expand Down
63 changes: 63 additions & 0 deletions exercises/practice/rectangles/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Instructions

Count the rectangles in an ASCII diagram like the one below.

```text
+--+
++ |
+-++--+
| | |
+--+--+
```

The above diagram contains these 6 rectangles:

```text


+-----+
| |
+-----+
```

```text
+--+
| |
| |
| |
+--+
```

```text
+--+
| |
+--+


```

```text


+--+
| |
+--+
```

```text


+--+
| |
+--+
```

```text

++
++


```

You may assume that the input is always a proper rectangle (i.e. the length of every line equals the length of the first line).
17 changes: 17 additions & 0 deletions exercises/practice/rectangles/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"authors": [
"colinleach"
],
"files": {
"solution": [
"rectangles.jl"
],
"test": [
"runtests.jl"
],
"example": [
".meta/example.jl"
]
},
"blurb": "Count the rectangles in an ASCII diagram."
}
40 changes: 40 additions & 0 deletions exercises/practice/rectangles/.meta/example.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
struct Pt
c::Integer # column
r::Integer # row
end

function rectangles(strings)
corners = Set{Pt}()
horiz = Set{Pt}()
vert = Set{Pt}()
for (y, line) in enumerate(strings)
for (x, char) in enumerate(line)
if char == '+'
push!(corners, Pt(x, y))
# corners are also valid for top & bottom
push!(horiz, Pt(x, y))
push!(vert, Pt(x, y))
elseif char == '-'
push!(horiz, Pt(x, y))
elseif char == '|'
push!(vert, Pt(x, y))
end
end
end

# get top-left and bottom-right corners
possibles = [(pt1, pt2) for pt1 in corners, pt2 in corners
if pt1.r < pt2.r && pt1.c < pt2.c
# check bottom-left and top-right
&& Pt(pt1.c, pt2.r) ∈ corners
&& Pt(pt2.c, pt1.r) ∈ corners]

sides(pt1, pt2) = all([Pt(pt1.c, row) ∈ vert for row in pt1.r:pt2.r]) &&
all([Pt(pt2.c, row) ∈ vert for row in pt1.r:pt2.r])

top_bottom(pt1, pt2) = all([Pt(col, pt1.r) ∈ horiz for col in pt1.c:pt2.c]) &&
all([Pt(col, pt2.r) ∈ horiz for col in pt1.c:pt2.c])

[(pt1, pt2) for (pt1, pt2) in possibles
Comment thread
colinleach marked this conversation as resolved.
if sides(pt1, pt2) && top_bottom(pt1, pt2)] |> length
end
15 changes: 15 additions & 0 deletions exercises/practice/rectangles/.meta/template.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{%- import "generator_macros.j2" as macros with context -%}
{{ macros.canonical_ref() }}

{{ macros.header()}}
{%- macro test_case(case) %}
{%- set input = case["input"] %}
@testset "{{ case["description"]}}" begin
@test rectangles({{ case["input"]["strings"] | replace("'", '"') }}) == {{ case["expected"] }}
end
{% endmacro %}

{% for case in cases -%}
{{ test_case(case) }}
{% endfor %}
end
52 changes: 52 additions & 0 deletions exercises/practice/rectangles/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -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.

[485b7bab-4150-40aa-a8db-73013427d08c]
description = "no rows"

[076929ed-27e8-45dc-b14b-08279944dc49]
description = "no columns"

[0a8abbd1-a0a4-4180-aa4e-65c1b1a073fa]
description = "no rectangles"

[a4ba42e9-4e7f-4973-b7c7-4ce0760ac6cd]
description = "one rectangle"

[ced06550-83da-4d23-98b7-d24152e0db93]
description = "two rectangles without shared parts"

[5942d69a-a07c-41c8-8b93-2d13877c706a]
description = "five rectangles with shared parts"

[82d70be4-ab37-4bf2-a433-e33778d3bbf1]
description = "rectangle of height 1 is counted"

[57f1bc0e-2782-401e-ab12-7c01d8bfc2e0]
description = "rectangle of width 1 is counted"

[ef0bb65c-bd80-4561-9535-efc4067054f9]
description = "1x1 square is counted"

[e1e1d444-e926-4d30-9bf3-7d8ec9a9e330]
description = "only complete rectangles are counted"

[ca021a84-1281-4a56-9b9b-af14113933a4]
description = "rectangles can be of different sizes"

[51f689a7-ef3f-41ae-aa2f-5ea09ad897ff]
description = "corner is required for a rectangle to be complete"

[d78fe379-8c1b-4d3c-bdf7-29bfb6f6dc66]
description = "large input with many rectangles"

[6ef24e0f-d191-46da-b929-4faca24b4cd2]
description = "rectangles must have four sides"
3 changes: 3 additions & 0 deletions exercises/practice/rectangles/rectangles.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function rectangles(strings)

end
70 changes: 70 additions & 0 deletions exercises/practice/rectangles/runtests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/rectangles/canonical-data.json
# File last updated on 2026-08-02

using Test

include("rectangles.jl")

@testset verbose = true "tests" begin
@testset "no rows" begin
@test rectangles([]) == 0
end

@testset "no columns" begin
@test rectangles([""]) == 0
end

@testset "no rectangles" begin
@test rectangles([" "]) == 0
end

@testset "one rectangle" begin
@test rectangles(["+-+", "| |", "+-+"]) == 1
end

@testset "two rectangles without shared parts" begin
@test rectangles([" +-+", " | |", "+-+-+", "| | ", "+-+ "]) == 2
end

@testset "five rectangles with shared parts" begin
@test rectangles([" +-+", " | |", "+-+-+", "| | |", "+-+-+"]) == 5
end

@testset "rectangle of height 1 is counted" begin
@test rectangles(["+--+", "+--+"]) == 1
end

@testset "rectangle of width 1 is counted" begin
@test rectangles(["++", "||", "++"]) == 1
end

@testset "1x1 square is counted" begin
@test rectangles(["++", "++"]) == 1
end

@testset "only complete rectangles are counted" begin
@test rectangles([" +-+", " |", "+-+-+", "| | -", "+-+-+"]) == 1
end

@testset "rectangles can be of different sizes" begin
@test rectangles(["+------+----+", "| | |", "+---+--+ |",
"| | |", "+---+-------+"]) == 3
end

@testset "corner is required for a rectangle to be complete" begin
@test rectangles(["+------+----+", "| | |", "+------+ |",
"| | |", "+---+-------+"]) == 2
end

@testset "large input with many rectangles" begin
@test rectangles(["+---+--+----+", "| +--+----+", "+---+--+ |",
"| +--+----+", "+---+--+--+-+", "+---+--+--+-+",
"+------+ | |", " +-+"]) == 60
end

@testset "rectangles must have four sides" begin
@test rectangles(["+-+ +-+", "| | | |", "+-+-+-+", " | | ", "+-+-+-+", "| | | |",
"+-+ +-+"]) == 5
end
end
Loading