How many 1's we get

Description

Count how many occurrences there are of the digit 1 between two given numbers $$\[a, b]\$$, inclusive.

For example, from 1 to 100 it should be 21:

1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 31, 41, 51, 61, 71, 81, 91, 100

The number 1 is repeated 21 times.

Rules

1. Each number in the input list is guaranteed is an integer in the range $$\0 \leq a \leq b < 2^{32}\$$.
2. The shortest answer in bytes wins.

Test cases

[1, 100] -> 21
[11, 200] -> 138
[123, 678] -> 182


Example

Here is my code using bash

eval echo {$1..$2}|grep -o 1|wc -l

• @Giuseppe, close, yeah. But the one I'm thinking of definitely took no input and used decimal, not binary. Obviously, it was a terrible challenge but, if I can find it, it's a definite dupe target. It's also extremely likely that my stupid broken brain is lying to me and no such challenge exists! Aug 6, 2020 at 21:50
• @Shaggy I also definitely remember that challenge.
– xnor
Aug 7, 2020 at 3:47
• are we to assume base-10 only? Aug 7, 2020 at 11:25
• Is the eval needed in your example?
– CSM
Aug 7, 2020 at 18:29
• you can also directly use grep -c 1 instead of grep -o 1| wc -l. Aug 8, 2020 at 5:57

05AB1E, 5 4 bytes

Thanks a lot to OP! Now I can save a byte

ŸSΘO


Try it online!

Explanation

Ÿ    Inclusive range
S   Split the string into individual chars
Θ  (Vectorizes) Does this character == "1"?
O Sum the resulting list

• I had the same in mind, but you beat me to it. A minor alternative is SΘO instead of J1¢. :) Aug 6, 2020 at 10:36
• You didn't had to change your original approach. The J1¢ is just as valid as SΘO. ;) Aug 6, 2020 at 10:39
• @KevinCruijssen Well, I read "a minor alternative" as "the way to make my answer more idiomatic"...
– user96495
Aug 6, 2020 at 10:41

Python 2, 39 36 bytes

-3 bytes thanks to @SurculoseSputum

lambda a,b:range(a,b+1).count('1')


Try it online!

Python 3, 42 40 bytes

-2 bytes thanks to @JoKing

lambda a,b:f"{*range(a,b),b}".count('1')


Try it online!

• In the Python 2 version, you can use back tick range(a,b+1) to save 3 bytes Aug 6, 2020 at 17:58

Rust+itertools, 42 bytes

|a,b|(a..=b).join("").matches('1').count()


Try it in the Rust Playground!

APL (Dyalog Extended), 9 bytes

+/'1'=⍕⍤…


Try it online!

+/ sum

'1'= where the character is equal to

⍕ the string representation

⍤ of

… the range

Octave, 29 28 27 bytes

@(x,y)sum(mat2str(x:y)==49)


Try it online!

• You can remove the square brackets. Also, does 48 work instead of "1"? Aug 6, 2020 at 12:40
• Luis probably meant 49, since 48 is zero? Aug 6, 2020 at 16:31

Java 8, 7167 66 bytes

a->b->{var s="";for(;b>=a;)s+=b--;return~-s.split("1",-1).length;}


-4 bytes thanks to @OlivierGrégoire.

Try it online.

Explanation:

a->b->{                // Method with two integer inputs and integer return-type
var s="";            //  String s, starting empty
for(;b>=a;)          //  Loop b downwards in the range [b, a]:
s+=b--;            //   And append b to to String s
return~-s.split("1", //  Split String s on "1",
-1)  //  and keep empty trailing items
.length;    //  Then get the amount of parts of this array
//  And decrease it by 1 with ~-, before turning it as result

• Nice use of the --> operator ;-)
– Neil
Aug 6, 2020 at 11:09
• 67 bytes Aug 6, 2020 at 19:17
• @OlivierGrégoire Thanks! And 1 more byte by using ~- instead of -1 to get rid of the space. :) Aug 6, 2020 at 21:17
• 3 different forms of writing -1 in one answer? I approve! 😁 Aug 6, 2020 at 22:13

