Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C++ arrays and vectors #173

Merged
merged 13 commits into from
Jul 21, 2023
File renamed without changes.
3 changes: 3 additions & 0 deletions cpp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@
- [bob](./bob/README.md)
- [difference-of-squares](./difference-of-squares/README.md)
- [luhn](./luhn/README.md)
- [making-the-grade](./making-the-grade/README.md)
- [hexadecimal](./hexadecimal/README.md)
- [trinary](./trinary/README.md)
29 changes: 29 additions & 0 deletions cpp/hexadecimal/.exercism/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"authors": [
"LegalizeAdulthood"
],
"contributors": [
"cyborgsphinx",
"elyashiv",
"jackhughesweb",
"KevinWMatthews",
"kytrinyx",
"patricksjackson"
],
"files": {
"solution": [
"hexadecimal.cpp",
"hexadecimal.h"
],
"test": [
"hexadecimal_test.cpp"
],
"example": [
".meta/example.cpp",
".meta/example.h"
]
},
"blurb": "Convert a hexadecimal number, represented as a string (e.g. \"10af8c\"), to its decimal equivalent using first principles (i.e. no, you may not use built-in or external libraries to accomplish the conversion).",
"source": "All of Computer Science",
"source_url": "http://www.wolframalpha.com/examples/NumberBases.html"
}
1 change: 1 addition & 0 deletions cpp/hexadecimal/.exercism/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"track":"cpp","exercise":"hexadecimal","id":"4035dd8bdcfe4438afd2cb745a7bdd2f","url":"https://exercism.org/tracks/cpp/exercises/hexadecimal","handle":"vpayno","is_requester":true,"auto_approve":false}
68 changes: 68 additions & 0 deletions cpp/hexadecimal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Get the exercise name from the current directory
get_filename_component(exercise ${CMAKE_CURRENT_SOURCE_DIR} NAME)

# Basic CMake project
cmake_minimum_required(VERSION 3.5.1)

# Name the project after the exercise
project(${exercise} CXX)

# Get a source filename from the exercise name by replacing -'s with _'s
string(REPLACE "-" "_" file ${exercise})

# Implementation could be only a header
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.cpp)
set(exercise_cpp ${file}.cpp)
else()
set(exercise_cpp "")
endif()

# Use the common Catch library?
if(EXERCISM_COMMON_CATCH)
# For Exercism track development only
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.hpp
$<TARGET_OBJECTS:catchlib>)
elseif(EXERCISM_TEST_SUITE)
# The Exercism test suite is being run, the Docker image already includes a
# pre-built version of Catch.
find_package(Catch2 REQUIRED)
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.hpp)
target_link_libraries(${exercise} PRIVATE Catch2::Catch2WithMain)
# When Catch is installed system wide we need to include a different header,
# we need this define to use the correct one.
target_compile_definitions(${exercise} PRIVATE EXERCISM_TEST_SUITE)
else()
# Build executable from sources and headers
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.hpp
test/tests-main.cpp)
endif()

set_target_properties(
${exercise}
PROPERTIES CXX_STANDARD 17
CXX_STANDARD_REQUIRED OFF
CXX_EXTENSIONS OFF)

set(CMAKE_BUILD_TYPE Debug)

if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(GNU|Clang)")
set_target_properties(
${exercise} PROPERTIES COMPILE_FLAGS "-Wall -Wextra -Wpedantic -Werror")
endif()

# Configure to run all the tests?
if(${EXERCISM_RUN_ALL_TESTS})
target_compile_definitions(${exercise} PRIVATE EXERCISM_RUN_ALL_TESTS)
endif()

# Tell MSVC not to warn us about unchecked iterators in debug builds
if(${MSVC})
set_target_properties(${exercise} PROPERTIES COMPILE_DEFINITIONS_DEBUG
_SCL_SECURE_NO_WARNINGS)
endif()

# Run the tests on every build
add_custom_target(
test_${exercise} ALL
DEPENDS ${exercise}
COMMAND ${exercise})
52 changes: 52 additions & 0 deletions cpp/hexadecimal/HELP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Help

## Running the tests

Running the tests involves running `cmake -G` and then using the build command appropriate for your platform.
Detailed instructions on how to do this can be found on the [Running the Tests][cpp-tests-instructions] page for C++ on exercism.org.

## Passing the Tests

Get the first test compiling, linking and passing by following the [three rules of test-driven development][three-laws-of-tdd].
Create just enough structure by declaring namespaces, functions, classes, etc., to satisfy any compiler errors and get the test to fail.
Then write just enough code to get the test to pass.
Once you've done that, uncomment the next test by moving the following line past the next test.

```C++
#if defined(EXERCISM_RUN_ALL_TESTS)
```

