## DEV Community 👩‍💻👨‍💻

Kevin Mungai

Posted on • Updated on

# caveat

This programming challenge is found at

http://neo.cellulant.com:3000/sw_internship.html

or

and it will be presented as is:

# the challenge

Cellulant has implemented a custom, card number verification system to ensure detection and blocking of fake cards. A scratch card consists of 4 sets of 5 digits (20 digits in total) e.g. [10006-12342-00081-99993] which are printed separated by a space or a dash.

Each set of 5 digits consists of two parts, the first 4 digits (the number) and a 5th digit (the checksum) The formula dictates that each of the sets must be validated as follows: The first 4 digits, e.g 1234, as decimal numbers be converted into an octal number (base 8) i.e. 23228. This octal number is then processed to generate the checksum, as follows:

1. Add all digits to each other to get a new number “X”
2. If “X” is more than 1 digit, repeat step (1) until you have a single digit. “Y”
3. Append “Y” to the end of the original decimal number e.g. 1234 2

#### For Example:

Given the set “10006”

Convert 1000 to octal =>1750>
1+7+5+0=15
1+5=68
Valid number is 10006 so;
return (TRUE)

Given the set “99998”

Convert 9999 to octal => 23417
2+3+4+1+7=21
2+1=3
Valid number is 99993 so;
return (FALSE)

Create a Java, Java-Script or PHP script with the function that will receive a string value (scratch card number) and return boolean TRUE or FALSE, on whether the card number is valid, as shown below

You should use as many other functions as you deem necessary within your code.

# really neat solution

This solution was contributed by Filipe Ramalho

1. We get the modulo operation of first-four with 7
2. Then we subtract the result from the checksum
3. Next we get the modulo operation of the result above with 7
4. Then we check if it is equal to 0

Better explained by Filipe Ramalho:

For 9999|8

1. 9999 % 7 = 3 //First you modulo through 7
2. 8 - 3 = 5 //Then you subtract the result from the checksum.
3. 5 % 7 = 5 //Then you modulo that through 7.

The end result isn't 0, so the digit isn't valid

``````(defn is-valid?
[number]
(let [first-four (quot number 10)
check-sum (rem number 10)]
(-> first-four
(mod 7)
(- check-sum)
(mod 7)
(= 0))))

user> (is-valid-modified? 10006)
true
user> (is-valid-modified? 99993)
true
user> (is-valid-modified? 99998)
false
user> (is-valid-modified? 12342)
true
user> (is-valid-modified? 11697)
true

