ตัวเลขนี้เป็นกำลังที่แน่นอนของ -2: (มาก) โหมดยาก


26

นี่เป็นรุ่นของการท้าทายล่าสุดตัวเลขนี้เป็นจำนวนเต็ม -2 หรือไม่ ด้วยชุดของเกณฑ์อื่นที่ออกแบบมาเพื่อเน้นลักษณะที่น่าสนใจของปัญหาและทำให้การท้าทายยากขึ้น ฉันใส่พิจารณาบางเป็นมันนี่

ความท้าทายที่ Toby กล่าวไว้อย่างน่าอัศจรรย์ในคำถามที่เชื่อมโยงคือ:

มีวิธีการที่ชาญฉลาดในการระบุว่าเป็นจำนวนเต็มเป็นพลังที่แท้จริงของ 2 นั่นคือไม่ได้เป็นปัญหาที่น่าสนใจเพื่อให้ตรวจสอบว่าเป็นจำนวนเต็มให้เป็นพลังที่แท้จริงของการมี-2 ตัวอย่างเช่น:

-2 => yes: (-2)¹
-1 => no
0 => no
1 => yes: (-2)⁰
2 => no
3 => no
4 => yes: (-2)²

กฎ:

  • จำนวนเต็มคือ 64 บิตเซ็นชื่อเป็นส่วนประกอบสองอย่าง นี่เป็นประเภทข้อมูลเดียวที่คุณสามารถใช้งานได้
  • คุณสามารถใช้การดำเนินการดังต่อไปนี้เท่านั้น แต่ละสิ่งเหล่านี้นับเป็นการดำเนินการครั้งเดียว
    • n << k, n >> k: เลื่อนไปทางซ้าย / ขวาทีnละkบิต บิตของเครื่องหมายถูกขยายในกะขวา
    • n >>> k: เลื่อนไปทางขวา แต่ไม่ขยาย bit sign 0 ถูกเลื่อน
    • a & b, a | b, a ^ b: Bitwise AND, OR แฮคเกอร์
    • a + b, a - b, a * b: บวกลบคูณ
    • ~b: การสลับบิต
    • -b: การปฏิเสธโดยสมบูรณ์ของสองคน
    • a / b, a % b: หาร (หารด้วยจำนวนเต็ม, ปัดเศษเป็น 0) และโมดูโล
      • Modulo ของตัวเลขที่ติดลบใช้กฎที่ระบุไว้ใน C99 : เท่ากับ(a/b) * b + a%b aดังนั้น5 % -3เป็น2และ-5 % 3เป็น-2:
      • 5 / 3คือ1, 5 % 3คือ2เป็น 1 * 3 + 2 = 5
      • -5 / 3is -1, -5 % 3is -2เท่ากับ -1 * 3 + -2 = -5
      • 5 / -3is -1, 5 % -3is 2เท่ากับ -1 * -3 + 2 = 5
      • -5 / -3คือ1, -5 % -3คือ-2เป็น 1 * -3 + -2 = -5
      • โปรดทราบว่า//ตัวดำเนินการหารพื้นของ Python ไม่พอใจคุณสมบัติ "รอบต่อ 0" ของการแบ่งที่นี่และ%ตัวดำเนินการของ Python ไม่ตรงตามข้อกำหนด
    • การมอบหมายไม่นับเป็นการดำเนินการ เช่นเดียวกับใน C การมอบหมายให้ประเมินค่าทางด้านซ้ายหลังจากการกำหนด: a = (b = a + 5)ตั้งค่าbเป็นa + 5จากนั้นตั้งค่าaเป็นbและนับเป็นการดำเนินการหนึ่งครั้ง
    • การมอบหมายแบบผสมอาจใช้a += bวิธีการa = a + bและนับเป็นการดำเนินการครั้งเดียว
  • คุณอาจใช้ค่าคงที่จำนวนเต็มพวกเขาไม่นับเป็นอะไร
  • วงเล็บเพื่อระบุลำดับของการดำเนินการเป็นที่ยอมรับ
  • คุณอาจประกาศฟังก์ชั่น การประกาศฟังก์ชันสามารถอยู่ในรูปแบบใดก็ได้ที่สะดวกสำหรับคุณ แต่โปรดทราบว่าจำนวนเต็ม 64 บิตเป็นชนิดข้อมูลที่ถูกต้องเท่านั้น การประกาศฟังก์ชันไม่นับเป็นการดำเนินการ แต่การเรียกใช้ฟังก์ชันจะนับเป็นหนึ่ง นอกจากนี้ยังมีความชัดเจน: ฟังก์ชั่นอาจมีหลายreturnงบและreturns จากจุดใดก็ได้ที่ได้รับอนุญาต returnตัวเองไม่ได้นับเป็นการดำเนินการ
  • คุณสามารถประกาศตัวแปรได้ฟรี
  • คุณอาจจะใช้whileลูป แต่คุณอาจจะไม่ใช้หรือif forผู้ประกอบการที่ใช้ในwhileเงื่อนไขจะนับรวมคะแนนของคุณ whileลูปดำเนินการตราบเท่าที่เงื่อนไขของพวกเขาประเมินเป็นค่าที่ไม่เป็นศูนย์ ("ความจริง" 0 ในภาษาที่มีแนวคิดนี้ไม่ใช่ผลลัพธ์ที่ถูกต้อง) เนื่องจากอนุญาตให้ส่งคืนได้ แต่เนิ่นๆคุณจึงได้รับอนุญาตให้ใช้breakเช่นกัน
  • อนุญาตให้ใช้มากเกิน / อันเดอร์โฟลว์และจะไม่ทำการหนีบค่า จะถือว่าเสมือนว่าการดำเนินการเกิดขึ้นจริงอย่างถูกต้องและถูกตัดทอนเป็น 64 บิต

