Проверьте, является ли целое число степенью 2, не используя операции +, - [closed]


30

Напишите программу, которая проверяет, является ли целое число степенью 2.


Пример ввода:

8

Образец вывода:

Yes

Пример ввода:

10

Образец вывода:

No

Правила:

  • Не используйте +, -операции.

  • Используйте какой-нибудь поток ввода, чтобы получить число. Входные данные не должны изначально храниться в переменной.

  • Самый короткий код (в байтах) выигрывает.

Вы можете использовать любой ответ «ложь / ложь» (например, true/ false). Вы можете предположить, что номер ввода больше, чем 0.


1
Разрешено ли выводить «true» вместо «yes» и «false» вместо «no»?
ProgramFOX

2
Да, вы можете использовать любой положительный / отрицательный ответ. Вопрос обновлен.
gthacoder

1
predФункция, когда применяется к целому числу п, п - возвращает 1. Существуют такие функции, как это, которые являются тонкими маскирует вокруг запрещенного оператора, также запрещено?
Уэйн Конрад

1
@ Уэйн, как в Golfscript )или в большинстве языков на основе c ' --.
Дверная ручка

2
Я знаю, что сейчас у нас 3 года в будущем, но «+/- операторы» ненаблюдаемы или, по крайней мере, слабо определены.
ATaco

Ответы:


13

GolfScript, 6 символов, без уменьшений

~.3/&!

Вот решение, которое не использует x & (x-1)метод в любой форме. Он использует x & (x/3)вместо этого. ;-) Выводит, 0если false, 1если true.

Объяснение:

  • ~ обнуляет входную строку, чтобы превратить ее в число,
  • .дублирует его (для последующего &),
  • 3/ делит его на три (обрезая),
  • & вычисляет побитовое И деленного значения с оригиналом, которое будет равно нулю тогда и только тогда, когда входное значение равно нулю или степени два (т. е. установлен не более одного бита), и
  • ! логически отрицает это, отображая ноль в одно, а все остальные значения в ноль.

Заметки:

  • Согласно разъясненным правилам, ноль не является допустимым вводом , поэтому этот код в порядке, даже если он выводит, 1если ввод равен нулю.

  • Если разрешен оператор декремента GolfScript (, то достаточно 5-символьного решения, ~.(&! размещенного aditsu . Однако, похоже, что это противоречит духу правил , если не букве.

  • Я придумал эту x & (x/3)хитрость несколько лет назад в списке рассылки Fun With Perl. (Я уверен, что я не первый, кто обнаружил это, но я (заново) изобрел его самостоятельно.) Вот ссылка на оригинальный пост , включая доказательство того, что он действительно работает.


Я думаю, что это немного глупо на самом деле, сценарий гольфа позволяет написать точное решение, которое ОП хотел исключить, фактически не нарушая правила.
Тим Сегин

1
@Tim: Хорошо, вот один без декрементов. ;)
Илмари Каронен

как это может работать? Например 7/3 = 2 (0010), так 7 & 2 = 0111 & 0010 = 0010что явно последний бит не 1
phuclv

@ LưuVĩnhPhúc: Нет, но второй бит есть. Попробуйте выполнить длинное деление на 3 в двоичном формате, и совершенно очевидно, почему это всегда происходит, если дивиденд имеет более одного установленного бита.
Илмари Каронен

ах я неправильно понял это с "делится на 2"
phuclv

15

APL (7)

Да, это 7 байтов . Предположим на данный момент, что я использую кодовую страницу IBM 907 вместо Unicode, и тогда каждый символ является байтом :)

0=1|2⍟⎕

т.е. 0 = mod(log(input(),2),1)


Просто интересно, что произойдет, если вы дадите ему 0 или отрицательное число?
aditsu

@aditsu Я не знаю, что такое бесконечный мод 1, но он, конечно, не должен быть нулевым.
Тим Сегин

1
@TimSeguine Mathematica дает мне, Indeterminateкогда я пытаюсь это сделать.
LegionMammal978

7

