Fastest algorithm to calculate the number of business days between two dates? - algorithm

I have stumbled upon this problem couple of times before and there are some SO answers around but they are extremely slow e.g.
def businessDaysBetween(startDate: DateTime, endDate: DateTime): Seq[DateTime] = {
1 to daysBetween(startDate, endDate) map {
startDate.withFieldAdded(DurationFieldType.days(), _)
} diff holidays filter {
_.getDayOfWeek() match {
case DateTimeConstants.SUNDAY | DateTimeConstants.SATURDAY => false
case _ => true
}
}
}
def daysBetween(startDate: DateTime, endDate: DateTime) =
Days.daysBetween(startDate.toDateMidnight(), endDate.toDateMidnight()).getDays()
My question is not only how to compute the number of business days between two dates but also the fastest possible solution. Note that I only need to know the number of business days and not the actual dates.

And this is I think the fastest solution, only need to consider which day of the week the startDate represents. The complexity is O(C):
def businessDaysBetween(startDate: DateTime, endDate: DateTime): Int = {
val numDays = daysBetween(startDate, endDate)
val numHolidays: Int = startDate.getDayOfWeek match {
case DateTimeConstants.MONDAY => (numDays / 7)*2 + (if (numDays % 7 > 4) min(numDays % 7 - 4, 2) else 0)
case DateTimeConstants.TUESDAY => (numDays / 7)*2 + (if (numDays % 7 > 3) min(numDays % 7 - 3, 2) else 0)
case DateTimeConstants.WEDNESDAY => (numDays / 7)*2 + (if (numDays % 7 > 2) min(numDays % 7 - 2, 2) else 0)
case DateTimeConstants.THURSDAY => (numDays / 7)*2 + (if (numDays % 7 > 1) min(numDays % 7 - 1, 2) else 0)
case DateTimeConstants.FRIDAY => (numDays / 7)*2 + (if (numDays % 7 > 0) min(numDays % 7, 2) else 0)
case DateTimeConstants.SATURDAY => 1 + (numDays / 7)*2 + (if (numDays % 7 > 0) 1 else 0)
case DateTimeConstants.SUNDAY => 1 + (numDays / 7)*2 + (if (numDays % 7 > 5) 1 else 0)
}
numDays - numHolidays
}

Here is a slightly more readable version in my opinion with the same O(C) complexity:
def getPreviousWorkDay(d: DateTime): DateTime = {
d.withDayOfWeek(Math.min(d.getDayOfWeek, DateTimeConstants.FRIDAY)).withTimeAtStartOfDay()
}
def businessDaysBetween(startDate: DateTime, endDate: DateTime): Int = {
val workDayStart = getPreviousWorkDay(startDate)
val workDayEnd = getPreviousWorkDay(endDate)
val daysBetween = Days.daysBetween(workDayStart, workDayEnd).getDays
val weekendDaysBetween = daysBetween / 7 * 2
val additionalWeekend = if(workDayStart.getDayOfWeek > workDayEnd.getDayOfWeek) 2 else 0
daysBetween - weekendDaysBetween - additionalWeekend
}
I consider that the week starts on Monday (the default for Joda).
I also consider that between a Saturday and the following Friday there are 5 business days, whereas between a Monday and the following Friday there are only 4 business days.

Related

Numerical sequence of 1 2 4

