Святые числа


44

Во многих шрифтах (особенно в шрифте Consolas ) 5 из 10 десятичных цифр имеют «дыры» в них. Мы назовем эти святые цифры:

46890

5 нечестивых цифр таковы:

12357

Таким образом, целое число может быть классифицировано как «священное», если оно содержит только святые цифры, и «нечестивое» в противном случае. Поскольку -это нечестиво, никакие отрицательные целые числа не могут быть святыми.

Святые целые числа могут быть далее классифицированы в зависимости от того, сколько у них дыр. Например, следующие цифры имеют святость 1:

469

И эти цифры имеют святость 2:

80

Мы говорим, что общая святость целого числа является суммой святости его цифр. Следовательно, 80будет иметь святость 4, и 99будет иметь святость 2.

Соревнование

Дано два целых числа n > 0и h > 0выведите nсвятое целое число, святость которого хотя бы равна h. Вы можете предположить, что входные и выходные данные будут не больше максимально представимого целого числа в вашем языке или в 2^64 - 1зависимости от того, что меньше.

Вот список первых 25 святых чисел со святостью h >= 1, для справки:

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
я сидел здесь тридцать секунд, размышляя «как, черт возьми 0, святость двоих», прежде чем я, наконец, нажал на ссылку в Википедии на Консолас
подземный

Является ли пятое 1-святое число 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 ...», который оказывается на 13 байт короче, чем его ленивый аналог. Тем не менее, эта версия вряд ли закончится до тепловой смерти вселенной. В любом случае стоит 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
}

Должен любить ленивую оценку :)
Emigna

Почему не takeвместо first?
Не то, что Чарльз

@NotthatCharles takeвозвращается Lazy, которые не могут быть проиндексированы в.
Дверная ручка

6

Питон 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

@ Мего Круто. Кажется, что он использует статический объем памяти, поэтому он не рискует исчерпать память. Я просто не был уверен, так как он уже полчаса работает на моей машине.
Морган Трепп

На самом деле это занимает приличный кусок времени только для расчета 2**64-1; см. stackoverflow.com/questions/34113609/…
Mego

@ Мего О, я даже не думала об этом. Да, когда я вставляю в код предварительно вычисленную константу, она начинает жевать немного оперативной памяти.
Морган Трепп

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оператора , чтобы отфильтровать нечестивые числа.

Вторая часть условной проверки количества отверстий в $i. Он использует -replaceоператор для замены каждого 8или 0на 11, а затем сравнивает, является ли длина> = $h. Нам не нужно беспокоиться об удалении нечестивых чисел, так как они находятся в первой части условного числа, а числа с одинарной дырой имеют ту же длину, что и в 1любом случае, поэтому нам также не нужно их заменять.

Если это все еще верно, мы уменьшаем $n(поскольку это означает, что мы нашли другое число, которое удовлетворяет входным требованиям). Таким образом, когда forусловие пересчитывается, чтобы проверить, $nравно ли оно нулю, это означает, что мы нашли n-е , поэтому мы выходим из forцикла, выводим $iи завершаем работу.

Edit - сохранил 13 байтов, используя массив вместо строки для $lи изменив порядок $nуменьшения / проверки.
Edit 2 - сохранил дополнительные 9 байтов, проверив $nв forусловных выражениях и переместив вывод за пределы цикла.
Edit 3 - сохранил колоссальные Еще 40 байтов, радикально изменив способ вычисления дырок.
Edit 4 - сохранил дополнительные 3 байта, переместив ++их в прединкремент первой части условного
Edit 5 - сохранил еще 2 байта благодаря TessellatingHeckler


Ухоженная. Сохранить еще пару байтов, изменив на for(--$i;$n)и -replace"8|0"?
TessellatingHeckler

@ TessellatingHeckler Да, спасибо. Это $i=-1сводило меня с ума. Я все еще пытаюсь найти способ, чтобы нам не нужно было инициализировать $iв первую очередь, но вещи, которые я пробовал до сих пор, длиннее (и, учитывая это, скорее всего, еще дольше).
AdmBorkBork


4

Утилиты Bash + GNU, 67

  • 20 байтов сохранено благодаря @TobySpeight!
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замените вдвое больше святых цифр Таким образом, одиночные святые цифры считаются один раз, а вдвое святые цифры считаются дважды.
    • /^.{$1}/!dЕсли не совпадают хотя бы $1отверстия, удалите и перейдите к следующей строке
    • x вернуть оригинальный номер обратно в пространство шаблона
    • неявная печать
  • sed
    • $2!dв любой строке перед строкой $2удалите и перейдите к следующей строке
    • qдолжен быть в строке $2- выход (и неявная печать)

Ideone.


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

Входы есть 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 109 байт

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 Ой, я поменял местами параметры iи и rв одном месте, и не смог правильно изменить изменение.
Нил

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-й элемент, и только он, и ноль, если он действителен, при условии, что входные данные равны n = 1 и h <= 2. Если я понимаю задачу, должен вернуть только этот один элемент, а не все до него , Но я неправильно понял и потерял на английском языке: D спасибо
Пауло Сезар Б. Синкос

Нет, ты совершенно прав. Я был введен в заблуждение списками для справок, и пропустил тот факт, что он просто просит 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

Луа, 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

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

Луа, 155 141 140 байт

Принимает оба ввода аргументом командной строки (сначала аргумент n, затем h)

Редактировать: Спасибо @DavisDude, который помог мне сбрить 14 байтов и напомнил мне, что мне не нужно печатать все святые числа до n, а только 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])

Неуправляемый и объяснения

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])экономит еще больше байтов. Спасибо за комментарий !
Катенкё

Вы пишите. По какой-то причине это даже не пришло мне в голову.
DavisDude

Вы можете снять один символ, написав x=0a={}вместо x,a=0,{}.
Дрянная Монахиня

1
@KennyLau На самом деле, вы не можете, потому 0aчто будет интерпретироваться как шестнадцатеричное число, но я могу обойтись 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;

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 байт

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)), который проверяет, что все числа являются святыми. strиспользуется вместо кавычек, чтобы избежать суффикса Lдля длинных.

Они объединены в одно равенство с использованием факта Python 2, что числа меньше, чем множества.

Функция определяется рекурсивно для подсчета чисел k, уменьшая счетчик nкаждый раз, когда святое число попаданий, если оно не попадет 0. Затем он мог бы вернуть то, kчто вызвало это, но короче, чтобы рекурсивно поддерживать счет, добавляя 1каждый раз, хотя для каждого по отдельности требуется базовый счет -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}}
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.