Skip to content

Commit 7cb535b

Browse files
committed
add exercise luhn
1 parent 8d0ac20 commit 7cb535b

File tree

7 files changed

+382
-0
lines changed

7 files changed

+382
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ foreach(exercise
6868
isogram
6969
reverse-string
7070
acronym
71+
luhn
7172
)
7273
travis_fixup(${exercise} ${alt_exercise_tree})
7374
add_subdirectory(${alt_exercise_tree}/${exercise})

config.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,16 @@
531531
"loops",
532532
"mathematics"
533533
]
534+
},
535+
{
536+
"slug": "luhn",
537+
"uuid": "885865bc-a197-436f-94bc-b1998d5cc081",
538+
"core": false,
539+
"unlocked_by": null,
540+
"difficulty": 1,
541+
"topics": [
542+
"strings"
543+
]
534544
}
535545
]
536546
}

exercises/luhn/CMakeLists.txt

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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.1.3)
6+
7+
# Name the project after the exercise
8+
project(${exercise} CXX)
9+
10+
# Locate Boost libraries: unit_test_framework and date_time
11+
set(Boost_USE_STATIC_LIBS ON)
12+
set(Boost_USE_MULTITHREADED ON)
13+
set(Boost_USE_STATIC_RUNTIME OFF)
14+
find_package(Boost 1.59 REQUIRED COMPONENTS unit_test_framework date_time)
15+
16+
# Get a source filename from the exercise name by replacing -'s with _'s
17+
string(REPLACE "-" "_" file ${exercise})
18+
19+
# Implementation could be only a header
20+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.cpp)
21+
set(exercise_cpp ${file}.cpp)
22+
else()
23+
set(exercise_cpp "")
24+
endif()
25+
26+
# Build executable from sources and headers
27+
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h)
28+
29+
set_target_properties(${exercise} PROPERTIES
30+
CXX_STANDARD 11
31+
CXX_STANDARD_REQUIRED OFF
32+
CXX_EXTENSIONS OFF
33+
)
34+
35+
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(GNU|Clang)")
36+
set_target_properties(${exercise} PROPERTIES
37+
COMPILE_FLAGS "-Wall -Wextra -Wpedantic -Werror"
38+
)
39+
endif()
40+
41+
# We need boost libraries
42+
target_link_libraries(${exercise}
43+
PRIVATE
44+
Boost::unit_test_framework
45+
Boost::date_time
46+
)
47+
48+
# Configure to run all the tests?
49+
if(${EXERCISM_RUN_ALL_TESTS})
50+
target_compile_definitions(${exercise} PRIVATE EXERCISM_RUN_ALL_TESTS)
51+
endif()
52+
53+
# Tell MSVC not to warn us about unchecked iterators in debug builds
54+
if(${MSVC})
55+
set_target_properties(${exercise} PROPERTIES
56+
COMPILE_DEFINITIONS_DEBUG _SCL_SECURE_NO_WARNINGS)
57+
endif()
58+
59+
# Run the tests on every build
60+
add_custom_target(test_${exercise} ALL DEPENDS ${exercise} COMMAND ${exercise})

