# Count the lucky tickets within the given range

In Russia we have something like a tradition: we like to look for lucky tickets.

Here's what a regular ticket looks like:

As you can see, the ticket has a six-digit number.

A six-digit number is considered lucky if the sum of the first three digits is equal to the sum of the last three.

The number on the photo is not lucky:

038937
038 937
0 + 3 + 8 = 11
9 + 3 + 7 = 19
11 != 19


## Challenge

Given the limits of a range (inclusive), return the number of lucky ticket numbers contained within it.

## Parameters

• Input: 2 integers: the first and last integers in the range
• The inputs will be between 0 and 999999 inclusive
• Output: 1 integer: how many lucky numbers are in the range
• You may take the inputs and return the output in any acceptable format
• Assume leading zeros for numbers less than 100000.

## Examples

0, 1 => 1
100000, 200000 => 5280
123456, 654321 => 31607
0, 999999 => 55252


This is so the shortest answer in bytes in every language wins.

Update: here's the lucky one

• – user202729 Jul 20 '18 at 5:28

# 05AB1E, 8 (or 10?) 11 (or 13?) bytes

Ÿʒ₄n+¦S3ôOË


NOTE: In 05AB1E strings and integers are interchangeable, so the output numbers doesn't contain leading zeroes. This could however be fixed with 1 additional byte (12 bytes):

Ÿ₄n+€¦ʒS3ôOË


+3 bytes to bug-fix numbers with a length of 3 or less (range [000000, 000999]).

Explanation:

Ÿ          # Create an inclusive (on both sides) range from the two inputs
#  i.e. 038920 and 038910 →
#   [38910,38911,38912,38913,38914,38915,38916,38917,38918,38919,38920]
ʒ         # Filter this list by:
₄n+      #  Add 1,000,000 to the number
|     #  And remove the leading 1
#   i.e. 38910 → 1038910 → '038910'
S        #  Transform it to a list of digits
#   i.e. '038910' → ['0','3','8','9','1','0']
3ô      #  Split it into chunks of length 3
#   i.e. ['0','3','8','9','1','0'] → [['0','3','8'],['9','1','0']]
O     #  Sum the digits in both parts
#   i.e. [['0','3','8'],['9','1','0']] → [11,10]
Ë    #  Check if they are equal (if they are, they remain in the filtered list)
#   i.e. [11,10] → 0


EDIT: Seems I (and most other answers) slightly misread the challenge and the amount of numbers is being asked instead of the numbers themselves within the range. In that case a trailing }g can be added (close the filter; and get the amount of numbers left in the filtered list), so it's 10 13 bytes instead:

Ÿʒ₄n+¦S3ôOË}g

• For range starting under 1000 (For example [0;1000]), your result seems to be a bit off (1000 lucky numbers are found). – frosqh Jul 20 '18 at 12:02
• If I understand the challenge correctly, adding 1.000.000 to each number and removing the first character would solve this problem. It would also get rid of using the R. – Adnan Jul 20 '18 at 12:57
• @Adnan Thanks, that's indeed a pretty nice way to handle it. – Kevin Cruijssen Jul 20 '18 at 13:19
• It is the count that is required (and the output does not require leading zeros), so 13. – Jonathan Allan Jul 22 '18 at 11:05

# C# (.NET Core), 93 + 18 = 111 bytes