เกณฑ์การให้คะแนน / ชนะ:

รหัสของคุณจะต้องสร้างค่าที่ไม่ใช่ศูนย์ถ้าอินพุตเป็นกำลังของ -2 และเป็นอย่างอื่น

นี่คืออะตอมรหัสกอล์ฟคะแนนของคุณคือจำนวนการดำเนินการทั้งหมดที่มีอยู่ในรหัสของคุณ (ตามที่กำหนดไว้ด้านบน) ไม่ใช่จำนวนการดำเนินการทั้งหมดที่ดำเนินการในเวลาทำงาน รหัสต่อไปนี้:

function example (a, b) {
    return a + ~b;
}

function ispowerofnegtwo (input) {
    y = example(input, 9);
    y = example(y, 42);
    y = example(y, 98);
    return y;
}

มีการดำเนินการ 5 รายการ: สองฟังก์ชันและการเรียกใช้ฟังก์ชันสามครั้ง

ไม่สำคัญว่าคุณจะนำเสนอผลลัพธ์ของคุณอย่างไรใช้สิ่งที่สะดวกในภาษาของคุณไม่ว่าจะเป็นการเก็บผลลัพธ์ไว้ในตัวแปรในที่สุดส่งคืนจากฟังก์ชั่นหรืออะไรก็ตาม

ผู้ชนะคือโพสต์ที่ถูกต้องซึ่งพิสูจน์ได้ (จัดหาหลักฐานยืนยันแบบเป็นทางการหรือเป็นทางการหากจำเป็น) และมีคะแนนต่ำสุดตามที่อธิบายไว้ข้างต้น

โบนัสโหมดท้าทายยากมาก !

เพื่อโอกาสในการชนะอย่างแน่นอนไม่มีอะไรนอกจากความสามารถที่จะสร้างความประทับใจให้ผู้คนในปาร์ตี้ส่งคำตอบโดยไม่ต้องใช้whileลูป! หากมีสิ่งเหล่านี้เพียงพอฉันอาจพิจารณาแบ่งกลุ่มที่ชนะเป็นสองหมวดหมู่ (มีและไม่มีลูป)


หมายเหตุ: หากคุณต้องการเสนอวิธีแก้ปัญหาในภาษาที่รองรับเฉพาะจำนวนเต็ม 32 บิตคุณสามารถทำได้โดยระบุว่าคุณเพียงพอที่จะพิสูจน์ว่ายังคงถูกต้องสำหรับจำนวนเต็ม 64 บิตในคำอธิบาย

