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 • 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). 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. Jul 20 '18 at 12:57
• @Adnan Thanks, that's indeed a pretty nice way to handle it. Jul 20 '18 at 13:19
• It is the count that is required (and the output does not require leading zeros), so 13. Jul 22 '18 at 11:05

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 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. 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.toInt()+it.toInt()+it.toInt()==it.toInt()+it.toInt()+it.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')+(d-'0')+(d-'0')==(d-'0')+(d-'0')+(d-'0')}}

Try it online!

• You can compact it until 133 bytes {a:Int,b:Int->(a..b).map{"%06d".format(it)}.filter{(it-'0')+(it-'0')+(it-'0')==(it-'0')+(it-'0')+(it-'0')}.count()} 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+c+c==c+c+c).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. 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! Jul 23 '18 at 12:39 PHP, 131 bytes <?$f='array_sum(str_split(str_split(sprintf("%06d",$i),3)[';for($i=$argv-1;$i++<$argv;)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)      [,]  [,[7,8]]  [,[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 µ. Jul 22 '18 at 14:40
• @Dennis ah yes, I was working from another solution which did not vectorise everything along the way! Jul 22 '18 at 18:38

Powershell, 85 bytes

($args..$args|%{'{0:D6}'-f$_}|?{+$_+$_+$_-eq+$_+$_+$_}).count Test script:$f = {

($args..$args|%{'{0:D6}'-f$_}|?{+$_+$_+$_-eq+$_+$_+$_}).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 $c "$($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
• Powershell? I really didn't see that one coming :D Jul 26 '18 at 14:46

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. 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? Aug 2 '18 at 13:15
• @ceilingcat My mistake, two bytes can be saved by assigning 10 to a variable. Thank you. 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.