Skip to content

Commit 36c7160

Browse files
authored
Merge branch 'main' into exercise/affine-cipher
2 parents ddfce4e + d126427 commit 36c7160

File tree

184 files changed

+18715
-706
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

184 files changed

+18715
-706
lines changed

bin/make-stub-files.sh

+1-3
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,8 @@ for exercise_dir in "${exercises_dir}"/*; do
2121
header="$exercise_name.h"
2222
source="$exercise_name.cpp"
2323
if ! test -f "$header"; then
24-
printf "#if !defined(${exercise_name^^}_H)\n" >> $header
25-
printf "#define ${exercise_name^^}_H\n" >> $header
24+
printf "#pragma once\n" >> $header
2625
printf "\nnamespace $exercise_name {\n\n} // namespace $exercise_name\n" >> $header
27-
printf "\n#endif // ${exercise_name^^}_H" >> $header
2826
git add $header
2927
fi
3028
if ! test -f "$source"; then

config.json

+18
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,24 @@
12601260
"booleans"
12611261
],
12621262
"difficulty": 6
1263+
},
1264+
{
1265+
"slug": "alphametics",
1266+
"name": "Alphametics",
1267+
"uuid": "0c69f8bd-c99a-4cb2-b113-82deaf0915ee",
1268+
"practices": [
1269+
"auto",
1270+
"literals"
1271+
],
1272+
"prerequisites": [
1273+
"includes",
1274+
"namespaces",
1275+
"if-statements",
1276+
"booleans",
1277+
"headers",
1278+
"comparisons"
1279+
],
1280+
"difficulty": 6
12631281
}
12641282
],
12651283
"foregone": [
+1-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#if !defined(ACRONYM_H)
2-
#define ACRONYM_H
1+
#pragma once
32

43
#include <string>
54

@@ -8,5 +7,3 @@ namespace acronym {
87
std::string acronym(std::string const&);
98

109
}
11-
12-
#endif

exercises/practice/acronym/acronym.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
#if !defined(ACRONYM_H)
2-
#define ACRONYM_H
1+
#pragma once
32

43
namespace acronym {
54

65
// TODO: add your solution here
76

87
} // namespace acronym
9-
10-
#endif // ACRONYM_H
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#if !defined(ALL_YOUR_BASE_H)
2-
#define ALL_YOUR_BASE_H
1+
#pragma once
32

43
#include <vector>
54

@@ -9,5 +8,3 @@ std::vector<unsigned int> convert(unsigned int input_base,
98
const std::vector<unsigned int>& input_digits,
109
unsigned int output_base);
1110
}
12-
13-
#endif
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
#if !defined(ALL_YOUR_BASE_H)
2-
#define ALL_YOUR_BASE_H
1+
#pragma once
32

43
namespace all_your_base {
54

65
// TODO: add your solution here
76

87
} // namespace all_your_base
9-
10-
#endif // ALL_YOUR_BASE_H

exercises/practice/allergies/.meta/example.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#if !defined(ALLERGIES_H)
2-
#define ALLERGIES_H
1+
#pragma once
32

43
#include <map>
54
#include <string>
@@ -23,5 +22,3 @@ class allergy_test {
2322
};
2423

2524
} // namespace allergies
26-
27-
#endif
+1-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
#if !defined(ALLERGIES_H)
2-
#define ALLERGIES_H
1+
#pragma once
32

43
namespace allergies {
54

65
// TODO: add your solution here
76

87
} // namespace allergies
9-
10-
#endif // ALLERGIES_H
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Instructions
2+
3+
Given an alphametics puzzle, find the correct solution.
4+
5+
[Alphametics][alphametics] is a puzzle where letters in words are replaced with numbers.
6+
7+
For example `SEND + MORE = MONEY`:
8+
9+
```text
10+
S E N D
11+
M O R E +
12+
-----------
13+
M O N E Y
14+
```
15+
16+
Replacing these with valid numbers gives:
17+
18+
```text
19+
9 5 6 7
20+
1 0 8 5 +
21+
-----------
22+
1 0 6 5 2
23+
```
24+
25+
This is correct because every letter is replaced by a different number and the words, translated into numbers, then make a valid sum.
26+
27+
Each letter must represent a different digit, and the leading digit of a multi-digit number must not be zero.
28+
29+
[alphametics]: https://en.wikipedia.org/wiki/Alphametics
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"marcelweikum"
4+
],
5+
"files": {
6+
"solution": [
7+
"alphametics.cpp",
8+
"alphametics.h"
9+
],
10+
"test": [
11+
"alphametics_test.cpp"
12+
],
13+
"example": [
14+
".meta/example.cpp",
15+
".meta/example.h"
16+
]
17+
},
18+
"blurb": "Given an alphametics puzzle, find the correct solution."
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#include <algorithm>
2+
#include <functional>
3+
#include <map>
4+
#include <optional>
5+
#include <sstream>
6+
#include <string>
7+
#include <unordered_set>
8+
#include <vector>
9+
10+
#include "alphametics.h"
11+
12+
namespace alphametics {
13+
14+
std::optional<std::map<char, int>> solve(const std::string& puzzle) {
15+
auto sep = puzzle.find("==");
16+
if (sep == std::string::npos) return std::nullopt;
17+
std::string left = puzzle.substr(0, sep);
18+
std::string right = puzzle.substr(sep + 2);
19+
20+
auto trim = [&](std::string& s) {
21+
auto b = s.find_first_not_of(' ');
22+
auto e = s.find_last_not_of(' ');
23+
s = (b == std::string::npos) ? std::string() : s.substr(b, e - b + 1);
24+
};
25+
trim(left);
26+
trim(right);
27+
28+
std::vector<std::string> addends;
29+
std::istringstream iss(left);
30+
for (std::string part; std::getline(iss, part, '+');) {
31+
trim(part);
32+
addends.push_back(part);
33+
}
34+
trim(right);
35+
std::string result = right;
36+
37+
std::vector<char> letters;
38+
std::unordered_set<char> seen, leading;
39+
auto collect = [&](const std::string& w) {
40+
if (w.size() > 1) leading.insert(w.front());
41+
for (char c : w) {
42+
if (seen.insert(c).second) letters.push_back(c);
43+
}
44+
};
45+
for (auto& w : addends) collect(w);
46+
collect(result);
47+
if (letters.size() > 10) return std::nullopt;
48+
49+
int n = letters.size();
50+
std::map<char, int> idx;
51+
for (int i = 0; i < n; ++i) idx[letters[i]] = i;
52+
std::vector<long long> weight(n, 0);
53+
54+
for (auto& w : addends) {
55+
long long mult = 1;
56+
for (int i = (int)w.size() - 1; i >= 0; --i) {
57+
weight[idx[w[i]]] += mult;
58+
mult *= 10;
59+
}
60+
}
61+
{
62+
long long mult = 1;
63+
for (int i = (int)result.size() - 1; i >= 0; --i) {
64+
weight[idx[result[i]]] -= mult;
65+
mult *= 10;
66+
}
67+
}
68+
69+
std::vector<bool> used(10, false);
70+
std::map<char, int> assign;
71+
bool found = false;
72+
std::map<char, int> solution;
73+
std::function<void(int, long long)> dfs = [&](int pos, long long sum) {
74+
if (found) return;
75+
if (pos == n) {
76+
if (sum == 0) {
77+
found = true;
78+
solution = assign;
79+
}
80+
return;
81+
}
82+
char c = letters[pos];
83+
for (int d = 0; d < 10 && !found; ++d) {
84+
if (used[d] || (d == 0 && leading.count(c))) continue;
85+
used[d] = true;
86+
assign[c] = d;
87+
dfs(pos + 1, sum + weight[pos] * d);
88+
used[d] = false;
89+
}
90+
};
91+
92+
dfs(0, 0);
93+
if (found) return solution;
94+
return std::nullopt;
95+
}
96+
97+
} // namespace alphametics
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
3+
#include <map>
4+
#include <optional>
5+
#include <string>
6+
7+
namespace alphametics {
8+
9+
std::optional<std::map<char, int>> solve(const std::string& puzzle);
10+
11+
} // namespace alphametics
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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+
[e0c08b07-9028-4d5f-91e1-d178fead8e1a]
13+
description = "puzzle with three letters"
14+
15+
[a504ee41-cb92-4ec2-9f11-c37e95ab3f25]
16+
description = "solution must have unique value for each letter"
17+
18+
[4e3b81d2-be7b-4c5c-9a80-cd72bc6d465a]
19+
description = "leading zero solution is invalid"
20+
21+
[8a3e3168-d1ee-4df7-94c7-b9c54845ac3a]
22+
description = "puzzle with two digits final carry"
23+
24+
[a9630645-15bd-48b6-a61e-d85c4021cc09]
25+
description = "puzzle with four letters"
26+
27+
[3d905a86-5a52-4e4e-bf80-8951535791bd]
28+
description = "puzzle with six letters"
29+
30+
[4febca56-e7b7-4789-97b9-530d09ba95f0]
31+
description = "puzzle with seven letters"
32+
33+
[12125a75-7284-4f9a-a5fa-191471e0d44f]
34+
description = "puzzle with eight letters"
35+
36+
[fb05955f-38dc-477a-a0b6-5ef78969fffa]
37+
description = "puzzle with ten letters"
38+
39+
[9a101e81-9216-472b-b458-b513a7adacf7]
40+
description = "puzzle with ten letters and 199 addends"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Get the exercise name from the current directory
2+
get_filename_component(exercise ${CMAKE_CURRENT_SOURCE_DIR} NAME)
3+
4+
# Basic CMake project
5+
cmake_minimum_required(VERSION 3.5.1)
6+
7+
# Name the project after the exercise
8+
project(${exercise} CXX)
9+
10+
# Get a source filename from the exercise name by replacing -'s with _'s
11+
string(REPLACE "-" "_" file ${exercise})
12+
13+
# Implementation could be only a header
14+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.cpp)
15+
set(exercise_cpp ${file}.cpp)
16+
else()
17+
set(exercise_cpp "")
18+
endif()
19+
20+
# Use the common Catch library?
21+
if(EXERCISM_COMMON_CATCH)
22+
# For Exercism track development only
23+
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h $<TARGET_OBJECTS:catchlib>)
24+
elseif(EXERCISM_TEST_SUITE)
25+
# The Exercism test suite is being run, the Docker image already
26+
# includes a pre-built version of Catch.
27+
find_package(Catch2 REQUIRED)
28+
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h)
29+
target_link_libraries(${exercise} PRIVATE Catch2::Catch2WithMain)
30+
# When Catch is installed system wide we need to include a different
31+
# header, we need this define to use the correct one.
32+
target_compile_definitions(${exercise} PRIVATE EXERCISM_TEST_SUITE)
33+
else()
34+
# Build executable from sources and headers
35+
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h test/tests-main.cpp)
36+
endif()
37+
38+
set_target_properties(${exercise} PROPERTIES
39+
CXX_STANDARD 17
40+
CXX_STANDARD_REQUIRED OFF
41+
CXX_EXTENSIONS OFF
42+
)
43+
44+
set(CMAKE_BUILD_TYPE Debug)
45+
46+
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(GNU|Clang)")
47+
set_target_properties(${exercise} PROPERTIES
48+
COMPILE_FLAGS "-Wall -Wextra -Wpedantic -Werror"
49+
)
50+
endif()
51+
52+
# Configure to run all the tests?
53+
if(${EXERCISM_RUN_ALL_TESTS})
54+
target_compile_definitions(${exercise} PRIVATE EXERCISM_RUN_ALL_TESTS)
55+
endif()
56+
57+
# Tell MSVC not to warn us about unchecked iterators in debug builds
58+
# Treat warnings as errors
59+
# Treat type conversion warnings C4244 and C4267 as level 4 warnings, i.e. ignore them in level 3
60+
if(${MSVC})
61+
set_target_properties(${exercise} PROPERTIES
62+
COMPILE_DEFINITIONS_DEBUG _SCL_SECURE_NO_WARNINGS
63+
COMPILE_FLAGS "/WX /w44244 /w44267")
64+
endif()
65+
66+
# Run the tests on every build
67+
add_custom_target(test_${exercise} ALL DEPENDS ${exercise} COMMAND ${exercise})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include "alphametics.h"
2+
3+
namespace alphametics {
4+
5+
// TODO: add your solution here
6+
7+
} // namespace alphametics

0 commit comments

Comments
 (0)