ตรวจสอบว่าจำนวนเต็มเป็นกำลัง 2 โดยไม่ใช้ +, - การดำเนินการ [ปิด]


30

เขียนโปรแกรมที่ตรวจสอบว่าจำนวนเต็มเป็นกำลัง 2


ตัวอย่างอินพุต:

8

ตัวอย่างผลลัพธ์:

Yes

ตัวอย่างอินพุต:

10

ตัวอย่างผลลัพธ์:

No

กฎ:

  • อย่าใช้+, -การดำเนินงาน

  • ใช้สตรีมอินพุตบางประเภทเพื่อรับจำนวน อินพุตไม่ควรถูกเก็บไว้ในตัวแปรเริ่มต้น

  • รหัสที่สั้นที่สุด (เป็นไบต์) ชนะ

คุณสามารถใช้การตอบสนองความจริง / เท็จ (เช่นtrue/ false) 0คุณอาจจะสมมติป้อนตัวเลขจำนวนที่มากกว่า


1
อนุญาตให้ส่งออก "จริง" แทน "ใช่" และ "เท็จ" แทน "ไม่" หรือไม่
ProgramFOX

2
ใช่คุณสามารถใช้การตอบสนองเชิงบวก / เชิงลบ อัปเดตคำถามแล้ว
gthacoder

1
predฟังก์ชั่นเมื่อนำไปใช้เป็นจำนวนเต็ม n ผลตอบแทน n - 1. ฟังก์ชั่นเช่นนี้ซึ่งมีการปลอมตัวบาง ๆ รอบ ๆ ผู้ประกอบการต้องห้ามห้ามยัง?
Wayne Conrad

1
@Wayne เช่นเดียวกับของ golfscript )หรือมากที่สุดคตามภาษา --
Doorknob

2
ฉันรู้ว่าเรา 3 ปีในอนาคตในขณะนี้ แต่ "+/- ตัวดำเนินการ" ไม่สามารถสังเกตได้หรืออย่างน้อยที่สุดก็นิยามอย่างอ่อน
ATaco

คำตอบ:


13

GolfScript 6 ตัวอักษรไม่มีการลดลง

~.3/&!

นี่คือโซลูชันที่ไม่ใช้x & (x-1)วิธีการในรูปแบบใด ๆ มันใช้x & (x/3)แทน ;-) เอาต์พุต0หากเป็นเท็จ1หากเป็นจริง

คำอธิบาย:

  • ~ evals สตริงการป้อนข้อมูลเพื่อเปลี่ยนเป็นตัวเลข
  • .ทำซ้ำ (สำหรับลำดับถัดมา&)
  • 3/ หารด้วยสาม (ตัดทอน)
  • & คำนวณ bitwise AND ของค่าที่หารด้วยต้นฉบับซึ่งจะเป็นศูนย์ถ้าและเฉพาะถ้าอินพุตเป็นศูนย์หรือกำลังสอง (นั่นคือมีการตั้งค่าบิตหนึ่งมากที่สุด) และ
  • ! ตรรกะนี้ขัดแย้งแมปเป็นศูนย์หนึ่งและค่าอื่น ๆ ทั้งหมดเป็นศูนย์