นอกจากนี้: บางคุณลักษณะเฉพาะภาษาอาจได้รับอนุญาตที่ไม่มีค่าใช้จ่ายหากพวกเขาไม่หลบเลี่ยงกฎระเบียบ แต่มีความจำเป็นที่จะบีบบังคับภาษาของคุณเป็นพฤติกรรมตามกฎดังกล่าวข้างต้น ตัวอย่างเช่น (contrived) ฉันจะอนุญาตให้เปรียบเทียบฟรีไม่เท่ากับ 0ในwhileลูปเมื่อนำไปใช้กับเงื่อนไขโดยรวมเป็นวิธีแก้ปัญหาสำหรับภาษาที่มี "ความจริง" 0 ความพยายามที่ชัดเจนในการใช้ประโยชน์จากสิ่งต่าง ๆ ประเภทนี้ไม่ได้รับอนุญาต - เช่นแนวคิดของค่า "ความจริง" 0 หรือ "ไม่ได้กำหนด" ไม่มีอยู่ในชุดกฎข้างต้นและอาจไม่ได้รับการพึ่งพา


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
เดนนิส

@hvd หากคุณอ่านข้อความนี้: คุณควรยกเลิกคำตอบของคุณทั้งหมด! สมมติว่ามันเป็นเรื่องที่ถูกต้องแม้โดยไม่ต้อง m ^= sก็ยังคงเป็นที่น่าประทับใจและผมคิดว่ามันจะตกลงทั้งหมดเพื่อทำการเปลี่ยนตัวผู้ที่จะปรับปรุงมันมากยิ่งขึ้น
Jason C

ไม่ได้ทำให้ความรู้สึกวิธีการอนุญาตให้whileและbreakแต่ไม่if? เทียบเท่ากับif (x) { ... } while (x) { ... break; }
. ..

@R .. มันไม่สมเหตุสมผล 100% ( breakและผลตอบแทนเร็วเป็นส่วนที่น่าเสียใจ) และเป็นเรื่องราวที่ยาวนานและบทเรียนที่ได้เรียนรู้ในกฎสำหรับความท้าทายในอนาคต มีเวอร์ชั่น "โบนัส" เสมอ! :)
Jason C

1
ทำไมifและforไม่ได้รับอนุญาต? int x=condition; while (x) { ... x=0; }ฟรีโค้ดเพิ่มเติมอีกเท่านั้น forสิ่งเดียวกันกับคสไตล์
Qwertiy

คำตอบ:


35

การดำเนินงาน C ++, 15

ฉันไม่รู้ว่าทำไมwhileลูปได้รับอนุญาตเพราะทำลายความท้าทายทั้งหมด นี่คือคำตอบโดยไม่ต้องใด ๆ :

int64_t is_negpow2(int64_t n) {
    int64_t neg = uint64_t(n) >> 63; // n >>> 63
    n = (n ^ -neg) + neg; // if (n < 0) n = -n;
    int64_t evenbits = n & int64_t(0xaaaaaaaaaaaaaaaaull >> neg);
    int64_t n1 = n - 1;
    int64_t pot = n & n1;
    int64_t r = pot | (n1 >> 63) | evenbits;
    return ~((r | -r) >> 63); // !r
}

ทำไมwhileลูปทำลายความท้าทายทั้งหมด ?
นาย Xcoder

10
@ Mr.Xcoder เพราะความท้าทายกำลังดำเนินไปด้วยการใช้งานระดับบิตที่เรียบง่ายและwhileต่อต้านสิ่งนั้นในทุกด้าน
orlp

ฉันหมายความว่าถ้าคุณทำในขณะที่ลูปคูณจำนวนของการดำเนินการคูณจำนวนครั้งที่ดำเนินการในลูปสำหรับสแตติกnหรือบางสิ่งบางอย่าง
Magic Octopus Urn

ผมได้แสดงความคิดเห็นเกี่ยวกับเรื่องนี้ที่นี่
Jason C

@ JasonC นั่นเป็นเพราะฉันควรจะใช้กะขวาโดยไม่ต้องบิตสัญญาณ ฉันแก้ไขโค้ด (ใช้uint64_tเพราะเป็นวิธีเดียวที่จะได้รับการเปลี่ยนแปลงที่ถูกต้องโดยไม่มีส่วนขยายของเครื่องหมาย)
orlp

25

