I numeri sacri


44

In molti tipi di carattere (in particolare nel carattere Consolas ), 5 cifre decimali su 10 presentano "buchi". Chiameremo queste cifre sante:

46890

Le 5 cifre empie sono quindi:

12357

Un numero intero può quindi essere classificato come "santo" se contiene solo cifre sante e "empio" altrimenti. Perché -è empio, nessun numero intero negativo può essere santo.

Gli interi sacri possono essere ulteriormente classificati in base a quanti buchi hanno. Ad esempio, le seguenti cifre hanno una santità di 1:

469

E queste cifre hanno una santità di 2:

80

Diciamo che la santità complessiva di un numero intero è la somma della santità delle sue cifre. Pertanto, 80avrebbe una santità di 4 e 99una santità di 2.

La sfida

Dato due numeri interi n > 0e h > 0, genera il nnumero intero santo la cui santità è almeno h. Si può presumere che gli input e gli output non siano maggiori dell'intero massimo rappresentabile nella propria lingua o 2^64 - 1, a seconda di quale sia il minore.

Ecco un elenco dei primi 25 numeri interi santi con santità h >= 1, come riferimento:

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

I primi 25 numeri interi santi con santità h >= 2sono:

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

Correlati - 1 2
Mego

26
sono stato seduto qui per trenta secondi a pensare "come diavolo 0ha una santità di due" prima di fare finalmente clic sul link di Wikipedia per Consolas
undergroundmonorail

Il quinto numero 1-Santo è 9 o 40?
Conor O'Brien,

3
È solo una coincidenza che l'ottavo 8 + numero -alcolico sia 8888? (sì, probabilmente lo è, ma mi ha divertito comunque ...)
Toby Speight,

5
Infatti, poiché puoi avere un numero qualsiasi di 0 iniziali prima di un numero, si potrebbe affermare che 0 è infinitamente santo. Sebbene ∞ sia apparentemente altrettanto santo. Ma stranamente, 666 è ancora più santo ...
Darrel Hoffman,

Risposte:


6

Pyth, 32 byte

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

Spiegazione

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

Provalo qui

Accetta input nel modulo h \n n


12

Rubino, 109 105 95 82 byte

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

Questo è il terribile approccio "calcola da 0 a 99999999999 ..." che risulta essere 13 byte più corto della sua controparte pigra. Tuttavia, è improbabile che questa versione finisca prima della morte per calore dell'universo. Vale 13 byte, comunque ¯ \ _ (ツ) _ / ¯

È possibile verificare per valori inferiori cambiando ?9*99, per esempio, '99999'.

Ecco la vecchia versione (95 byte, con valutazione pigra, che viene eseguita quasi istantaneamente anziché quasi mai):

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

Devo amare la valutazione pigra :)
Emigna,

Perché non takeinvece di first?
Non che Charles, il

takeRestituisce @NotthatCharles Lazy, che non può essere indicizzato.
Maniglia della porta

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]

Ecco una soluzione che utilizza un approccio più efficiente in termini di memoria, ma altrimenti utilizza lo stesso algoritmo se si desidera testarlo.

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

Casi test:

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

@Mego Cool. Sembra utilizzare una quantità statica di memoria, quindi non corre il rischio di rimanere senza memoria. Non ne ero sicuro dal momento che è in esecuzione sulla mia macchina già da mezz'ora.
Morgan Thrapp,

In realtà ci vuole un bel po 'di tempo solo per calcolare 2**64-1; vedi stackoverflow.com/questions/34113609/…
Mego

@Mego Oh, non ci ho nemmeno pensato. Sì, quando inserisco la costante pre-calcolata nel codice, inizia a masticare un po 'di RAM.
Morgan Thrapp,

6

PowerShell, 163 150 141 101 98 96 byte

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

Accetta input, quindi esegue un loop fino a $nzero. Inizialmente impostiamo $i=-1utilizzando un trucco di pre-elaborazione, che funziona perché $i, non essendo stato precedentemente dichiarato, lo è $null. Quindi lo facciamo --, il che fa sì che PowerShell lo valuti $i = $null - 1, ovvero $i=-1.

