44
\$\begingroup\$

Question :

You will be given the starting and ending integers of a sequence and should return the number of integers within it which do not contain the digit 5. The start and end numbers should be included!

Examples:

1,9 → 1,2,3,4,6,7,8,9 → Result 8

4,17 → 4,6,7,8,9,10,11,12,13,14,16,17 → Result 12

50,60 → 60 → Result 1

-59,-50 → → Result 0

The result may contain five.

The start number will always be smaller than the end number. Both numbers can be also negative!

I'm very curious for your solutions and the way you solve it. Maybe someone of you will find an easy pure mathematics solution.

Edit This is a code-golf challenge, so the shortest code wins.

\$\endgroup\$
9
  • 3
    \$\begingroup\$ @betseq: That´s close; but this one has a variable range (and requires no modulo). \$\endgroup\$
    – Titus
    Commented Jan 20, 2017 at 5:42
  • 4
    \$\begingroup\$ I'd recommend shortest code as winning criterion and the code-golf tag (I didn't even spot that it wasn't!). Also, you should probably should put a test case that spans 50 or 500; also maybe one that spans -50, and one that spans 0 would be a good idea. \$\endgroup\$ Commented Jan 20, 2017 at 5:45
  • 1
    \$\begingroup\$ @JonathanAllan : I will update examples. \$\endgroup\$
    – Arasuvel
    Commented Jan 20, 2017 at 5:51
  • 4
    \$\begingroup\$ Test case: 50, 59 -> 0. \$\endgroup\$
    – Zgarb
    Commented Jan 20, 2017 at 12:28
  • 14
    \$\begingroup\$ You say: "The start number will always be smaller than the end number." but one of your examples (-50,-59) directly contradicts this \$\endgroup\$
    – minseong
    Commented Jan 21, 2017 at 10:36

56 Answers 56

1
2
1
\$\begingroup\$

C#, 67 bytes

a=>b=>{int c=0;for(;a<=b;)c+=(a+++"").Contains("5")?0:1;return c;};
\$\endgroup\$
1
  • \$\begingroup\$ I was hoping to use for(int c=0;...) but then it fails to compile because the return is outside the scope for c \$\endgroup\$ Commented Jan 20, 2017 at 12:48
1
\$\begingroup\$

JavaScript (ES6), 58 56 49 bytes

let f =

(s,e)=>{for(c=0;s<=e;)c+=!/5/.test(s++);return c}

console.log(f(1, 9));
console.log(f(4, 17));
console.log(f(-9, -1));