Python 2 , 3 การดำเนินงาน

def f(n):
 while n>>1:
  while n&1:return 0
  n=n/-2
 return n

ลองออนไลน์!

การดำเนินงานที่มี>>, ,&/

แนวคิดคือการหารด้วย -2 ซ้ำ ๆ อำนาจของ -2 ห่วงโซ่ลงไป -8 -> 4 -> -2 -> 11: ถ้าเรากดปุ่ม1ยอมรับ หากเรากดเลขคี่ก่อนกดปุ่ม1ปฏิเสธ เรายังต้องปฏิเสธ0ซึ่งจะไปกับตัวเองตลอดไป

while n>>1:ลูปจนnเป็น 0 หรือ 1 เมื่อแบ่งวงที่nตัวเองถูกส่งกลับและ1เป็นผลผลิต Truthy และ0Falsey หนึ่ง ภายในวงที่เราปฏิเสธซ้ำ ๆ ใช้และปฏิเสธที่แปลกn -> n/-2n

เนื่องจาก/มีการใช้ค่าที่เท่ากันเท่านั้นพฤติกรรมการปัดเศษจึงไม่เข้ามามีบทบาท ดังนั้นมันไม่สำคัญว่า Python จะปัดแตกต่างจากสเป็ค


ดี ตรรกะที่ฉลาดในอัลกอริทึมและการทำงานที่ดีรวมเงื่อนไขเข้ากับการดำเนินการบิต นอกจากนี้ยังสามารถยืนยันได้ว่าการติดตั้งใช้งานใน C.
Jason C

ทำไมwhile n&1แทนif n&1?
Mark Ransom

2
@MarkRansom ifความท้าทายที่ไม่อนุญาตให้
xnor

อ่าพลาดไปแล้ว การทดแทนที่ฉลาดมาก
Mark Ransom

1
@EvSunWoodard การให้คะแนนคือจำนวนผู้ประกอบการในรหัสไม่ใช่จำนวนการโทรหาพวกเขาระหว่างการดำเนินการซึ่งขึ้นอยู่กับอินพุต: "นี่คือรหัสอะตอมมิกกอล์ฟคะแนนของคุณคือจำนวนการปฏิบัติการทั้งหมดที่มีในรหัสของคุณ ."
xnor

11

สนิม, 14 12 การดำเนินการ (ไม่มีลูป)

ต้องการการปรับให้เหมาะสม ( -O) หรือ-C overflow-checks=noเปิดใช้งานการลบการโอเวอร์โฟลว์แทนการตื่นตระหนก

fn is_power_of_negative_2(input: i64) -> i64 {
    let sign = input >> 63;
    // 1 op
    let abs_input = (input ^ sign) - sign;
    // 2 ops
    let bad_power_of_two = sign ^ -0x5555_5555_5555_5556; // == 0xaaaa_aaaa_aaaa_aaaa
    // 1 op
    let is_not_power_of_n2 = abs_input & ((abs_input - 1) | bad_power_of_two);
    // 3 ops 
    let is_not_power_of_n2 = (is_not_power_of_n2 | -is_not_power_of_n2) >> 63;
    // 3 ops 
    input & !is_not_power_of_n2
    // 2 ops
}

(เพื่อชี้แจง: !xis bitwise-NOTที่นี่ไม่ใช่ logical-NOT)

กรณีทดสอบ:

#[test]
fn test_is_power_of_negative_2() {
    let mut value = 1;
    for _ in 0 .. 64 {
        assert_ne!(0, is_power_of_negative_2(value), "wrong: {} should return nonzero", value);
        value *= -2;
    }
}

#[test]
fn test_not_power_of_negative_2() {
    for i in &[0, -1, 2, 3, -3, -4, 5, -5, 6, -6, 7, -7, 8, 1<<61, -1<<62, 2554790084739629493, -4676986601000636537] {
        assert_eq!(0, is_power_of_negative_2(*i), "wrong: {} should return zero", i);
    }
}

ลองออนไลน์!


