Los santos numeros


44

En muchas fuentes (específicamente en la fuente Consolas ), 5 de los 10 dígitos decimales tienen "agujeros" en ellas. Llamaremos a estos dígitos sagrados:

46890

Los 5 dígitos impíos son así:

12357

Por lo tanto, un número entero puede clasificarse como "sagrado" si solo contiene dígitos sagrados, y "impío" de lo contrario. Porque -es impío, ningún número entero negativo puede ser sagrado.

Los enteros sagrados pueden clasificarse aún más según la cantidad de agujeros que tengan. Por ejemplo, los siguientes dígitos tienen una santidad de 1:

469

Y estos dígitos tienen una santidad de 2:

80

Decimos que la santidad general de un número entero es la suma de la santidad de sus dígitos. Por 80lo tanto, tendría una santidad de 4 y 99tendría una santidad de 2.

El reto

Dados dos enteros n > 0y h > 0, se obtiene el nth entero entero cuya santidad es al menos h. Puede suponer que las entradas y salidas no serán mayores que el número entero máximo representable en su idioma o 2^64 - 1, lo que sea menor.

Aquí hay una lista de los primeros 25 enteros sagrados con santidad h >= 1, como referencia:

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

Los primeros 25 enteros sagrados con santidad h >= 2son:

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

Relacionado - 1 2
Mego

26
Estuve sentado aquí como treinta segundos pensando "cómo diablos 0tiene una santidad de dos" antes de hacer clic en el enlace de Wikipedia a Consolas
undergroundmonorail

¿Es el quinto 1-Santo número 9 o 40?
Conor O'Brien

3
¿Es solo coincidencia que el octavo número 8 + sea 8888? (sí, probablemente lo sea, pero de todos modos me divirtió ...)
Toby Speight

55
De hecho, dado que puede tener cualquier número de ceros delante de un número, se podría afirmar que 0 es infinitamente sagrado. Aunque ∞ es aparentemente igual de sagrado. Pero extrañamente, el 666 es aún más sagrado ...
Darrel Hoffman

Respuestas:


6

Pyth, 32 bytes

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

Explicación

                                 - 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]

Pruébalo aquí

Toma entrada en el formulario h \n n


12

Ruby, 109 105 95 82 bytes

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

Este es el terrible enfoque "calcular de 0 a 99999999999 ..." que resulta ser 13 bytes más corto que su contraparte perezosa. Sin embargo, es poco probable que esta versión termine antes de la muerte por calor del universo. Vale 13 bytes, de todos modos ¯ \ _ (ツ) _ / ¯

Puede probarlo para valores más pequeños cambiando ?9*99a, por ejemplo, '99999'.

Aquí está la versión anterior (95 bytes, con evaluación diferida, que se ejecuta casi al instante en lugar de casi nunca):

->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
}

Tengo que amar la evaluación perezosa :)
Emigna

¿Por qué no en takelugar de first?
No es que Charles

@NotthatCharles takeregresa Lazy, que no se puede indexar.
Pomo de la puerta

6

Pitón 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]

Aquí hay una solución que utiliza un enfoque más eficiente en la memoria, pero de lo contrario utiliza el mismo algoritmo si desea probarlo.

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

Casos de prueba:

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

@Mego Cool. Parece usar una cantidad estática de memoria, por lo que no corre el peligro de quedarse sin memoria. Simplemente no estaba seguro, ya que ha estado funcionando en mi máquina durante media hora.
Morgan Thrapp

Realmente toma una buena cantidad de tiempo solo para calcular 2**64-1; ver stackoverflow.com/questions/34113609/…
Mego

@Mego Oh, ni siquiera pensé en eso. Sí, cuando pongo la constante precalculada en el código, comienza a masticar un poco de RAM.
Morgan Thrapp

6

PowerShell, 163 150 141 101 98 96 bytes

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

Toma entrada, luego realiza un bucle hasta que $nsea ​​cero. Inicialmente establecemos $i=-1mediante el uso de un truco de preprocesamiento, que funciona porque $i, al no haber sido declarado previamente, es$null . Luego lo hacemos --, lo que hace que PowerShell lo evalúe como $i = $null - 1, que es $i=-1.