This may result in compile errors as new constructs may be invoked that you haven't yet declared or defined.
Again, fix the compile errors minimally to get a failing test, then change the code minimally to pass the test, refactor your implementation for readability and expressiveness and then go on to the next test.

Try to use standard C++11 facilities in preference to writing your own low-level algorithms or facilities by hand.

[cpp-tests-instructions]: https://exercism.org/docs/tracks/cpp/tests
[three-laws-of-tdd]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd

## Submitting your solution

You can submit your solution using the `exercism submit hexadecimal.cpp hexadecimal.h` command.
This command will upload your solution to the Exercism website and print the solution page's URL.

It's possible to submit an incomplete solution which allows you to:

- See how others have completed the exercise
- Request help from a mentor

## Need to get help?

If you'd like help solving the exercise, check the following pages:

- The [C++ track's documentation](https://exercism.org/docs/tracks/cpp)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)

Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.

To get help if you're having trouble, you can use one of the following resources:

- [`c++-faq` tag on StackOverflow](https://stackoverflow.com/tags/c%2b%2b-faq/info)
- [C++ FAQ from isocpp.com](https://isocpp.org/faq)
- [CppReference](http://en.cppreference.com/) is a wiki reference to the C++ language and standard library
- [C traps and pitfalls](http://www.slideshare.net/LegalizeAdulthood/c-traps-and-pitfalls-for-c-programmers) is useful if you are new to C++, but have programmed in C
23 changes: 23 additions & 0 deletions cpp/hexadecimal/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.PHONY: clean
clean:
rm -rf ./build

.PHONY: test
test: clean
mkdir -pv ./build

@printf "\n"
@# each line is executed in a subshell, we have to daisy chain them so they
@# run in the build directory
cd ./build; export LDFLAGS="-lgcov --coverage" CXXFLAGS="--coverage"; cmake -DEXERCISM_RUN_ALL_TESTS=1 -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -G 'Unix Makefiles' ../; if make; then printf "\n=== All Tests Passed ===\n"; else printf "\n=== Test Failure ===\n"; false; fi

.PHONY: coverage
coverage: test
@printf "\n"
find . -regextype posix-egrep -regex "^.*(tests-main|CompilerId).*[.](gcda|gcno)$$" -print -delete

@printf "\n"
find . -regextype posix-egrep -regex "^.*[.](gcda|gcno)25893"

@printf "\n"
gcovr --print-summary
37 changes: 37 additions & 0 deletions cpp/hexadecimal/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Hexadecimal

Welcome to Hexadecimal on Exercism's C++ Track.
If you need help running the tests or submitting your code, check out `HELP.md`.

## Instructions

Convert a hexadecimal number, represented as a string (e.g. "10af8c"), to its decimal equivalent using first principles (i.e. no, you may not use built-in or external libraries to accomplish the conversion).

On the web we use hexadecimal to represent colors, e.g. green: 008000,
teal: 008080, navy: 000080).

The program should handle invalid hexadecimal strings.

## Source

### Created by

- @LegalizeAdulthood

### Contributed to by

- @cyborgsphinx
- @elyashiv
- @jackhughesweb
- @KevinWMatthews
- @kytrinyx
- @patricksjackson

### Based on

All of Computer Science - http://www.wolframalpha.com/examples/NumberBases.html

### My Solution

- [my solution]()
- [run-tests](./run-tests-cpp.txt)
17 changes: 17 additions & 0 deletions cpp/hexadecimal/compile_commands.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[
{
"directory": "/home/vpayno/git_vpayno/exercism-workspace/cpp/hexadecimal/build",
"command": "/usr/bin/c++ -DEXERCISM_RUN_ALL_TESTS -g -Wall -Wextra -Wpedantic -Werror -std=c++17 -o CMakeFiles/hexadecimal.dir/hexadecimal_test.cpp.o -c /home/vpayno/git_vpayno/exercism-workspace/cpp/hexadecimal/hexadecimal_test.cpp",
"file": "/home/vpayno/git_vpayno/exercism-workspace/cpp/hexadecimal/hexadecimal_test.cpp"
},
{
"directory": "/home/vpayno/git_vpayno/exercism-workspace/cpp/hexadecimal/build",
"command": "/usr/bin/c++ -DEXERCISM_RUN_ALL_TESTS -g -Wall -Wextra -Wpedantic -Werror -std=c++17 -o CMakeFiles/hexadecimal.dir/hexadecimal.cpp.o -c /home/vpayno/git_vpayno/exercism-workspace/cpp/hexadecimal/hexadecimal.cpp",
"file": "/home/vpayno/git_vpayno/exercism-workspace/cpp/hexadecimal/hexadecimal.cpp"
},
{
"directory": "/home/vpayno/git_vpayno/exercism-workspace/cpp/hexadecimal/build",
"command": "/usr/bin/c++ -DEXERCISM_RUN_ALL_TESTS -g -Wall -Wextra -Wpedantic -Werror -std=c++17 -o CMakeFiles/hexadecimal.dir/test/tests-main.cpp.o -c /home/vpayno/git_vpayno/exercism-workspace/cpp/hexadecimal/test/tests-main.cpp",
"file": "/home/vpayno/git_vpayno/exercism-workspace/cpp/hexadecimal/test/tests-main.cpp"
}
]
8 changes: 8 additions & 0 deletions cpp/hexadecimal/compile_flags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-std=c++17
-stdlib=libstdc++
-g
-Wall
-Wextra
-Wpedantic
-Werror
-Wno-unused-parameter
47 changes: 47 additions & 0 deletions cpp/hexadecimal/hexadecimal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "hexadecimal.hpp"

namespace hexadecimal {

/* To convert a hexadecimal to a decimal manually,
* you must start by multiplying the hex number by 16.
*
* Then, you raise it to a power of 0 and
* increase that power by 1 each time according to the hexadecimal number
* equivalent.
*
* We start from the right of the hexadecimal number and
* go to the left when applying the powers.
*
* Each time you multiply a number by 16, the power of 16 increases.
*/
int convert(const std::string hexadecimal) {
if (!is_valid_input(hexadecimal)) {
return 0;
}

int exp{0};

auto h2d_op = [exp](int sum, char rune) mutable -> int {
const char digit = (char)std::tolower(rune);

// we already know the input string is valid so we can keep it simple
if ((bool)std::isdigit(digit)) {
sum += (digit - '0') * (int)std::pow(16, exp++);
} else {
sum += (digit - 'W') * (int)std::pow(16, exp++);
}

return sum;
};

return std::accumulate(hexadecimal.rbegin(), hexadecimal.rend(), 0, h2d_op);
}

// input must only contain [0-9a-f]
bool is_valid_input(const std::string hexadecimal) {
const std::regex re_hex_num("^[a-fA-F0-9]+$", std::regex_constants::egrep);

return std::regex_search(hexadecimal, re_hex_num);
}

} // namespace hexadecimal
17 changes: 17 additions & 0 deletions cpp/hexadecimal/hexadecimal.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#if !defined(HEXADECIMAL_HPP)
#define HEXADECIMAL_HPP

#include <cmath>
#include <numeric>
#include <regex>
#include <string>

namespace hexadecimal {

int convert(std::string hexadecimal);

bool is_valid_input(std::string hexadecimal);

} // namespace hexadecimal

#endif // HEXADECIMAL_HPP
14 changes: 14 additions & 0 deletions cpp/hexadecimal/hexadecimal.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>clang_version</key>
<string>Debian clang version 16.0.6 (++20230610113348+7cbf1a259152-1~exp1~20230610233446.99)</string>
<key>diagnostics</key>
<array>
</array>
<key>files</key>
<array>
</array>
</dict>
</plist>
38 changes: 38 additions & 0 deletions cpp/hexadecimal/hexadecimal_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "hexadecimal.hpp"
#ifdef EXERCISM_TEST_SUITE
#include <catch2/catch.hpp>
#else
#include "test/catch.hpp"
#endif

TEST_CASE("hex_1_is_decimal_1") { REQUIRE(0x1 == hexadecimal::convert("1")); }

#if defined(EXERCISM_RUN_ALL_TESTS)
TEST_CASE("hex_c_is_decimal_12") { REQUIRE(0xc == hexadecimal::convert("c")); }

TEST_CASE("hex_10_is_decimal_16") {
REQUIRE(0x10 == hexadecimal::convert("10"));
}

TEST_CASE("hex_af_is_decimal_175") {
REQUIRE(0xaf == hexadecimal::convert("af"));
}

TEST_CASE("hex_100_is_decimal_256") {
REQUIRE(0x100 == hexadecimal::convert("100"));
}

TEST_CASE("hex_19ace_is_decimal_105166") {
REQUIRE(0x19ace == hexadecimal::convert("19ace"));
}

TEST_CASE("invalid_hex_is_decimal_0") {
REQUIRE(0 == hexadecimal::convert("carrot"));
}

TEST_CASE("black") { REQUIRE(0x000000 == hexadecimal::convert("000000")); }

TEST_CASE("white") { REQUIRE(0xffffff == hexadecimal::convert("ffffff")); }

TEST_CASE("yellow") { REQUIRE(0xffff00 == hexadecimal::convert("ffff00")); }
#endif
14 changes: 14 additions & 0 deletions cpp/hexadecimal/hexadecimal_test.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>clang_version</key>
<string>Debian clang version 16.0.6 (++20230610113348+7cbf1a259152-1~exp1~20230610233446.99)</string>
<key>diagnostics</key>
<array>
</array>
<key>files</key>
<array>
</array>
</dict>
</plist>
Loading