Les chiffres sacrés


44

Dans de nombreuses polices (en particulier dans la police Consolas ), 5 «chiffres décimaux» ont des «trous». Nous appellerons ces chiffres sacrés:

46890

Les 5 chiffres impies sont donc:

12357

Un entier peut donc être classé comme "sacré" s'il ne contient que des chiffres sacrés, et "impie" dans le cas contraire. Parce que -c'est impie, aucun entier négatif ne peut être saint.

Les entiers sacrés peuvent être classés en fonction de leur nombre de trous. Par exemple, les chiffres suivants ont une sainteté de 1:

469

Et ces chiffres ont une sainteté de 2:

80

Nous disons que la sainteté globale d'un entier est la somme de la sainteté de ses doigts. Par conséquent, 80aurait une sainteté de 4 et 99aurait une sainteté de 2.

Le défi

Soit deux entiers n > 0et h > 0sort le nentier saint dont la sainteté est au moins h. Vous pouvez supposer que les entrées et les sorties ne seront pas supérieures au nombre entier représentable maximum dans votre langue ou 2^64 - 1, selon la valeur la moins élevée.

Voici une liste des 25 premiers entiers sacrés avec la sainteté h >= 1, pour référence:

0, 4, 6, 8, 9, 40, 44, 46, 48, 49, 60, 64, 66, 68, 69, 80, 84, 86, 88, 89, 90, 94, 96, 98, 99

Les 25 premiers entiers sacrés avec la sainteté h >= 2sont:

0, 8, 40, 44, 46, 48, 49, 60, 64, 66, 68, 69, 80, 84, 86, 88, 89, 90, 94, 96, 98, 99, 400, 404, 406

Connexes - 1 2
Mego

26
J'étais assis ici pendant une trentaine de secondes à penser "comment diable 0a une sainteté de deux" avant de cliquer enfin sur le lien wikipedia vers Consolas
undergroundmonorail

Le cinquième numéro 1-Saint est-il 9 ou 40?
Conor O'Brien

