Святі числа


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є святість двох", перш ніж я нарешті натиснув на посилання вікіпедії на "Консолі"
undergroundmonorail

Чи є п’яте 1-Святе число 9 чи 40?
Conor O'Brien

3
Чи просто збіг обставин, що 8-е число + + святе - 8888? (так, це, мабуть, є, але це все одно мене розвеселило ...)
Toby Speight

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
}

Треба любити ліниві оцінки :)
Емінья

Чому б не 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

@Mego Cool. Здається, використовується статичний об'єм пам'яті, тому не загрожує втрата пам'яті. Я просто не був впевнений, оскільки він працює на моїй машині вже півгодини.
Морган Трапп

Насправді потрібен пристойний шматок часу лише для того, щоб прорахувати 2**64-1; дивіться stackoverflow.com/questions/34113609/…
Mego

@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і закінчуємо.

Редагувати - збережено 13 байт за допомогою масиву замість рядка для $lта зміни способу $nзменшення / перевірки
Правка 2 - збереження додаткових 9 байт шляхом перевірки $nв forумовному режимі та переміщення виходу за межі циклу
Правка 3 - збережена колосальна Ще 40 байт, докорінно змінивши спосіб обчислення отворів
Edit 4 - зберегли додаткові 3 байти, перемістивши на ++попередній приріст у першій частині умовного
редагування 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- киньте (та неявна друк)

Ідеон.


1
Гоління 9 : sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x". І ще 4: sed $2!d\;q. І якщо вас порадує верхня межа всього 4611686018427387904, ви можете пітиseq 0 $[1<<62]
Toby Speight

1
Ой, моє seqсприймає NaNяк значення: я зараз маю seq 0 NaN|sed -r "h;/[12357]/d;s/8|0/&&/g;/^.{$1}/!d;x"|sed $2!d\;q, забив 67.
Toby Speight

@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 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 На жаль, я поміняв місцями параметри 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

Безголівки:

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])економить ще більше байт. Дякуємо за коментар!
Katenkyo

Ви пишете. Чомусь це мені навіть не траплялося.
DavisDude

Ви можете зняти один char, написавши 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;

Без гольфу

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