I need help in providing an algorithm for a numerical sequence which should display a series of 1 2 4 and its consecutive summations.
e.g. If my input value is 20, it should display
1 2 4 8 9 11 15 16 18
Wherein
1 = 1
2 = 1 + 1
4 = 2 + 2
8 = 4 + 4
And the summation of 1 and 2 and 4 will repeat again starting with the present number which is 8 and so on..
9 = 8 + 1
11 = 9 + 2
15 = 11 + 4
16 = 15 + 1
18 = 16 + 2
As you can see, it should not proceed to 22 (18 + 4) since our sample input value is 20. I hope you guys get my point. I'm having a problem in designing the algorithms in the for loop. What I have now which is not working is
$input = 20;
for ($i = $i; $i < $input; $i = $i+$i) {
if($i==0){
$i = 4;
$i = $i - 3;
}elseif($i % 4 == 0){
$i = $i + 1;
}
print_r("this is \$i = $i<br><br>");
}
NOTE: Only one variable and one for loop is required, it will not be accepted if we use functions or arrays. Please help me, this is one of the most difficult problems I've encountered in PHP..
you can use the code
$input = 20;
$current = 1;
$val = 1;
while($val < $input){
print_r("this is \$val = $val\n");
$val = $val + $current;
$current = ($current == 4 ? 1 : $current*2);
}
see the online compiler
Since you have mentioned Only one variable and one for loop is required
Try this,
$input = 20;
for ($i = 1; $i < $input; $i) {
if($i>$input) break;
print_r("this is \$i = $i<br><br>");
$i=$i+1;
if($i>$input) break;
print_r("this is \$i = $i<br><br>");
$i=$i+2;
if($i>$input) break;
print_r("this is \$i = $i<br><br>");
$i=$i+4;
}
Online Compiler
def getSeq(n):
if n == 1:
return [1]
temp = [1]
seq = [ 1, 2, 4]
count, current, prev = 0, 0, 1
while True:
current = prev + seq[count]
if current > n:
break
prev = current
temp += [current]
count = (count + 1) % 3
return temp
print getSeq(20)
I'm pretty sure that this one is going to work
the case that we have to take care of is n == 1 and return a static result [1].
in other cases the second value is repeating circularly and adding up to previous value.
This Python solution should be implementable in any reasonable language:
limit = 20
n = 1 << 2
while n >> 2 < limit:
print(n >> 2)
n = (((n >> 2) + (2 ** (n & 3))) << 2) + ((n & 3) + 1) % 3
Perl Equivalent (using the style of for loop you expect):
$limit = 20;
for ($n = 1 << 2; $n >> 2 < $limit; $n = ((($n >> 2) + (2 ** ($n & 3))) << 2) + (($n & 3) + 1) % 3) {
print($n >> 2, "\n");
}
OUTPUT
1
2
4
8
9
11
15
16
18
EXPLANATION
The basic solution is this:
limit = 20
n = 1
i = 0
while n < limit:
print(n)
n = n + (2 ** i)
i = (i + 1) % 3
But we need to eliminate the extra variable i. Since i only cycles through 0, 1 and 2 we can store it in two bits. So we shift n up two bits and store the value for i in the lower two bits of n, adjusting the code accordingly.
Not only one variable and one for loop, no if statements either!

3 condition python while loop regarding checking if two dates are the same

I'm currently working on this problem of counting how many days between two dates including leap years.
However it keeps skipping the loop from the beginning, even though the two months and days aren't the same?
def daysBetweenDates(year1, month1, day1, year2, month2, day2):
day_count = 0
while (year2 != year1) and (month2 != month1) and (day2! = day 1):
# print "in loop" // tester
if (day2 != 0):
day2 = day2 - 1
day_count = day_count + 1
else:
if(month2 != 0):
month2 = month2 - 1
if month2 == (9 or 4 or 6 or 11):
day2 = 30
if month2 == 2:
day2 = 28
if (month2 == 2) and (year2 % 4):
day2 = 29
else:
day2 == 31
else:
year2 = year2 - 1
month2 = 12
#print day_count //tester
return day_count
# Test routine
def test():
test_cases = [((2012,1,1,2012,2,28), 58),
((2012,1,1,2012,3,1), 60),
((2011,6,30,2012,6,30), 366),
((2011,1,1,2012,8,8), 585 ),
((1900,1,1,1999,12,31), 36523)]
for (args, answer) in test_cases:
result = daysBetweenDates(*args)
if result != answer:
print "Test with data:", args, "failed"
else:
print "Test case passed!"
test()
Here's one way.
>>> from datetime import datetime
>>> diff = datetime(2012, 2, 28)-datetime(2012, 1, 1)
>>> diff.days
58

Count day combinations in the date range