a=>b=>Enumerable.Range(a,b-a+1).Select(e=>$"{e:D6}").Count(e=>e[0]+e[1]+e[2]==e[3]+e[4]+e[5])  Try it online! 18 bytes for using System.Linq;. I supposed that the input and output formats could be flexible. So I take two integers as input (the range, inclusive). Some test results: a=1000 b=1100 Lucky numbers = 3 [001001, 001010, 001100] a=2000 b=2100 Lucky numbers = 3 [002002, 002011, 002020] a=222000 b=222100 Lucky numbers = 7 [222006, 222015, 222024, 222033, 222042, 222051, 222060] a=0 b=999999 Lucky numbers = 55252 (that's 5.5% of the total numbers)  # JavaScript (ES6), 66 bytes Takes input in currying syntax (m)(n), where m is the exclusive inclusive upper bound and n is the inclusive lower bound. m=>g=n=>n<=m&&![...n+=''].reduce((t,d,i)=>t-=n[i+3]?d:-d,0)+g(-~n)  Try it online! ### How? We test each number $n$ by walking through its digits $d_i$ and updating a total $t$: • $t \gets t - d_i$ if there are at least 3 remaining digits after this one • $t \gets t + d_i$ otherwise If we have $t=0$ at the end of the process, then $n$ is a lucky number. # JavaScript (ES6), 67 bytes Same input format. m=>g=n=>n<=m&&!eval([...n/1e3+''].join+.split+..join^)+g(n+1)  Try it online! ### How? For each number $n$: • divide it by $1000$: e.g. 38937 --> 38.937 • coerce to a string and split: ['3','8','.','9','3','7'] • join with +: "3+8+.+9+3+7" • replace +. with ^: "3+8^+9+3+7" • evaluate as JS code and test whether the result is $0$: 24 ($11$ XOR $19$) If $n \equiv 0 \pmod{1000}$, no decimal point is generated and the evaluated expression is just a positive sum (falsy), unless $n=0$ (truthy). This is the expected result in both cases. • It's been made inclusive. – Jonathan Allan Jul 20 '18 at 19:43 # Ruby, 56 54 bytes ->a,b{(a..b).count{|i|j=i.digits;j[0,3].sum*2==j.sum}}  Try it online! ### Method: 1. For every number, creates an array of digits (which comes out reversed) 2. Compares the sum of the first 3 digits in the array (last 3 in the number) multiplied by 2 to the sum of the entire array 3. Counts the numbers for which the two sums are equal # Japt, 38 15 bytes õV Ëì ò3n)mx r¥  -23 thanks to Shaggy! My first Japt submission; thanks to Shaggy for all the help! Try it online! • Welcome to Japt! :) – Shaggy Jul 20 '18 at 13:52 • @Shaggy thanks! It's a pretty neat language! – Amphibological Jul 20 '18 at 13:56 • To help get you started. Feel free to ping me in chat if you've any questions. – Shaggy Jul 20 '18 at 13:57 • @Shaggy That's amazing. I definately learned a lot from that. Are you planning to post it as your own answer? You should! – Amphibological Jul 20 '18 at 14:05 • No, you can have it :) Like I said, to help you get started. – Shaggy Jul 20 '18 at 14:07 # Python 3, 117113106 135 bytes This is my first answer ever so I'm sure there's room for improvement. def x(a,b): n=0 for i in range(a,b+1): if sum(map(int,str(i//1000)))==sum(map(int,str(i%1000))):n+=1 print(n)  • -4 bytes thanks to W W • -7 bytes thanks to Asone Tuhid • +29 bytes to create a function Gets the first three digits through integer division, and the last three through modulo. The first and last integers in the range are inputted as arguments of the x function, as a and b, respectively. Output is n, printed. Ungolfed: def x(a, b): n = 0 for i in range(a, b + 1): if sum(map(int, str(i // 1000))) == sum(map(int, str(i % 1000))): n += 1 print(n)  • You don't need the indentation after the if btw. Also it will probably be cheaper to convert to string before you take the first or last 3 digits. – Sriotchilism O'Zaic Jul 21 '18 at 15:43 • Welcome to PPCG! Check out Tips for golfing in Python for tips and tricks, there's a similar thread for most languages if you're interested. Also, it's good practice to include a TIO link as demonstration. – Asone Tuhid Jul 21 '18 at 17:07 • I'd suggest replacing n=n+1 with n+=1 and moving it right after the if statement (if...:n+=1) – Asone Tuhid Jul 21 '18 at 17:08 • You can't take a and b as pre-declared variables. You either have to have a function or take them via input – Jo King Jul 21 '18 at 22:15 • If you're keeping it as a function, you can move the n=0 part into the header, like def x(a,b,n=0) – Jo King Jul 23 '18 at 12:20 # R, 93 86 bytes Shorter logic at the end compliments of @Giuseppe/ function(a,b){for(i in sprintf("%06d",a:b)){x=utf8ToInt(i);F=F+!sum(x[1:3]-x[4:6])} F}  Try it online! Integer inputs. Pad them with 0. Convert to the six ASCII code points. Abuse the F builtin. • I'm getting an NA returned from that function. – Robert S. Jul 20 '18 at 20:19 • I've rolled back the edit. The new version fails at 0 because of the scipen problem. Oh well. – ngm Jul 20 '18 at 20:30 • 91 bytes – Giuseppe Jul 24 '18 at 15:18 • 86 bytes – Giuseppe Jul 24 '18 at 15:21 # Husk, 12 bytes #ȯ§¤=Σ↓↑3↔d…  Try it online! ## Explanation #(§¤=Σ↓↑3↔d)… -- example input: 100000 101000 … -- inclusive range: [100000,100001..100999,101000] #( ) -- count elements where (example with 100010) d -- | digits: [1,0,0,0,1,0] ↔ -- | reversed: [0,1,0,0,0,1] § 3 -- | fork elements (3 and [0,1,0,0,0,1]) ↑ -- | | take: [0,1,0] ↓ -- | | drop: [0,0,1] ¤= -- | > compare the results by equality of their Σ -- | | sums 1 == 1 -- | : 1 -- : 3  • It seems your solution has the same flaw my initial version had: [000000, 001001] should result in 2 (000000 and 001001), but results in 1001 instead. (I added 1,000,000 and removed the trailing 1 as fix for that, not sure how easy / byte-efficient that is in Husk, though.) – Kevin Cruijssen Oct 9 '18 at 12:20 • @KevinCruijssen: I think I can remember this challenge was initially not clear, I don't have time to look into it rn, so I just rolled back to my initial submission which seems to be right. – ბიმო Oct 9 '18 at 14:19 # Charcoal, 15 bytes ＩＬΦ…·ＮＮ⁼Σι⊗Σ÷ιφ  Try it online! Link is to verbose version of code. Edit: I originally thought that it was the list of lucky numbers that was required. This can be done in 14 bytes (by removing the Ｌ, which takes the length of the list), or in 20 bytes if you want some nice formatting: ＥΦ…·ＮＮ⁼Σι⊗Σ÷ιφ﹪%06dι  Try it online! Link is to verbose version of code. Explanation:  ＮＮ Input the range endpoints …· Inclusive range Φ Filter ι Current value Σ Sum of digits ι Current value φ Predefined variable 1000 ÷ Integer divide Σ Sum of digits ⊗ Doubled ⁼ Equals Ｅ Map over results ι Current value %06d Literal string ﹪ Format value Implicitly print each result on its own line  ## Perl 5 + -pl -MList::Util+(sum), 49 bytes @F=/./g,$\+=sum@F[5,4,3]==sum@F[2,1,0]for$_..<>}{  Try it online! ## Perl 5 + -nl -MList::Util+(sum) -M5.010, 50 bytes To output each ticket instead is +1 byte: @F=/./g,sum@F[5,4,3]-sum(@F[2,1,0])||say for$_..<>


