Ne m'en donne pas cinq!

38

Question:

Vous recevrez les entiers de début et de fin d'une séquence et devriez lui renvoyer le nombre d'entiers ne contenant pas le chiffre 5. Les numéros de début et de fin doivent être inclus!

Exemples:

1,9 → 1,2,3,4,6,7,8,9 → résultat 8

4,17 → 4,6,7,8,9,10,11,12,13,14,16,17 → résultat 12

50,60 → 60 → résultat 1

-59, -50 → → résultat 0

Le résultat peut en contenir cinq.

Le numéro de départ sera toujours inférieur au numéro de fin. Les deux nombres peuvent être aussi négatifs!

Je suis très curieux de vos solutions et de la façon dont vous le résolvez. Peut-être que quelqu'un d'entre vous trouvera une solution simple de mathématiques pures.

Edit Ceci est un défi code-golf, donc le code le plus court gagne.

Arasuvel
la source
3
@betseq: c'est proche; mais celui-ci a une plage variable (et ne nécessite aucun modulo).
Titus
4
Je recommanderais le code le plus court comme critère gagnant et la balise code-golf (je ne l'avais même pas vue!). En outre, vous devriez probablement mettre un scénario de test couvrant 50 ou 500; aussi peut-être un qui couvre -50, et un qui couvre 0 serait une bonne idée.
Jonathan Allan
1
@ JonathanAllan: Je vais mettre à jour des exemples.
Arasuvel
4
Cas de test: 50, 59 -> 0.
Zgarb
14
Vous dites: "Le numéro de départ sera toujours inférieur au nombre de fin." mais l'un de vos exemples (-50, -59) contredit directement ceci
theonlygusti

Réponses:

21

JavaScript (ES6), 36 33 octets

Prend les entrées avec la syntaxe de currying (a)(b).

a=>F=b=>b<a?0:!/5/.test(b)+F(b-1)

Formaté et commenté

a =>                 // outer function: takes 'a' as argument, returns F
  F = b =>           // inner function F: takes 'b' as argument, returns the final result
    b < a ?          // if b is less than a
      0              //   return 0
    :                // else
      !/5/.test(b) + //   add 1 if the decimal representation of b does not contain any '5'
      F(b - 1)       //   and do a recursive call to F with b - 1

Cas de test

Arnauld
la source
(Normalement , je préfère testplus execlorsque vous avez seulement besoin d' un booléen.)
Neil
@ Neil Cela fait plus de sens en effet. Mis à jour.
Arnauld
NB: Je ne trouvais aucun conseil sur la syntaxe de curry ES6, alors j'en ai écrit un .
Arnauld
5
@TheLethalCoder b<aest là pour arrêter la récursion après avoir compté tous les nombres de bà a, de sorte que son élimination ne ferait que provoquer une récursion infinie.
ETHproductions
1
@HristiyanDodov La fonction externe non nommée prend acomme argument et retourne la Ffonction, qui à son tour prend bpour argument et - comme vous l'avez remarqué - est appelée de manière récursive pour itérer de bà a, incrémentant un compteur pour tous les entiers ne contenant pas de valeur 5décimale. représentation.
Arnauld
17

Gelée , 8 7 octets

-1 octet grâce à Dennis (sachant que l'indexation dans un nombre traite ce nombre comme une liste décimale)

rAw€5¬S

TryItOnline!

Comment?

rAw€5¬S - Main link: from, to    e.g. -51, -44
r       - range(from, to)        e.g. [-51,-50,-49,-48,-47,-46,-45,-44]
 A      - absolute value         e.g. [51,50,49,48,47,46,45,44]
  w€    - first index of... for €ach (0 if not present)
    5   - five                   e.g. [1,1,0,0,0,0,2,0]
     ¬  - logical not            e.g. [0,0,1,1,1,1,0,1]
      S - sum                    e.g. 5

* La valeur absolue atome Aest nécessaire puisqu'un nombre négatif converti en une liste décimale a des entrées négatives, dont aucune ne sera jamais un 5(l'exemple donné compterait les huit au lieu de deux).

Jonathan Allan
la source
rAw€5¬Senregistre un octet.
Dennis
@ Dennis merci! Est-ce que ma description "traite ce nombre comme une liste décimale" est exacte?
Jonathan Allan
2
Plutôt. wconvertit un argument entier en chiffres décimaux.
Dennis
13

2sable , 6 5 octets

Enregistrement d'un octet grâce à Adnan

Ÿ5¢_O

Essayez-le en ligne!

Explication

 Ÿ      # inclusive range
  5¢    # count 5's in each element of the range
    _   # negate
     O  # sum

Remarque: cela fonctionne en raison d'un bogue ¢qui oblige la fonction à s'appliquer à chaque élément au lieu de compter les éléments correspondants dans la liste.

Emigna
la source
Vous pouvez supprimer le `car il se comporte de la même façon sur les tableaux: p.
Adnan
@Adnan: Merci! J'allais tester ça mais j'ai oublié;)
Emigna
9

Python2, 59 55 52 51 47 43 42 octets

f=lambda a,b:a<=b and-(`5`in`a`)-~f(a+1,b)

Une solution récursive. Merci à @xnor de me motiver à trouver une solution à l'aide d'opérateurs logiques! Merci également à @JonathanAllan et à @xnor de m'avoir guidé coupé l'octet de 43 à 42!

Autres tentatives à 43 octets

f=lambda a,b:a<=b and-~-(`5`in`a`)+f(a+1,b)
f=lambda a,b:a<=b and 1-(`5`in`a`)+f(a+1,b)
Yytsi
la source
Serait if!`x`.count('5')travailler?
Titus
2
@Titus Python a un notopérateur qui est !dans les langages de type C, mais cela prend 3 octets :(
Yytsi
1
Pensez à utiliser un court-circuit logique avec andet or.
xnor
1
Yup, bien fait! Maintenant, pensez à raccourcir cela not.
xnor
1
Tu es vraiment proche! Continuez d'essayer des trucs.
xnor
6

05AB1E , 8 7 6 octets

Enregistrement d'un octet grâce à Adnan

Ÿ5.å_O

Essayez-le en ligne!

Explication

Ÿ         # inclusive range
 5.å      # map 5 in y for each y in the list
    _     # logical negation 
     O    # sum
Emigna
la source
05AB1E also has vectorized å, which is , so you can do Ÿ5.å_O for 6 bytes.
Adnan
negate meaning -n, or n==0?1:0?
ETHproductions
@ETHproductions: Sorry, that was unclear. I meant logical negation, so n==0?1:0
Emigna
6

Pyth, 9 8 bytes

Saved a byte thanks to FryAmTheEggman!

lf-\5T}E

Explanation:

        Q # Input
      }E  # Form an inclusive range starting from another input
          #   order is reversed, but doesn't matter
 f-\5T    # Filter by absence of '5'
l         # Count the number of elements left

Try it online!

busukxuan
la source
5

Perl 6, 23 bytes

{+grep {!/5/},$^a..$^b}

Try it online!

How it works

{                     }  # A lambda.
              $^a..$^b   # Range between the two lambda arguments.
  grep {!/5/},           # Get those whose string representation doesn't match the regex /5/.
 +                       # Return the size of this list.
smls
la source
5

Haskell, 39 bytes

s!e=sum[1|x<-[s..e],notElem '5'$show x]

Try it online! Usage:

Prelude> 4 ! 17
12

Explanation:

             [s..e]                     -- yields the range from s to e inclusive
          x<-[s..e]                     -- for each x in this range
          x<-[s..e],notElem '5'$show x  -- if the char '5' is not in the string representation of x
       [1|x<-[s..e],notElem '5'$show x] -- then add a 1 to the resulting list      
s!e=sum[1|x<-[s..e],notElem '5'$show x] -- take the sum of the list
Laikoni
la source
4

R, 33 bytes

f=function(x,y)sum(!grepl(5,x:y))

Usage:

> f=function(x,y)sum(!grepl(5,x:y))
> f(40,60)
[1] 10
> f(1,9)
[1] 8
> f(4,17)
[1] 12
plannapus
la source
4

Groovy, 47 45 43 40 bytes

{a,b->(a..b).findAll{!(it=~/5/)}.size()}

This is an unnamed closure. findAll is similar to adding an if condition in a list comprehension in python.

Try it online!

Gurupad Mamadapur
la source
4

PHP 7.1, 57 55 bytes

for([,$a,$b]=$argv;$a<=$b;)$n+=!strstr($a++,53);echo$n;

Run with php -r '<code>' <a> <b>

Titus
la source
Isn't this PHP7.1 syntax?
aross
@aross: It is. But PHP 7.1 is older than 5 hours (pubished on December, 1)
Titus
1
of course, I just asked because I'm used to specifying the version if it's 7 or up. That's also kind of the convention for Python
aross
1
Convention for PHP - as far as I have seen - is to use the most recent version unless specified otherwise.
Titus
I don't think many people have the latest minor version. The least common denominator at the moment would probably be 5.5. Personally I'm using FC 25 (considered pretty cutting edge), which currently distributes PHP 7.0. If you're on Windows you probably need to update manually.
aross
4

Mathematica, 46 44 42 bytes

Thanks to alephalpha and DavidC for saving 2 bytes each!

Tr@Boole[FreeQ@5/@IntegerDigits@Range@##]&

Unnamed function taking two integer arguments and returning an integer. IntegerDigits@Range@## converts all the numbers between the inputs into lists of digits; FreeQ@5 tests those lists to decide which ones do not contain any 5. Then Boole converts booleans to zeros and ones, and Tr sums the results.

Other solutions (44 and 47 bytes):

Count[Range@##,x_/;IntegerDigits@x~FreeQ~5]&

IntegerDigits@x~FreeQ~5 determines whether the list of digits of a number is free of 5s, and Count[Range@##,x_/;...]& counts how many numbers between the inputs pass that test.

Tr[Sign[1##&@@IntegerDigits@#-5]^2&/@Range@##]&

1##&@@IntegerDigits@#-5 takes the list of digits of a number, subtracts 5 from all of them, and multplies the answers together; Sign[...]^2 then converts all nonzero numbers to 1.

Greg Martin
la source
1
Count[Range@##,x_/;IntegerDigits@x~FreeQ~5]&
DavidC
1
Tr@Boole[FreeQ@5/@IntegerDigits@Range@##]&
alephalpha
3

Ruby, 36 35 bytes

->a,b{(a..b).count{|x|!x.to_s[?5]}}

Thx IMP1 for -1 byte

G B
la source
1
Doesn't this return the list without the numbers containing 5, rather than the size of that list?
IMP1
You are right, I have copy/pasted the wrong version.
G B
1
You can also use ?5 (the '5' character) instead of /5/ in the search to save a byte.
IMP1
3

Java 7, 80 78 bytes

int c(int a,int b){int r=0;for(;a<=b;)r+=(""+a++).contains("5")?0:1;return r;}

Ungolfed:

int c(int a, int b){
  int r = 0;
  for (; a <= b; ) {
    r += ("" + a++).contains("5")
          ? 0
          : 1;
  }
  return r;
}

Test code:

Try it here.

class M{
  static int c(int a,int b){int r=0;for(;a<=b;)r+=(""+a++).contains("5")?0:1;return r;}

  public static void main(String[] a){
    System.out.println(c(1, 9));
    System.out.println(c(4, 17));
  }
}

Output:

8
12
Kevin Cruijssen
la source
3

PowerShell, 42 41 bytes

param($a,$b)$a..$b|%{$z+=!($_-match5)};$z

Called from the command line as .\no5s.ps1 1 20

mcmurdo
la source
1
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).
AdmBorkBork
Ah, nice, thanks @AdmBorkBork
mcmurdo
2

Python 2, 61 56 bytes

lambda a,b:len([n for n in range(a,b+1) if not"5"in`n`])

-5 bytes thanks to tukkaaX

sagiksp
la source
Don't get discouraged! Having fun and challenging yourself is what matters. You can remove two whitespaces at not "5" in :) Also, if you're using Python2, you can surround x with `` quotes, instead of doing str(x).
Yytsi
@TuukkaX Thanks! also removed space between in and `x`
sagiksp
You can remove the []. You also don't need the space before if.
Dennis
@Dennis I tried that already, but it complains that "object of type 'generator' has no len()".
Yytsi
@TuukkaX Right. lambda a,b:sum(not"5"in`n`for n in range(a,b+1)) works though. tio.run/nexus/…
Dennis
2

Swift 52 bytes

($0...$1).filter { !String($0).contains("5") }.count
Arasuvel
la source
Since your challenge is a codegolf challenge, you should include your bytecount. Also, in codegolf (at least here), it's a requirement that all programs muse be actually contending (e.g. your function name can be just a single character, your actual function can probably be reduced to a single line). I don't know Swift, you might have to correct me on stuff.
clismique
2

Batch, 95 bytes

@set/an=0,i=%1
:g
@if "%i%"=="%i:5=%" set/an+=1
@set/ai+=1
@if %i% leq %2 goto g
@echo %n%

Manually looping saves some bytes because I need the loop counter in a variable anyway.

Neil
la source
2

PHP, 56 bytes

for($i=$argv[1];$i<=$argv[2];)trim(5,$i++)&&$x++;echo$x;

Run like this:

php -r 'for($i=$argv[1];$i<=$argv[2];)trim(5,$i++)&&$x++;echo$x;' 1 9 2>/dev/null;echo
> 8

A version for PHP 7.1 would be 53 bytes (credits to Titus):

for([,$i,$e]=$argv;$i<=$e;)trim(5,$i++)&&$x++;echo$x;

Explanation

for(
  $i=$argv[1];          # Set iterator to first input.
  $i<=$argv[2];         # Loop until second input is reached.
)
  trim(5,$i++) && $x++; # Trim string "5" with the characters in the
                        # current number; results in empty string when
                        # `5` is present in the number. If that is not
                        # the case, increment `$x`

echo$x;                 # Output `$x`
aross
la source
Ah dang I forgot about the second trim parameter again.
Titus
2

CJam "easy pure mathematics solution", 60

{{Ab5+_,\_5#)<\9e]);_4f>.m9b}%}:F;q~_:z$\:*0>{((+F:-}{F:+)}?

Try it online

It takes the numbers in any order, in an array.

Explanation:

One core problem is to calculate f(n) = the number of non-5 numbers from 1 to n (inclusive) for any positive n. And the answer is: take n's decimal digits, replace all digits after the first 5 (if any) with 9, then replace all digits 5..9 with 4..8 (decrement), and convert from base 9. E.g. 1752 → 1759 → 1648 → 1*9^3+6*9^2+4*9+8=1259. Basically, each digit position has 9 acceptable values, and a 5xxxx is equivalent to a 49999 because there are no more valid numbers between them.

Once we solved this, we have a few cases: if the input numbers (say a and b, a<b) are (strictly) positive, then the result is f(b)-f(a-1). If they are negative, then we can take the absolute values, reorder them and use the same calculation. And if a<=0<=b then the result is f(-a)+f(b)+1.

The program first implements the function F as described above (but applied to each number in an array), then reads the input, converts the numbers to the absolute value and reorders them, and uses one of the 2 calculations above, based on whether a*b>0 initially.

aditsu
la source
Not "pure" but nice method. here, get a +1 :)
Matthew Roh
@MatthewRoh thanks, but what do you mean not pure? It's a solution that does fairly direct mathematical calculations on the input numbers, without iterating through the range. What else were you expecting?
aditsu
2

Python 2, 54 bytes

i,j=input();k=0
while i<=j:k+=not"5"in`i`;i+=1
print k

Try it online!

Not the shortest Python answer Uses same algorithm but a different way of implementing with a while loop and is not a lambda function.

ElPedro
la source
It is a program and not a function and it uses while instead of for. What is not different? OK, it is still looking for a string "5" inside the incremented input, agreed. Is there a better way?
ElPedro
That's exactly what it is and that's why it is deferent. Sorry, maybe should have made my comment different.
ElPedro
Same algorithm, different way of implementing. No problem with your comments. Is that better worded?
ElPedro
It is, yes :) I'll remove these comments to make the comment section look clean.
Yytsi
1

Java 7, 77 bytes

This is an improvement of Kevins Answer, but since I don't have the reputation to comment yet, this new answer will have to do.

So what I did was:

  • Replace the indexOf statements with contains (-1 byte)
  • Move the incrementing part of the for-loop into the conditional statement (-2 bytes)

for-loop (77 bytes):

int c(int a,int b){int r=1;for(;a++<b;)r+=(""+a).contains("5")?0:1;return r;}

recursive (79 bytes):

int d(int r,int a,int b){r+=(""+a).contains("5")?0:1;return a!=b?d(r,a+1,b):r;}

Output:

8
12

8
12

Test it here !

Tobias Meister
la source
Wellcome to PPCG ! Nice findings in an already quite nicely golfed answer. I don't know about Java that much but shouldn't (""+a).contains("5")?0:1 be replacable by !(""+a).contains("5")?
Christoph
1
@Christoph sadly no, since in Java a boolean really is just a boolean. So a ternary operation is the only way to go.
Tobias Meister
Hm that's sad. What about (""+a).contains("5")||r++?
Christoph
1
@Christoph that won't work either, because you can't have a boolean expression on its own. I've been trying to make it work in other places (like the for-loop declaration) but not with much success. Nice idea tho ;)
Tobias Meister
1

C#, 67 bytes

a=>b=>{int c=0;for(;a<=b;)c+=(a+++"").Contains("5")?0:1;return c;};
TheLethalCoder
la source
I was hoping to use for(int c=0;...) but then it fails to compile because the return is outside the scope for c
TheLethalCoder
1

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.

Hristiyan Dodov
la source
1
You can use c+=!/5/.test(s++) to save a few bytes :-)
ETHproductions
Thanks a lot! I had to delete my golfs, though. I was so proud of them. :(
Hristiyan Dodov
I think you can use currying i.e.` s=>e=>`
TheLethalCoder
The top answer uses currying syntax. I won't edit mine because it would become almost the same. Thanks for pointing that out, though!
Hristiyan Dodov
1

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
Suever
la source
1

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("")).

devRicher
la source
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.
Kevin Cruijssen
@KevinCruijssen Fixed.
devRicher
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=>
TheLethalCoder
Also this outputs the list not the count
TheLethalCoder
1
@KevinCruijssen With your edits this is essentially my answer...
TheLethalCoder
1

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
Mego
la source