# artemkorsakov's solution

## to Luhn in the Go Track

Published at Mar 05 2019 · 0 comments
Instructions
Test suite
Solution

#### Note:

This exercise has changed since this solution was written.

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

The 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

``````4539 1488 0343 6467
``````

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

``````4_3_ 1_8_ 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:

``````8569 2478 0383 3437
``````

Then sum all of the digits:

``````8+5+6+9+2+4+7+8+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

``````8273 1232 7352 0569
``````

Double the second digits, starting from the right

``````7253 2262 5312 0539
``````

Sum the digits

``````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.

## 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.

## Further information

For more detailed information about the Go track, including how to get help if you're having trouble, please visit the exercism.io Go language page.

## Source

The Luhn Algorithm on Wikipedia http://en.wikipedia.org/wiki/Luhn_algorithm

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### cases_test.go

``````package luhn

// Source: exercism/problem-specifications
// Commit: 4a80663 luhn: non-digit at end is invalid
// Problem Specifications Version: 1.4.0

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,
},
{
"055 444 285",
true,
},
{
"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 strings with a non-digit included become invalid",
"055a 444 285",
false,
},
{
"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,
},
{
"strings with non-digits is invalid",
":9",
false,
},
}``````

### luhn_test.go

``````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) {
for i := 0; i < b.N; i++ {
Valid("2323 2005 7766 3554")
}
}``````
``````package luhn

// Valid determines whether or not given a number is valid per the Luhn formula.
func Valid(input string) bool {
index := 1
luhnSum := 0
for i := len(input) - 1; i >= 0; i-- {
c := input[i]
if c == ' ' {
continue
}

if c < '0' || c > '9' {
return false
}

num := int(c) - '0'
if index%2 == 0 {
num *= 2
if num > 9 {
num -= 9
}
}
luhnSum += num
index++
}

return index > 2 && luhnSum%10 == 0
}``````