Try it online!

# Python 3, 89 86 bytes

-2 thanks to Mr. Xcoder.

-3 inspiring from Asone Tuhid answer's.

lambda a,b:sum(sum(map(int,str(i)))==2*sum(map(int,str(i)[-3:]))for i in range(a,b+1))


Tests results :

Example 1 :
a = 0
b = 1
Lucky numbers : 1

Example 2 :
a = 100000
b = 200000
Lucky numbers : 5280

Example 3 :
a = 123456
b = 654321
Lucky numbers : 31607

Example 3 :
a = 0
b = 999999
Lucky numbers : 55252


Try it online!

• In the counting version, sum can make any generator so the brackets [...] are not needed – Mr. Xcoder Jul 20 '18 at 15:13
• range(a,b+1) spec now states "inclusive" (if it were not you could use *r in place of a,b by the way - see my Python 2 answer). Also note that the spec now confirms it should indeed be the count that is output. – Jonathan Allan Jul 22 '18 at 13:25

# MATL, 24 bytes

&:1e3&\,!'%03d'&V2&sw]=s


Try it online!

(-2 bytes thanks to Luis Mendo.)

&: - Make an inclusive range between the two given numbers

1e3&\ - 'divrem' - divide by 1000 and get the reminders and floored quotients in two arrays.

, - do twice

!'03d'&V - transpose and convert each value to a zero-padded three-width string

&s - sum each row's values

w - switch to bring the reminder array out and do this again on that

] - end loop

= - check for equality (returns 1s in places where the arrays are equal)

s - sum those to get the count (implicit output)

# Kotlin, 152 119 bytes

{a:Int,b:Int->(a..b).map{String.format("%06d",it)}.filter{it[0].toInt()+it[1].toInt()+it[2].toInt()==it[3].toInt()+it[4].toInt()+it[5].toInt()}.count()}