GolfScript, 11 (для 1 (true) и 0 (false))

.,{2\?}%?0>

Поместите число в стек и затем бегите.

GolfScript, 22 (для Да / Нет)

.,{2\?}%?0>'Yes''No'if

Мне нравится, как преобразование 1/ 0в Yes/ Noзанимает столько же кода, сколько и сам вызов: D

Предупреждение: ЧРЕЗВЫЧАЙНО неэффективно;) Он отлично работает для чисел до 10000, но как только вы достигнете такого высокого уровня, вы начнете замечать небольшое отставание.

Объяснение:

  • .,: превращается nв n 0..n( .дубликат, ,диапазон 0..n)
  • {2\?}: к силе 2
  • %: отобразить "мощность 2" на "0..n", чтобы оно стало n [1 2 4 8 16 ...]
  • ?0>: проверяет, содержит ли массив число (0 больше индекса)

1
1 байт короче для Да / Нет .,{2\?}%?0<'YesNo'3/=:; также я думаю, что вы обманываете, спрашивая «Поместите число в стек», вы должны начать с ~.
aditsu

1
Сбой на 1, что составляет 2 ^ 0
Иоахим Исакссон

6

Mathematica 28

Numerator[Input[]~Log~2]==1

Для целых степеней 2, числитель логарифма с основанием 2 будет 1 (это означает, что логарифм является дробной единицей).