Cada ciclo lo incrementamos $iy luego ejecutamos una larga ifdeclaración. La primera parte del condicional verifica que$i no tiene nada de 12357esto usando el -notmatchoperador , para filtrar los números impíos.

La segunda parte del condicional verifica la cantidad de agujeros $i. Utiliza el -replaceoperador para reemplazar cada 8o0 con 11, y luego compara si la longitud es> = $h. No debemos preocuparnos por eliminar los números impíos, ya que eso se encuentra en la primera parte del condicional, y los números de un solo orificio tienen la misma longitud que de 1todos modos, por lo que tampoco necesitamos reemplazarlos.

Si eso sigue siendo cierto, disminuimos $n(ya que eso significa que hemos encontrado otro número que satisface los requisitos de entrada). Por lo tanto, cuando la forcondición se recalcula para verificar si $nes cero, eso significa que hemos encontrado el enésimo , por lo que salimos del forbucle, salimos y terminamos $i.

Edición: ahorró 13 bytes mediante el uso de una matriz en lugar de una cadena $ly cambió la forma en que $nse disminuye / verificó
Edición 2: guardó 9 bytes adicionales al verificar $nel forcondicional y mover la salida fuera del bucle
Edición 3: ahorró una friolera 40 bytes más cambiando radicalmente la forma en que calculamos los agujeros
Edición 4: ahorró 3 bytes adicionales moviendo el ++para que sea un pre-incremento en la primera parte de la Edición condicional
5: ahorró otros 2 bytes gracias a TessellatingHeckler


Ordenado. Ahorre otro par de bytes cambiando a for(--$i;$n)y -replace"8|0"?
TessellatingHeckler

@TessellatingHeckler Sí, gracias. Eso $i=-1me estaba volviendo loco. Todavía estoy tratando de resolver un camino para no tener que inicializar $ien primer lugar, pero las cosas que he intentado hasta ahora son más largas (y, dado esto, es probable que aún sean más largas).
AdmBorkBork


4

Bash + utilidades GNU, 67

  • ¡20 bytes guardados gracias a @TobySpeight!
seq 0 NaN|sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x"|sed $2!d\;q
  • seqsimplemente genera enteros comenzando desde 0arriba
  • sed -r:
    • h copia la línea de entrada al espacio de espera
    • /12357/d eliminar números impíos
    • s/8|0/&&/greemplazar los dígitos doblemente sagrados con dos veces ellos mismos. Por lo tanto, los dígitos sagrados individuales se cuentan una vez y los dígitos sagrados dobles se cuentan dos veces.
    • /^.{$1}/!dSi no coincide al menos con los $1agujeros, elimine y continúe con la siguiente línea
    • x devolver el número original al espacio del patrón
    • impresión implícita
  • sed
    • $2!den cualquier línea anterior a la línea $2, elimine y continúe con la línea siguiente
    • qdebe estar en la línea $2: salir (e impresión implícita)

Ideona


1
Afeitarse 9: sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x". Y otro 4: sed $2!d\;q. Y si está satisfecho con un límite superior de solo 4611686018427387904, podría salirse con la suyaseq 0 $[1<<62]
Toby Speight

1
Ooh, mi seqacepta NaNcomo un valor: ahora tengo seq 0 NaN|sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x"|sed $2!d\;q, anotando 67.
Toby Speight

@TobySpeight ¡guau, eso es increíble!
Trauma digital

@TobySpeight: falta un \ antes del!, De lo contrario:-sh: !d\: event not found
Olivier Dulac

1
@OlivierDulac ` before ! `No es necesario en un script . Solo es necesario cuando se ejecuta esto directamente en la línea de comandos, lo cual no creo que sea un requisito.
Trauma digital

3

MATL , 39 40 bytes

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

Las entradas son ny hen ese orden.

Pruébalo en línea!