Try it online!

Taking two integers than convert it into six symbol strings and count.

Optimized it thanks to mazzy and his solution to 119 bytes.

{a:Int,b:Int->(a..b).count{val d="%06d".format(it);(d[0]-'0')+(d[1]-'0')+(d[2]-'0')==(d[3]-'0')+(d[4]-'0')+(d[5]-'0')}}


Try it online!

• You can compact it until 133 bytes {a:Int,b:Int->(a..b).map{"%06d".format(it)}.filter{(it[0]-'0')+(it[1]-'0')+(it[2]-'0')==(it[3]-'0')+(it[4]-'0')+(it[5]-'0')}.count()} – mazzy Jul 23 '18 at 8:19

# dc, 44 bytes

sb[d]sD[dA00~[rA~rA~++rx]dx=D1+dlb!<L]dsLxkz


Takes two arguments from an otherwise empty stack, outputs to top of stack.

Try it online!

The clever bit here is the use of an unnamed (i.e., unstored) macro that's duplicated before execution in order to run a copy of itself on the other three-digit part.

# Explanation

The inner macro [rA~rA~++rx] has the effect "calculate the digit sum of the three digit number that is second-to-top on the stack, then execute the original top of the stack as a macro".

Main program:

sb             Saves the upper bound as b so we'll know when to quit
[d]sD          Defines the macro D, which contextually is "increment stack depth"
[              Start the main loop - the next number to test is on top
d              Make a copy to increment later for loop purposes
A00            The literal "1000"
~              Quotient and remainder, so "123456" is now "123 456"
[rA~rA~++rx]d  Stack is now "123 456 M M", where M is the anonymous macro
x              Run M on the stack "123 456 M", which (see definition
above) ends up running M on the stack "123 15", which
leaves "15 6" (and executes the 6, which is a no-op)
=D             If the two sums were equal, increment the stack depth
1+             Increment the current test number
dlb!<L         Loop unless the test number is now larger than b
]dsLx          Name and start the loop
kz             Current depth is 1+answer, so throw away top and return


# Pascal (FPC), 163 153 bytes

var a,b:Int32;begin read(a,b);for a:=a to b do if a div$186A0+a div$2710mod$A+a div$3E8mod$A=a div$64mod$A+a div$Amod$A+a mod$Athen b:=b+1;write(b-a)end.


Try it online!

## Explanation

Here is some normal-looking code first:

var a,b,i,s,c,d:Int32;
begin
s:=0;
for i:=a to b do begin
c:=i div 1000;
d:=i mod 1000;
if c div 100+(c div 10) mod 10+c mod 10=d div 100+(d div 10) mod 10+d mod 10 then begin s:=s+1; {writeln(i)} end;
end;
write('There are ',s,' numbers');
end.


Try it online!

Then I abused the behaviour of the for loop:

• the loop values are set beforehand (from a to b), so a can be reused as the loop variable, dropping i;
• at the end of the for loop, loop variable is left at the final value (value of b before the loop). I used b as a container, incrementing it when a lucky number is found and at the end of the loop b is away from its old value by amount of lucky numbers, so b-a gives the correct result. This dropped s.

Replacing d with operations directly on a shortens the loop. Replacing c with operations directly on a dose not shorten the loop, but, after dropping d, loop's begin and end are unnecessary and I ended with using only 2 variables :)