``````
``````(defn validate-scratch-card [card-number]
(let [f (comp is-valid? #(Integer/parseInt %))]
(->> (string/split card-number #"(-|\s)")
(map f)
(every? true?))))

user> (validate-scratch-card "10006 12342 00081 99998")
false
user> (validate-scratch-card "10006 12342 00081 99993")
true

``````

It is an elegant solution.

# the old solution

Instead of using any of the proposed languages above, I shall use Clojure.

`validate-scratch-card` is a function which takes a string which may look like:

1. "`10006-12342-00081-99993`"
2. "`10006 12342 00081 99993`"

It would be nice to split the argument based on the presence of a space or a hyphen so that I could work on each substring:

``````;; has hyphen
user> (clojure.string/split "10006-12342-00081-99993" #("-|\s)")
;; ["10006" "12342" "00081" "99993"]

;; has spaces
user> (clojure.string/split "10006 12342 00081 99993" #"(-|\s)")
;; ["10006" "12342" "00081" "99993"]
``````

Next item on the agenda is to parse each individual substring to `Integer` via the Java method `Integer/parseInt`.

``````user> (Integer/parseInt "10006")
;; 10006
``````

`map` can be used to parse each individual substring

``````user> (map #(Integer/parseInt %) "10006 12342 00081 99993")
;; 10006
``````

Each Integer can be checked for validity based on the rules above.
Each Integer has 2 parts:

1. first four digits (the number)
2. the fifth digit (the checksum)
``````user> (quot 10006 10)
;; 1000   first four digits (the number)

user> (rem 10006 10)
;; 6   fifth digit (checksum)
``````

Next is to convert the first four digits to octal.

This will be achieved by creating a base converter

``````(defn- to-digits [number base]
(loop [n number
digits '()]
(if (pos? n)
(recur (quot n base)
(conj digits (mod n base)))
digits)))

(defn to-octal [number]
"returns a list of octal numbers"
(to-digits number 8))
``````
``````user> (to-octal 1000)
;; (1 7 5 0)
``````

Subsequent step is to sum up each of the generated numbers.

But before that, a function that takes two octal numbers and sums them up is needed.

``````(defn add-two-octal [x y]
(let [a (Integer/parseInt (str x) 8)
b (Integer/parseInt (str y) 8)]
(-> (+ a b)
Integer/toOctalString
Integer/parseInt)))
``````
``````user> (add-two-octal 3 6)
;; 11
``````

This `add-two-octal` function can then be used to sum up a list of octal numbers together as follows:

``````user> (reduce #(add-two-octal %1 %2)
(to-octal 1000))
;; 15

'(1 7 5 0))
;; 15
``````

Although the addition works fine it doesn't satisfy the requirement that the result of the sum should be a single digit.
If a single digit is the result of the sum then the single digit should be returned else the summation should be done again.
Also there is need for a function to separate the new summation if it happens to be two digits.

``````(defn separate [number]
"a utility function to separate digits"
(loop [n number
digits '()]
(if (zero? n)
digits
(recur (quot n 10)
(conj digits (rem n 10))))))

(defn sum-octal [number]
(let [sum (reduce #(add-two-octal %1 %2)
(to-octal number))]
(if (zero? (quot sum 10))
sum
``````
``````user> (sum-octal 1000)
;; 6
``````

Next a function that takes a number and checks for validity can be written as follows:

``````(defn is-valid? [number]
(let [first-four (quot number 10)
check-sum (rem number 10)
verify (sum-octal first-four)]
(= verify check-sum)))
``````
``````user> (is-valid? 10006)
;; true

user> (is-valid? 99998)
;; false
``````

The `is-valid?` function and the `#(Integer/parseInt %)` can be composed together

``````(comp is-valid? #(Integer/parseInt %))

user> ((comp is-valid? #(Integer/parseInt %)) "10006")
;; true
``````

Finally, the `validate-scratch-card` function will shape up as follows

``````(defn validate-scratch-card [card-number]
(let [f (comp is-valid? #(Integer/parseInt %))]
(->> (string/split card-number #"(-|\s)")
(map f)
(every? true?))))
``````
``````user> (validate-scratch-card "10006 12342 00081 99993")
;; true

user> (validate-scratch-card "10006 12342 00081 99998")
;; false
`````` Filipe Ramalho • Edited on

You can also use modulo. You calculate the iterative digit sum with number % 9. If 0 comes out the sum is 9.
sjsu.edu/faculty/watkins/Digitsum0...

I'm not familiar with Clojure so I can't give you a code example of Clojure. But here in pseudocode

``````boolean checkdigit(int digit,int checksum):
int sum = converttooctal(digit) % 9 //% is the modulo operator
if(sum == 0):
sum = 9
return checksum - sum == 0
``````

You can also consider 0 and 9 equal and spare the conversion from 0 to 9:

``````boolean checkdigit(int digit,int checksum):
int sum = converttooctal(digit) % 9 //% is the modulo operator
return checksum - sum == 0 || checksum - sum == 9
``````

Or you could modulo the difference through 9. If it's 0 the result is 0, if it's 9 the result is also 0.

``````boolean checkdigit(int digit,int checksum):
int sum = converttooctal(digit) % 9 //% is the modulo operator
return (checksum - sum) % 9 == 0
``````

So in one line it would look like this

``````boolean check = (checksum - converttooctal(digit) % 9 ) % 9 == 0
`````` Filipe Ramalho • Edited on

Actually I had an error. You shouldn't convert the digit. And instead modulo through 7.

For 9999|8

1. 9999 % 7 = 3 //First you modulo through 7
2. 8 - 3 = 5 //Then you subtract the result from the checksum.
3. 5 % 7 = 5 //Then you modulo that through 7.

The end result isn't 0, so the digit isn't valid

For 1234|2

1. 1234 % 7 = 2 //First you modulo through 7
2. 2 - 2 = 0 //Then you subtract the result from the checksum.
3. 0 % 7 = 0 //Then you modulo that through 7

The end result is 0, so the digit is valid

For 1169|7

1.1169 % 7 = 0 //If you modulo through 7, when the digit sum is 7 instead 0 comes out, so you can consider 0=7.

1. 7 - 0 = 7
2. 7 % 7 = 0 //If you modulo 0 or 7 through 7, the result is 0.

The end result is 0, so the digit is valid

Updated code

``````boolean checkdigit(int digit,int checksum):
int sum = digit % 7 //% is the modulo operator
if(sum == 0):
sum = 7
return checksum - sum == 0
``````

You can also consider 0 and 7 equal and spare the conversion from 0 to 7:

``````boolean checkdigit(int digit,int checksum):
int sum = digit % 7 //% is the modulo operator
return checksum - sum == 0 || checksum - sum == 7
``````

Or you could modulo the difference through 7. The difference must be either 7 or 0 and both have the same result for modulo 7.

``````boolean checkdigit(int digit,int checksum):
int sum = digit % 7 //% is the modulo operator
return (checksum - sum) % 7 == 0
``````

So in one line it would look like this

``````boolean check = (checksum - digit % 7 ) % 7 == 0
``````
x digitsum(x) x%7
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 0
8 1 1
9 2 2
10 3 3
11 4 4
12 5 5
13 6 6
14 7 0 Kevin Mungai • Edited on

Thank you for clarifying. I have now understood.

It is actually a really neat solution it basically reduces the code to just two functions.

``````(defn is-valid-modified?
[number]
(let [first-four (quot number 10)
check-sum (rem number 10)]
(-> first-four
(mod 7)
(- check-sum)
(mod 7)
(= 0))))

user> (is-valid-modified? 10006)
true
user> (is-valid-modified? 99993)
true
user> (is-valid-modified? 99998)
false
user> (is-valid-modified? 12342)
true
user> (is-valid-modified? 11697)
true
``````
``````(defn validate-scratch-card [card-number]
(let [f (comp is-valid-modified? #(Integer/parseInt %))]
(->> (string/split card-number #"(-|\s)")
(map f)
(every? true?))))

user> (validate-scratch-card "10006 12342 00081 99998")
false
user> (validate-scratch-card "10006 12342 00081 99993")
true
``````

I have learnt something, thank you. Hey! We would love your help!

Fill out this survey and help us moderate our community by becoming a tag moderator here at DEV.