แนวคิดคือการตรวจสอบว่า | x | คือพลังของ 2 (ใช้(y & (y - 1)) == 0ตามปกติ) ถ้า x คือพลังของ 2 เราจะตรวจสอบต่อไป (1) เมื่อx >= 0มันควรจะเป็นกำลังคู่ของ 2 หรือ (2) เมื่อx < 0มันควรจะเป็นพลังแปลก ๆ ของ 2 เราตรวจสอบนี้โดย&การ " bad_power_of_two"หน้ากาก 0x ... AAAA เมื่อx >= 0(0 ผลิตเฉพาะเมื่อมันเป็นพลังงานมาก) หรือ 0x ... 5555 x < 0เมื่อ


ฉันขโมย~((r | -r) >> 63)เคล็ดลับของคุณเพื่อแก้ไขคำตอบของฉันให้เสร็จ
orlp

6

Haskell, 2 3 การดำเนินงาน

import Data.Bits (.&.)

f 0 = False
f 1 = True
f n | n .&. 1 == 0 = f (n `div` -2)
f n | otherwise    = False

f(n)กำหนดฟังก์ชันเวียน การดำเนินการที่ใช้คือการเรียกใช้ฟังก์ชัน ( f), การหาร ( div) และบิตและและ ( .&.)

ไม่มีลูปเนื่องจากข้อเท็จจริงที่ว่า Haskell ไม่มีคำสั่งวนซ้ำ :-)


4
เหตุใดฉันจึงไม่แปลกใจที่โซลูชัน Haskell ที่ไม่มีการวนซ้ำนั้นให้บริการโดยบุคคลที่ชื่อว่า "Opportunist" =)
Cort Ammon - Reinstate Monica

1
ฉันมากลังเลเกี่ยวกับf 0, f 1, f n ...นี่เพราะพวกเขาเป็นหลักif's ในการปลอมตัวแม้ว่าแล้วอีกครั้งผมไม่อนุญาตให้while+ breakและต้นreturns จึงดูเหมือนว่ายุติธรรม ในขณะที่มันดูเหมือนจะใช้ประโยชน์จากกฎของฉันถูกเปิดทิ้งไว้โดยไม่ตั้งใจไปสู่การตีความมันเป็นทางออกที่ดี
Jason C

3
โดยเฉพาะอย่างยิ่ง|s โดยเฉพาะอย่างยิ่งในอากาศ ที่กล่าวว่านี่เป็นการละเมิดกฎหนึ่งข้อโดยใช้วิธีถกเถียงกันน้อยกว่า: ==ไม่อนุญาตให้ทำการเปรียบเทียบ แต่โปรดทราบว่าถ้าตีความของฉันรหัสนี้ถูกต้องการใช้งานของ booleans ที่นี่ไม่ปรากฏเป็นที่ยอมรับแทนค่าจำนวนเต็มโดยพลการในสถานที่ของพวกเขาจะไม่ปรากฏในการเปลี่ยนแปลงผลและพวกเขามีมากขึ้นของรูปแบบการนำเสนอสุดท้าย
Jason C

@ JasonC ฉันใช้==เพราะไม่มีวิธีอื่นในการส่งจากหรือIntถึงBool"Truthy" ใน Haskell การจับคู่รูปแบบและเจ้าหน้าที่รักษาความปลอดภัยนั้นละเมิดกฎ "no ifs" หรือไม่คือการโทรของคุณ ;-)
Opportunist

18
ด้วยการจับคู่รูปแบบคุณสามารถ hardcode ผลลัพธ์สำหรับจำนวนเต็ม 64 บิตทั้งหมดโดยใช้การดำเนินการ 0
xnor

5

Python 3, 10 หรือ 11 9 การทำงาน

def g(x):
 while x:
  while 1 - (1 + ~int(x - -2 * int(float(x) / -2))) & 1: x /= -2
  break
 while int(1-x):
     return 0
 return 5  # or any other value

ผลตอบแทน5สำหรับอำนาจของ-2, 0มิฉะนั้น


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
เดนนิส

5

C, 5 การดำเนินงาน

long long f(long long x){
    x=x ^ ((x & 0xaaaaaaaaaaaaaaaa) * 6);
    while(x){
        while(x&(x-1))
            return 0;
        return 1;
    }
    return 0;
}

C, 10 การดำเนินงานโดยไม่ต้องลูป

long long f(long long x){
    x = x ^ ((x & 0xaaaaaaaaaaaaaaaa) * 6);
    long long t = x & (x-1);
    return (((t-1) & ~t) >> 63) * x;
}