$ starts hexadecimal constants in the golfed code. While they do not save bytes, they eliminate spaces needed before decimal constants. # Java (OpenJDK 8), 162 bytes ... borrows from the Kotlin example above. import java.util.stream.IntStream; (a,b)->IntStream.range(a,b+1).mapToObj(i->String.format("%06d",i).getBytes()).filter(c->c[0]+c[1]+c[2]==c[3]+c[4]+c[5]).count();  Try it online! Comparing the sum of the String's bytes is just as good as summing up the actual digits. • You can save a byte by currying (a->b->), but you'll need to fully qualify IntStream since it's not in java.lang. – Jakob Jul 22 '18 at 15:31 • Welcome to PPCG! As @Jakob mentioned, imports are part of the byte-count, so you'll have to add the java.util.stream. in front of the IntStream to your code and byte-count. As also mentioned by Jakob, you can save a byte by using a->b->, and you can also save some additional bytes by changing String.format to "".format. Try it online: 139 bytes. Nice first answer, though. +1 from me. Enjoy your stay! – Kevin Cruijssen Jul 23 '18 at 12:39 # PHP, 131 bytes <?$f='array_sum(str_split(str_split(sprintf("%06d",$i),3)[';for($i=$argv[1]-1;$i++<$argv[2];)eval("$a+=f 0]))==f 1]));");echoa;  To run it: php -n <filename> <from> <to>  Example: php -n lucky_tickets.php 100 100000  # Perl 6, 51 49 bytes {+grep {[==] .flip.comb[^3,3..*]>>.sum},^a..^b}  Try it online! Anonymous code block that takes a two numbers and returns the number of lucky ones. Times out for larger inputs # Jelly, 9 8 bytes -1 thanks to Dennis (rµ...E)S -> r...E€S since everything vectorises.) rdȷD§E€S  A dyadic Link accepting the two endpoints of the range (either way around) which yields the count of lucky tickets. Try it online! Or see a test-suite ### How? Note that for any non-negative integer less than$1000000$,$N$, we can get two numbers with digits that sum to the required values to check using integer division by$1000$(yielding, say,$X=\lfloor\frac{N}{1000}\rfloor$) and its remainder (say$Y=N\mod{1000}$) ...that is,$N=1000\times X+Y$Now we want to compare the sums of the digits of$X$and$Y$for each$N\$ in a range and count those that are equal.

rdȷD§E€S - Link: integer a; integer b
r        - inclusive range [a,b] (either [a,a+1,a+2,...,b] or [a,a-1,a-2,...,b])
-                              e.g.: 0       or 78        or 7241
ȷ      - literal 1000
d       - divmod (vectorises)                [0,0]      [0,78]       [7,241]
D     - to decimal lists (vectorises)      [[0],[0]]  [[0],[7,8]]  [[7],[2,4,1]]
§    - sum each (vectorises)              [0,0]      [0,15]       [7,7]
E€  - for €ach: all equal?               1          0            1
S - sum (counts the 1s in the resulting list)

• E€S saves the µ. – Dennis Jul 22 '18 at 14:40
• @Dennis ah yes, I was working from another solution which did not vectorise everything along the way! – Jonathan Allan Jul 22 '18 at 18:38

# Powershell, 85 bytes

($args[0]..$args[1]|%{'{0:D6}'-f$_}|?{+$_[0]+$_[1]+$_[2]-eq+$_[3]+$_[4]+$_[5]}).count  Test script: $f = {

($args[0]..$args[1]|%{'{0:D6}'-f$_}|?{+$_[0]+$_[1]+$_[2]-eq+$_[3]+$_[4]+$_[5]}).count } @( ,((0,1), 1) ,((1000,2000), 3) ,((2000,3000), 6) ,((10000, 20000), 282) ,((101000, 102000), 6) ,((201000, 202000), 10) ,((901000, 902000), 63) ,((100000, 200000), 5280) ,((123456, 654321), 31607) #,((0, 999999), 55252) ) | % {$c, $e =$_
"      $c"$r = &$f$c[0] $c[1] "$($e-eq$r): actual=$r expected=$e"
}


Output:

      0 1
True: actual=1 expected=1
1000 2000
True: actual=3 expected=3
2000 3000
True: actual=6 expected=6
10000 20000
True: actual=282 expected=282
101000 102000
True: actual=6 expected=6
201000 202000
True: actual=10 expected=10
901000 902000
True: actual=63 expected=63
100000 200000
True: actual=5280 expected=5280
123456 654321
True: actual=31607 expected=31607


# Kotlin, 95 bytes

{a:Int,b:Int->(a..b).count{val d="%06d".format(it);d.chars().sum()==2*d.take(3).chars().sum()}}


.kt for test:

var  f = {a:Int,b:Int->(a..b).count{val d="%06d".format(it);d.chars().sum()==2*d.take(3).chars().sum()}}

fun main(args: Array<String>) {
println(f(0,1))             // 1
println(f(1000,2000))       // 3
println(f(2000,3000))       // 6
println(f(101000, 102000))  // 6
println(f(201000, 202000))  // 10
println(f(901000, 902000))  // 63
println(f(10000, 20000))    // 282
println(f(100000, 200000))  // 5280
println(f(123456, 654321))  // 31607
println(f(0, 999999))       // 55252
}


# Explanation

