Bilangan Suci


44

Dalam banyak font (khususnya font Consolas ), 5 dari 10 digit desimal memiliki "lubang" di dalamnya. Kami akan menyebut angka-angka suci ini:

46890

Dengan demikian, 5 digit tidak suci:

12357

Jadi bilangan bulat dapat diklasifikasikan sebagai "suci" jika hanya berisi angka suci, dan "tidak suci" sebaliknya. Karena -tidak suci, tidak ada bilangan bulat negatif yang dapat menjadi kudus.

Bilangan bulat suci dapat diklasifikasikan lebih lanjut berdasarkan berapa banyak lubang yang mereka miliki. Misalnya, angka-angka berikut memiliki kekudusan 1:

469

Dan digit ini memiliki kekudusan 2:

80

Kami mengatakan bahwa keseluruhan kekudusan bilangan bulat adalah jumlah dari kekudusan digitnya. Karena itu, 80akan memiliki kekudusan 4, dan 99akan memiliki kekudusan 2.

Tantangan

Diberi dua bilangan bulat n > 0dan h > 0, nhasilkan bilangan bulat suci ke-2 yang kesuciannya setidaknya h. Anda dapat mengasumsikan bahwa input dan output tidak akan lebih besar dari integer maksimum yang dapat diwakili dalam bahasa Anda atau 2^64 - 1, mana yang kurang.

Berikut adalah daftar 25 bilangan bulat suci pertama dengan kekudusan h >= 1, untuk referensi:

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

25 bilangan bulat suci pertama dengan kekudusan h >= 2adalah:

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

Terkait - 1 2
Mego

26
Saya duduk di sini selama tiga puluh detik berpikir "bagaimana sih 0memiliki kekudusan dua" sebelum saya akhirnya mengklik tautan wikipedia ke Consolas
undergroundmonorail

Apakah yang kelima 1-Kudus nomor 9 atau 40?
Conor O'Brien

3
Apakah ini hanya kebetulan bahwa angka 8 + 8 + -889 adalah 8888? (ya, mungkin memang begitu, tetapi itu tetap membuat saya terhibur ...)
Toby Speight

5
Faktanya, karena Anda dapat memiliki angka 0 di depan sebelum angka, orang dapat menyatakan bahwa 0 adalah suci yang tak terhingga. Meskipun ∞ tampaknya sama suci. Tapi anehnya, 666 bahkan lebih suci ...
Darrel Hoffman

Jawaban:


6

Pyth, 32 byte

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

Penjelasan

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

Coba di sini

Mengambil input dalam formulir h \n n


12

Ruby, 109 105 95 82 byte

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

Ini adalah pendekatan "hitung dari 0 hingga 99999999999 ..." yang mengerikan, yang kebetulan 13 byte lebih pendek daripada rekannya yang malas. Namun, versi ini tidak mungkin selesai sebelum kematian panas alam semesta. Layak, bernilai 13 byte, ¯ ¯ _ (ツ) _ / ¯

Anda dapat mengujinya untuk nilai yang lebih kecil dengan mengubah ?9*99ke, katakanlah '99999',.

Ini versi lama (95 byte, dengan evaluasi malas, yang berjalan dekat-langsung daripada hampir tidak pernah):

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

Harus cinta evaluasi malas :)
Emigna

Mengapa tidak takebukan first?
Bukan karena Charles

@NotthatCharles takekembali Lazy, yang tidak dapat diindeks ke.
Gagang Pintu

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]

Berikut adalah solusi yang menggunakan pendekatan yang lebih efisien memori, tetapi sebaliknya menggunakan algoritma yang sama jika Anda ingin mengujinya.

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

Kasus uji:

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

@Mego Cool. Tampaknya menggunakan jumlah memori statis, sehingga tidak dalam bahaya kehabisan memori. Saya hanya tidak yakin karena sudah berjalan di mesin saya selama setengah jam sudah.
Morgan Thrapp

Ini sebenarnya membutuhkan waktu yang cukup lama hanya untuk menghitung 2**64-1; lihat stackoverflow.com/questions/34113609/…
Mego

@Mego Oh, aku bahkan tidak memikirkan itu. Ya, ketika saya meletakkan konstanta yang dikomputasi ke dalam kode, itu mulai mengunyah melalui sedikit 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

Mengambil input, lalu loop sampai $nnol. Kami awalnya mengatur $i=-1dengan menggunakan trik pra-pemrosesan, yang bekerja karena $i, setelah sebelumnya tidak dinyatakan, adalah $null. Lalu kita --, yang menyebabkan PowerShell untuk mengevaluasinya sebagai $i = $null - 1, yang $i=-1.

Setiap loop kami bertambah $idan kemudian jalankan ifpernyataan panjang . Bagian pertama dari kondisional memverifikasi yang $itidak memiliki bagian 12357di dalamnya dengan menggunakan -notmatchoperator , untuk menyaring angka-angka yang tidak suci.

Bagian kedua dari kondisi memeriksa jumlah lubang di $i. Ia menggunakan -replaceoperator untuk mengganti masing 8- masing atau 0dengan 11, dan kemudian membandingkan apakah panjangnya> = $h. Kita tidak perlu khawatir melucuti angka-angka yang tidak suci, karena itu ada di bagian pertama dari persyaratan, dan angka satu-lamanya sama panjangnya 1, jadi kita juga tidak perlu menggantinya.

Jika itu masih benar, kami mengurangi $n(karena itu berarti kami telah menemukan nomor lain yang memenuhi persyaratan input). Jadi ketika forkondisi dihitung ulang untuk memeriksa apakah $nnol, itu berarti kami telah menemukan yang ke - n , jadi kami keluar dari forloop, output, $idan berakhir.

Edit - disimpan 13 byte dengan menggunakan sebuah array bukan string untuk $ldan mengubah cara $ndecremented / diperiksa
Edit 2 - disimpan tambahan 9 byte dengan memeriksa $ndi forkondisional dan bergerak output di luar lingkaran
Edit 3 - disimpan kekalahan sebuah 40 byte lebih banyak dengan secara radikal mengubah cara kita menghitung lubang
Edit 4 - menyimpan 3 byte tambahan dengan memindahkannya ++menjadi pra-kenaikan pada bagian pertama dari Edit bersyarat
5 - menyimpan 2 byte lainnya berkat TessellatingHeckler


Rapi. Simpan beberapa byte lagi dengan mengubah ke for(--$i;$n)dan -replace"8|0"?
TessellatingHeckler

@ TessellatingHeckler Ya, terima kasih. Itu $i=-1membuat saya benar-benar gila. Saya masih mencoba mencari cara agar kita tidak harus menginisialisasi $isejak awal, tetapi hal yang saya coba sejauh ini lebih lama (dan, sekarang mengingat ini, kemungkinan akan lebih lama lagi).
AdmBorkBork


4

Utilitas Bash + GNU, 67

  • 20 byte disimpan berkat @TobySpeight!
seq 0 NaN|sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x"|sed $2!d\;q
  • seqhanya menghasilkan bilangan bulat mulai dari 0atas
  • sed -r:
    • h salin baris input ke ruang penahanan
    • /12357/d hapus nomor yang tidak suci
    • s/8|0/&&/gganti dua kali lipat angka suci dengan diri mereka sendiri. Jadi digit suci tunggal dihitung satu kali dan digit suci ganda dihitung dua kali.
    • /^.{$1}/!dJika tidak cocok dengan setidaknya $1lubang, hapus dan lanjutkan ke baris berikutnya
    • x bawa nomor asli kembali ke ruang pola
    • cetak tersirat
  • sed
    • $2!dpada baris mana saja sebelum baris $2, hapus dan lanjutkan ke baris berikutnya
    • qharus tepat $2- keluar (dan cetak tersirat)

Ideone.


1
Mencukur 9: sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x". Dan lain 4: sed $2!d\;q. Dan jika Anda senang dengan batas atas hanya 4611686018427387904, Anda bisa lolosseq 0 $[1<<62]
Toby Speight

1
Ooh, nilai saya seqterima NaN: Sekarang saya miliki seq 0 NaN|sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x"|sed $2!d\;q, nilai 67.
Toby Speight

@TobySpeight wow itu luar biasa!
Digital Trauma

@TobySpeight: hilang \ sebelum!, Jika tidak:-sh: !d\: event not found
Olivier Dulac

1
@OlivierDulac ` before ! `Tidak diperlukan dalam skrip . Ini hanya diperlukan ketika menjalankan ini secara langsung pada command-line, yang menurut saya bukan persyaratan.
Trauma Digital

3

MATL , 39 40 byte

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

Inpunts ndan hdalam urutan itu.

Cobalah online!

Kita perlu melacak dua angka: nomor kandidat saat ini (untuk memeriksa kekudusannya) dan jumlah angka yang ditemukan cukup kudus. Yang pertama adalah bagian atas tumpukan, dan yang terakhir disimpan sebagai jumlah elemen dalam tumpukan. Ketika program selesai, hanya bagian atas yang perlu ditampilkan.

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}

Dengan baris dan lekukan baru:

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
}

Pemakaian:

> 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

Solusi rekursif ekor yang mengakumulasikan bilangan suci dalam sebuah array.

Tanpa minat, tidak mengharuskan angka untuk sepenuhnya (!) Kudus membuat kekudusan lebih canggung, tetapi masih menghemat 10% secara keseluruhan:

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 Ups, saya menukar idan rparameter pada satu titik, dan gagal mengedit perubahan dengan benar.
Neil

1

JavaScript ES6, 191 byte

Tentu, ini bukan cara yang paling efisien. Tapi Anda tahu saya, saya suka generator <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)))

Sedikit tidak berbulu:

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

Ini adalah Ekspresi Lambda dari tipe Func <int, int, int>. Kode ini diautimisasi untuk ukuran minimum (tidak berkinerja).

Di bawah ini, kode yang dipercantik dalam deklarasi metode (dengan lebih banyak kinerja):

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

Hai Bobson, maaf jika saya salah paham, tetapi tidak mendeteksi kesalahan yang Anda tunjukkan dalam kode saya? Ini mengembalikan elemen ke-n yang diperlukan, dan hanya dia, dan nol jika valid, dengan asumsi bahwa inputnya adalah n = 1 dan h <= 2. Jika saya memahami tantangannya, harus mengembalikan hanya elemen yang satu ini dan tidak semuanya tergantung padanya. . Tapi saya salah paham dan kehilangan bahasa Inggris: D, terima kasih
Paulo César B. Sincos

Tidak, Anda sepenuhnya benar. Saya disesatkan oleh daftar-untuk-referensi, dan melewatkan fakta bahwa itu hanya meminta digit ke-n. Lanjut!
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")

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

Uji

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

Tidak Disatukan:

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

Mengambil kedua input dengan argumen baris perintah (argumen pertama adalah n, lalu h)

Sunting: Terima kasih kepada @DavisDude, yang membantu saya mencukur 14 byte dan mengingatkan saya bahwa saya tidak harus mencetak semua angka suci hingga n, tetapi hanya n.

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

Tidak terseret dan penjelasan

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

Anda bisa melepas beberapa karakter dengan melakukanprint(a[arg[1]])
DavisDude

@ Davidvis Saya bodoh, ketika saya menulis ini, saya pikir saya harus mencetak seluruh daftar nomor yang tidak suci hingga n. Sebenarnya, print(a[#a])menyimpan byte lebih banyak lagi. Terima kasih atas komentarnya!
Katenkyo

Anda menulis. Untuk beberapa alasan yang bahkan tidak terpikir oleh saya.
DavisDude

Anda dapat melepas satu char dengan menulis x=0a={}alih-alih x,a=0,{}.
Leaky Nun

1
@ KennyLau Sebenarnya, Anda tidak bisa karena 0aakan diartikan sebagai angka heksadesimal, tapi saya bisa melakukannya a={}x=0whiletanpa masalah :)
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;

Tidak bermain 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 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)

Kondisi kesucian kdiperiksa oleh

  • sum(map(s.count,`k`))>=h, yang menghitung jumlah lubang dengan menjumlahkan jumlah untuk setiap karakter s="0046889", di mana 0dan 8muncul dua kali.
  • set(str(k))<=set(s)), yang memeriksa bahwa semua angka adalah kudus. strdigunakan daripada backticks untuk menghindari akhiran Luntuk waktu yang lama.

Ini dirantai ke dalam kesetaraan tunggal menggunakan fakta Python 2 bahwa jumlahnya lebih kecil dari set.

Fungsi ini didefinisikan secara rekursif untuk menghitung angka k, mengurangi penghitung nsetiap kali jumlah hit suci kecuali jika hit 0. Kemudian dapat mengembalikan kyang memicu ini, tetapi lebih pendek untuk menjaga penghitungan secara rekursif dengan menambahkan 1setiap waktu, meskipun off-by-one membutuhkan hitungan dasar -1untuk memperbaikinya.


0

Haskell, 94 byte

cadalah kekudusan digit, vkekudusan angka, n!hmelakukan sisanya.

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

Catatan: Saya pikir ini adalah satu-satunya jawaban tanpa karakter 4,6,8.


0

Cepat

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}}
    }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.