C, 1 การดำเนินงาน

long long f(long long x){
    long long a0=1, a1=-2, a2=4, a3=-8, a4=16, a5=-32, a6=64, a7=-128, a8=256, a9=-512, a10=1024, a11=-2048, a12=4096, a13=-8192, a14=16384, a15=-32768, a16=65536, a17=-131072, a18=262144, a19=-524288, a20=1048576, a21=-2097152, a22=4194304, a23=-8388608, a24=16777216, a25=-33554432, a26=67108864, a27=-134217728, a28=268435456, a29=-536870912, a30=1073741824, a31=-2147483648, a32=4294967296, a33=-8589934592, a34=17179869184, a35=-34359738368, a36=68719476736, a37=-137438953472, a38=274877906944, a39=-549755813888, a40=1099511627776, a41=-2199023255552, a42=4398046511104, a43=-8796093022208, a44=17592186044416, a45=-35184372088832, a46=70368744177664, a47=-140737488355328, a48=281474976710656, a49=-562949953421312, a50=1125899906842624, a51=-2251799813685248, a52=4503599627370496, a53=-9007199254740992, a54=18014398509481984, a55=-36028797018963968, a56=72057594037927936, a57=-144115188075855872, a58=288230376151711744, a59=-576460752303423488, a60=1152921504606846976, a61=-2305843009213693952, a62=4611686018427387904, a63=-9223372036854775807-1, a64=0;
    while(a0){
        long long t = x ^ a0;
        long long f = 1;
        while(t){
            f = 0;
            t = 0;
        }
        while(f)
            return 1;
        a0=a1; a1=a2; a2=a3; a3=a4; a4=a5; a5=a6; a6=a7; a7=a8; a8=a9; a9=a10; a10=a11; a11=a12; a12=a13; a13=a14; a14=a15; a15=a16; a16=a17; a17=a18; a18=a19; a19=a20; a20=a21; a21=a22; a22=a23; a23=a24; a24=a25; a25=a26; a26=a27; a27=a28; a28=a29; a29=a30; a30=a31; a31=a32; a32=a33; a33=a34; a34=a35; a35=a36; a36=a37; a37=a38; a38=a39; a39=a40; a40=a41; a41=a42; a42=a43; a43=a44; a44=a45; a45=a46; a46=a47; a47=a48; a48=a49; a49=a50; a50=a51; a51=a52; a52=a53; a53=a54; a54=a55; a55=a56; a56=a57; a57=a58; a58=a59; a59=a60; a60=a61; a61=a62; a62=a63; a63=a64;
    }
    return 0;
}

2
โอ้มนุษย์คนสุดท้ายว่าเป็นเพียงความชั่วร้าย ดี
Jason C

4

การประกอบ 1 การดำเนินงาน

.data

    .space 1         , 1 # (-2)^31
    .space 1610612735, 0
    .space 1         , 1 # (-2)^29
    .space 402653183 , 0
    .space 1         , 1 # (-2)^27
    .space 100663295 , 0
    .space 1         , 1 # (-2)^25
    .space 25165823  , 0
    .space 1         , 1 # (-2)^23
    .space 6291455   , 0
    .space 1         , 1 # (-2)^21
    .space 1572863   , 0
    .space 1         , 1 # (-2)^19
    .space 393215    , 0
    .space 1         , 1 # (-2)^17
    .space 98303     , 0
    .space 1         , 1 # (-2)^15
    .space 24575     , 0
    .space 1         , 1 # (-2)^13
    .space 6143      , 0
    .space 1         , 1 # (-2)^11
    .space 1535      , 0
    .space 1         , 1 # (-2)^9
    .space 383       , 0
    .space 1         , 1 # (-2)^7
    .space 95        , 0
    .space 1         , 1 # (-2)^5 = -32
    .space 23        , 0
    .space 1         , 1 # (-2)^3 = -8
    .space 5         , 0
    .space 1         , 1 # (-2)^1 = -2
    .space 1         , 0
