Я номер каллена?


25

Цифровий номер - це будь-яке число, яке міститься в послідовності, згенерованої за формулою:

C (n) = (n * 2 ^ n) +1.

Ваше завдання:

Напишіть програму або функцію, яка отримує вхід і виводить значення truthy / falesy на основі того, чи є вхідним номером Cullen.

Вхід:

Невід’ємне ціле число від 0 до 10 ^ 9 (включно).

Вихід:

Кореневе / хибне значення, яке вказує, чи є вхідним номером Cullen.

Випробування:

Input:    Output:
1   --->  truthy
3   --->  truthy
5   --->  falsy
9   --->  truthy
12  --->  falsy
25  --->  truthy

Оцінка:

Це , тому найнижча оцінка в байтах виграє.


1
Який діапазон n ? Зокрема, чи є 1 номер Cullen?

3
@ ais523 згідно OEIS , це так. nздається, на основі 0.
steenbergh

Досить справедливо. Просто потрібно було знати, чи має у моїй відповіді Jelly або є R:-)


Гм, що з головою?
Грифон - Відновіть Моніку

Відповіді:



16

машинний код x86_64 ( System V ABI ), 28 27 байт

-1 байт дякую @Cody Grey, дякую!

Алгоритм постійного часу!

_cullen:
   0:   0f bd cf    bsrl    %edi, %ecx
   3:   0f bd c1    bsrl    %ecx, %eax
   6:   89 ca       movl    %ecx, %edx
   8:   29 c2       subl    %eax, %edx
   a:   0f bd c2    bsrl    %edx, %eax
   d:   29 c1       subl    %eax, %ecx
   f:   d3 e1       shll    %cl, %ecx
  11:   ff c1       incl    %ecx
  13:   31 c0       xorl    %eax, %eax
  15:   39 f9       cmpl    %edi, %ecx
  17:   0f 94 c0    sete    %al
  1a:   c3          retq

Пояснення:

Нехай y ціле число і x=y*2^y + 1. y + log2(y) = log2(x-1)Таким чином , ми беремо колоди y=log2(x-1)-log2(y). Підключивши назад значення y, отримаємо y=log2(x-1)-log2(log2(x-1)-log2(y)). Роблячи це ще раз, ми отримаємо: y=log2(x-1)-log2[log2(x-1)-log2(log2(x-1)-log2(log2(x-1)-log2(y)))].

Давайте видалимо останні умови (з порядку log2(log2(log2(log2(x)))), це повинно бути безпечно!), І припустимо, що x-1≈xми отримаємо: y≈log2(x)-log2[log2(x)-log2(log2(x))]

Тепер, дозволяючи f(n) = floor(log2(n)), це можна перевірити вручну, що yможе бути точно отримано за:, y=f(x)-f[f(x)-f(f(x))]для y <26 , і, таким чином, x ⩽ 10 ^ 9 , як визначено викликом (1) .

Потім алгоритм просто складається з обчислення y, заданого x , і перевірки, що x == y * 2 ^ y + 1 . Хитрість полягає в тому, що f(n)може бути просто реалізована як bsrінструкція (біт-сканування назад), яка повертає індекс першого 1-біта в n , і y*2^yяк y << y.

Детальний код:

_cullen:                                 ; int cullen(int x) {
   0:   0f bd cf    bsrl    %edi, %ecx   ;  int fx = f(x);
   3:   0f bd c1    bsrl    %ecx, %eax   ;  int ffx = f(f(x));
   6:   89 ca       movl    %ecx, %edx   
   8:   29 c2       subl    %eax, %edx   ;  int a = fx - ffx;
   a:   0f bd c2    bsrl    %edx, %eax   ;  int ffxffx = f(a);
   d:   29 c1       subl    %eax, %ecx   ;  int y = fx - ffxffx;
   f:   d3 e1       shll    %cl, %ecx    ;  int x_ = y<<y;
  11:   ff c1       incl    %ecx         ;  x_++;
  13:   31 c0       xorl    %eax, %eax
  15:   39 f9       cmpl    %edi, %ecx
  17:   0f 94 c0    sete    %al
  1a:   c3          retq                 ;  return (x_ == x);
                                         ; }

(1) Насправді ця рівність, як видається, виконується для значень y до 50000.


4
Ну, я впевнений, що це кваліфікується як найцікавіший код цього виклику поки що. +1
Грифон - Відновіть Моніку

1
Попередній XORing eaxдозволить вам усунути movzbl, заощадивши 1 байт. Вам потрібно буде зробити XOR перед тим, cmplщоб він, звичайно, не розтушовував прапори, але це абсолютно добре, тому що нічого після цього не залежить eax. Або ви можете просто вирішити, що метод повертає булевий рівень лише в 8 нижніх бітах, зберігаючи всі 3 байти!
Коді Грей

@CodyGray Дійсно, спасибі велике :)
yoann