Ogni ciclo incrementiamo $ie quindi eseguiamo ifun'istruzione lunga . La prima parte del condizionale verifica che $inon ci sia nulla 12357usando l' -notmatchoperatore , per filtrare i numeri empi.

La seconda parte del condizionale controlla la quantità di buchi $i. Utilizza l' -replaceoperatore per sostituire ciascuno 8o 0con 11, quindi confronta se la lunghezza è> = $h. Non dobbiamo preoccuparci di mettere a nudo i numeri empi, poiché questo è nella prima parte del condizionale, e i numeri a foratura singola hanno la stessa lunghezza di 1comunque, quindi non abbiamo bisogno di sostituirli, neanche.

Se ciò è ancora vero, diminuiamo $n(poiché ciò significa che abbiamo trovato un altro numero che soddisfa i requisiti di input). Pertanto, quando la forcondizione viene ricalcolata per verificare se $nè zero, significa che abbiamo trovato l' ennesima , quindi usciamo dal forciclo, emettiamo $ie terminiamo.

Modifica: salvato 13 byte utilizzando un array anziché stringa $le cambiando il modo in cui $nviene diminuito / controllato
Modifica 2: salvato altri 9 byte controllando $nil forcondizionale e spostando l'output all'esterno del ciclo
Modifica 3: salvato un enorme 40 byte in più cambiando radicalmente il modo in cui calcoliamo i fori
Modifica 4: salvato altri 3 byte spostando il ++pre-incremento sulla prima parte della modifica condizionale
5: salvato altri 2 byte grazie a TessellatingHeckler


Neat. Salvare un altro paio di byte cambiando in for(--$i;$n)e -replace"8|0"?
TessellatingHeckler,

@TessellatingHeckler Sì, grazie. Mi $i=-1stava facendo impazzire. Sto ancora cercando di trovare un modo per cui non dobbiamo inizializzare $iin primo luogo, ma le cose che ho provato finora sono più lunghe (e, dato questo, probabilmente saranno ancora più lunghe).
AdmBorkBork,


4

Utilità Bash + GNU, 67

  • 20 byte salvati grazie a @TobySpeight!
seq 0 NaN|sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x"|sed $2!d\;q
  • seqgenera semplicemente numeri interi a partire da 0verso l'alto
  • sed -r:
    • h copia la riga di input nello spazio di attesa
    • /12357/d elimina i numeri empi
    • s/8|0/&&/gsostituire due cifre sante con due volte stesse. Quindi le singole cifre sante vengono contate una volta e due volte le cifre sante vengono contate due volte.
    • /^.{$1}/!dSe non corrispondono almeno i $1fori, eliminare e passare alla riga successiva
    • x riporta il numero originale nello spazio del motivo
    • stampa implicita
  • sed
    • $2!dsu qualsiasi riga prima della riga $2, elimina e continua con la riga successiva
    • qdeve essere alla riga $2- esci (e stampa implicita)

Ideone.


1
Shave 9: sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x". E un altro 4: sed $2!d\;q. E se sei soddisfatto di un limite superiore di soli 4611686018427387904, potresti scappare conseq 0 $[1<<62]
Toby Speight,

1
Ooh, il mio seqaccetta NaNcome valore: ora ho seq 0 NaN|sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x"|sed $2!d\;q, segnando 67.
Toby Speight

@TobySpeight wow, è fantastico!
Trauma digitale,

@TobySpeight: manca un \ prima del!, Altrimenti:-sh: !d\: event not found
Olivier Dulac,

1
@OlivierDulac ` before ! `Non è necessario in uno script . È necessario solo quando si esegue questo direttamente dalla riga di comando, che non credo sia un requisito.
Trauma digitale,

3

MATL , 39 40 byte

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

Le entrate sono ne hin quell'ordine.

Provalo online!

