Skip to content

Commit

Permalink
complete luhn
Browse files Browse the repository at this point in the history
  • Loading branch information
koheiyamayama committed May 29, 2022
1 parent e84eea7 commit cc364ee
Show file tree
Hide file tree
Showing 8 changed files with 337 additions and 0 deletions.
37 changes: 37 additions & 0 deletions luhn/.exercism/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"blurb": "Given a number determine whether or not it is valid per the Luhn formula.",
"authors": [
"soniakeys"
],
"contributors": [
"alebaffa",
"bitfield",
"da-edra",
"ekingery",
"ferhatelmas",
"hilary",
"kytrinyx",
"leenipper",
"michaelorr",
"petertseng",
"robphoenix",
"sebito91",
"tehsphinx"
],
"files": {
"solution": [
"luhn.go"
],
"test": [
"luhn_test.go"
],
"example": [
".meta/example.go"
],
"editor": [
"cases_test.go"
]
},
"source": "The Luhn Algorithm on Wikipedia",
"source_url": "http://en.wikipedia.org/wiki/Luhn_algorithm"
}
1 change: 1 addition & 0 deletions luhn/.exercism/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"track":"go","exercise":"luhn","id":"7bbeac9d18bd4ddea3f7e1ed4cc1f5a5","url":"https://exercism.org/tracks/go/exercises/luhn","handle":"koheiyamayama","is_requester":true,"auto_approve":false}
40 changes: 40 additions & 0 deletions luhn/HELP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Help

## Running the tests

To run the tests run the command `go test` from within the exercise directory.

If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:

go test -v --bench . --benchmem

Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.

## Submitting your solution

You can submit your solution using the `exercism submit luhn.go` 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 [Go track's documentation](https://exercism.org/docs/tracks/go)
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
- 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:

- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
95 changes: 95 additions & 0 deletions luhn/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Luhn

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

## Instructions

Given a number determine whether or not it is valid per the Luhn formula.

The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is
a simple checksum formula used to validate a variety of identification
numbers, such as credit card numbers and Canadian Social Insurance
Numbers.

The task is to check if a given string is valid.

## Validating a Number

Strings of length 1 or less are not valid. Spaces are allowed in the input,
but they should be stripped before checking. All other non-digit characters
are disallowed.

### Example 1: valid credit card number

```text
4539 3195 0343 6467
```

The first step of the Luhn algorithm is to double every second digit,
starting from the right. We will be doubling

```text
4_3_ 3_9_ 0_4_ 6_6_
```

If doubling the number results in a number greater than 9 then subtract 9
from the product. The results of our doubling:

```text
8569 6195 0383 3437
```

Then sum all of the digits:

```text
8+5+6+9+6+1+9+5+0+3+8+3+3+4+3+7 = 80
```

If the sum is evenly divisible by 10, then the number is valid. This number is valid!

### Example 2: invalid credit card number

```text
8273 1232 7352 0569
```

Double the second digits, starting from the right

```text
7253 2262 5312 0539
```

Sum the digits

```text
7+2+5+3+2+2+6+2+5+3+1+2+0+5+3+9 = 57
```

57 is not evenly divisible by 10, so this number is not valid.

## Source

### Created by

- @soniakeys

### Contributed to by

- @alebaffa
- @bitfield
- @da-edra
- @ekingery
- @ferhatelmas
- @hilary
- @kytrinyx
- @leenipper
- @michaelorr
- @petertseng
- @robphoenix
- @sebito91
- @tehsphinx

### Based on

The Luhn Algorithm on Wikipedia - http://en.wikipedia.org/wiki/Luhn_algorithm
102 changes: 102 additions & 0 deletions luhn/cases_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package luhn

// Source: exercism/problem-specifications
// Commit: f375a46 luhn: Update non-ASCII test case
// Problem Specifications Version: 1.6.1

var testCases = []struct {
description string
input string
ok bool
}{
{
"single digit strings can not be valid",
"1",
false,
},
{
"a single zero is invalid",
"0",
false,
},
{
"a simple valid SIN that remains valid if reversed",
"059",
true,
},
{
"a simple valid SIN that becomes invalid if reversed",
"59",
true,
},
{
"a valid Canadian SIN",
"055 444 285",
true,
},
{
"invalid Canadian SIN",
"055 444 286",
false,
},
{
"invalid credit card",
"8273 1232 7352 0569",
false,
},
{
"valid number with an even number of digits",
"095 245 88",
true,
},
{
"valid number with an odd number of spaces",
"234 567 891 234",
true,
},
{
"valid strings with a non-digit added at the end become invalid",
"059a",
false,
},
{
"valid strings with punctuation included become invalid",
"055-444-285",
false,
},
{
"valid strings with symbols included become invalid",
"055# 444$ 285",
false,
},
{
"single zero with space is invalid",
" 0",
false,
},
{
"more than a single zero is valid",
"0000 0",
true,
},
{
"input digit 9 is correctly converted to output digit 9",
"091",
true,
},
{
"valid number with an odd number of digits and non-zero first digit",
"109",
true,
},
{
"using ascii value for non-doubled non-digit isn't allowed",
"055b 444 285",
false,
},
{
"using ascii value for doubled non-digit isn't allowed",
":9",
false,
},
}
3 changes: 3 additions & 0 deletions luhn/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module luhn

go 1.16
39 changes: 39 additions & 0 deletions luhn/luhn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package luhn

import (
"strconv"
"strings"
)

func Valid(id string) bool {
id = strings.ReplaceAll(id, " ", "")

if len(id) <= 1 {
return false
}

ids := strings.Split(id, "")
sum := 0

for i := 1; i <= len(ids); i++ {
n, e := strconv.Atoi(ids[len(ids)-i])

if e != nil {
return false
}

if i%2 == 0 {
n *= 2

if 9 < n {
sum += n - 9
} else {
sum += n
}
} else {
sum += n
}
}

return sum%10 == 0
}
20 changes: 20 additions & 0 deletions luhn/luhn_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package luhn

import "testing"

func TestValid(t *testing.T) {
for _, test := range testCases {
if ok := Valid(test.input); ok != test.ok {
t.Fatalf("Valid(%s): %s\n\t Expected: %t\n\t Got: %t", test.input, test.description, test.ok, ok)
}
}
}

func BenchmarkValid(b *testing.B) {
if testing.Short() {
b.Skip("skipping benchmark in short mode.")
}
for i := 0; i < b.N; i++ {
Valid("2323 2005 7766 3554")
}
}

0 comments on commit cc364ee

Please sign in to comment.