Count numbers from range where sum of all number digits is equal to double sum of first 3 digits.

# Stax, 14 bytes

ît║lYµß╖vYü╢^


Run and debug it, but be patient!

# Python 2,  83  80 bytes

-3 by using Asone Tuhid's observation - go give credit!

lambda a,b:sum(sum(map(int,v/1000))*2==sum(map(int,v))for v in range(a,b+1))


Try it online!

Much like my Jelly answer (but the inputs must be sorted here i.e. a<=b)

75 bytes for input a, b+1 (i.e. range excludes the right bound):

lambda*r:sum(sum(map(int,v/1000))*2==sum(map(int,v))for v in range(*r))


Try this one

## Clojure, 102 bytes

#(count(for[i(range %(inc %2)):when(=(let[d(map int(format"%06d"i))](apply +(map -(drop 3 d)d)))0)]i))


Mixing strings and math isn't too fun.

# J, 35 bytes

[:+/(6#10)([:=/_3+/\])@#:[+i.@>:@-~


Try it online!

# C (gcc), 90 88 bytes

l=10;u(c,k,y){for(y=0;c<=k;)c++%l+c/l%l+c/100%l-c/1000%l-c/10000%l-c/100000%l?:++y;c=y;}


Port of my Java answer. Try it online here. Thanks to ceilingcat for golfing two bytes.

Ungolfed:

l=10; // constant, we will be using the number 10 rather a lot
u(c, k, // function returning an integer and taking two integer arguments: lower and upper bound
y) { // abusing the argument list to declare a variable of type integer: the number of lucky tickets found in the range
for(y = 0; c <= k; ) // set count to 0 and loop through the range
c++ %l + c/l %l + c/100 %l // if the digit sum of the second half of the ticket number ...
- c/1000 %l - c/10000 %l - c/100000 %l // ... is the same as the digit sum of the first half ...
?: ++y; // ... it's a lucky ticket: increment the count
c = y; // return the count
}

• Suggest L'✐' instead of 10000 and assign 10 to a variable. – ceilingcat Aug 2 '18 at 3:01
• @ceilingcat I like that it gives me an extra variable name, but I couldn't save any bytes by assigning 10: bit.ly/2O5ND2Y As for the L'…' trick, that's neat; but does it save bytes? Seems to me that is a multi-byte character, so while saving chars, it can't save bytes … or can it? – O.O.Balance Aug 2 '18 at 13:15
• @ceilingcat My mistake, two bytes can be saved by assigning 10 to a variable. Thank you. – O.O.Balance Aug 2 '18 at 14:44

# Java 8, 101 99 bytes

u->l->{int n=0,d=10;for(;l<=u;)if(l++%d+l/d%d+l/100%d==l/1000%d+l/10000%d+l/100000%d)++n;return n;}


A different approach than the other Java answer. Instead of using streams and Strings, this uses a loop and evaluates the numbers directly. Try it online here.

Thanks to ceilingcat for golfing two bytes.

Ungolfed:

u -> l -> { // lambda taking two integer arguments in currying syntax and returning an integer
int n = 0, // the counter
d = 10; // auxiliary constant, we will be using the number 10 rather a lot
for(; l <=u ; ) // loop over all ticket numbers in the range
if(l++ %d + l/d %d + l/100 %d // if the digit sum of the second half of the number ...
== l/1000 %d + l/10000 %d + l/100000 %d) // ... is the same as the digit sum of the first half ...
++n; // ... it's a lucky ticket, add 1 to the counter
return n; // return the count
}


# VBA (Excel), 159 bytes

Using Immediate Window and Cells [A1] [A2] as input.

c=[A1]-[A2]:d=IIf(c<0,[A1],[A2]):For x=d To d+Abs(c):e=String(6-Len(x),"0")&x:For y=1To 3:i=i+Mid(e,y,1):j=j+Mid(e,7-y,1):Next:z=IIf(i=j,z+1,z):i=0:j=0:Next:?z


## F#, 110 bytes

let t=string>>Seq.sumBy(int>>(-)48)
let r s e=Seq.where(fun n->t(n/1000)=t(n-(n/1000)*1000)){s..e}|>Seq.length


Try it online!

t converts the string into numbers and sums them up. r takes the range of numbers from s to e, and filters out the numbers that are unlucky. The first three digits are collected by n/1000. The second three digits are computed by n-(n/1000)*1000`.