Skip to content

Commit a6846bb

Browse files
Add piecing-it-together (#481)
1 parent 3342d6a commit a6846bb

File tree

8 files changed

+403
-0
lines changed

8 files changed

+403
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,14 @@
985985
"prerequisites": [],
986986
"difficulty": 6
987987
},
988+
{
989+
"slug": "piecing-it-together",
990+
"name": "Piecing It Together",
991+
"uuid": "6e8760d1-f231-42b8-a6ad-ac9cd36528d9",
992+
"practices": [],
993+
"prerequisites": [],
994+
"difficulty": 6
995+
},
988996
{
989997
"slug": "two-bucket",
990998
"name": "Two Bucket",
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Instructions
2+
3+
Given partial information about a jigsaw puzzle, add the missing pieces.
4+
5+
If the information is insufficient to complete the details, or if given parts are in contradiction, the user should be notified.
6+
7+
The full information about the jigsaw puzzle contains the following parts:
8+
9+
- `pieces`: Total number of pieces
10+
- `border`: Number of border pieces
11+
- `inside`: Number of inside (non-border) pieces
12+
- `rows`: Number of rows
13+
- `columns`: Number of columns
14+
- `aspectRatio`: Aspect ratio of columns to rows
15+
- `format`: Puzzle format, which can be `portrait`, `square`, or `landscape`
16+
17+
For this exercise, you may assume square pieces, so that the format can be derived from the aspect ratio:
18+
19+
- If the aspect ratio is less than 1, it's `portrait`
20+
- If it is equal to 1, it's `square`
21+
- If it is greater than 1, it's `landscape`
22+
23+
## Three examples
24+
25+
### Portrait
26+
27+
A portrait jigsaw puzzle with 6 pieces, all of which are border pieces and none are inside pieces. It has 3 rows and 2 columns. The aspect ratio is 1.5 (3/2).
28+
29+
![A 2 by 3 jigsaw puzzle](https://assets.exercism.org/images/exercises/piecing-it-together/jigsaw-puzzle-2x3.svg)
30+
31+
### Square
32+
33+
A square jigsaw puzzle with 9 pieces, all of which are border pieces except for the one in the center, which is an inside piece. It has 3 rows and 3 columns. The aspect ratio is 1 (3/3).
34+
35+
![A 3 by 3 jigsaw puzzle](https://assets.exercism.org/images/exercises/piecing-it-together/jigsaw-puzzle-3x3.svg)
36+
37+
### Landscape
38+
39+
A landscape jigsaw puzzle with 12 pieces, 10 of which are border pieces and 2 are inside pieces. It has 3 rows and 4 columns. The aspect ratio is 1.333333... (4/3).
40+
41+
![A 4 by 3 jigsaw puzzle](https://assets.exercism.org/images/exercises/piecing-it-together/jigsaw-puzzle-4x3.svg)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Introduction
2+
3+
Your best friend has started collecting jigsaw puzzles and wants to build a detailed catalog of their collection — recording information such as the total number of pieces, the number of rows and columns, the number of border and inside pieces, aspect ratio, and puzzle format.
4+
Even with your powers combined, it takes multiple hours to solve a single jigsaw puzzle with one thousand pieces — and then you still need to count the rows and columns and calculate the remaining numbers manually.
5+
The even larger puzzles with thousands of pieces look quite daunting now.
6+
"There has to be a better way!" you exclaim and sit down in front of your computer to solve the problem.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"keiravillekode"
4+
],
5+
"files": {
6+
"solution": [
7+
"piecing_it_together.zig"
8+
],
9+
"test": [
10+
"test_piecing_it_together.zig"
11+
],
12+
"example": [
13+
".meta/example.zig"
14+
]
15+
},
16+
"blurb": "Fill in missing jigsaw puzzle details from partial data",
17+
"source": "atk just started another 1000-pieces jigsaw puzzle when this idea hit him",
18+
"source_url": "https://github.com/exercism/problem-specifications/pull/2554"
19+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
pub const PuzzleError = error{
2+
InsufficientData,
3+
ContradictoryData,
4+
};
5+
6+
pub const Format = enum {
7+
portrait,
8+
square,
9+
landscape,
10+
};
11+
12+
pub const PartialInformation = struct {
13+
pieces: ?u30 = null, //
14+
border: ?u30 = null, //
15+
inside: ?u30 = null, //
16+
rows: ?u30 = null, //
17+
columns: ?u30 = null, //
18+
aspectRatio: ?f64 = null, //
19+
format: ?Format = null, //
20+
};
21+
22+
pub const FullInformation = struct {
23+
pieces: u30, //
24+
border: u30, //
25+
inside: u30, //
26+
rows: u30, //
27+
columns: u30, //
28+
aspectRatio: f64, //
29+
format: Format, //
30+
};
31+
32+
fn fmt(rows: u30, columns: u30) Format {
33+
if (columns < rows) {
34+
return .portrait;
35+
}
36+
37+
if (columns > rows) {
38+
return .landscape;
39+
}
40+
41+
return .square;
42+
}
43+
44+
fn complete(rows: u30, columns: u30) FullInformation {
45+
return FullInformation{
46+
.pieces = rows * columns,
47+
.border = 2 * (rows + columns) - 4,
48+
.inside = (rows - 2) * (columns - 2),
49+
.rows = rows,
50+
.columns = columns,
51+
.aspectRatio = @as(f64, @floatFromInt(columns)) * 1.0 / @as(f64, @floatFromInt(rows)),
52+
.format = fmt(rows, columns),
53+
};
54+
}
55+
56+
fn match(candidate: FullInformation, puzzle: PartialInformation) bool {
57+
if (puzzle.pieces) |pieces| {
58+
if (candidate.pieces != pieces) {
59+
return false;
60+
}
61+
}
62+
63+
if (puzzle.border) |border| {
64+
if (candidate.border != border) {
65+
return false;
66+
}
67+
}
68+
69+
if (puzzle.inside) |inside| {
70+
if (candidate.inside != inside) {
71+
return false;
72+
}
73+
}
74+
75+
if (puzzle.rows) |rows| {
76+
if (candidate.rows != rows) {
77+
return false;
78+
}
79+
}
80+
81+
if (puzzle.columns) |columns| {
82+
if (candidate.columns != columns) {
83+
return false;
84+
}
85+
}
86+
87+
if (puzzle.aspectRatio) |aspectRatio| {
88+
if (candidate.aspectRatio != aspectRatio) {
89+
return false;
90+
}
91+
}
92+
93+
if (puzzle.format) |format| {
94+
if (candidate.format != format) {
95+
return false;
96+
}
97+
}
98+
99+
return true;
100+
}
101+
102+
pub fn jigsawData(puzzle: PartialInformation) PuzzleError!FullInformation {
103+
var solution: ?FullInformation = null;
104+
105+
// sufficient for current test cases
106+
const limit: usize = 400;
107+
108+
for (2..limit) |rows| {
109+
for (2..limit) |columns| {
110+
const candidate = complete(@as(u30, @intCast(rows)), @as(u30, @intCast(columns)));
111+
112+
if (!match(candidate, puzzle)) {
113+
continue;
114+
}
115+
116+
if (solution) |_| {
117+
return PuzzleError.InsufficientData;
118+
}
119+
120+
solution = candidate;
121+
}
122+
}
123+
124+
return solution orelse PuzzleError.ContradictoryData;
125+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[ad626f23-09a2-4f5f-ba22-eec0671fa2a9]
13+
description = "1000 pieces puzzle with 1.6 aspect ratio"
14+
15+
[3e0c5919-3561-42f5-b9ed-26d70c20214e]
16+
description = "square puzzle with 32 rows"
17+
18+
[1126f160-b094-4dc2-bf37-13e36e394867]
19+
description = "400 pieces square puzzle with only inside pieces and aspect ratio"
20+
21+
[a9743178-5642-4cc0-8fdb-00d6b031c3a0]
22+
description = "1500 pieces landscape puzzle with 30 rows and 1.6 aspect ratio"
23+
24+
[f6378369-989c-497f-a6e2-f30b1fa76cba]
25+
description = "300 pieces portrait puzzle with 70 border pieces"
26+
27+
[f53f82ba-5663-4c7e-9e86-57fdbb3e53d2]
28+
description = "puzzle with insufficient data"
29+
30+
[a3d5c31a-cc74-44bf-b4fc-9e4d65f1ac1a]
31+
description = "puzzle with contradictory data"
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
pub const PuzzleError = error{
2+
InsufficientData,
3+
ContradictoryData,
4+
};
5+
6+
pub const Format = enum {
7+
portrait,
8+
square,
9+
landscape,
10+
};
11+
12+
pub const PartialInformation = struct {
13+
pieces: ?u30 = null, //
14+
border: ?u30 = null, //
15+
inside: ?u30 = null, //
16+
rows: ?u30 = null, //
17+
columns: ?u30 = null, //
18+
aspectRatio: ?f64 = null, //
19+
format: ?Format = null, //
20+
};
21+
22+
pub const FullInformation = struct {
23+
pieces: u30, //
24+
border: u30, //
25+
inside: u30, //
26+
rows: u30, //
27+
columns: u30, //
28+
aspectRatio: f64, //
29+
format: Format, //
30+
};
31+
32+
pub fn jigsawData(puzzle: PartialInformation) PuzzleError!FullInformation {
33+
_ = puzzle;
34+
@compileError("please implement the jigsawData function");
35+
}

0 commit comments

Comments
 (0)