Golfed 7 bytes thanks to ETHproductions.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ You can use c+=!/5/.test(s++) to save a few bytes :-) \$\endgroup\$ Commented Jan 20, 2017 at 12:41
  • \$\begingroup\$ Thanks a lot! I had to delete my golfs, though. I was so proud of them. :( \$\endgroup\$
    – dodov
    Commented Jan 20, 2017 at 12:55
  • \$\begingroup\$ I think you can use currying i.e.` s=>e=>` \$\endgroup\$ Commented Jan 20, 2017 at 12:58
  • \$\begingroup\$ The top answer uses currying syntax. I won't edit mine because it would become almost the same. Thanks for pointing that out, though! \$\endgroup\$
    – dodov
    Commented Jan 20, 2017 at 13:01
1
\$\begingroup\$

MATL, 10 bytes

&:!V53-!As

Try it online!

Explanation

        % Implicitly grab two input arguments
&:      % Create an array from [input1....input2]
!V      % Convert to a string where each number is it's own row
53-     % Subtract ASCII '5' from each character.
!A      % Detect which rows have no false values (no 5's). Returns a logical array
s       % Sum the logical array to get the # numbers without 5's
        % Implicitly display the result
\$\endgroup\$
1
\$\begingroup\$

C#, 77 bytes

(n,m)=>{var g=0;for(var i=n;i<m+1;i++)g+=(i+"").Contains("5")?0:1;return g;};

Anonymous lambda call.

Uses n (first number) and m (last number) as input, then checks via string containment ("".Contains("")).

\$\endgroup\$
9
  • \$\begingroup\$ I'm not the one downvoting, but modulo 5 isn't the correct solution for the challenge given by OP. It should exclude anything containing the digit 5 in its number, so 10 (which your answer wouldn't count) should be counted. \$\endgroup\$ Commented Jan 20, 2017 at 8:41
  • \$\begingroup\$ @KevinCruijssen Fixed. \$\endgroup\$
    – devRicher
    Commented Jan 20, 2017 at 11:02
  • \$\begingroup\$ This doesn't compile as g must be initialised when stated as it is named var so you need var g=""; and you can use currying i.e. n=>m=> \$\endgroup\$ Commented Jan 20, 2017 at 12:30
  • \$\begingroup\$ Also this outputs the list not the count \$\endgroup\$ Commented Jan 20, 2017 at 12:32
  • 1
    \$\begingroup\$ @KevinCruijssen With your edits this is essentially my answer... \$\endgroup\$ Commented Jan 20, 2017 at 14:53
1
\$\begingroup\$

Actually, 13 bytes

u@x`$'5íuY`░l

Try it online!

Explanation:

u@x`$'5íuY`░l
u@x            range(a, b+1)
   `$'5íuY`░   take where:
    $            string representation
     '5íuY       does not contain "5"
            l  length
\$\endgroup\$
1
\$\begingroup\$

PowerShell, 37 36 bytes

($args[0]..$args[1]-notmatch5).Count

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ You can drop the space to save a byte. With strictly numerical regex patterns, you don't need a delimiter (e.g., -replace3 or -split1 or -notmatch5). \$\endgroup\$ Commented Jan 20, 2017 at 15:09
  • \$\begingroup\$ Doh, how'd I miss that?! Thanks @AdmBorkBork \$\endgroup\$
    – briantist
    Commented Jan 20, 2017 at 15:11
1
\$\begingroup\$

CJam, 18 17 bytes

q~:S-){S+s'5&!},,

Input is end number followed by start number.

Try it online!

How it works

q~                  Read and evaluate all input. Pushes end and start.
  :S                Save the start in S.
    -)              Subtract and increment, computing L =: end - start + 1.
      {       },    Filter [0 ... L-1]; for each N in the range:
       S+             Add S to N.
         s            Cast to string.
          '5&         Intersect with '5'.
             !        Take the logical NOT.
                ,   Compute the length of the resulting array.
\$\endgroup\$
1
\$\begingroup\$

C 143 141 132 122 bytes

f(a,b){j=0,k,f;for(;a<=b;a++){k=a;f=0;while(k!=0){if(abs(k%10)==5){f=1;break;}else f=0;k/=10;}if(f<1)j++;}printf("%d",j);}

This is a solution that adopts a mathematical approach and checks every digit for number 5. Can definitely be shortened!

Ungolfed version:

  void f(int a,int b)
  { 
       int j=0,k=0,f=0;

       for(;a<=b;a++)     
       { 
          k=a;f=0;

          while(k!=0)
          {          

            if(abs(k%10)==5) // If one of the digits in the number is 5, set a flag and break while loop, else reset the flag and continue checking.
            {
              f=1; 
              break;
            }  
            else
              f=0;

            k/=10; 

          }        

       if(f<1)
         j++; 
      }
      printf("%d ",j);       


  }

@TuukkaX Thanks for saving 2 bytes.

@nmjcman101 Thanks for saving 9 bytes.

@nmjcman101 Thanks for saving 10 bytes more, make so much sense. :)

\$\endgroup\$
9
  • \$\begingroup\$ Redundant whitespace at &&. I think that you can do a^b in each case you check for disequality, such as abs(i%10)!=5. \$\endgroup\$
    – Yytsi
    Commented Jan 20, 2017 at 7:20
  • \$\begingroup\$ @TuukkaX I'm gonna have to modify this answer anyways since it would not work for 150, 500 \$\endgroup\$
    – Abel Tom
    Commented Jan 20, 2017 at 7:25
  • \$\begingroup\$ Useless whitespace at (f==0) j++. If f can't be negative, you can check whether f<1. \$\endgroup\$
    – Yytsi
    Commented Jan 20, 2017 at 13:02
  • \$\begingroup\$ @TuukkaX You're right! Updated! \$\endgroup\$
    – Abel Tom
    Commented Jan 20, 2017 at 13:14
  • \$\begingroup\$ You don't need the first if(a<b). OP says "The start number will always be smaller than the end number." \$\endgroup\$
    – nmjcman101
    Commented Jan 20, 2017 at 13:29
1
\$\begingroup\$

Perl 5, 29 bytes

perl -le 'print 0+grep!/5/,shift..shift' 4 17               #prints 12
\$\endgroup\$
1
  • \$\begingroup\$ Nice answer, welcome to the site! \$\endgroup\$
    – DJMcMayhem
    Commented Jan 23, 2017 at 18:21
1
\$\begingroup\$

C++, 84 81 + 16 = 100 97 bytes

int f(int a,int b){int c;while(a<=b)c+=!~std::to_string(a++).find('5');return c;}

#include<string> - +16

Ungolfed:

int func(int start, int end) {
  // Defaults to 0
  int count;

  // Iterates from start to end (inclusive) and increments the count by one
  // if '5' is not found
  while (start <= end)
    count += !~std::to_string(start++).find('5');

  return count;
}

The function itself should be pretty clear. I essentially just iterate from start (or a) to end (or b). The only more complex line is this:

count += !~std::to_string(start++).find('5');

However it is also easiy explained. find returns std::npos which is the maximum value size_t can hold (exact value depends on how the compiler defines it) when the character cannot be found. Which essentially means the it is an integer value filled with binary ones. ~ performs a binary not, meaning that the value is 0 when no 5 character could be found and not 0 when it could. Then ! converts it to a bool (0 => false, everything else => true) and itverts it. So now when the 5 could be found the value is false and true if it could not. Then it gets added to the count variable. (true => 1, false => 0).

Try it online!

@Christoph Thanks for giving me the idea to save 3 bytes

\$\endgroup\$
3
  • 1
    \$\begingroup\$ std::to_string(start++).find('5')<0; \$\endgroup\$
    – Christoph
    Commented Jan 23, 2017 at 9:28
  • 1
    \$\begingroup\$ @Christoph since size_t (the return type of find) is an unsiged integer the check < 0 is always false since -1 becomes int max. However using bitwise manipulation I managed to work out a short solution. Thanks for giving me the idea for it though! \$\endgroup\$
    – BrainStone
    Commented Jan 23, 2017 at 23:54
  • \$\begingroup\$ Damn you're right! nice that I could help anyway :) \$\endgroup\$
    – Christoph
    Commented Jan 24, 2017 at 11:56
1
\$\begingroup\$

TI-BASIC, 37 34 bytes

:Prompt A,B
:Delvar CFor(N,A,B
:C+not(inString(toString(N),"5→C
:End
:C

I believe count is correct, however toString() is only supported on the TI-84+ CE calculators which I do not have, so I was unable to count it or test it to make sure it runs correctly. I therefore counted it as 2 bytes in addition to the others which were counted directly on a TI-84.

Thx to Jakob Cornell for removing

\$\endgroup\$
2
  • \$\begingroup\$ Try DelVar C on line 2. Then you can combine lines 2 and 3. Also on line 4, not( should work in place of 0=. And finally, print and "return" C on the last line by omitting Disp. \$\endgroup\$
    – Jakob
    Commented Jan 20, 2017 at 17:32
  • \$\begingroup\$ Wow, thx, I'll make the changes. Looking at this again now, yeah I definitely wasn't thinking about cutting that down, especially with Disp C :( \$\endgroup\$ Commented Jan 25, 2017 at 9:41
1
\$\begingroup\$

Vyxal s, 5 bytes

ṡ5vc†

Try it Online!

Port of the 05ab1e/2sable answer

Explained

ṡ5vc†
ṡ     # inclusive range
 5vc  # is the number 5 in each number? 
    † # negate each item. s flag sums the list
\$\endgroup\$
1
\$\begingroup\$

Arturo, 36 bytes

$=>[enumerate&..&'x->¬in?{5}~{|x|}]

Try it!

$=>[                   ; a function where inputs are assigned to &
    enumerate&..&'x->  ; count in input range; assign current elt to x
        in?{5}~{|x|}   ; is the string "5" in x converted to a string?
        ¬              ; logical not
]                      ; end function
\$\endgroup\$
1
\$\begingroup\$

Lua, 65 bytes

n=0s,e=...for i=s,e do n=n+((i..''):find'5'and 0or 1)end print(n)

Try it online!

\$\endgroup\$
0
\$\begingroup\$

SimpleTemplate, 63 bytes

This was harder than expected.

Expects each number as a single parameter in the class, outputting the number of element without 5.

{@eachargv as_}{@if"~5~"is not matches_}{@incX}{@/}{@/}{@echoX}

Ungolfed

{@each argv as argument}
    {@if "~5~"is not matches argument}
        {@inc result}
    {@/}
{@/}
{@echo result}
\$\endgroup\$
3
  • \$\begingroup\$ If I read this right you are returning the list of numbers in the range, you need to return the count. \$\endgroup\$ Commented Jan 20, 2017 at 12:57
  • \$\begingroup\$ @TheLethalCoder Crap. Ignore this... \$\endgroup\$ Commented Jan 20, 2017 at 13:02
  • \$\begingroup\$ Fixed! (I hope...) \$\endgroup\$ Commented Jan 20, 2017 at 13:06
0
\$\begingroup\$

C#, 82 81 bytes

using System.Linq;a=>b=>Enumerable.Range(a,++b-a).Count(n=>(n+"").All(d=>d!=53));

Added as a separate answer as it's logic is different.

\$\endgroup\$
2
  • \$\begingroup\$ I think one of those two using System.Linq; should be removed (byte-count is correct, though). ;) \$\endgroup\$ Commented Jan 20, 2017 at 15:01
  • \$\begingroup\$ @KevinCruijssen Woops looks like I can't copy and paste! \$\endgroup\$ Commented Jan 20, 2017 at 15:03
0
\$\begingroup\$

Perl 6, 21 bytes

+(+*..+*).grep:{!/5/}

Basically equivalent to smls's solution, but I was able to shave off a couple of bytes by expressing the range as (+*..+*) and eliminating the brackets. (The plusses are necessary, otherwise the stars would be interpreted as negative or positive infinity rather than as arguments to the WhateverCode lambda.)

\$\endgroup\$
0
\$\begingroup\$

Perl, 35 20+1 bytes

$\+=!/5/ for$_..<>}{

After considerable help from @Dada in the comment below, this turned into a beautiful 20 bytes - plus 1 for the p. I've left my original answer below, for posterity.

for(shift..shift){$z+=!/5/}print$z;

Call from command line as no5s.pl 1 20.

First Perl golf, so hopefully someone can improve it :)

Also using Strawberry Perl on Windows, so I can run no5s.pl 1 20 directly on the command line and it works - might try using perl -e ...

\$\endgroup\$
1
  • \$\begingroup\$ Nice first Perl golf. shift..pop will save you one 2 bytes. Using the for in statement modifier position ($z+=!/5/ for shift..pop) should save3 more bytes. Using $\ instead of $z should save two bytes (since just print with no argument will print it). Drop the last semi column. And finally, you can combine all of this and take the numbers from stdin instead of @ARGV. It becomes then perl -pe '$\+=!/5/ for$_..<>}{' (with a little trick with -p and }{, see here). \$\endgroup\$
    – Dada
    Commented Jan 20, 2017 at 15:18
0
\$\begingroup\$

Scala, 51 bytes

(a:Int,b:Int)=>a to b map{_+""indexOf "5"}count(0>)

I haven't been able to concisely combine the map and count.

\$\endgroup\$
0
\$\begingroup\$

Clojure, 64 bytes

#(count(for[i(range % (inc %2)):when(not(some #{\5}(str i)))]i))
\$\endgroup\$
0
\$\begingroup\$

Clojure, 73 bytes

(fn[i a](count(for[n(range i(inc a)):when(every? #(not=\5 %)(str n))]n)))

I had to rollback my previous "improvement", as somehow count was dropped from the new version, and it ended up being longer when I fixed it.

Filters the range of numbers; selecting only the numbers where every digit is not a 5.

(defn count-minus-5 [mi ma]
  (count ; Get the length of the resulting list
    ; Comprehension over the range mi(n) to ma(x).
    (for [n (range mi (inc ma))
          ; Only allow the number when every digit isn't a 5.
          :when (every? #(not= \5 %) (str n))]
      n)))
\$\endgroup\$
3
  • \$\begingroup\$ I think your answer is missing a count, the function "...should return the number of integers within it...". \$\endgroup\$
    – NikoNyrh
    Commented Jan 21, 2017 at 12:53
  • \$\begingroup\$ @NikoNyrh That'd weird. Somehow it got taken out of the golfed version (note the preformed version has it). I'll update it in a bit. \$\endgroup\$ Commented Jan 21, 2017 at 14:33
  • \$\begingroup\$ *preformed -> pregolfed \$\endgroup\$ Commented Jan 21, 2017 at 14:43
0
\$\begingroup\$

C++ (function), 115

int f(int a,int b){int r=b-a+1,t;while((t=a++)<=b)while(t!=0)if(abs(t)%10==5){r--;break;}else t/=10;std::cout<<r;}

C++ (full), 143

#include<iostream> 
int main(){int a=0,b=4,r=b-a+1,t;while((t=a++)<=b)while(t!=0)if(abs(t)%10==5){r--;break;}else t/=10;std::cout<<r;return 0;}

Ungolfed version:

#include<iostream> 
int main()
{
    int a=0, b=4, r = b-a+1, t;
    while((t = a++) <= b)
        while(t != 0)
            if(abs(t) % 10 == 5)
            {
                r--;
                break;
            }
            else 
                t /= 10;
    std::cout<<r;
    return 0;
}
\$\endgroup\$
0
\$\begingroup\$

Java 8, 68 bytes

(a,b)->IntStream.range(a,b+1).map(i->(""+i).contains("5")?0:1).sum()

This is basically just a rewrite of the Java7 solution by @Kevin Cruijssen to Java8. And I hope we don't care about imports here, otherwise it would be longer by 17 bytes due to the package).

Ungolfed:

(a,b)->IntStream.range(a,b+1)
  .map(i->(""+i).contains("5")?0:1)
  .sum()

Test code:

Try it here.

import java.util.function.BiFunction;
import java.util.stream.IntStream;

class M {
  public static void main (String[] args) {
    BiFunction<Integer, Integer, Integer> dontGimme5 = 
      (a,b)->IntStream.range(a,b+1).map(i->(""+i).contains("5")?0:1).sum();
    System.out.println(dontGimme5.apply(1,9));
    System.out.println(dontGimme5.apply(4,17));
    System.out.println(dontGimme5.apply(-50,-59));
  }
}

Output:

8
12
0
\$\endgroup\$
0
\$\begingroup\$

C++, 187 bytes

int f(int a,int b){int r=0;for(int i=a;i<=b;i++){r++;for(int j=0;j<floor(log(abs(i)));j++){int k=floor(abs(i)%int(pow(10,j+1))/pow(10,j));if(k==5){r--;break;}}}return r;}

#include <cmath> - 16 bytes

I couldn't think of a purely mathematical way, so I did this.

  1. Loop through a to b
  2. Calculate the length with floor(log(abs(i)))
  3. Get numbers of each digit with floor(abs(i)%int(pow(10, j + 1)) / pow(10,j))
  4. If it is 5, subtract then move to next number

Still, isn't practical for code-golf, but used much math as I could.

Try it online!

\$\endgroup\$
4
  • 2
    \$\begingroup\$ You can remove all the unnecessary space to save bytes \$\endgroup\$
    – user41805
    Commented Jan 23, 2017 at 9:21
  • \$\begingroup\$ @KritixiLithos Forgot it. thanks! by the way, do you like how it works? \$\endgroup\$ Commented Jan 23, 2017 at 9:23
  • 1
    \$\begingroup\$ By moving the int declarations around, you can save some bytes: tio.run/nexus/… \$\endgroup\$
    – user41805
    Commented Jan 23, 2017 at 9:30
  • \$\begingroup\$ somewhat around i/pow(10,j)%10 should save a lot of bytes. j<9 should work, too. There's still a lot to golf, keep trying ! \$\endgroup\$
    – Christoph
    Commented Jan 24, 2017 at 13:59
0
\$\begingroup\$

QBIC, 33 32 bytes

Saved a byte by reversing the conditional and moving the increment to ELSE

::[a,b|~instr(!c$,@5`)|\d=d+1}?d

Explanation:

::       get a and b from the command line
[a,b|    FOR c = a; c <= b; c++
~instr(  IF indexOf ( instr is a QBasic function that doesn't have a QBIC equivalent)
    !c$  our loop iterator cast to string
    ,@5` a literal 5
)        instr returns 0 if it didn't find '5', which is truthy.
|        THEN --> Don't do anything for values with a '5'
\d=d+1   ELSE count this number into the total
}        Close all constructs (END IF, NEXT c)
?d       Print 'd': the total number of numbers without a '5'
\$\endgroup\$
0
\$\begingroup\$

TI-Basic, 43 bytes

Since linear regression to string is so costly, let's try a different approach.

DelVar AInput 
For(I,X,Y
1
For(J,1,9
Ans and 5≠int(10fPart(I/10^(J
End
A+Ans→A
End

Old method, 55 bytes

Majority of the program size is converting number to string through linear regression... why wasn't there a built-in for this?

DelVar AInput 
For(I,X,Y
{0,1→L₁
{0,A→L₂
LinReg(ax+b) Y₁
Equ►String(Y₁,Str1
A+not(inString(Str1,"5→A
End

P.S. (For both methods:) Since the last statement evaluated by the program is that seventh line, it will return the value as normal through Ans. Also, Input stores to X and Y similar to Prompt X,Y.

\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.