Imagine that you have a range of dates, for example 2017-08-01 - 2017-09-15, and start day (Monday - sonday in numerical format 1-7) and endDay. You have to calculate the number of combinations of this days.
For the input 4-7 what is thusday - sonday and mentioned dates the output will be 6. How would you do that?
In your example you would have these values:
rangeStart = 2017-08-01
rangeEnd = 2017-09-15
startDay = 4
endDay = 7
I suppose you also have the following functions:
weekday(date) determines the day of the week for the given date, and returns it as a number: 1 for Monday, ... 7 for Sunday.
date_add(date, days) adds days days to the given date and returns the resulting date.
date_diff(date1, date2) returns the number of days between two dates, excluding date2 itself, i.e. when both dates fall on the same week day, this will be a multiple of 7.
Then this could be the algorithm:
# Align range start with closest start day in the range
rangeStart = date_add(rangeStart, (startDay + 7 - weekday(rangeStart)) % 7)
# Align range end with closest end day within the range
rangeEnd = date_add(rangeEnd, -((weekday(rangeEnd) + 7 - endDay) % 7))
# Get number of full weeks in range, and add 1
result = floor(date_diff(rangeStart, rangeEnd) / 7) + 1
NB: % is the modulo operator, and floor truncates a decimal number down to the nearest integer value.
Implementation in JavaScript:
// Define utility functions whose implementations depend on the programming language
function weekday(date) {
return (date.getDay()+6)%7+1; // in JavaScript Sunday is 0
}
function date_add(date, days) {
var result = new Date(date); // get clone
result.setDate(result.getDate() + days); // mutate
return result;
}
function date_diff(date1, date2) {
return Math.round((date2-date1)/(1000*60*60*24));
}
var floor = Math.floor;
// Main algorithm
function count(rangeStart, rangeEnd, startDay, endDay) {
rangeStart = date_add(rangeStart, (startDay + 7 - weekday(rangeStart)) % 7);
rangeEnd = date_add(rangeEnd, -((weekday(rangeEnd) + 7 - endDay) % 7));
return floor(date_diff(rangeStart, rangeEnd) / 7) + 1;
}
var rangeStart = new Date("2017-08-01"),
rangeEnd = new Date("2017-09-15"),
startDay = 4,
endDay = 7;
var result = count(rangeStart, rangeEnd, startDay, endDay);
console.log(result);
Implementation in Python:
import datetime
def count(rangeStart, rangeEnd, startDay, endDay):
rangeStart = rangeStart + datetime.timedelta((startDay + 7 - rangeStart.isoweekday()) % 7)
rangeEnd = rangeEnd - datetime.timedelta((rangeEnd.isoweekday() + 7 - endDay) % 7)
return (rangeEnd - rangeStart).days // 7 + 1
rangeStart = datetime.date(2017, 8, 3)
rangeEnd = datetime.date(2017, 9, 15)
startDay = 4
endDay = 7
result = count(rangeStart, rangeEnd, startDay, endDay)
print(result)

Generate maximum HH:MM from a list of 4 integers [duplicate]