7

Желе , 7 6 байт

Ḷæ«`i’

Спробуйте в Інтернеті!

Вводиться як аргумент командного рядка. Якщо задано число Cullen C ( n ), виводить n +1 (що є втілковим в Jelly, будучи ненульовим цілим числом; зауважте, що у нас n ≥0, оскільки вхід є цілим числом, а числа Каллена з від'ємним n ніколи не є цілими числами) . Якщо буде вказано число, яке не є Cullen, повертає 0, що є фальсі в Jelly.

Пояснення

Ḷæ«`i’
Ḷ        Form a range from 0 to (the input minus 1)
 æ«      Left-shift each element in the range by 
   `       itself
    i’   Look for (the input minus 1) in the resulting array

В основному сформуйте масив чисел Каллена мінус один, а потім шукайте вхід мінус один у ньому. Якщо вхід - це номер Каллена, ми його знайдемо, інакше не будемо. Зауважте, що масив обов'язково достатньо довгий, щоб дійти до входу, оскільки C ( n ) завжди більше n .


7

JavaScript (ES6), 37 35 байт

Збережено 2 байти завдяки Нілу

f=(n,k,x=k<<k^1)=>x<n?f(n,-~k):x==n

Демо


Чи x<n?f(n,k+1):x==nпрацює?
Ніл

@Neil Це точно. :-)
Арнольд

Чому `~ k працює, тоді як k + 1 перевантажує ставок виклику?
trlkly

@trlkly В основному, undefined+1===NaNале -~undefined===1. Більше про це можна прочитати тут .
Арнольд


3

Ом , 8 байт

@Dº*≥Dlε

Спробуйте в Інтернеті!

           Implicit input
@          Range [1,...,Input]
 D         Duplicate
  º        2^n each element
   *       Multiply those two array
    ≥      Increment everything (now I have an array of all Cullen Numbers)
     Dl    Push array length (= get input again, can't get again implicitly or using a function because it would be a string so I'd waste a byte again)
       ε   Is input in array?


3

05AB1E , 7 байт

ÝDo*¹<å

Спробуйте в Інтернеті!

Пояснення:

ÝDo*¹<å Example input: 9. Stack: [9]
Ý       Range 0-input. Stack: [[0,1,2,3,4,5,6,7,8,9]]
 D      Duplicate. Stack: [[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9]]
  o     2** each item in the list. Stack: [[0,1,2,3,4,5,6,7,8,9], [1,2,4,8,16,32,64,128,256,512]]
   *    Multiply the two lists. Stack: [[0, 2, 8, 24, 64, 160, 384, 896, 2048, 4608]]
    ¹   Push input again. Stack: [[0, 2, 8, 24, 64, 160, 384, 896, 2048, 4608],9]
     <  Decrement. Stack: [[0, 2, 8, 24, 64, 160, 384, 896, 2048, 4608],8]
      å Is the first item of the stack in the second item? Stack: [1]
        Implicit print.

3

R , 53 51 46 байт

pryr::f(x%in%lapply(0:x,function(y)(y*2^y+1)))

Анонімна функція. Перевіряє, чи xгенерується в послідовності C (n) для n в [0, x].

3 байти в гольф Джузеппе.

Спробуйте в Інтернеті!


використовувати x%in%...замість any(x==...); це скине вас на 4 байти
Джузеппе

Тож якщо я пограю цим шляхом, змінивши lapplyна просто перевірку вектора і використовую scanзамість того, щоб брати аргументи функції - я отримую відповідь @giuseppe. Дякую, що розмістив його окремо, щоб я міг побачити, чого мені не вистачає - я дізнаюся більше, намагаючись щось самостійно, хоча зазвичай програю.
BLT

3

C, C ++, Java, C #, D: 70 байт

Через подібність між усіма цими мовами цей код працює для кожної

int c(int n){for(int i=0;i<30;++i)if((1<<i)*i+1==n)return 1;return 0;}

Цього разу я опублікую оптимізовану D-версію, можна використати деякі досить хитромудрі D-хитрощі.
Zacharý

Запропонувати i=30;i--;)if(i<<i==n-1)замістьi=0;i<30;++i)if((1<<i)*i+1==n)
roofcat




2

APL (Dyalog) , 9 байт

Щоб охопити випадок n = 1, ⎕IO←0для багатьох систем потрібно встановити за замовчуванням.

⊢∊1+⍳×2*⍳

Спробуйте в Інтернеті!

 [є] n (аргумент)

 член

1 один

+ плюс

 в I ntegers 0 ... ( п -1)

× разів

2 два

* під силу

 в I ntegers 0 ... ( п -1)


Отже, "за замовчуванням у багатьох системах" означає, що він просто існує ?
Zacharý

@ Zacharý Так, було б неправильно називати ⎕IO←0нестандартним, оскільки багато хто насправді завжди встановлює так, без специфікацій, необхідних кожного разу.
Адам