dataZero:
    .space 1         , 0
    .space 1         , 1 # (-2)^0 = 1
    .space 2         , 0
    .space 1         , 1 # (-2)^2 = 4
    .space 11        , 0
    .space 1         , 1 # (-2)^4 = 16
    .space 47        , 0
    .space 1         , 1 # (-2)^6 = 64
    .space 191       , 0
    .space 1         , 1 # (-2)^8
    .space 767       , 0
    .space 1         , 1 # (-2)^10
    .space 3071      , 0
    .space 1         , 1 # (-2)^12
    .space 12287     , 0
    .space 1         , 1 # (-2)^14
    .space 49151     , 0
    .space 1         , 1 # (-2)^16
    .space 196607    , 0
    .space 1         , 1 # (-2)^18
    .space 786431    , 0
    .space 1         , 1 # (-2)^20
    .space 3145727   , 0
    .space 1         , 1 # (-2)^22
    .space 12582911  , 0
    .space 1         , 1 # (-2)^24
    .space 50331647  , 0
    .space 1         , 1 # (-2)^26
    .space 201326591 , 0
    .space 1         , 1 # (-2)^28
    .space 805306367 , 0
    .space 1         , 1 # (-2)^30
    .space 3221225471, 0
    .space 1         , 1 # (-2)^32

.globl isPowNeg2
isPowNeg2:
    movl dataZero(%edi), %eax
    ret

ใช้ตารางการค้นหาขนาดใหญ่เพื่อค้นหาว่าจำนวนนั้นเป็นกำลัง 2 หรือไม่คุณสามารถขยายได้ถึง 64 บิต แต่การค้นหาคอมพิวเตอร์เพื่อเก็บข้อมูลที่เหลือจะเป็นการออกกำลังกายของผู้อ่าน :-P


1
การสร้างดัชนีตารางไม่ใช่หนึ่งในการดำเนินการที่อนุญาต
. ..

1
นอกจากนี้ยังเห็นได้ชัดว่าไม่สามารถขยายได้ถึง 64 บิต :-)
R ..

อันที่จริงการจัดทำดัชนีตารางไม่ได้ตั้งใจจะอนุญาตภายใต้กฎปัจจุบัน ฉันระบุ "คุณอาจประกาศตัวแปร" และ "คุณอาจระบุตัวอักษรจำนวนเต็ม" ด้วยความตั้งใจของ scalars และ semantically นี้เป็นอาร์เรย์ (และพูดอวดรู้ฉันไม่อนุญาตประเภทอาร์เรย์และฉันไม่อนุญาตให้มีการจัดทำดัชนีของการเรียงลำดับใด ๆ การดำเนินงานแม้ว่าคุณจะเรียกมันว่า "นอกจากนี้" ในบริบทของการประกอบ) แต่เป็นฉวยโอกาสที่คุณมี ... :)
เจสันซี

3

C, 31 การดำเนินงาน

การสาธิตสด

ความคิดของฉันนั้นง่ายถ้ามันมีกำลังสองถ้าเป็นบันทึกมันก็ต้องเป็นบวกไม่เช่นนั้นล็อกจะต้องเป็นเลขคี่

int isPositive(int x) // 6
{
    return ((~x & (~x + 1)) >> 31) & 1;
}

int isPowerOfTwo(int x) // 5
{
    return isPositive(x) & ~(x & (x-1));
}

int log2(int x) // 3
{
    int i = (-1);

    while(isPositive(x))
    {
        i  += 1;
        x >>= 1;
    }

    return i;
}

int isPowerOfNegativeTwo(int x) // 17
{
    return (  isPositive(x) &  isPowerOfTwo(x) & ~(log2(x) % 2) )
         | ( ~isPositive(x) & isPowerOfTwo(-x) & (log2(-x) % 2) );
}

1
คุณทำได้ดีกว่าที่คุณคิด การเรียกใช้ฟังก์ชันจะนับเป็น 1 เท่านั้นไม่เท่ากับจำนวนตัวดำเนินการในฟังก์ชัน ดังนั้นถ้าฉันนับอย่างถูกต้อง (ตรวจสอบอีกครั้ง) คุณมีบางอย่างเช่น 6 สำหรับ isPositive + 5 สำหรับ isPowerOfTwo + 3 สำหรับ log2 + 17 สำหรับ isPowerOfNegativeTwo = 31.
Jason C

1

C, 7 การดำเนินงาน