This question already has answers here:
Find maximum possible time HH:MM by permuting four given digits
(25 answers)
Closed 5 years ago.
Note: Another question is the duplicate of this one. If I posted this question 6 months earlier than that one, then how can mine be a duplicate?
I have 4 non-negative integers a,b,c,d. All of them are less than or equal to 9. I have to return the maximum time that can be shown on the clock in 24-hour format.
For example: a=9, b=4, c=3, d=1, would yield 19:43
I have so far only been able to come up with brute-force approach which kind of tests all 24-possible combinations. Although this isn't too bad, I was wondering if there are more elegant approaches. All ideas better than brute force are welcome.
Note: It is not a homework question. I got this from an interview prep site but has no solutions there.
Generating all 24 permutations would work, but you don't have to do that. Your validation for the brute force method would require you to validate each digit, and you may as well build up the permutation as you validate each digit. Start with big numbers.
sort numbers in high -> low
iterate over each digit [i] and search through the list until you find the highest number that fits the requirements.
[0] must be <=2
[1] must be <=3 if [0]==2
[2] must be <=5
[3] can be anything
Remove that number from the list, and place it in position [i]
repeat for each digit
Each of those conditions could be expressed as lambda function in a list, making it easy to separate the search loop from the conditions.
The key is to sort the data and then apply these simple rules:
At least one element has to be <= 2
A second element has to be <= 5
If there are only two elements meeting the first two rules then one of them must be < 2
If the element selected for the first value is 2 then the element selected for the second value must be less than 4
The rules are easy to implement by using three counters:
less_than_3 - this must always be at least 1
less_than_6 - this must always be at least 2
less_than_4 - if a == 2 then less_than_4 must be at least 2
Here's a solution in JavaScript that could be further refactored.
function find_the_time(data) {
var arr = data.slice(), ans = {};
var count_less_than_three = 0, count_less_than_four = 0, count_less_than_six = 0;
console.log(arr);
arr.sort(function(a,b) { return a - b; });
if ((arr[0] > 2) || (arr[1] > 5)) {
// Rule 1 - Hh:mm must be <= 2
// Rule 2 - hh:Mm must be <= 5
console.log('No solution');
return -1;
}
for (var el of arr) {
if (el < 3) {
// count_less_than_three will be at least 1
count_less_than_three++;
}
if (el < 4) {
// count_less_than_four will be at least 1
count_less_than_four++;
}
if (el < 6) {
// count_less_than_six will be at least 2
count_less_than_six++;
}
}
if (count_less_than_three === count_less_than_six) {
if (count_less_than_three == 2) {
// Two elements have values less than 3
// so the time must be earlier than 20:00
// Rule 3 - Hh:mm must be <= 1
if (arr[0] > 1) {
console.log('No solution');
return -1;
} else {
ans.c = arr.splice((count_less_than_three - 1), 1);
ans.a = arr.splice((count_less_than_three - 2), 1);
ans.b = arr.splice(1, 1);
ans.d = arr.splice(0, 1);
}
} else {
ans.a = arr.splice((count_less_than_three - 1), 1);
ans.b = arr.splice((count_less_than_three - 2), 1);
if (arr[1] < 6) {
ans.c = arr.splice(1, 1);
ans.d = arr.splice(0, 1);
} else {
ans.d = arr.splice(1, 1);
ans.c = arr.splice(0, 1);
}
}
} else {
ans.a = arr.splice((count_less_than_three - 1), 1);
if (ans.a < 2) {
// b can have any value so select the largest available
ans.b = arr.splice(2, 1);
} else {
// a == 2 so count_less_than_four comes into play
// Rule 4 - hH:mm must be <= 3
// Array size has been reduced so decrement count_less_than_four
count_less_than_four--;
ans.b = arr.splice((count_less_than_four - 1), 1);
}
if (arr[1] < 6) {
ans.c = arr.splice(1, 1);
ans.d = arr.splice(0, 1);
} else {
ans.d = arr.splice(1, 1);
ans.c = arr.splice(0, 1);
}
}
console.log('Answer: ' + ans.a + '' + ans.b + ':' + ans.c + '' + ans.d);
return ans.a + '' + ans.b + ':' + ans.c + '' + ans.d;
}
var test_data = [
[ 2, 1, 2, 1 ],
[ 9, 5, 7, 1 ],
[ 2, 2, 7, 6 ],
[ 2, 6, 6, 1 ],
[ 0, 5, 9, 8 ],
[ 0, 6, 9, 8 ],
[ 2, 5, 9, 3 ]
];
test_data.forEach(find_the_time);
You can change time to minutes.
Then you can compare it.
//23:59 ==> 23*60+59 ==1439 min
//(10a+b)*60+(10c+d)<=1439
This is my code.
String function(int[] numbers){
int num[] = numbers;
int temp = 0;
int cnt=0;
int numA=0;
int numB=0;
int numC=0;
int numD=0;
for(int a=0;a<num.length; a++){
for(int b=0;b<num.length; b++){
for(int c=0;c<num.length; c++){
for(int d=0;d<num.length; d++){
if(a!=b && a!=c && a!=d
&& b!=c && b!=d
&& c!=d){
if((10*num[c]+num[d])<60) {
int cal = (10 * num[a] + num[b]) * 60 + (10 * num[c] + num[d]);
Log.d("Joon1979", "Input Numbers [ " + num[a] + ", " + num[b] + ", " + num[c] + ", " + num[d] + " ]");
if (cal <= 1439) {
cnt++;
if (temp < cal) {
temp = cal;
numA = num[a];
numB = num[b];
numC = num[c];
numD = num[d];
}
}
}
}
}
}
}
}
if(cnt==0){
return "impossible";
}else {
return numA+""+numB+" : "+numC+""+numD;
}
}