exercises/luhn/README.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Luhn
2+
3+
Given a number determine whether or not it is valid per the Luhn formula.
4+
5+
The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is
6+
a simple checksum formula used to validate a variety of identification
7+
numbers, such as credit card numbers and Canadian Social Insurance
8+
Numbers.
9+
10+
The task is to check if a given string is valid.
11+
12+
Validating a Number
13+
------
14+
15+
Strings of length 1 or less are not valid. Spaces are allowed in the input,
16+
but they should be stripped before checking. All other non-digit characters
17+
are disallowed.
18+
19+
## Example 1: valid credit card number
20+
21+
```text
22+
4539 1488 0343 6467
23+
```
24+
25+
The first step of the Luhn algorithm is to double every second digit,
26+
starting from the right. We will be doubling
27+
28+
```text
29+
4_3_ 1_8_ 0_4_ 6_6_
30+
```
31+
32+
If doubling the number results in a number greater than 9 then subtract 9
33+
from the product. The results of our doubling:
34+
35+
```text
36+
8569 2478 0383 3437
37+
```
38+
39+
Then sum all of the digits:
40+
41+
```text
42+
8+5+6+9+2+4+7+8+0+3+8+3+3+4+3+7 = 80
43+
```
44+
45+
If the sum is evenly divisible by 10, then the number is valid. This number is valid!
46+
47+
## Example 2: invalid credit card number
48+
49+
```text
50+
8273 1232 7352 0569
51+
```
52+
53+
Double the second digits, starting from the right
54+
55+
```text
56+
7253 2262 5312 0539
57+
```
58+
59+
Sum the digits
60+
61+
```text
62+
7+2+5+3+2+2+6+2+5+3+1+2+0+5+3+9 = 57
63+
```
64+
65+
57 is not evenly divisible by 10, so this number is not valid.
66+
67+
## Getting Started
68+
69+
Make sure you have read the [Installing](https://exercism.io/tracks/cpp/installation) and
70+
[Running the Tests](https://exercism.io/tracks/cpp/tests) pages for C++ on exercism.io.
71+
This covers the basic information on setting up the development
72+
environment expected by the exercises.
73+
74+
## Passing the Tests
75+
76+
Get the first test compiling, linking and passing by following the [three
77+
rules of test-driven development](http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd).
78+
Create just enough structure by declaring namespaces, functions, classes,
79+
etc., to satisfy any compiler errors and get the test to fail. Then write
80+
just enough code to get the test to pass. Once you've done that,
81+
uncomment the next test by moving the following line past the next test.
82+
83+
```C++
84+
#if defined(EXERCISM_RUN_ALL_TESTS)
85+
```
86+
87+
This may result in compile errors as new constructs may be invoked that
88+
you haven't yet declared or defined. Again, fix the compile errors minimally
89+
to get a failing test, then change the code minimally to pass the test,
90+
refactor your implementation for readability and expressiveness and then
91+
go on to the next test.
92+
93+
Try to use standard C++11 facilities in preference to writing your own
94+
low-level algorithms or facilities by hand. [CppReference](http://en.cppreference.com/)
95+
is a wiki reference to the C++ language and standard library. If you
96+
are new to C++, but have programmed in C, beware of
97+
[C traps and pitfalls](http://www.slideshare.net/LegalizeAdulthood/c-traps-and-pitfalls-for-c-programmers).
98+
99+
## Source
100+
101+
The Luhn Algorithm on Wikipedia [http://en.wikipedia.org/wiki/Luhn_algorithm](http://en.wikipedia.org/wiki/Luhn_algorithm)
102+
103+
## Submitting Incomplete Solutions
104+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

exercises/luhn/example.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include "luhn.h"
2+
3+
using namespace std;
4+
5+
namespace luhn{
6+
7+
bool valid(std::string const& input_str)
8+
{
9+
10+
string reversed;
11+
reversed.assign(input_str.rbegin(),input_str.rend());
12+
reversed.erase(0,reversed.find_first_not_of(" "));
13+
reversed.erase(reversed.find_last_not_of(" ") + 1);
14+
15+
if(reversed.size()<=1){
16+
return false;
17+
}
18+
19+
int result = 0;
20+
int counter=0;
21+
for(auto c:reversed)
22+
{
23+
if(c==' ')
24+
{
25+
continue;
26+
} else if(isdigit(c)) {
27+
int digit = (int)c-48;
28+
29+
if(counter%2==1){
30+
result=digit*2>9?result+digit*2-9:result+digit*2;
31+
}else{
32+
result=result+digit;
33+
}
34+
counter++;
35+
} else {
36+
return false;
37+
}
38+
}
39+
return result % 10 == 0;
40+
41+
}
42+
43+
44+
} // namespace luhn

exercises/luhn/example.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#if !defined(LUHN_H)
2+
#define LUHN_H
3+
4+
#include <string>
5+
6+
namespace luhn{
7+
8+
bool valid(std::string const&);
9+
10+
}
11+
#endif // LUHN_H

0 commit comments

Comments
 (0)