R, 43 bytes

function(x,y)sum(unlist(gregexpr(1,x:y))>0)


Try it online!

• Nice! I had this at 44; regex were definitely the way to go. Aug 6, 2020 at 18:17

Ruby, 6246 28 bytes

->c,d{[*c..d].join.count ?1}


-18 bytes, courtesy of Dingus.

Try it online!

• 28 bytes Aug 6, 2020 at 11:41

JavaScript (ES6), 44 bytes

Expects (a)(b).

a=>g=b=>b<a?0:(b+g).split(1).length-3+g(b-1)


Try it online!

How?

We use a recursive function g to count how many 1's we have in b and decrement b until it's lower than a.

In order to count the 1's, we have to coerce b to a string. We could do b+'' but it's shorter to use b+g. Because the source code of g itself contains two 1's, we subtract 3 instead of just 1 from the result of (b+g).split(1).length.

Retina 0.8.2, 36 32 bytes

\d+
$*_ (?<=(_+) _*)(?=\1)$.'
1


Try it online! Link includes test cases. Explanation:

\d+
$*_  Convert a and b to unary, but use _ instead of 1 to avoid confusion. (In Retina 1 this would just be *, saving 2 bytes.) (?<=(_+) _*)(?=\1)$.'


At each boundary in b up to and including a from the end, insert the distance to the end in decimal, thus generating the range from b down to a.

1


Count the resulting number of 1s.

• Out of curiosity: if it's shorter in Retina instead of Retina 0.8.2, why not just post that version instead? At least, that's what I usually do with 05AB1E / 05AB1E (legacy) / 2sable. Sometimes bytes can be saved by switching the language to a previous or later version. Aug 6, 2020 at 13:34
• @KevinCruijssen I prefer to answer in Retina 0.8.2 if it's reasonably possible, only using Retina when I need a few feature, e.g. randomness.
– Neil
Aug 6, 2020 at 15:41
• Ah ok. Is there a reason why you prefer to answer in 0.8.2? Tbh, I was the same a few years back with only answering in Java 7, even though Java 8 with lambdas was always shorter, so I can definitely relate. :) Aug 6, 2020 at 15:42
• Maybe I'm just trying to show off how well I can golf by deliberately using an "inferior" language? (Having said that, I've just golfed off 4 bytes...)
– Neil
Aug 6, 2020 at 15:51