EAN 8 : How to calculate checksum digit?

I need to create EAN 8 bar code programmatically.
I search an algorithm to calculate the checksum digit.
The algorithm is covered in this wikipedia article on EAN, note that EAN-8 is calculated in the same way as EAN-13.
Here's a worked example from http://www.barcodeisland.com/ean8.phtml :
Assuming we wish to encode the 7-digit message "5512345", we would calculate the checksum in the following manner:
Barcode 5 5 1 2 3 4 5
Odd/Even Pos? O E O E O E O
Weighting 3 1 3 1 3 1 3
Calculation 5*3 5*1 1*3 2*1 3*3 4*1 5*3
Weighted Sum 15 5 3 2 9 4 15
The total is 15 + 5 + 3 + 2 + 9 + 4 + 15 = 53. 7 must be added to 53 to produce a number evenly divisible by 10, thus the checksum digit is 7 and the completed bar code value is "55123457".
string code="55123457";
int sum1 = code[1] + code[3] + code[5]
int sum2 = 3 * (code[0] + code[2] + code[4] + code[6]);
int checksum_value = sum1 + sum2;
int checksum_digit = 10 - (checksum_value % 10);
if (checksum_digit == 10)
checksum_digit = 0;
int checkSum(const std::vector<int>& code) const
{
if (code.size() < 8) return false;
for( SIZE_T i = 0; i< code.size(); i++ )
{
if( code[i] < 0 ) return false;
}
int sum1 = code[1] + code[3] + code[5]
int sum2 = 3 * (code[0] + code[2] + code[4] + code[6]);
int checksum_value = sum1 + sum2;
int checksum_digit = 10 - (checksum_value % 10);
if (checksum_digit == 10) checksum_digit = 0;
return checksum_digit;
}
Sorry for re-opening
JAVA VERSION
public int checkSum(String code){
int val=0;
for(int i=0;i<code.length();i++){
val+=((int)Integer.parseInt(code.charAt(i)+""))*((i%2==0)?1:3);
}
int checksum_digit = 10 - (val % 10);
if (checksum_digit == 10) checksum_digit = 0;
return checksum_digit;
}
Reawakened with a C# version:
public static bool IsValidEan13(string eanBarcode)
{
return IsValidEan(eanBarcode, 13);
}
public static bool IsValidEan12(string eanBarcode)
{
return IsValidEan(eanBarcode, 12);
}
public static bool IsValidEan14(string eanBarcode)
{
return IsValidEan(eanBarcode, 14);
}
public static bool IsValidEan8(string eanBarcode)
{
return IsValidEan(eanBarcode, 8);
}
private static bool IsValidEan(string eanBarcode, int length)
{
if (eanBarcode.Length != length) return false;
var allDigits = eanBarcode.Select(c => int.Parse(c.ToString(CultureInfo.InvariantCulture))).ToArray();
var s = length%2 == 0 ? 3 : 1;
var s2 = s == 3 ? 1 : 3;
return allDigits.Last() == (10 - (allDigits.Take(length-1).Select((c, ci) => c*(ci%2 == 0 ? s : s2)).Sum()%10))%10;
}
Here is a MySQL version for EAN13:
SET #first12digits="123456789012";
SELECT #first12digits,
IF (
(#check:=10-MOD(
(CAST(SUBSTRING(#first12digits, 1, 1) AS DECIMAL))+
(CAST(SUBSTRING(#first12digits, 2, 1) AS DECIMAL) * 3)+
(CAST(SUBSTRING(#first12digits, 3, 1) AS DECIMAL))+
(CAST(SUBSTRING(#first12digits, 4, 1) AS DECIMAL) * 3)+
(CAST(SUBSTRING(#first12digits, 5, 1) AS DECIMAL))+
(CAST(SUBSTRING(#first12digits, 6, 1) AS DECIMAL) * 3)+
(CAST(SUBSTRING(#first12digits, 7, 1) AS DECIMAL))+
(CAST(SUBSTRING(#first12digits, 8, 1) AS DECIMAL) * 3)+
(CAST(SUBSTRING(#first12digits, 9, 1) AS DECIMAL))+
(CAST(SUBSTRING(#first12digits, 10, 1) AS DECIMAL) * 3)+
(CAST(SUBSTRING(#first12digits, 11, 1) AS DECIMAL))+
(CAST(SUBSTRING(#first12digits, 12, 1) AS DECIMAL) * 3)
,10)) = 10, 0, #check
) AS checkDigit;
There was a bug. If Calc result = 10 then check digit = 0.
Here below a better version for EAN14.
SET #first13digits="1234567890123";
SELECT #txCode13:=#first13digits,
#iCheck := (
10 - (
(
MID(#txCode13, 2, 1) +
MID(#txCode13, 4, 1) +
MID(#txCode13, 6, 1) +
MID(#txCode13, 8, 1) +
MID(#txCode13, 10, 1) +
MID(#txCode13, 12, 1)
) + (
MID(#txCode13, 1, 1) +
MID(#txCode13, 3, 1) +
MID(#txCode13, 5, 1) +
MID(#txCode13, 7, 1) +
MID(#txCode13, 9, 1) +
MID(#txCode13, 11, 1) +
MID(#txCode13, 13, 1)
) * 3 ) % 10
) AS iCheck,
#iCheckDigit := IF(#iCheck = 10, 0, #iCheck) AS checkDigit,
CONCAT(#t
xCode13, CAST(#iCheckDigit AS CHAR)) AS EAN14WithCheck
Here is the Java version for EAN13
private int calcChecksum(String first12digits) {
char[] char12digits = first12digits.toCharArray();
int[] ean13 = {1,3};
int sum = 0;
for(int i = 0 ; i<char12digits.length; i++){
sum += Character.getNumericValue(char12digits[i]) * ean13[i%2];
}
int checksum = 10 - sum%10;
if(checksum == 10){
checksum = 0;
}
return checksum;
}
class GTIN(object):
def __init__(self, barcode=''):
self.barcode = barcode
def __checkDigit(self, digits):
total = sum(digits) + sum(map(lambda d: d*2, digits[-1::-2]))
return (10 - (total % 10)) % 10
def validateCheckDigit(self, barcode=''):
barcode = (barcode if barcode else self.barcode)
if len(barcode) in (8,12,13,14) and barcode.isdigit():
digits = map(int, barcode)
checkDigit = self.__checkDigit( digits[0:-1] )
return checkDigit == digits[-1]
return False
def addCheckDigit(self, barcode=''):
barcode = (barcode if barcode else self.barcode)
if len(barcode) in (7,11,12,13) and barcode.isdigit():
digits = map(int, barcode)
return barcode + str(self.__checkDigit(digits))
return ''
Today I need a PHP version, I remember about this page and copy from the Java version. Thank you.
function getEAN13($txEan12)
{
$iVal=0;
for($i=0; $i<strlen($txEan12); $i++)
{
$iSingleCharVal = intval(substr($txEan12, $i, 1)); // extract value of one char
$iSingleCharMult = $iSingleCharVal * ($i%2==0 ? 1 : 3); // calculate depending from position
$iVal+= $iSingleCharMult; // sum
}
$iCheckDigit = 10 - ($iVal % 10);
if ($iCheckDigit == 10) $iCheckDigit = 0;
return $txEan12 . $iCheckDigit;
}
Java Version:
It works perfectly
public static int checkSum(String code){
int val=0;
for(int i=0; i<code.length()-1; i++){
val+=((int)Integer.parseInt(code.charAt(i)+""))*((i%2==0)?1:3);
}
int checksum_digit = (10 - (val % 10)) % 10;
return checksum_digit;
}
Python EAN13 check-digit calculation based on Najoua Mahi's Java function:
def generateEAN13CheckDigit(self, first12digits):
charList = [char for char in first12digits]
ean13 = [1,3]
total = 0
for order, char in enumerate(charList):
total += int(char) * ean13[order % 2]
checkDigit = 10 - total % 10
if (checkDigit == 10):
return 0
return checkDigit
This works on both EAN 13 and EAN8:
public static String generateEAN(String barcode) {
int first = 0;
int second = 0;
if(barcode.length() == 7 || barcode.length() == 12) {
for (int counter = 0; counter < barcode.length() - 1; counter++) {
first = (first + Integer.valueOf(barcode.substring(counter, counter + 1)));
counter++;
second = (second + Integer.valueOf(barcode.substring(counter, counter + 1)));
}
second = second * 3;
int total = second + first;
int roundedNum = Math.round((total + 9) / 10 * 10);
barcode = barcode + String.valueOf(roundedNum - total);
}
return barcode;
}
This is a code I wrote in VFP (Visual FoxPro 9), for both EAN-8 and EAN-13
Lparameters lcBarcode,llShowErrorMessage
If Vartype(m.lcBarcode)<>'C'
If m.llShowErrorMessage
MessageBox([Type of parameter is incorect!],0+16,[Error Message])
EndIf
Return .f.
EndIf
If Len(Chrtran(Alltrim(m.lcBarcode),[0123456789],[]))>0
If m.llShowErrorMessage
MessageBox([Provided barcode contains invalid characters!],0+16,[Error Message])
EndIf
Return .f.
EndIf
If Len(Alltrim(m.lcBarcode))=0
If m.llShowErrorMessage
MessageBox([The length of provided barcode is 0 (zero)!],0+16,[Error Message])
EndIf
Return .f.
EndIf
If !InList(Len(Alltrim(m.lcBarcode)),8,13)
If m.llShowErrorMessage
MessageBox([Provided barcode is not an EAN-8 or EAN-13 barcode!],0+16,[Error Message])
EndIf
Return .f.
EndIf
Local lnCheck as Integer, lnSum as Integer, lnOriginalCheck as Integer,jj as Integer
jj=0
lnSum=0
m.lnOriginalCheck = Cast(Right(Alltrim(m.lcBarcode),1) as Integer)
m.lcBarcode = Left(Alltrim(m.lcBarcode),Len(Alltrim(m.lcBarcode))-1)
For ii = Len(m.lcBarcode) to 1 step -1
jj=jj+1
lnSum = lnSum + Cast(Substr(m.lcBarcode,ii,1) as Integer) * Iif(Mod(jj,2)=0,1,3)
Next
lnCheck = 10-Mod(lnSum,10)
lnCheck = Iif(lnCheck =10,0,lnCheck)
Return (lnCheck = lnOriginalCheck)
JavaScript version for EAN-8 and EAN-13
function checksum(code) {
const sum = code.split('').reverse().reduce((sum, char, idx) => {
let digit = Number.parseInt(char);
let weight = (idx + 1) % 2 === 0 ? 1 : 3;
let partial = digit * weight;
return sum + partial;
}, 0);
const remainder = sum % 10;
const checksum = remainder ? (10 - remainder) : 0;
return checksum;
}
Mini Javascript Version
function checksum(code){
return (10 - (code.split('').reduce((s, e, i) => { return s + parseInt(e) * ((i%2==0)?1:3) },0) % 10)) % 10;
}
=INT(CONCAT([#Code],MOD(10 - MOD((MID([#Code], 2, 1) + MID([#Code], 4, 1) + MID([#Code], 6, 1)) + (3*(MID([#Code], 1, 1) + MID([#Code], 3, 1) + MID([#Code], 5, 1) + MID([#Code], 7, 1))),10), 10)))
The above formula will calculate the check character without the need to use a macro or change to XLSM.
Note: Only works for EAN-8.

Resources