Necesitamos hacer un seguimiento de dos números: el número de candidato actual (para verificar su santidad) y la cantidad de números encontrados que son lo suficientemente santos. La primera es la parte superior de la pila, y la segunda se mantiene como el número de elementos en la pila. Cuando finaliza el programa, solo se debe mostrar la parte superior.

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, 109107 bytes

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}

Con nuevas líneas y hendiduras:

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
}

Uso:

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

3

JavaScript (ES6), 110 bytes

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

Solución recursiva de cola que acumula números sagrados en una matriz.

Por interés, no requerir que el número sea totalmente (!) Hace que la santidad cuente más incómoda, pero aún ahorra un 10% en general:

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 Whoops, cambié los parámetros iy ren un punto, y no pude editar el cambio correctamente.
Neil

1

JavaScript ES6, 191 bytes

Claro, esta no es la forma más eficiente. Pero me conoces, me encantan los generadores <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)))

Ligeramente incólume:

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 bytes

(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;}

Esta es una Expresión Lambda de tipo Func <int, int, int>. Este código está optimizado para un tamaño mínimo (no performatico).

A continuación, el código embellecido en la declaración del método (con más rendimiento):

    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;
    }

Hola Bobson, perdón si entendí mal, pero ¿no detecta las fallas que usted señaló en mi código? Devuelve el enésimo elemento requerido, y solo él, y cero si es válido, suponiendo que las entradas son n = 1 y h <= 2. Si entiendo el desafío, debe devolver solo este elemento y no todo depende de él . Pero me he entendido mal y he perdido en inglés: D gracias
Paulo César B. Sincos

No, tienes toda la razón. Yo era errónea por las listas-para-referencia, y se perdió el hecho de que fue simplemente pidiendo el dígito enésima. ¡Continua!
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")

Menos 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
}  

Prueba

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 bytes

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

Sin golf:

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 Bytes

Toma ambas entradas por argumento de línea de comando (el primer argumento es n, luego h)

Editar: Gracias a @DavisDude, que me ayudó a eliminar 14 bytes y me recordó que no tenía que imprimir todos los números sagrados hasta n, sino solo el enésimo.

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])

Sin golfos y explicaciones

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

Podrías quitarte algunos caracteres haciendoprint(a[arg[1]])
DavisDude

@DavisDude Era tonto, cuando escribí esto, pensé que tenía que imprimir toda la lista de números impíos hasta n. En realidad, print(a[#a])ahorra aún más bytes. Gracias por el comentario !
Katenkyo

Usted es escribir Por alguna razón, eso ni siquiera se me ocurrió.
DavisDude

Puedes quitar un personaje escribiendo en x=0a={}lugar de x,a=0,{}.
Leaky Nun

1
@KennyLau En realidad, no puedes porque 0ase interpretaría como un número hexadecimal, pero puedo hacerlo a={}x=0whilesin ningún problema :)
Katenkyo

0

Oracle SQL 11.2, 229 bytes

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;

Sin 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 bytes

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 condición de santidad en kes verificada por

  • sum(map(s.count,`k`))>=h, que cuenta el número de agujeros sumando los recuentos de cada personaje en s="0046889", dónde 0y 8aparecen dos veces.
  • set(str(k))<=set(s)), que comprueba que todos los números son santos. strse usa en lugar de backticks para evitar el sufijo Ldurante largos.

Estos están encadenados en una sola igualdad utilizando el hecho de Python 2 de que los números son más pequeños que los conjuntos.

La función se define de forma recursiva para contar los números k, disminuyendo el contador ncada vez que se alcanza un número sagrado de golpes, a menos que golpee 0. Luego podría devolver el kque desencadenó esto, pero es más corto mantener el recuento recursivamente agregando 1cada vez, aunque un off-by-one requiere un recuento base de -1para solucionarlo.


0

Haskell, 94 bytes

ces la santidad de un dígito, vla santidad de un número, n!hhace el resto.

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

Nota: Creo que esta es la única respuesta sin los caracteres 4,6,8.


0

Rápido

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}}
    }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.