3
Est-ce juste une coïncidence si le 8ème chiffre 8 + saint est 8888? (oui, probablement, mais ça m'amuse quand même ...)
Toby Speight

5
En fait, puisque vous pouvez avoir n'importe quel nombre de zéros en tête avant un nombre, vous pouvez affirmer que 0 est infiniment saint. Bien que soit apparemment aussi saint. Mais étrangement, 666 est encore plus saint ...
Darrel Hoffman

Réponses:


6

Pyth, 32 octets

e.fg*g.{`46890J`Z++lJ/J`8/J`0QE0

Explication

                                 - autoassign Q = eval(input())
 .f                           E0 -  first eval(input()) terms of func V starting Z=0

     g.{`46890J`Z                -    Are all the digits in Z in "46890"?
               `Z                -      str(Z)
              J                  -     autoassign J = ^
     g                           -    is_subset(V,^)
      .{`46890                   -     set("46890")

    *                            -   ^*V (Only return non-zero if only contains holy numbers)

                 ++lJ/J`8/J`0    -    Get the holiness of the number
                   lJ            -      len(J)
                  +              -     ^+V
                     /J`8        -      J.count("8") 
                 +               -    ^+V
                         /J`0    -     J.count("0")
   g                         Q   -  ^>=Q (Is the holiness great enough)
e                                - ^[-1]

Essayez ici

Prend la saisie sous la forme h \n n


12

Ruby, 109 105 95 82 octets

->n,h{(?0..?9*99).select{|x|x.count('469')+2*x.count('80')>=h&&/[12357]/!~x}[n-1]}

C’est la terrible approche "calculer entre 0 et 99999999999 ..." qui a 13 octets de moins que son équivalent paresseux. Cependant, il est peu probable que cette version se termine avant la mort de l'univers par la chaleur. De toute façon, une valeur de 13 octets ¯ \ _ (ツ) _ / ¯

Vous pouvez tester des valeurs plus petites en changeant ?9*99, disons, '99999'.

Voici l'ancienne version (95 octets, avec une évaluation paresseuse, qui tourne presque instantanément plutôt que presque jamais):

->n,h{(?0..?9*99).lazy.select{|x|x.count('469')+2*x.count('80')>=h&&/[12357]/!~x}.first(n)[-1]}
->n,h{
(?0..?9*99)  # range '0' (string) to '9' repeated 99 times, way more than 2**64
.lazy        # make the range lazy, so we can call `select' on it
.select{|x|  # choose only elements such that...
 x.count('469')+2*x.count('80')  # naive holiness calculation
 >=h         # is at least h
 &&/[12357]/!~x                  # naive "is holy" calculation
}
.first(n)    # take the first n elements that satisfy the condition
[-1]         # choose the last one from this array
}

Je dois aimer l'évaluation paresseuse :)
Emigna 17/02/2016

Pourquoi pas takeau lieu de first?
Pas que Charles

@NotthatCharles takerenvoie Lazy, qui ne peut pas être indexé.
Poignée de porte

6

Python 3, 103

lambda n,h,l='4698080':[y for y in range(2**64-1)if(sum(l.count(x)-(x not in l)for x in str(y))>=h)][n]

Voici une solution qui utilise une approche plus efficace en termes de mémoire, mais utilise le même algorithme si vous souhaitez le tester.

l='4689080'
def f(n,h):
 c=i=0
 while i<n:
  if sum(l.count(x)-(x not in l)for x in str(c))>=h:u=c;i+=1
  c+=1
 return u

Cas de test:

assert f(3, 1) == 6
assert f(4, 2) == 44

@ Mego Cool. Il semble utiliser une quantité de mémoire statique, de sorte qu'il ne risque pas de manquer de mémoire. Je n'étais juste pas sûr puisque cela fait déjà une demi-heure que ma machine tourne.
Morgan Thrapp

En fait, il faut une bonne quantité de temps pour calculer 2**64-1; voir stackoverflow.com/questions/34113609/…
Mego

@ Mego Oh, je n'y avais même pas pensé. Oui, lorsque je mets la constante précalculée dans le code, elle commence à grignoter un peu de RAM.
Morgan Thrapp

6

PowerShell, 163 150 141 101 98 96 octets

param($n,$h)for(--$i;$n){if(++$i-notmatch"[12357]"-and($i-replace"8|0",11).Length-ge$h){$n--}}$i

Prend les entrées, puis boucle jusqu'à $nzéro. Nous réglons initialement $i=-1en utilisant une astuce de pré-traitement, ce qui fonctionne car $i, n'ayant pas encore été déclaré, is $null. Ensuite, nous --, ce qui amène PowerShell à l’évaluer $i = $null - 1, ce qui est $i=-1.

Chaque boucle est incrémentée $ipuis exécutée par une longue ifinstruction. La première partie du conditionnel vérifie qu’il $in’y a aucun élément 12357en utilisant l’ -notmatchopérateur , pour filtrer les nombres impies.

La deuxième partie du conditionnel vérifie la quantité de trous dans $i. Il utilise l' -replaceopérateur pour les remplacer 8ou 0par 11, puis compare si la longueur est> = $h. Nous n'avons pas à nous soucier de supprimer les chiffres impies, car cela fait partie de la première partie du conditionnel, et les chiffres à trou unique ont la même longueur que de 1toute façon, nous n'avons donc pas besoin de les remplacer.

Si cela reste vrai, nous décrémentons $n(car cela signifie que nous avons trouvé un autre nombre qui satisfait aux exigences d'entrée). Ainsi, lorsque la forcondition est recalculée pour vérifier si $nest égal à zéro, cela signifie que nous avons trouvé le nième , nous quittons donc la forboucle, la sortie $iet nous terminons.

Edit - sauvegardé 13 octets en utilisant un tableau au lieu de chaîne pour $let en modifiant la façon dont $nest décrémentée / vérifiée
Edit 2 - sauvegardé 9 octets supplémentaires en cochant $nla forcondition et en déplaçant la sortie en dehors de la boucle
Edit 3 - sauvé énormément 40 octets de plus en modifiant radicalement la manière dont nous calculons les trous
Edit 4 - économisé 3 octets supplémentaires en déplaçant le ++pour être une pré-incrémentation sur la première partie du conditionnel Edit 5 - enregistré 2 octets supplémentaires
grâce à TessellatingHeckler


Soigné. Enregistrer quelques octets supplémentaires en remplaçant par for(--$i;$n)et -replace"8|0"?
TessellatingHeckler

@TessellatingHeckler Oui, merci. Cela $i=-1me rendait absolument dingue. J'essaie toujours de trouver un moyen d'éviter les initialisations $i, mais les choses que j'ai essayées jusqu'à présent sont plus longues (et, étant donné cela, ce sera probablement encore plus long).
AdmBorkBork


4

Utilitaires Bash + GNU, 67

  • 20 octets sauvés grâce à @TobySpeight!
seq 0 NaN|sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x"|sed $2!d\;q
  • seqgénère simplement des entiers à partir de 0haut
  • sed -r:
    • h copier la ligne d'entrée dans l'espace d'attente
    • /12357/d effacer les chiffres impies
    • s/8|0/&&/gremplacez doublement les chiffres sacrés par deux fois eux-mêmes. Ainsi, les chiffres sacrés sont comptés une fois et les chiffres doublement sacrés sont comptés deux fois.
    • /^.{$1}/!dSi les $1trous ne correspondent pas , effacez et passez à la ligne suivante.
    • x ramener le numéro original dans l'espace du motif
    • impression implicite
  • sed
    • $2!dsur toutes les lignes avant ligne $2, supprimez et passez à la ligne suivante
    • qdoit être à la ligne $2- quitter (et impression implicite)

Idéone.


1
Rasez 9: sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x". Et un autre 4: sed $2!d\;q. Et si vous êtes satisfait d'une limite haute de 4611686018427387904, vous pourriez vous en tirerseq 0 $[1<<62]
Toby Speight

1
Ooh, mon seqaccepte NaNcomme valeur: j'ai maintenant un seq 0 NaN|sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x"|sed $2!d\;qscore de 67.
Toby Speight

@TobySpeight wow c'est incroyable!
Digital Trauma

@TobySpeight: il manque un \ avant le!, Sinon:-sh: !d\: event not found
Olivier Dulac le

1
@OlivierDulac ` before ! ` N'est pas nécessaire dans un script . Cela n'est nécessaire que lorsque vous exécutez ceci directement sur la ligne de commande, ce qui, à mon avis, n'est pas une obligation.
Digital Trauma

3

MATL , 39 40 octets

x~q`QtV4688900V!=stA*s2G<?T}N1G=?F1$}tT

Les envois sont net hdans cet ordre.

Essayez-le en ligne!

Nous devons suivre deux nombres: le numéro actuel du candidat (pour vérifier sa sainteté) et le nombre de chiffres trouvés qui sont suffisamment sacrés. Le premier est le sommet de la pile et le dernier est conservé en nombre d'éléments dans la pile. Lorsque le programme est terminé, seul le haut doit être affiché.

x~q          % implicitly take two inputs. Delete one and transform the other into -1
`            % do...while loop
  Q          %   add 1 to current candidate number
  tV         %   duplicate and convert to string
  4688900V!  %   column char array of '4', '6' etc. Note '8' and '0' are repeated 
  =          %   compare all combinations. Gives 2D array
  s          %   sum of each column: holiness of each digit of candidate number
  tA*        %   are all digits holy? Multiply by that
  s          %   sum of holiness of all digits, provided they are all holy
  2G<        %   is that less than second input (h)?
  ?          %   if so: current candidate not valid. We'll try the next
    T        %     push true to be used as loop condition: next iteration
  }          %   else: current candidate valid
    N1G=     %     does stack size equal first input (n)?
    ?        %     if so: we're done
      F1$    %       push false to exit loop. Spec 1 input, to display only top
    }        %     else: make a copy of this number
      tT     %       duplicate number. Push true to continue with next iteration
             %     implicit end if 
             %   implicit end if 
             % implicit end do...while. If top of stack is truthy: next iteration
             % implicit display

3

R, 109 107 octets

f=function(n,h){m=-1;while(n){m=m+1;if(!grepl("[12357]",m))if(nchar(gsub("([08])","\\1\\1",m))>=h)n=n-1};m}

Avec de nouvelles lignes et empreintes:

f=function(n,h){
    m=-1
    while(n){
        m=m+1
        if(!grepl("[12357]",m))
            if(nchar(gsub("([08])","\\1\\1",m))>=h)
                n=n-1
    }
    m
}

Usage:

> f(4,3)
[1] 68
> f(4,2)
[1] 44
> f(6,2)
[1] 48
> f(10,2)
[1] 66

3

JavaScript (ES6), 110 octets

f=(n,h,r=[],i=0)=>r.length<n?f(n,h,/[12357]/.test(i)|[...''+i].reduce((t,c)=>t+1+!(c%8),0)<h?r:[...r,i],i+1):r

Queue solution récursive qui accumule des nombres sacrés dans un tableau.

Par intérêt, ne pas exiger que le nombre soit totalement (!) Saint rend la sainteté plus difficile à gérer, mais cela permet néanmoins d'économiser 10% au total:

f=(n,h,r=[],i=0)=>r.length<n?f(n,h,[...''+i].reduce((t,c)=>+"2000101021"[c]+t,0)<h?r:[...r,i],i+1):r

@ edc65 Oups, j'ai échangé sur les paramètres iet rà un moment donné et je n'ai pas pu modifier correctement la modification.
Neil

1

JavaScript ES6, 191 octets

Bien sûr, ce n'est pas le moyen le plus efficace. Mais tu me connais, j'aime les générateurs <3

H=(x,o=x+"")=>(F=/^[46890]+$/).test(o)&&[...o].map(y=>d+=(F.test(y)+/8|0/.test(y)),d=0)&&d;(n,h)=>(a=(function*(h){q=0;while(1){if(H(q)>=h)yield q;q++}})(h),eval("a.next().value;".repeat(n)))

Légèrement non-golfé:

H = (x, o = x + "") => (F = /^[46890]+$/).test(o) && [...o].map(y => d += (F.test(y) + /8|0/.test(y)), d = 0) && d;
Q = (n, h) => (a = (function*(h) {
    q = 0;
    while (1) {
        if (H(q) >= h) yield q;
        q++
    }
})(h), eval("a.next().value;".repeat(n)))

1

C # 6, 168 octets

(n,h)=>{for(int i=0;i<=int.MaxValue;i++){string d=$"{i}";if(d.Any(y=>"12357".Contains(y)))continue;n-=d.Sum(y=>y=='0'||y=='8'?2:1)>=h?1:0;if(n==0)return i;}return -1;}

Ceci est une expression Lambda de type Func <int, int, int>. Ce code est optimisé pour une taille minimale (non performatique).

Ci-dessous, le code embelli dans la déclaration de méthode (avec plus de performances):

    int GetHolyNumber(int n, int h)
    {
        for (int i = 0; i <= int.MaxValue; i++)
        {
            string d = $"{i}";
            char[] cs = "12357".ToArray();
            if (d.Any(y => cs.Contains(y))) continue;

            n -= d.Sum(y => y == '0' || y == '8' ? 2 : 1) >= h ? 1 : 0;

            if (n == 0)
                return i;
        }
        return -1;
    }

Bonjour Bobson, désolée si j'ai mal compris, mais je ne détecte pas les défauts que vous avez signalés dans mon code? Il retourne le nième élément requis, et lui seul, et zéro s'il est valide, en supposant que les entrées sont n = 1 et h <= 2. Si je comprends le défi, ne doit renvoyer que cet élément et pas tout à lui. . Mais je me suis mal compris et perdu en anglais: D merci
Paulo César B. Sincos

Non, vous avez entièrement raison. J'ai été induit en erreur par les listes de référence, et j'ai raté le fait qu'il s'agissait simplement de demander le nième chiffre. Continuer!
Bobson

1

JavaScript (ES6), 87

(n,h)=>eval("for(i=0;[...i+''].map(d=>r-=~!(d%8),r=0),/[12357]/.test(i)|r<h||--n;)++i")

Moins golfé

f=(n,h)=>{
  for (i=0;
    // this is the loop condition
    /[12357]/.test(i) // go on if not holy
    ||([...i+''].map(d=>r-=~!(d%8),r=0),r<h) // go on if not holy enough
    ||--n; // ok, found one! go on if we need to find more
  )
    ++i; // loop body - using eval this is the returned value
  return i; // not using eval, an explicit return is needed
}  

Tester

f=(n,h)=>eval("for(i=0;[...i+''].map(d=>r-=~!(d%8),r=0),/[12357]/.test(i)|r<h||--n;)++i")

function test() {
  var a,b
  [a,b]=I.value.match(/\d+/g)
  R.textContent = f(a,b)
}

test()
N, H: <input id=I value="25 2" oninput="test()"> >>
<span id=R></span>


1

Lua, 169 octets

function a(n,h)H=0N=0I=-1while N<n do I=I+'1'H=0 if not I:find('[12357]') then _,b=I:gsub('[469]',1)_,c=I:gsub('[08]',1)H=b+2*c end N=H>=h and N+1 or N end print(I) end

Ungolfed:

function a(n,h) -- nth term, holiness
    H=0N=0I=-1 -- Really ugly, but hey, it works. Set up 3 vars
    while N<n do -- While nth term is lower than desired term
        I=''..I+1 -- Convert number to string (can't coerce since it will become a float)
        if not I:find('[12357]') then -- If the number doesn't have those numbers
            _,b=I:gsub('[469]',1) -- _ is the new string, b is the number of changes
            _,c=I:gsub('[08]',1) -- Same as above. Use 1 to replace to save chars
            H=b+2*c -- Increase holiness appropriately
        end
        N=H>=h and N+1 or N -- If current holiness >= desired holiness, increment N
    end 
    print(I) -- Once the loop ends, print the current term
end

1

Lua, 155 141 140 octets

Prend les deux entrées par un argument de ligne de commande (le premier argument est n, puis h)

Edit: Merci à @DavisDude, qui m'a aidé à éliminer 14 octets et m'a rappelé que je n'avais pas à imprimer tous les nombres sacrés jusqu'à n, mais seulement le nième.

a={}x=0while(#a<arg[1])do b,c=(x..""):gsub("[08]","")e,d=b:gsub("[469]","")a[#a+1],x=c*2+d>=arg[2]and #e<1 and x or nil,x+1 end print(a[#a])

Ungolfed et explications

x,a=0,{}                      -- initialise a counter, and the array which 
                              -- contains the holy numbers found
while(#a<arg[1])              -- iterate while we found less holy numbers than n
do
  b,c=(x..""):gsub("[08]","") -- replace [08] by "", b=the new string
                              -- c=the number of subsitution
  e,d=b:gsub("[469]","")      -- same thing for [469]
  a[#a+1]=c*2+d>=arg[2]       -- insert the number into a if:nb[08]*2+nb[469]>h
             and #e<1         -- and e is empty (no unholy numbers)
             and x or nil
      x=x+1                   -- increment x
end
print(a[#a])                  -- print the last element of a

Vous pourriez enlever quelques personnages en faisant celaprint(a[arg[1]])
DavisDude

@DavisDude J'étais bête, quand j'ai écrit ça, je me suis dit que je devais imprimer la liste complète des nombres impurs jusqu'à n. En fait, print(a[#a])sauve encore plus d'octets. Merci pour le commentaire !
Katenkyo

Vous êtes en écriture. Pour une raison quelconque, cela ne m'est même pas venu à l'esprit.
DavisDude

Vous pouvez enlever un caractère en écrivant à la x=0a={}place de x,a=0,{}.
Leaky Nun

1
@KennyLau En fait, vous ne pouvez pas parce que 0aserait interprété comme un nombre hexadécimal, mais je peux le faire a={}x=0whilesans problème :)
Katenkyo

0

Oracle SQL 11.2, 229 octets

WITH v(c,p,i,j,n)AS(SELECT 0,-1,0,0,0 FROM DUAL UNION ALL SELECT c+1,c,REGEXP_COUNT(c||'','[4,6,9]'),REGEXP_COUNT(c,'[8,0]'),n+DECODE(LENGTH(p),i+j,DECODE(SIGN(i+j*2-:h),-1,0,1),0)FROM v WHERE p<c AND n<:n)SELECT MAX(p)-1 FROM v;

Non-golfé

:h -> required min holy value
:n -> nth number 

curv   -> current number
precv  -> previous number
prech1 -> number of holy 1 letters in previous number 
prech2 -> number of holy 2 letters in previous number
n      -> how many numbers with at least the required holy value 

WITH v(curv,precv,prech1,prech2,n)AS 
(
  SELECT 0 curv, -1 precv, 0 prech1, 0 prech2, 0 n FROM DUAL     -- Start with 0
  UNION ALL
  SELECT curv+1,   -- Next number
         curv,     -- Current Number 
         REGEXP_COUNT(curv||'','[4,6,9]'),  -- number of holy 1 letters
         REGEXP_COUNT(curv,'[8,0]'),        -- number of holy 2 letters
         n+DECODE(LENGTH(precv),prech1+prech2,DECODE(SIGN(prech1+prech2*2-:h),-1,0,1),0) -- Is the previous number holy enough ?
  FROM   v 
  WHERE  precv<curv   -- Needed to trick oracle cycle detection 
         AND n<:n     -- Until clause
)
SELECT MAX(precv)-1 FROM v 

0

Python 2, 96 octets

f=lambda n,h,k=0,s="0046889":-0**n or-~f(n-(sum(map(s.count,`k`))>=h<set(str(k))<=set(s)),h,k+1)

La condition d'holyness on kest vérifiée par

  • sum(map(s.count,`k`))>=h, qui compte le nombre de trous en additionnant les comptes de chaque personnage dans s="0046889", où 0et 8apparaissent deux fois.
  • set(str(k))<=set(s)), qui vérifie que les nombres sont tous saints. strest utilisé plutôt que des backticks pour éviter le suffixe Lpour les longs.

Celles-ci sont chaînées en une seule égalité en utilisant le fait Python 2 que les nombres sont plus petits que les ensembles.

La fonction est définie de manière récursive pour compter les nombres k, en diminuant le compteur à nchaque fois qu'un nombre sacré de touches est atteint, à moins qu'il ne frappe 0. Il pourrait alors renvoyer l' kélément qui a déclenché cette opération, mais il est plus court de conserver le nombre récursivement en ajoutant 1chaque fois, même si une analyse décalée nécessite un nombre de base -1à corriger.


0

Haskell, 94 octets

cest la sainteté d'un chiffre, vla sainteté d'un nombre, n!hfait le reste.

c=([2,0,0,0,1,0,1,0,2,1]!!)
v n|n>9=c(mod n 10)+v(div n 10)|1<2=c n
n!h=[i|i<-[0..],v i<=h]!!n

Note: Je pense que c'est la seule réponse sans les caractères 4,6,8.


0

Rapide

func f(n: Int, h: Int) {
    var m = 0
    let a = [1,2,3,5,7]
    for j in 0..<Int.max {
        var c = 0
        for i in (j.description.characters.map{(String($0) as NSString).integerValue}) {
            c += (a.contains(i)) ? 0 : (i == 8 || i == 0) ? 2 :1
        }
        if c >= h { m += 1; if m >= n {print(j); break}}
    }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.