int64_t is_power_of_neg2(int64_t n)
{
    int64_t x = n&-n;
    while (x^n) {
        while (x^-n)
            return 0;
        return x & 0xaaaaaaaaaaaaaaaa;
    }
    return x & 0x5555555555555555;
}

หรือ:

C, 13 การดำเนินการโดยไม่มีลูป - ตามเงื่อนไข

int64_t is_power_of_neg2(int64_t n)
{
    int64_t s = ~(n>>63);
    int64_t a = ((n/2)^s)-s;
    int64_t x = n&-(uint64_t)n; // Cast to define - on INT64_MIN.
    return ~(a/x >> 63) & x & (0xaaaaaaaaaaaaaaaa^s);
}

คำอธิบาย:

  • n&-nnอัตราผลตอบแทนบิตชุดต่ำสุดของ
  • aเป็นค่าสัมบูรณ์ของ negated ของn/2จำเป็นต้องลบเนื่องจาก/2precludes ล้นของการปฏิเสธ
  • a/xเป็นศูนย์เฉพาะในกรณีที่aเป็นพลังที่แน่นอนของทั้งสอง; มิฉะนั้นจะมีการตั้งค่าบิตอื่นอย่างน้อยหนึ่งบิตและสูงกว่าxบิตต่ำสุดซึ่งให้ผลลัพธ์เป็นลบ
  • ~(a/x >> 63)ถ้าอย่างนั้นก็ให้บิทมาสก์ที่ทุกคนถ้าnหรือ-nเป็นพลังของสอง, มิฉะนั้นเป็นศูนย์ทั้งหมด
  • ^sถูกนำไปใช้หน้ากากเพื่อตรวจสอบสัญญาณของการที่จะดูว่าเป็นอำนาจของn-2

1

PHP, 3 การดำเนินงาน

ประกอบไปด้วยและifไม่ได้รับอนุญาต; ดังนั้นการละเมิดwhile:

function f($n)
{
    while ($n>>1)               # 1. ">>1"
    {
        while ($n&1)            # 2. "&1"
            return 0;
        return f($n/-2|0);      # 3. "/-2" ("|0" to turn it into integer division)
    }
    return $n;
}
  1. $n>>1: ถ้า number เป็น 0 หรือ 1 ให้ return number
  2. $n&1: ถ้า number เป็นเลขคี่ส่งคืน 0
  3. การทดสอบอื่น$n/-2(+ ส่งถึง int)

0

JavaScript ES6, 7 การทำงาน

x=>{
  while(x&1^1&x/x){
    x/=-2;x=x|0
  }
  while(x&0xfffffffe)x-=x
  return x
}

ลองออนไลน์!

คำอธิบาย

while(x&1^1&x/x)

ในขณะที่ x! = 0 และ x% 2 == 0 4 ops
x / x เท่ากับ 1 ตราบใดที่ x ไม่ใช่ 0 (0/0 ให้ NaN ซึ่งประเมินว่าเป็นเท็จ)
& bitwise และ
x & 1 ^ 1 เท่ากับ 1 ถ้า x เป็นเลขคู่ (x และ 1) xor 1

x/=-2;x=x|0

นี่คือรูปแบบของการแบ่งที่กำหนดโดยคำถามที่1 op

while(x&0xfffffffe)  

ในขณะที่ x! = 1 และ x! = 0 1 op
เงื่อนไขที่ต้องการออกเมื่อ x == 0 หรือ x == 1 เนื่องจากทั้งสองเป็นค่าที่ส่งคืนและการเข้าสู่วงวนไม่สิ้นสุดจะไม่ได้ผล ในทางทฤษฎีสามารถขยายได้สำหรับค่าที่มากขึ้นโดยการเพิ่มเลขฐานสิบหก ปัจจุบันทำงานได้ถึง± 2 ^ 32-1

x-=x

ตั้งค่า x เป็น 0 1 op
ในขณะที่ฉันสามารถใช้ return 0 เป็น 0 ops ได้ฉันรู้สึกว่าในขณะที่วนรอบที่แตกโดยคำสั่งอื่นให้ความรู้สึกเหมือนการโกงมากเกินไป

return x

ส่งกลับค่า x (1 ถ้ากำลังของ -2, 0 เป็นอย่างอื่น)

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