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


25

Номер Каллена - это любое число, которое содержится в последовательности, сгенерированной по формуле:

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

Твое задание:

Напишите программу или функцию, которая получает входные данные и выводит истинное / ложное значение в зависимости от того, является ли этот вход числовым значением Каллена.

Входные данные:

Неотрицательное целое число от 0 до 10 ^ 9 (включительно).

Выход:

Истинное / ложное значение, которое указывает, является ли ввод Калленом.

Тестовые случаи:

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

Подсчет очков:

Это , поэтому выигрывает самая низкая оценка в байтах.


1
Какой диапазон п ? В частности, является ли номер 1 Калленом?

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

Объяснение:

Пусть у целое число и x=y*2^y + 1. Взяв бревна у нас y + log2(y) = log2(x-1), таким образом y=log2(x-1)-log2(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’

Попробуйте онлайн!

Принимает ввод в качестве аргумента командной строки. Если дано число Каллена C ( n ), выводит n +1 (что верно в Jelly, являющееся ненулевым целым числом; обратите внимание, что у нас n ≥ 0, потому что входное значение является целым числом, а числа Каллена с отрицательным n никогда не являются целыми числами) , Если дано число не по Каллену, возвращает 0, что неверно в желе.

объяснение

Ḷæ«`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

PHP , 43 байта

for(;$argn>$c=1+2**$n*$n++;);echo$argn==$c;

Попробуйте онлайн!


Это $argnспециальная переменная? Изменение этого параметра $aпозволит сэкономить 6 байт: tio.run/##K8go@G9jX5BRwKWSaKtkaGaoZP0/…
выше

@topher Да $argnдоступно, если вы запускаете PHP из командной строки с -Rопцией
Jörg Hülsermann

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 приемы.
Захари

Предлагаю i=30;i--;)if(i<<i==n-1)вместоi=0;i<30;++i)if((1<<i)*i+1==n)
floorcat



2

R , 26 байт

a=0:26;scan()%in%(1+a*2^a)

Попробуйте онлайн!

Немного другой подход, чем другой ответ R ; читает из stdinи поскольку входные данные гарантированно будут между 0 и 10 ^ 9, мы просто должны проверить nмежду 0 и 26.


Я никогда не помню scan(). Хорошая работа.
BLT

2

APL (Дьялог) , 9 байт

Чтобы охватить случай n = 1, требуется, ⎕IO←0что по умолчанию во многих системах.

⊢∊1+⍳×2*⍳

Попробуйте онлайн!

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

 членом

1 один

+ плюс

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

× раз

2 два

* в силу

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


Итак, «по умолчанию во многих системах» означает, что он просто существует ?
Захари

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

Что ж. Я собираюсь использовать этот трюк в MY наверняка (и MY может иметь не-0 и не-1 Index Origins), если я когда-либо получу шанс.
Захари

@ Zacharý Разве это не потребует фактической установки базы / версий, где эти значения по умолчанию? Например, в SAX и NGN ⎕IO←0.
адам

Да, наверное. И МОЙ имеет три йоты, так что я думаю, что они не будут использованы в любом случае.
Захари

2

Python 2 , 32 байта

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

Попробуйте онлайн!

Создает список чисел Каллена до 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

Mathematica, 30 байт

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

Чистая функция, принимающая неотрицательное целое число в качестве входных данных и возвращающая Trueили False. Если ввод n, то (r=Range@#-1)устанавливает переменную rравной {0, 1, ..., n-1}, а затемr2^r+1 векторно вычисляет первые nцифры Cullen. 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]

Ввод, вывод

Ввод / вывод, как видно из окна 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

Сви-пролог, 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.

0

К , 19 байт

{&1=x-{x**/x#2}'!x}

Попробуйте онлайн. Истина - это массив с числом в нем: ,3или ,0так далее. Falsey - пустой массив: ()или !0зависит от вашего интерпретатора.



Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.