Здесь мы немного изменим функцию, чтобы отобразить предполагаемый ввод. Мы используем #вместо Input[]и добавить, &чтобы определить чистую функцию. Он возвращает тот же ответ, который будет возвращен, если пользователь введет число в вышеуказанной функции.

    Numerator[#~Log~2] == 1 &[1024]
    Numerator[#~Log~2] == 1 &[17]

Правда
ложь

Тестирование нескольких номеров одновременно.

    Numerator[#~Log~2] == 1 &&/@{64,8,7,0}

{True, True, False, False}


4

Perl 6 (17 символов)

say get.log(2)%%1

Эта программа получает строку из getфункции STDIN , вычисляет логарифм с основанием 2 на нем ( log(2)) и проверяет, делится ли результат на 1 ( %%1где %%делится на оператор). Не так коротко, как решение GolfScript, но я нахожу это приемлемым (GolfScript все равно выигрывает), но намного быстрее (даже учитывая, что Perl 6 сейчас медленный).

~ $ perl6 -e 'say get.log(2)%%1'
256
True
~ $ perl6 -e 'say get.log(2)%%1'
255
False

2
Причина, по которой +и -запрещены для этой задачи, заключается в том, что если x & (x - 1)равен равен 0, то xимеет степень 2.
ProgramFOX

@ProgramFOX: Понятно. Интересный трюк.
Конрад Боровски

1
@ProgramFOX Но x&~(~0*x)все еще работает. Это всего на 2 символа длиннее.
orlp

4

Октава ( 15 23)

РЕДАКТИРОВАТЬ: Обновлено из-за требования ввода пользователя;

~mod(log2(input('')),1)

Позволяет пользователю ввести значение и вывести 1 для true, 0 для false.

Протестировано в Octave, должно работать и в Matlab.


Работает также в Matlab :)
jub0bs

4

Р, 13 11

Основано на решении Perl. Возвращает FALSEили TRUE.

!log2(i)%%1

Параметр iпредставляет входную переменную.

Альтернативная версия с пользовательским вводом:

!log2(scan())%%1

4

GolfScript, 5

Выходы 1 для истины, 0 для ложных. Основано на идее user3142747:

~.(&!

Примечание: (это декремент, надеюсь, он не считается как -:).
Если это так (и комментарии ОП предполагают, что это возможно), пожалуйста, обратитесь к решению Илмари Каронена .
Для вывода Y / N добавьте 'NY'1/=в конце (еще 7 байтов).


4

Python, 31

print 3>bin(input()).rfind('1')

31, если вы делаетеbin(input()).rfind('1')<3
Blender

@ Блендер Хорошо замечен. Я использовал, 2==потому что я полагал, что это должно работать и для неположительных чисел. Это явно не требуется правилами, так что ...
Boothby

1
+1. Я собирался опубликовать print bin(input()).count('1')<2в общей сложности 31 символов, но это слишком похоже на ваш.
Стивен Румбальски

4

С, 48

main(x){scanf("%i",&x);puts(x&~(x*~0)?"F":"T");}

Может быть короче, если разрешено унарное отрицание, больше, если недопустимы отрицательные константы. Предполагает два дополнения.
orlp

*имеет более высокий приоритет, чем двоичный &, вам не нужны парены. И если возвращаемое значение принимается (только что спросил) exit(x&x*-1)будет намного короче.
Кевин

Существует -: x*-1.
klingt.net

@ klingt.net да, но это часть числовой константы. Технически, как это сформулировано сейчас, -запрещен только оператор .
Кевин

1
@ klingt.net Заменил на версию, которая не использует никаких знаков.
orlp

4

Я решил использовать другой подход, основанный на подсчете численности населения или поперечной сумме числа (число 1-бит). Идея состоит в том, что все степени двух имеют ровно один 1бит, а никакое другое число не имеет. Я добавил версию JavaScript, потому что нашел ее забавной, хотя она, безусловно, не выиграет ни одного соревнования по гольфу.

J, 14 15 символов (выходы 0 или 1)

1=##~#:".1!:1]1

JavaScript, 76 символов (выводит true или false)

alert((~~prompt()).toString(2).split("").map(Number).filter(Boolean).length)

Это использует сложение, которое препятствует вызову.
FUZxxl

Да. Я понятия не имею, о чем я думал, когда писал это ... Я исправил это сейчас, так что на самом деле он следует правилам.
FireFly

4

Зажим , 9 8 7

!%lnxWO

Читает число из стандартного ввода.

Объяснение:

Начнем с, Z= 0, W= 2и O= 1. Это позволяет размещать Wи Oрядом друг с другом, тогда как использование 2и 1будет интерпретироваться как число 21 без разделительного пробела (нежелательный дополнительный символ). В Clip функция modulo ( %) работает vс нецелыми числами, поэтому, чтобы определить, является ли какое-либо значение целым числом, вы проверяете, является ли vmod 1 = 0. Используя синтаксис Clip, это записывается как =0%v1. Тем не менее, поскольку булевы значения хранятся как 1(или что-то еще), и 0проверка, что-то равно, 0просто «не» это. Для этого у Клипа есть !оператор. В моем коде vесть lnx2. xэто вход от стандартного ввода,nпреобразует строку в число и labявляется основой bжурнала a. Программа поэтому переводит (более читабельно) в 0 = ((log base 2 of parseInt(readLine)) mod 1).

Примеры:

8

выходы

1

а также

10

выходы

0

Редактировать 1: заменить 0, 1и 2с Z, Oи W.

Изменить 2: заменено =Zна !.

Также:

Пиф , 5

Сжимает версию Clip еще больше, так как Pyth имеет Q для уже оцененного ввода и функцию log2 (a) вместо обычного log (a, b).

!%lQ1


3

Математика (21)

IntegerQ@Log2@Input[]

Без ввода это немного короче

IntegerQ@Log2[8]

Правда

IntegerQ@Log2[7]

Ложь


⌊#⌋==#&@Log2@Input[]
алефальфа

1
@alephalpha Это заканчивается использованием 24 байтов для символов UTF-8. Еще одна 21-байтовая программа есть Log2@Input[]~Mod~1==0.
LegionMammal978

2

JavaScript, 41 40 символов

l=Math.log;alert(l(prompt())/l(2)%1==0);

Как это работает: вы берете логарифм по основанию 2, используя l(prompt()) / l(2), и если этот результат по модулю 1 равен нулю, то это степень 2.

Например: взяв логарифм 8 на основе 2, вы получите 3. 3 modulo 1равно 0, так что это возвращает истину.

Взяв логарифм 7 на основании 2, вы получите 2.807354922057604. 2.807354922057604 modulo 1равно 0.807354922057604, так что это возвращает ложь.


Вам не нужно приводить ввод к числу; Math.logбудет делать это уже : «Каждая из следующих функций объекта Math применяет абстрактный оператор
ToNumber

Разве он не страдает от численных неточностей?
Марк Иеронимус

@MarkJeronimus: я действительно не знаю. Возможно, но я еще не столкнулся с неверным результатом.
ProgramFOX

2

JavaScript, 35

Работает на байты.

alert((+prompt()).toString(2)%9==1)

46-символьная версия , работает для 16-битных чисел.

x=(+prompt()).toString(2)%99;alert(x==1|x==10)

Трюк работает в большинстве динамических языков.

Объяснение: Преобразовать число в основание 2, интерпретировать эту строку как основание 10, выполнить по модулю 9, чтобы получить сумму цифр, которая должна быть 1.


Как насчет того 0x2ff, что в базе 2 1111111111?
Питер Тейлор

@PeterTaylor Вы правы, исправлено
скопируйте

так что реальная вещь, которую вы делаете, это проверка по модулю 10 без остатка, но вы использовали 9, чтобы побрить символ вашего кода +1,!
Математический чиллер

Это своего рода обман, но другой метод:alert(!(Number.MAX_VALUE%prompt()))
Плутон

2

Perl 5.10+, 13 + 1 = 14 символов

say!($_&$_/3)

Использует тот же метод из старого потока FWP, что и моя запись GolfScript . Печатает, 1если на входе есть степень двойки, а в противном случае - пустая строка.

Нужно бежать с perl -nE; n стоит один дополнительный символ , в общей сложности 14 символов. Кроме того, вот 18-символьная версия, которая не нуждается в n:

say!(($_=<>)&$_/3)

2

питон 3, 38

print(1==bin(int(input())).count('1'))

питон, 32

Тем не менее, код не работает в каждой версии.

print 1==bin(input()).count('1')

Обратите внимание, что решение работает и для 0 (выведите False).


Проголосовал, потому что это было и мое решение.
Джош Касвелл

1
Что если заменить ==на &?
SimonT

@SimonT Это не правда. Замена '==' на '&' выведет 1 для каждого числа с нечетным числом '1' в его двоичном представлении. Проверьте, например, 7 = 111. Есть 3 = 11. Он вернется 11 & 1 = 1.
Гари BN

2

Рубин - 17 символов (четвертая попытка)

p /.1/!~'%b'%gets

Мой лучший результат - это слияние ответа @ steenslag с моим собственным. Ниже приведены мои предыдущие попытки.

Рубин - 19 символов (третья попытка)

p /10*1/!~'%b'%gets

Рубин - 22 символа (вторая попытка)

p !('%b'%gets)[/10*1/]

Рубин - 24 символа (первая попытка)

p !!('%b'%gets=~/^10*$/)

в вашей программе все еще есть "+"
phuclv

Я знаю. : / / Я попросил уточнить, строго ли запрещены '+' и '-', или их можно использовать в других контекстах, кроме сложения и вычитания. Я в процессе переписывания независимо.
OI

Большое улучшение Кажется, это лучший результат Ruby на данный момент. Я обновил таблицу лидеров в тексте вопроса.
gthacoder

@gthacoder Просто соединил регулярное выражение steenslag с моим двоичным форматированием. Определенно не могу взять весь кредит.
OI

2

К / Кона ( 24 17)

d:{(+/(2_vs x))~1

Возвращает 1, если истина, и 0, если ложь. Любая степень 2 имеет один бит, равный 1:

2_vs'_(2^'(!10))
(,1
1 0
1 0 0
1 0 0 0
1 0 0 0 0
1 0 0 0 0 0
1 0 0 0 0 0 0
1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0)

(это распечатывает все степени 2 (от 0 до 9) в двоичном виде)

Итак, я суммирую все компоненты двоичного выражения xи посмотрим, равно ли оно 1; если да, то x=2^nнет.

... знал, что могу сделать его меньше


@gthacoder: я сделал код меньше, надеюсь, вы сможете обновить ваш основной пост, чтобы отразить это!
Кайл Канос

Разве это не использует дополнение? И разве этот вопрос не запрещает это?
zgrep

2

C # (54 символа)

 Math.Log(int.Parse(Console.ReadLine()),2)%1==0?"Y":"N"

В задаче четко указано, что входные данные не хранятся в переменной, они должны быть получены из входного потока какого-либо типа (например, stdin), также это код-гольф , попробуйте немного сократить код, по крайней мере, удаляя пробелы
МНИИП

Я думаю, что вы просто имеете в виду Int32, а не ToInt32...
Крис

Я. Я. Спасибо, что указали на Криса. Ранее это был Convert.ToInt32, и я хотел изменить его на Int32.Parse, чтобы сократить его. : D
Мерин Накарми

2
используйте intвместо Int322 символов меньше.
Рик

2

Ребму (9 символов)

z?MOl2A 1

Тест

>> rebmu/args [z?MOl2A 1] 7
== false

>> rebmu/args [z?MOl2A 1] 8 
== true

>> rebmu/args [z?MOl2A 1] 9 
== false

Rebmu - сжатый диалект Rebol. Код по сути:

z? mo l2 a 1  ; zero? mod log-2 input 1

альтернатива

14 символов - у Ребму нет разбитого по кусочкам И ~

z?AND~aTIddA 3

В Реболе:

zero? a & to-integer a / 3


1

Python, 35

print bin(input()).strip('0')=='b1'

Не использует не только +/- операции, но и любые математические операции, кроме преобразования в двоичную форму.

Другие вещи (интересные, но не для конкурса):

У меня также есть версия регулярного выражения (61) :

import re;print re.match(r'^0b10+$',bin(input())) is not None

(Идея нравится, но функция импорта и сопоставления делает ее слишком длинной)

И хорошая, но скучная битовая версия операций (31) :

x=input();print x and not x&~-x

(да, он короче, но для декремента используется ~ -x - операция)


Ответы Бутби используют ту же идею, что и мои первые, но они короче :(
Анищук Иван

1

Python 2,7 ( 30 29 39 37)

РЕДАКТИРОВАТЬ: Обновлено из-за требования ввода пользователя;

a=input()
while a>1:a/=2.
print a==1

Грубая сила, попробуйте разделить до = 1 (успех) или <1 (неудача)


1
not a%2можно записать как a%2==0. Конечно, это будет длиннее во многих языках, но не в Python.
Конрад Боровски

@xfix Спасибо, проверено и обновлено.
Иоахим Исакссон

1
или даже лучше a%2<1.
Boothby

после 2.удаления у вас есть пробел , который сохранит байт!
Киртана Прабхакаран

1

Python (33)

print int(bin(input())[3:]or 0)<1

int(bin(input()*2)[3:])<1также работает из оболочки Python только с 25 символами.
gmatht


1

APL (12 для 0/1, 27 для да / нет)

≠/A=2*0,ιA←⍞ 

или, если мы должны вывести текст:

3↑(3x≠/A=2*0,ιA←⍞)↓'YESNO '

Прочитайте в A. Сформируйте вектор 0..A, затем вектор 2 0 ..2 A (да, это намного больше, чем необходимо), затем вектор, сравнивающий A с каждым из них (в результате получается вектор из 0 и самое большее один 1), затем xor это (в APL нет оператора xor, но ≠, примененный к логическим значениям, будет действовать как единое целое.) Теперь у нас есть 0 или 1.

Чтобы получить ДА или НЕТ: умножьте 0 или 1 на 3, отбросьте это количество символов из «ДА», а затем возьмите первые 3 символа.


1

C 65 байт

main(k){scanf("%i",&k);while(k&&!(k%2))k/=2;puts(k==1?"T":"F");}

Вы можете отрезать 5 символов, используя main(k){...неявную intтипизацию. Это может быть UB, но это код гольф. НИКОГДА не используйте что-то подобное в производстве, конечно.
Кевин

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