หมายเหตุ:

  • ตามกฎที่ชี้แจงศูนย์จะไม่ใช่อินพุตที่ถูกต้องดังนั้นโค้ดนี้จะใช้ได้แม้ว่ามันจะออกมา1ถ้าอินพุตนั้นเป็นศูนย์

  • หากผู้ประกอบการลดลง GolfScript (ที่ได้รับอนุญาตแล้วตัวอักษร 5 ตัวโซลูชั่นที่~.(&! โพสต์โดย aditsuเป็นพอ อย่างไรก็ตามดูเหมือนว่าจะต่อต้านวิญญาณของกฎถ้าไม่ใช่ตัวอักษร

  • ฉันคิดวิธีx & (x/3)หลอกลวงเมื่อหลายปีก่อนในรายชื่อผู้รับจดหมาย Fun With Perl (ฉันแน่ใจว่าฉันไม่ใช่คนแรกที่ค้นพบมัน แต่ฉันทำ (อีกครั้ง) คิดค้นมันอย่างอิสระ) นี่คือลิงค์ไปยังโพสต์ต้นฉบับรวมถึงหลักฐานที่ใช้งานได้จริง


ฉันคิดว่ามันค่อนข้างโง่จริง ๆ Golfscript อนุญาตให้หนึ่งเขียนโซลูชันที่แน่นอนที่ OP ต้องการยกเว้นโดยไม่ทำลายกฎจริงๆ
Tim Seguine

1
@Tim: ตกลงนี่คือหนึ่งโดยไม่ต้องลดลงแล้ว ;)
Ilmari Karonen

มันทำงานอย่างไร ยกตัวอย่างเช่น7/3 = 2 (0010)เพื่อ7 & 2 = 0111 & 0010 = 0010ที่ชัดเจนบิตสุดท้ายไม่ได้เป็น 1
phuclv

@ LưuVĩnhPhúc: ไม่ แต่บิตที่สองคือ ลองแบ่งเป็น 3 ส่วนด้วยเลขฐานสองและมันค่อนข้างชัดเจนว่าทำไมมันถึงเกิดขึ้นได้เสมอถ้าเงินปันผลมีชุดมากกว่าหนึ่งบิต
Ilmari Karonen

อ่าฉันอ่านผิดด้วย "หารด้วย 2"
phuclv

15

APL (7)

ใช่ว่าเป็น 7 ไบต์ สมมติว่าฉันใช้IBM codepage 907แทน Unicode และอักขระแต่ละตัวเป็นไบต์ :)

0=1|2⍟⎕

กล่าวคือ 0 = mod(log(input(),2),1)


แค่สงสัยว่าจะเกิดอะไรขึ้นถ้าคุณให้ 0 หรือจำนวนลบ?
aditsu

@aditsu ฉันไม่รู้ว่าอินฟินิตี้ mod 1 คืออะไร แต่แน่นอนว่าไม่ควรเป็นศูนย์
Tim Seguine

1
@TimSeguine Mathematica ให้ฉันIndeterminateเมื่อฉันลองมัน
LegionMammal978

7

GolfScript, 11 (สำหรับ 1 (จริง) และ 0 (เท็จ))

.,{2\?}%?0>

ใส่หมายเลขบนสแต็กแล้วเรียกใช้

GolfScript, 22 (สำหรับใช่ / ไม่ใช่)

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

ฉันรักการแปลง1/0เป็นYes/ Noรับรหัสมากเท่าความท้าทาย: D

คำเตือน: ไม่มีประสิทธิภาพมาก;) มันทำงานได้ดีสำหรับตัวเลขสูงถึง 10,000 แต่เมื่อคุณได้รับที่สูงคุณจะเริ่มสังเกตเห็นความล่าช้าเล็กน้อย

คำอธิบาย:

  • .,: กลาย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
Joachim Isaksson

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}

{จริงจริงเท็จเท็จ}


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: ฉันเห็น เคล็ดลับที่น่าสนใจ
Konrad Borowski

1
@ProgramFOX แต่x&~(~0*x)ก็ยังใช้งานได้ มีความยาวเพียง 2 ตัวอักษร
orlp

4

ระดับแปดเสียง ( 15 23)

แก้ไข: อัปเดตเนื่องจากความต้องการอินพุตของผู้ใช้;

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

ให้ผู้ใช้ป้อนค่าและผลลัพธ์ 1 สำหรับจริง, 0 สำหรับเท็จ

ทดสอบใน Octave แล้วควรทำงานใน Matlab ด้วย


ทำงานได้ใน Matlab ด้วยเช่นกัน :)
jub0bs


4

GolfScript, 5

Outputs 1 for true, 0 for false. Based on user3142747's idea:

~.(&!

Note: ( is decrement, hopefully it doesn't count as - :)
If it does (and the OP's comments suggest that it might), then please refer to Ilmari Karonen's solution instead.
For Y/N output, append 'NY'1/= at the end (7 more bytes).


4

Python, 31

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

31 if you do bin(input()).rfind('1')<3
Blender

@Blender Well-spotted. I'd used 2== because I figured it should work for nonpositive numbers too. That's explicitly not required by the rules, so...
boothby

1
+1. I was going to post print bin(input()).count('1')<2 at a total of 31 characters, but it's too similar to yours.
Steven Rumbalski

4

C, 48

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

Can be shorter if unary negate is allowed, is longer if negative constants aren't allowed. Assumes two's complement.
orlp

* has higher precedence than binary &, you don't need the parens. And if return value is accepted (just asked) exit(x&x*-1) would be much shorter.
Kevin

There is a -: x*-1.
klingt.net

@klingt.net yes, but that's part of a numerical constant. Technically, as it is worded now, only the operator - is forbidden.
Kevin

1
@klingt.net Replaced it with a version that uses no signs.
orlp

4

I decided to to use another approach, based on the population count or sideways sum of the number (the number of 1-bits). The idea is that all powers of two have exactly one 1 bit, and no other number does. I added a JavaScript version because I found it amusing, though it certainly won't win any golfing competition.

J, 14 15 chars (outputs 0 or 1)

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

JavaScript, 76 chars (outputs true or false)

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

This uses addition, which is precluded by the challenge.
FUZxxl

Huh. I've no idea what I was thinking when I wrote this... I've fixed it now so it actually follows the rules.
FireFly

4

Clip, 9 8 7

!%lnxWO

Reads a number from stdin.

Explanation:

To start with, Z = 0, W = 2 and O = 1. This allows placing of W and O next to each other, whereas using 2 and 1 would be interpreted as the number 21 without a separating space (an unwanted extra character). In Clip, the modulo function (%) works on non-integers, so, to work out if some value v is an integer, you check if v mod 1 = 0. Using Clip syntax, this is written as =0%v1. However, as booleans are stored as 1 (or anything else) and 0, checking if something is equal to 0 is just 'not'ing it. For this, Clip has the ! operator. In my code, v is lnx2. x is an input from stdin, n converts a string to a number and lab is log base b of a. The program therefore translates (more readably) to 0 = ((log base 2 of parseInt(readLine)) mod 1).

Examples:

8

outputs

1

and

10

outputs

0

Edit 1: replaced 0, 1 and 2 with Z, O and W.

Edit 2: replaced =Z with !.

Also:

Pyth, 5

Compresses the Clip version even further, as Pyth has Q for already evaluated input and a log2(a) function instead of just general log(a, b).

!%lQ1


3

Mathematica (21)

IntegerQ@Log2@Input[]

Without input it is a bit shorter

IntegerQ@Log2[8]

True

IntegerQ@Log2[7]

False


⌊#⌋==#&@Log2@Input[]
alephalpha

1
@alephalpha That ends up using 24 bytes for the UTF-8 characters. Another 21-byte program is Log2@Input[]~Mod~1==0.
LegionMammal978

2

JavaScript, 41 40 characters

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

How this works: you take the logarithm at base 2 using l(prompt()) / l(2), and if that result modulo 1 is equal to zero, then it is a power of 2.

For example: after taking the logarithm of 8 on base 2, you get 3. 3 modulo 1 is equal to 0, so this returns true.

After taking the logarithm of 7 on base 2, you get 2.807354922057604. 2.807354922057604 modulo 1 is equal to 0.807354922057604, so this returns false.


You don't need to cast the input to a number; Math.log will do that already: "Each of the following Math object functions applies the ToNumber abstract operator to each of its arguments..."
apsillers

Doesn't it suffer from numerical inaccuracies?
Mark Jeronimus

@MarkJeronimus: I actually don't know. It could be, but I haven't yet encountered an incorrect result.
ProgramFOX

2

JavaScript, 35

Works for bytes.

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

46 character version, Works for 16 bit numbers.

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

The trick works in most dynamic languages.

Explanation: Convert the number to base 2, interpret that string as base 10, do modulo 9 to get the digit sum, which must be 1.


What about 0x2ff, which in base 2 is 1111111111?
Peter Taylor

@PeterTaylor You're right, fixed
copy

so the real thing your doing is checking for modulo 10 without a remainder, but you used 9 to shave a character of your code, +1!
Math chiller

This is kinda cheating but another method: alert(!(Number.MAX_VALUE%prompt()))
Pluto


2

python 3, 38

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

python, 32

However, the code doesn't work in every version.

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

Notice that the solution works also for 0 (print False).


Upvoted because this was my solution as well.
Josh Caswell

1
What if you replace == with &?
SimonT

@SimonT This is not true. Replacing the '==' with '&' will print 1 for every number that has odd number of '1' in its binary representation. Check for example 7=111. There are 3=11 ones. It will return 11&1 = 1.
Gari BN

2

Ruby — 17 characters (fourth try)

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

My current best is a fusion of @steenslag's answer with my own. Below are my previous attempts.

Ruby — 19 characters (third try)

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

Ruby — 22 characters (second try)

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

Ruby — 24 characters (first try)

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

there's still a "+" in your program
phuclv

I know. :-/ I've asked for clarification whether '+' and '-' are strictly forbidden, or whether they can be used in other contexts besides addition and subtraction. I'm in the process of rewriting regardless.
O-I

Great improvement. It seems like it's the best Ruby result so far. I updated the leaders table in the question text.
gthacoder

@gthacoder Just combined steenslag's regex with my binary formatting. Definitely can't take all the credit.
O-I

2

K/Kona (24 17)

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

Returns 1 if true and 0 if false. Any power of 2 has a single bit equal to 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)

(this prints out all the powers of 2 (from 0 to 9) in binary)

So I sum up all the components of the binary expression of x and see if it's equal to 1; if yes then x=2^n, otherwise nope.

...knew I could make it smaller


@gthacoder: I made the code smaller, hope you can update you main post to reflect this!
Kyle Kanos

Doesn't this use addition? And doesn't the question, err, forbid that?
zgrep

2

C# (54 characters)

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

The task clearly states that input is not stored in a variable, it should be obtained from an input stream of some kind (like stdin), also, this is code-golf, try shortening your code a little, at least by removing whitespace
mniip

I think you just mean Int32, not ToInt32...
Chris

Ya ya. Thanks for pointing out Chris. Earlier it was Convert.ToInt32 and I wanted to change it to Int32.Parse to shorten it. :D
Merin Nakarmi

2
use int instead of Int32 for 2 fewer characters.
Rik

2

Rebmu (9 chars)

z?MOl2A 1

Test

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

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

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

Rebmu is a constricted dialect of Rebol. The code is essentially:

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

Alternative

14 chars—Rebmu does not have a 'mushed' bitwise AND~

z?AND~aTIddA 3

In Rebol:

zero? a & to-integer a / 3


1

Python, 35

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

Doesn't use not only +/- operations, but any math operations aside from converting to binary form.

Other stuff (interesting, but not for competition):

I have also a regexp version (61):

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

(Love the idea, but import and match function make it too long)

And nice, but boring bitwise operations version (31):

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

(yes, it's shorter, but it uses ~-x for decrement which comtains - operation)


boothby's answers uses the same idea as my first, but is shorter :(
Ivan Anishchuk

1

Python 2.7 (30 29 39 37)

EDIT: Updated due to user input requirement;

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

Brute force, try to divide until =1 (success) or <1 (fail)


1
not a%2 can be written as a%2==0. Granted, this would be longer in many languages, but not Python.
Konrad Borowski

@xfix Thanks, tested and updated.
Joachim Isaksson

1
or even better, a%2<1.
boothby

you have a space after 2. Removing that would save a byte!
Keerthana Prabhakaran



1

APL (12 for 0/1, 27 for yes/no)

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

or, if we must output text:

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

Read in A. Form a vector 0..A, then a vector 20..2A (yes, that's way more than necessary), then a vector comparing A with each of those (resulting in a vector of 0's and at most one 1), then xor that (there's no xor operator in APL, but ≠ applied to booleans will act as one.) We now have 0 or 1.

To get YES or NO: multiply the 0 or 1 by 3, drop this number of characters from 'YESNO ', then take the first 3 characters of this.


1

C, 65 bytes

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

You can cut off 5 chars by using main(k){..., relying on the implicit int typing. It might be UB, but this is code golf. NEVER use something like that in production, of course.
Kevin

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.