=SUM(ArrayFormula(LEN(REGEXREPLACE(""&SEQUENCE(A2-A1+1,1,A1),"[^1]",


Sheets auto-closes parens.

This is super slow at large ranges, but as this is Code Golf, we're here to optimize character count. My first attempt was to use JOIN(SEQUENCE(...)) to make one long string then count the 1's, but as it turns out, Sheets has a limit of 50000 characters, so that didn't work.

{x:Int,y:Int->(x..y).sumBy{"$it".count{it=='1'}}}  Try it online! Haskell, 26 bytes a!b=sum[1|'1'<-show[a..b]]  Try it online! MathGolf, 8 bytes ↨æ▒m┴Σ]Σ  Try it online. Explanation: ↨ # Loop in the range [a,b] using the two implicit inputs a,b, æ # and execute the following four commands: ▒ # Convert the integer to a list of digits m # Map over each digit: ┴ # And check which are equal to 1 (1 if 1; 0 otherwise) Σ # Get the sum of those checks ] # After the loop, wrap all values on the stack into a list Σ # And sum this list # (after which the entire stack joined together is output implicitly as result)  Perl 5-p, 21 bytes map$\+=y/1//,$_..<>}{  Try it online! • 20 bytes: $\+=y/1//for$_..<>}{ – Zaid Aug 8, 2020 at 14:12 PowerShell, 40 bytes $a,$b=$args
($a..$b|sls 1 -a|% m*).Count


Try it online!

($args-join'..'|iex|sls 1 -a|% m*).Count  Try it online! PHP, 46 45 bytes fn($a,$b)=>substr_count(join(range($a,$b)),1)  Try it online! C (gcc), 58 bytes i;c;f(a,b){for(c=0;b/a;)for(i=a++;i;i/=10)c+=i%10==1;a=c;}  Try it online! Factor, 65 bytes : f ( a b -- n ) [a,b] [ number>string [ 49 = ] count ] map sum ;  Try it online! K (oK), 19 17 bytes Solution: {+/"1"=,/$x_!1+y}


Try it online!

Explanation:

Range generation is inefficient (i.e. generate range 0..Y and then drop from front, rather than generating range X..Y) but saves 2 bytes.

{+/"1"=,/$x_!1+y} / the solution { } / lambda taking implicit x & y args 1+y / add 1 to y ! / range 0..N x_ / drop (_) x items from front$        / convert to string
,/         / flatten
"1"=           / is string equal to "1"?
+/               / sum

• Not worth it's own answer, but 16 bytes is possible in ngn/k. Nov 14, 2020 at 21:57

JavaScript (ES6), 63 62 bytes

a=>b=>([...Array(b-a+1)].map((_,i)=>i+a)+'').split(1).length-1


Try it online

[...Array(b-a+1)] // an array of length b-a+1
map((_,i)=>i+a)   // fill it with numbers from a to b
+''               // convert it to a string with each number separated by a comma
.split(1)         // split at each 1
.length-1         // count the chunks and subtract 1


-1 byte thanks to @Jo King

• Nice first solution! You can take input curry'ed to save a byte
– Jo King
Aug 9, 2020 at 10:39
• @JoKing appreciate that. I was reluctant to post since there were so many great solutions. Aug 9, 2020 at 14:28

J, 19 16 bytes

-3 bytes thanks to Jonah!

1#.1=/&":[,-.&i.


Try it online!

• 1#.1=/&":[,-.&i. for 16 bytes Sep 4, 2020 at 17:07
• @Jonah Thank you, yours is much better! Sep 4, 2020 at 18:31

Japt, 5 bytes

The spec contradicts itself as to whether the range should be inclusive or not. If it shouldn't then replace õ with o.

õ ¬è1


Try it

• You will need to add V after õ since the challenge now asks for inclusive range between a to b rather than inclusive range between 1 and a Aug 7, 2020 at 10:45

Rust, 63 bytes

|a,b|(a..=b).map(|x|format!("{}",x).matches('1').count()).sum()


Try it online!

MATL, 7 bytes

&:V1V=s


Try it online!

Explanation

&:V1V=s
=s  % Count occurrences
1V    % of '1' in
V      % string of
&:       % inclusive range of input


Java (OpenJDK 8), 80 bytes

a->b->IntStream.range(a,b+1).flatMap(i->(""+i).chars()).filter(x->x==49).count()


Try it online!

Doesn't need much of an explanation, but here's one anyways:

Function<Integer, Function<Integer, Long>> f =
a -> b->
IntStream
.range(a,b+1) //Create an IntStream going from a to b
.flatMap(i -> //Map every int i in that stream
(""+i)      //Make it a string
.chars()    //Turn that string to an IntStream
)    //Flatten that
.filter(x -> x == 49)  //Keep all the '1's
.count();              //Find out how many '1's there are


Jelly, 5 bytes

rDFċ1


Try it online!

Explanation:

rDFċ1
r      range of the inputs
DF    make decimal and flatten; list of all the digits in the range
ċ1  count occurences of 1


Pyth, 8 7 bytes

-1 byte thanks to @FryAmTheEggman

/}QE"1


Try it online!

Explanation

/}QE"1
}QE     # Inclusive range on input
        # string of the range ([1, 2, 3] -> "[1, 2, 3]")
/    "1   # count ones

• Since the list characters don't matter, you can just use backtick instead of jk. Aug 6, 2020 at 17:04

Wolfram Language (Mathematica), 29 bytes

Tr@DigitCount[Range@##,10,1]&


Try it online!

Dart, 56 bytes

f(a,b)=>'1'.allMatches([for(;a<=b;a++)a].join()).length;
`

Try it online!