Добре. Я буду використовувати цей трюк у MY напевно (і у MY може бути не 0 і не 1 Походження індексу), якщо я коли-небудь отримаю можливість.
Zacharý

@ Zacharý Чи не вимагають фактичної установки / версії, де ці значення за замовчуванням? Наприклад , в SAX і СПП ⎕IO←0.
Adám

Так, я думаю. У МОЕ є три йоти, тому я думаю, що це не було б використане.
Zacharý

2

Python 2 , 32 байти

[n<<n|1for n in range(26)].count

Спробуйте в Інтернеті!

Створює список номерів Cullen до 10^9, а потім підраховує, скільки разів відображається вхід у ньому. Дякуємо Вінсенту за те, що він вказав n<<n|1замість цього (n<<n)+1, економив 2 байти.


Ви можете зберегти два байти, використовуючи n<<n|1( n<<nбути рівним);)
Вінсент

Це не вдається 838860801. Вам потрібно range(26), тому що асортимент не включає все.
mbomb007

@ mbomb007 Дякую Я робив це деякий час і досі іноді забуваю, що діапазони є виключно правильними.
xnor

2

D, 65 байт

Це порт алгоритму @ HatsuPointerKun до D (в оригіналі вже був D код, але це з хитрощами D)

T c(T)(T n){for(T i;i<30;++i)if((1<<i)*i+1==n)return 1;return 0;}

Як? (D конкретні хитрощі)

Система шаблонів D коротша, ніж у C ++, і може робити висновки про типи. D також ініціалізує свої змінні до дефолту після декларування.


1

Математика, 30 байт

MemberQ[(r=Range@#-1)2^r+1,#]&

Чистий функція приймає невід'ємне ціле число в якості вхідних даних і повернення Trueабо False. Якщо вхід є n, то (r=Range@#-1)встановлює змінну, rяка буде {0, 1, ..., n-1}, а потім r2^r+1векторіально обчислює перші nчисла Каллена. MemberQ[...,#]потім перевіряє, чи nє елементом списку.



1

Excel VBA, 45 байт

Анонімна функція негайного вікна VBE, яка приймає вхід з комірки [A1]та вихід у безпосереднє вікно VBE

Потрібно запустити в чистому модулі або мати значення для i, j бути скинуто до значення за замовчуванням 0 між прогонами

While j<[A1]:j=(i*2 ^ i)+1:i=i+1:Wend:?j=[A1]

Введення-виведення

I / O, як видно у безпосередньому вікні VBE

[A1]=25
While j<[A1]:j=(i*2 ^ i)+1:i=i+1:Wend:?j=[A1]
True

[A1]=1: i=0:j=0 ''# clearing module values
While j<[A1]:j=(i*2 ^ i)+1:i=i+1:Wend:?j=[A1]
True    

[A1]=5: i=0:j=0 ''# clearing module values
While j<[A1]:j=(i*2 ^ i)+1:i=i+1:Wend:?j=[A1]
False 

1

Swi-Prolog, 69 байт

f(X)досягає успіху, якщо він може знайти значення I, де X = I * 2 ^ I + 1. Підказка про діапазон зупиняє його відсутність у просторі стеку, але цього достатньо для діапазону чисел Каллена до 10 ^ 9 у специфікації запитання.

:-use_module(library(clpfd)).
f(X):-I in 0..30,X#=I*2^I+1,label([I]).

напр

f(838860801).
true


1

TI-BASIC, 17 байт

max(Ans=seq(X2^X+1,X,0,25

Пояснення

seq(X2^X+1,X,0,25 Generate a list of Cullen numbers in the range
Ans=              Compare the input to each element in the list, returning a list of 0 or 1
max(              Take the maximum of the list, which is 1 if any element matched

Ви можете додати пояснення до цього.
Грифон - Відновити Моніку

Готово, дякую за пораду.
calc84maniac

Це працює, але пояснення "команда за командою", як правило, допомагає отримати більшу частину результатів. Я б рекомендував робити щось подібне до пояснення цієї відповіді . Я не знаю, чому хтось порушив вашу посаду. Зазвичай зазвичай люб’язно залишати коментар, коли ви це робите, хоча ця ідея часто ігнорується.
Грифон - Відновити Моніку

Будь ласка. Пам’ятаю, коли я вперше зайшов на сайт, люди розповідали мені такі речі. Тільки передаючи прихильність.
Грифон - Відновіть Моніку

0

QBIC , 24 байти

[0,:|~a*(2^a)+1=b|_Xq}?0

Пояснення

[0,:|           FOR a = 0 to b (input from cmd line)
~a*(2^a)+1=b    IF calculating this a results in b
|_Xq            THEN quit, printing 1
}               NEXT a
?0              We haven't quit early, so print 0 and end.



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.