Skip to content

Instantly share code, notes, and snippets.

@dusnm
Last active October 28, 2021 22:49
Show Gist options
  • Save dusnm/1c1c2d19c8c169a50db3a543418efb6b to your computer and use it in GitHub Desktop.
Save dusnm/1c1c2d19c8c169a50db3a543418efb6b to your computer and use it in GitHub Desktop.
A small go program calculating the UMCN (Unique Master Citizen Number) checksum for the numbers of former Yugoslav republics.
/*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Licensed under the GNU General Public License, Version 3.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* https://www.gnu.org/licenses/gpl-3.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package main
import (
"fmt"
"strings"
"strconv"
"os"
)
const (
EXIT_FAILURE = 1
UMCN_LENGTH = 13
)
type UMCN struct {
digits []int
}
func New(number string) (UMCN, error) {
umcn := UMCN{digits: make([]int, 0, UMCN_LENGTH)}
digits := strings.Split(number, "")
for _, digit := range digits {
digit, err := strconv.ParseInt(digit, 10, 0)
if err != nil {
return umcn, err
}
umcn.digits = append(umcn.digits, int(digit))
}
return umcn, nil
}
func (umcn *UMCN) GetLength() int {
return len(umcn.digits)
}
func (umcn *UMCN) CalculateChecksum() int {
checksum := 0
// Let UMCN DD MM YYY RR BBB C = AB CD EFG HI JKL M
// The checksum M is calculated by the following formula:
// 11 - ((7(A+G) + 6(B+H) + 5(C+I) + 4(D+J) + 3(D+K) + 2(E+L)) mod 11)
for i, j := 0, 7; i < 6; i, j = i + 1, j - 1 {
checksum += j * (umcn.digits[i] + umcn.digits[i + 6])
}
checksum = 11 - (checksum % 11)
// The cheksum is a single digit value.
// Sometimes the formula produces either 10 or 11.
// This is the rule for those cases.
if (checksum == 10 || checksum == 11) {
return 0
}
return checksum
}
func main() {
var number string
fmt.Println("Please enter your UMCN:")
if _, err := fmt.Scan(&number); err != nil {
fmt.Fprint(os.Stderr, "Unable to read input.")
os.Exit(EXIT_FAILURE)
}
umcn, err := New(number)
if err != nil {
fmt.Fprint(os.Stderr, "Unable to convert digits to integers.")
os.Exit(EXIT_FAILURE)
}
if umcn.GetLength() != 13 {
fmt.Fprint(os.Stderr, "Number must be exactly 13 digits long.")
os.Exit(EXIT_FAILURE)
}
fmt.Printf("Checksum: %d\n", umcn.CalculateChecksum())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment