聖なる数字


44

多くのフォント(特にConsolasフォント)では、10進数の10桁のうち5桁に「穴」があります。これらの聖なる数字を呼び出します。

46890

したがって、5つの不浄な数字は次のとおりです。

12357

したがって、整数は、それが神聖な数字のみを含む場合は「神聖」として分類され、そうでない場合は「神聖でない」として分類されます。-聖ではないので、負の整数は聖になることができません。

聖なる整数は、それらが持つ穴の数に基づいてさらに分類されます。たとえば、次の数字の聖性は1です。

469

そして、これらの数字の神聖さは2です。

80

整数の全体的なホーリネスは、その桁のホーリネスの合計であると言います。したがって、80聖性は4になり99、聖性は2になります。

挑戦

2つの整数n > 0とが与えられた場合、ホーリー性が少なくともでh > 0あるnthの整数を出力しhます。入力および出力は、言語で表現可能な最大整数またはの2^64 - 1いずれか小さい方よりも大きくないと仮定できます。

h >= 1参照用に、holinessを含む最初の25個の聖なる整数のリストを以下に示します。

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の聖なる整数h >= 2は次のとおりです。

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

関連-1 2
Mego

26
i「は一体どのように考えて30秒間のようなここに座っていた0私は最終的にConsolasへのウィキペディアのリンクをクリックする前に2の神聖さを持っている」
undergroundmonorail

5番目の1-Holy番号は9または40ですか?
コナーオブライエン

3
8番目の8 +-聖数が8888であることは偶然ですか?(はい、それはおそらくですが、それは...とにかく私を面白がって)
トビースパイツ

5
実際、数字の前に任意の数の先行0を置くことができるため、0が無限に神聖であると主張することができます。∞は明らかに聖なるもののようです。しかし、不思議なこと、666 ...でも聖人である
ダレル・ホフマン

回答:


6

Pyth、32バイト

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

説明

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

ここで試してみてください

フォームに入力を取ります h \n n


12

ルビー、109 105 95 82バイト

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

これは、「0から99999999999まで計算する」というひどいアプローチで、たまたまその怠zyな対応よりも13バイト短くなります。ただし、このバージョンは、宇宙の熱死の前に終了することはほとんどありません。とにかく¯\ _(ツ)_ /¯

?9*99たとえばに変更することで、より小さい値をテストできます'99999'

古いバージョン(95バイト、遅延評価付き、これはほとんどないのではなく、ほぼ瞬時に実行されます)は次のとおりです。

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


なぜではtakeなくfirst
チャールズ

@NotthatCharles takeLazy、インデックスを作成できないを返します。
ドアノブ

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]

メモリ効率の高いアプローチを使用するソリューションを次に示しますが、テストする場合は同じアルゴリズムを使用します。

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

テストケース:

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

@Mego Cool。静的な量のメモリを使用しているようですので、メモリ不足になる危険はありません。マシン上ですでに30分実行されているので、私は確信がありませんでした。
モーガンスラップ

実際には、計算するだけでもかなりの時間がかかります2**64-1。参照stackoverflow.com/questions/34113609/...
MEGO

@Megoああ、私もそれについて考えませんでした。ええ、事前計算済みの定数をコードに入れると、RAMを少し噛み始めます。
モーガンスラップ

6

PowerShellの、163の 150 141 101 98 96バイト

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

入力を受け取り、$nゼロになるまでループします。最初に設定$i=-1するのは、前処理トリックを使用して設定すること$iです$null。それ--から、PowerShellがを評価します。$i = $null - 1これは$i=-1です。

各ループでは、増分して$iから長いif文を実行します。条件付きの最初の部分は、演算子を使用$iして不聖な数を除外する12357ことにより、その中に何も含まれていないことを検証します。-notmatch

条件の2番目の部分は、の穴の量をチェックし$iます。-replace演算子を使用して、8または0をそれぞれ置換し11、長さが> =かどうかを比較し$hます。それは条件の最初の部分にあり、単一の穴のある数字は1とにかく同じ長さなので、不聖な数字を取り除くことを心配する必要はありません。したがって、それらを置き換える必要もありません。

それでも真実であれば、デクリメントします$n(つまり、入力要件を満たす別の数値が見つかったということです)。したがって、for条件が$n0であるかどうかを確認するために再計算されると、n番目の条件が見つかったため、forループを終了し、出力$iして終了します。

編集-の配列の代わりに文字列を使用して13のバイトを保存$lし、どのように変化$nデクリメント/チェック
編集2 -をチェックすることによって、追加の9つのバイトを保存$nfor、条件とループの外出力を移動
編集3 -なんと保存穴の計算方法を根本的に変更することでさらに40バイト
編集4- ++条件付き編集5の最初の部分でプリインクリメントになるように移動することでさらに3バイトを
節約-TessellatingHecklerのおかげでさらに2バイト節約


きちんとした。for(--$i;$n)および-replace"8|0"?に変更して、さらに数バイト節約します。
TessellatingHeckler

@TessellatingHecklerはい、ありがとうございます。それ$i=-1は私を絶対に狂気に駆り立てていました。私はまだ方法を試しているので$i、最初に初期化する必要はありませんが、これまで試してきたことはもっと長くなります(これを考えると、おそらくもっと長くなります)。
AdmBorkBork


4

Bash + GNUユーティリティ、67

  • @TobySpeightのおかげで20バイト節約されました!
seq 0 NaN|sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x"|sed $2!d\;q
  • seq単純に0上から始まる整数を生成します
  • sed -r
    • h 入力行を保留スペースにコピーします
    • /12357/d 不浄な数字を削除する
    • s/8|0/&&/g二重の神聖な数字を2回に置き換えます。したがって、単一の聖数字は1回カウントされ、二重の聖数字は2回カウントされます。
    • /^.{$1}/!d少なくとも$1穴に一致しない場合は、削除して次の行に進みます
    • x 元の番号をパターンスペースに戻す
    • 暗黙の印刷
  • sed
    • $2!dlineの前の任意の行で$2、削除して次の行に進みます
    • q行になければならない$2-終了(および暗黙の印刷)

イデオネ。


1
シェービング9: sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x"。そして別の4 :sed $2!d\;q。そして、あなたは上だけ4611686018427387904の上限としている幸せ、あなたが逃げることができればseq 0 $[1<<62]
トビースパイツ

1
ああ、私はseq受け入れNaN値として:私は今持っているseq 0 NaN|sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x"|sed $2!d\;q、67得点
トビースパイツ

@TobySpeightすごいすごい!
デジタル外傷

@TobySpeight:!の前に\がない、そうでない場合:-sh: !d\: event not found
オリビエデュラック

1
@OlivierDulac ` before ! `はスクリプトでは必要ありません。コマンドラインで直接これを実行する場合にのみ必要ですが、これは要件ではないと思います。
デジタル外傷

3

MATL、39 40バイト

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

Inpuntsはありnかつhその順序で。

オンラインでお試しください!

現在の候補番号(その神聖さを確認するため)と、十分に神聖な番号の数を追跡する必要があります。最初はスタックの一番上で、後者はスタック内の要素の数として保持されます。プログラムが終了したら、上部のみを表示する必要があります。

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バイト

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}

新しい行とインデント:

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
}

使用法:

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

3

JavaScript(ES6)、110バイト

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

配列に聖なる数字を蓄積する末尾再帰ソリューション。

興味深いことに、数字を完全に(!)聖にする必要はありませんが、神聖さはより厄介になりますが、それでも全体で10%節約されます:

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おっと、私は以上のスワップir一点でのパラメータを、編集正しく変更に失敗しました。
ニール

1

JavaScript ES6、191バイト

確かに、これは最も効率的な方法ではありません。しかし、あなたは私を知っています、私は発電機が大好きです<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)))

わずかに未使用:

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バイト

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

これは、Func <int、int、int>型のラムダ式です。このコードは最小サイズに最適化されています(パフォーマティックではありません)。

以下に、メソッド宣言の美化されたコード(より多くのパフォーマンス):

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

こんにちはボブソン、誤解して申し訳ありませんが、私のコードで指摘された障害を検出しませんか?入力がn = 1およびh <= 2であると仮定して、必要なn番目の要素、および彼のみを返し、有効な場合はゼロを返します。 。しかし、私は私を誤解し、英語で失った:Dおかげで
パウロセザールB.シンコス

いいえ、あなたは完全に正しいです。参照用リストに誤解され、n番目の桁を求めているだけであるという事実を見逃しました。続ける!
ボブソン

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

少ないゴルフ

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
}  

テスト

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バイト

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

ゴルフをしていない:

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バイト

コマンドライン引数で両方の入力を取ります(最初の引数はn、次にh)

編集:14バイトを削るのを手伝ってくれた@DavisDudeに感謝します。

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

非ゴルフと説明

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

いくつかの文字を脱ぐことができますprint(a[arg[1]])
-DavisDude

@DavisDude私がこれを書いたとき、私は愚かでしたが、私は私までの神聖な数のリスト全体を印刷しなければならなかったけれどもn。実際、print(a[#a])さらに多くのバイトを節約できます。コメントありがとう!
かてんきょう

あなたは書いています。なんらかの理由で、それは私にも起こりませんでした。
デイビスデュード

x=0a={}代わりに書くことで1つの文字を削除できますx,a=0,{}
漏れの修道女

1
@KennyLau実際には0a、16進数として解釈されるため、できませんa={}x=0whileが、問題なく実行できます:)
Katenkyo

0

Oracle SQL 11.2、229バイト

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;

ゴルフをしていない

: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バイト

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)

上の聖さの状態k

  • sum(map(s.count,`k`))>=h、これは、各文字の数を合計することによって、穴の数をカウントしs="0046889"0そして8二回表示されます。
  • set(str(k))<=set(s))、数値がすべて神聖であることを確認します。longs strの接尾辞を避けるために、バックティックよりもむしろ使用されLます。

これらは、数値がセットよりも小さいというPython 2の事実を使用して、単一の等式にチェーンされます。

この関数は再帰的に定義され、数字をカウントアップし、ヒットしない限り神聖なヒットのたびkにカウンターを減らします。その後、これをトリガーしたものを返すことができますが、毎回追加することで再帰的にカウントを維持する方が短くなりますが、オフバイワンでは修正するための基本カウントが必要です。n0k1-1


0

Haskell、94バイト

c数字の聖性、数字vの聖性がn!h残りを行います。

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

注:これは、文字のない唯一の答えだと思います4,6,8


0

迅速

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}}
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.