Dobbiamo tenere traccia di due numeri: il numero del candidato attuale (per verificarne la santità) e la quantità di numeri trovati abbastanza santi. Il primo è il primo della pila e il secondo viene mantenuto come il numero di elementi nella pila. Al termine del programma, è necessario visualizzare solo la parte superiore.

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 byte

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 nuove linee e rientranze:

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 byte

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

Soluzione ricorsiva di coda che accumula numeri sacri in un array.

Per interesse, non richiedere che il numero sia completamente (!) Santo rende il conteggio della santità più imbarazzante, ma conserva comunque un 10% complessivo:

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, ho scambiato i parametri ie rad un certo punto e non sono riuscito a modificare correttamente la modifica.
Neil,

1

JavaScript ES6, 191 byte

Certo, questo non è il modo più efficiente. Ma mi conosci, adoro i generatori <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)))

Leggermente non golfato:

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 byte

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

Questa è un'espressione Lambda di tipo Func <int, int, int>. Questo codice è otimizzato per dimensioni minime (non performative).

Di seguito, il codice abbellito nella dichiarazione del metodo (con maggiori prestazioni):

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

Ciao Bobson, scusa se ho frainteso, ma non rilevi i difetti che hai indicato nel mio codice? Restituisce l'ennesimo elemento richiesto, e solo lui e zero se è valido, supponendo che gli input siano n = 1 e h <= 2. Se capisco la sfida, deve restituire solo questo elemento e non tutto fino a lui . Ma ho capito male e ho perso in inglese: D grazie
Paulo César B. Sincos,

No, hai perfettamente ragione. Sono stato fuorviato dagli elenchi per riferimento e ho perso il fatto che stava solo chiedendo l'ennesima cifra. Proseguire!
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")

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

Test

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 byte

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 byte

Accetta entrambi gli input dall'argomento della riga di comando (il primo argomento è n, quindi h)

Modifica: Grazie a @DavisDude, che mi ha aiutato a radere 14 byte e mi ha ricordato che non dovevo stampare tutti i numeri sacri fino a n, ma solo l'ennesimo.

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 e spiegazioni

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

Potresti decollare alcuni print(a[arg[1]])
personaggi

@DavisDude Ero stupido, quando ho scritto questo, ho pensato di stampare l'intero elenco di numeri empi fino a n. In realtà, print(a[#a])salva ancora più byte. Grazie per il commento !
Katenkyo,

Stai scrivendo. Per qualche motivo che non mi è nemmeno venuto in mente.
DavisDude,

Puoi togliere un carattere scrivendo x=0a={}invece di x,a=0,{}.
Leaky Nun,

1
@KennyLau In realtà, non puoi perché 0asarebbe interpretato come un numero esadecimale, ma posso fare a a={}x=0whilemeno di un problema :)
Katenkyo

0

Oracle SQL 11.2, 229 byte

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;

Un-golfed

: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 byte

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 condizione di santità kè verificata da

  • sum(map(s.count,`k`))>=h, che conta il numero di buche sommando i conteggi per ciascun personaggio in s="0046889", dove 0e 8appaiono due volte.
  • set(str(k))<=set(s)), che verifica che i numeri siano tutti santi. strviene utilizzato anziché i backtick per evitare il suffisso Lper lunghi periodi.

Questi sono concatenati in una singola uguaglianza usando il fatto di Python 2 che i numeri sono più piccoli degli insiemi.

La funzione è definita in modo ricorsivo per contare i numeri k, diminuendo il contatore nogni volta che un numero sacro di colpi a meno che non colpisca 0. Potrebbe quindi restituire kciò che lo ha innescato, ma è più breve mantenere il conteggio ricorsivamente aggiungendolo 1ogni volta, anche se uno off-by-one richiede un conteggio di base -1da correggere.


0

Haskell, 94 byte

cè la santità di una cifra, vla santità di un numero, n!hfa il 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: penso che questa sia l'unica risposta senza i personaggi 4,6,8.


0

veloce

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}}
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.