บิต, แทะหรือไบต์?


45

แรงบันดาลใจจากความท้าทายนี้

กำหนดจำนวนเต็มในช่วง0 <= n < 2**64เอาท์พุทคอนเทนเนอร์ขนาดต่ำสุดที่สามารถใส่ได้

  • บิต: 1
  • แทะ: 4
  • ไบต์: 8
  • สั้น: 16
  • int: 32
  • ยาว: 64

Testcases:

0 -> 1
1 -> 1
2 -> 4
15 -> 4
16 -> 8
123 -> 8
260 -> 16
131313 -> 32
34359750709 -> 64

นี่คือดังนั้นคำตอบที่สั้นที่สุดในหน่วยไบต์ชนะ


10
สิ่งนี้จะง่ายขึ้นถ้า2ได้รับผลลัพธ์เช่นกัน ...
ETHproductions

1
@ETHproductions แต่จะไม่เป็นไร (มันใช้เวลานานมากในการเขียนอัลกอริธึมที่ทำได้)
Blue Blue

ฉันหวังว่าฉันเข้าใจปัญหา ... เดี๋ยวก่อนสิ่งที่มันต้องการคือจำนวนบิตที่จำเป็นต้องมีเพื่อปัดเศษให้เป็นโครงสร้างพื้นฐานต่อไปหรือไม่
z0rberg ใน

2
ขอบคุณ! ฉันรู้ว่าเมื่อฉันเขียนความคิดเห็นและแก้ไขมันสายเกินไป ฉันเดาว่าฉันต้องการเป็ดยางเพื่อคุยกับ ...
z0rberg ใน

2
@Daniel คำตอบที่นี่ใช้แนวทางที่แตกต่างอย่างสิ้นเชิงกับคำถามอื่น เมื่อฉันพูดว่า 'ได้แรงบันดาลใจจาก' มันไม่ได้แปลว่า 'ซ้ำซ้อน' ไม่มีคำตอบที่สามารถแก้ไขได้เล็กน้อยสำหรับคำถามนี้
Blue

คำตอบ:



22

Python ขนาด 39 ไบต์

f=lambda n:4**(n>1)*(n<16)or 2*f(n**.5)

นับจำนวนครั้งที่ต้องใช้สแควร์รูทสำหรับnอยู่ด้านล่าง16พร้อมเคสพิเศษเพื่อหลีกเลี่ยงเอาต์พุต 2

หากรวม 2 เราสามารถทำได้

f=lambda n:n<2or 2*f(n**.5)

กับ True สำหรับ 1


41 ไบต์:

f=lambda n,i=1:i*(2**i>n)or f(n,i<<1+i%2)

ซ้ำแล้วซ้ำอีกคู่เลขชี้กำลังจนกว่าi 2**i>nข้ามจากi=1ไปi=4โดยขยับบิตเพิ่มเติมเมื่อiคี่

Alt 45 ไบต์:

f=lambda n,i=4:4**(n>1)*(2**i>n)or 2*f(n,i*2)

7
ไม่เคยทำให้ฉันประหลาดใจเลยว่าคุณจะหาวิธีแก้ปัญหาได้มากมายแค่ไหน โดยพื้นฐานในฐานะโปรแกรมเมอร์ฉันเรียนรู้ที่จะหาทางแก้ไขปัญหาและทำงานกับมันจนกว่ามันจะทำงาน เดาว่าฉันยังมีอะไรอีกมากมายให้เรียนรู้เกี่ยวกับกอล์ฟ! เคารพ.
ElPedro

@xnor คำตอบแรกของคุณส่งออกอย่างไร1เมื่อสแควร์รูทของ 0 หรือ 1 เป็น 1 เสมอ (เรียกซ้ำไม่สิ้นสุดor 2*f(n**.5))
dfernan

2
@defan ฉันเชื่อว่าส่วนหลังจากที่orถูกประเมินเฉพาะในกรณีที่ส่วนก่อนที่จะประเมินถึงสิ่งที่ผิดพลาด (ศูนย์) สำหรับ n = 0 และสำหรับ n = 1 ให้n>1ประเมินถึงFalseซึ่งถือว่าเป็นศูนย์ในนิพจน์ตัวเลขและn<16ประเมินถึงTrueซึ่งถือเป็นหนึ่งในนิพจน์ตัวเลข ดังนั้น4**(n>1)*(n<16)คือ 1
trichoplax

1
@trichoplax ถูกต้อง ขอบคุณสำหรับคำอธิบาย
dfernan

12

J, 19 ไบต์

คำกริยา Monadic ใช้ตัวเลขทางด้านขวาและกระจายขนาดของภาชนะ มีวิธีการเขียนสองวิธีที่เทียบเท่ากันดังนั้นฉันจึงรวมทั้งสองอย่างไว้ด้วยกัน

2^2(>.+1=>.)@^.#@#:
2^s+1=s=.2>.@^.#@#:

อธิบายโดยการระเบิด:

2^2(>.+1=>.)@^.#@#: NB. takes one argument on the right...
                 #: NB. write it in binary
               #@   NB. length (i.e. how many bits did that take?)
  2          ^.     NB. log base 2 of that
   (>.     )@       NB. ceiling
      +1=>.         NB. +1 if needed (since no container is two bits wide)
2^                  NB. base 2 exponential

สิ่งที่เจ๋งคือเราเห็นสองวิธีที่แตกต่างกันในการทำ log ฐาน 2 ใน J วิธีแรกคือชัดเจน2^.ซึ่งเป็นลอการิทึมตัวเลข ประการที่สองคือ#@#:ซึ่งสามารถอ่านได้ว่า "ความยาวของการแสดงฐาน 2" นี่เกือบเทียบเท่ากับหนึ่ง-plus-floor-of-log-base-2 ยกเว้นว่า#:0เป็นรายการองค์ประกอบหนึ่ง0ซึ่งเป็นสิ่งที่เราต้องการ สิ่งนี้จะเต้น1+2<.@^.1&>.8 ไบต์

ใช้งานที่ REPL:

   f =: 2^2(>.+1=>.)@^.#@#:
   f 131313
32
   f 34359750709
64
   (,.f"0) 0 1 2 15 16 123 260
  0  1
  1  1
  2  4
 15  4
 16  8
123  8
260 16

วิธีแก้ปัญหาแบบเก่าที่ฉลาดมากเกินไป 20 ไบต์

2&^.(>.+1=>.&.)@#@#: NB. takes one argument on the right...
                #@#: NB. how many bits
2&^.                 NB. log base 2 of that
     >.              NB. ceiling
       +1=>.         NB. +1 if needed (since no container is two bits wide)
    (       &.)      NB. undo log base 2

9

งูหลาม53 50 49 ไบต์

lambda n:[w for w in[1,4,8,16,32,64]if n<2**w][0]

1
lambda n:[w for w in[1,4,8,16,32,64]if n<2**w][0]สั้นลงหนึ่งไบต์
บลู

เป็นเพียงการโพสต์สิ่งที่คล้ายกัน +1
ElPedro

8

Mathematica, 44 39 38 ไบต์

ขอบคุณ @ orlp สำหรับ 5 ไบต์และ @MartinEnder 1 ไบต์

FirstCase[{1,4,8,16,32,64},x_/;2^x>#]&

ค้นหาองค์ประกอบแรกในรายการ{1, 4, 8, 16, 32, 64}ที่มีหมายเลข 2 ^ มากกว่าอินพุต


8

Pip , 19 ไบต์

(a<2**_FI2**,7RM2i)

ลองออนไลน์!

มันทำงานอย่างไร

                     a is 1st cmdline arg, i is 0 (implicit)
         2**,7       Construct powers of 2 from 0 to 6 [1 2 4 8 16 32 64]
              RM2    Remove 2
       FI            Filter for elements for which:
 a<2**_                a is less than 2 to that element
(                i)  Get 0th item of resulting list and autoprint

7

JavaScript (ES7), 35 ไบต์

n=>[1,4,8,16,32,64].find(b=>2**b>n)

2
เวอร์ชันเรียกซ้ำเช่นf=(n,b=1)=>2**b>n&&b-2?b:f(n,b*2)ควรสั้นลงเล็กน้อย
Arnauld

6

Mathematica, 46 43 38 ไบต์

ขอบคุณ JungHwan Min และ Martin Ender ที่ช่วยประหยัด 3 ไบต์! ขอบคุณ ngenisis สำหรับการประหยัด 5 ไบต์ที่ยิ่งใหญ่!

2^⌈Log2@BitLength@#⌉/.{2->4,0->1}&

ฟังก์ชั่นที่ไม่มีชื่อการใช้จำนวนเต็มที่ไม่ใช่ค่าลบเป็นอินพุตและส่งคืนจำนวนเต็มบวก BitLength@#คำนวณจำนวนบิตในอินพุตจากนั้น2^⌈Log2@...⌉คำนวณพลังงานที่เล็กที่สุดของ 2 นั่นคืออย่างน้อยใหญ่เท่ากับจำนวนบิต สุดท้าย/.{2->4,0->1}จะดูแลกรณีพิเศษที่ไม่มี "niblit" ระหว่างบิตและ nybble 0และยังแก้ไขคำตอบสำหรับการป้อนข้อมูลที่แปลก


2
บันทึก 3 ไบต์โดยใช้แทนBitLength@# ⌊1+Log2@#⌋จากนั้นแทนที่จะแทนที่ด้วย1คุณสามารถแทนที่ได้0แล้วบันทึกอีก 2 ไบต์และคุณจะถูกผูกไว้ก่อน
ngenisis

1
BitLengthนี้สามารถทำได้จริงอย่างสิ้นเชิงกับ ดูคำตอบของฉัน
ngenisis

4

จูเลีย 40 ไบต์

n->filter(x->n<big(2)^x,[1;2.^(2:6)])[1]

นี้เป็นฟังก์ชั่นที่ไม่ระบุชื่อที่สร้างอาร์เรย์ของอำนาจของ 2 0-6 ไม่รวม 2 และกรองมันเพียงองค์ประกอบเหล่านั้นxเช่นที่ 2 xมีค่ามากกว่าการป้อนข้อมูล องค์ประกอบดังกล่าวแรกคือคำตอบ น่าเสียดายที่ต้องมีการส่งเสริม 2 ถึง a BigIntเพื่อหลีกเลี่ยงการล้นเมื่อx = 64

ที่จริงแล้วมันค่อนข้างคล้ายกับคำตอบ Python ของ orlp แม้ว่าฉันจะไม่เห็นก่อนที่จะสร้างวิธีการนี้

ลองออนไลน์!


4

Perl 6 , 30 ไบต์

{first 1+<*>$_,1,4,8,16,32,64}

+<เป็นผู้ดำเนินการกะบิต Perl 6 ซ้ายซึ่งภาษาอื่น ๆ <<อีกมากมายเรียก



2

Java, 143 ไบต์

int f(long a){a=Long.toBinaryString(a).length();if(a<2)return 1;if(a<5)return 4;if(a<9)return 8;if(a<17)return 16;if(a<33)return 32;return 64;}

1
ฉันรู้ว่าฉันสามารถทำให้เรื่องนี้สั้นลงได้ Io ทำได้เมื่อฉันอยู่ที่คอมพิวเตอร์
Pavel

2
บันทึก 50 ไบต์: return a<2?1:a<5?4:a<9?8:a<17?16:a<33?32:64;
Mindwin

@Mindwin ฉันรู้ แต่ฉันกำลังเดินทางและจะไม่สามารถเข้าถึงคอมพิวเตอร์ได้สักพัก ฉันจะไปกับมัน
Pavel

ไม่คะแนนทำให้มันเป็น ... ความรักไบต์ ?
Engineer Toast


2

Ruby, 39 36 ไบต์

->n{2**[0,*2..6].find{|p|2**2**p>n}}

ขอบคุณ GB ที่ช่วยกอล์ฟ


ควรทำงานโดยไม่มีวงเล็บ นอกจากนี้รายการอาจเป็น 0,2,3,4,5,6 และใช้ 1 << 2 ** p
GB

... เพราะคุณสามารถใช้ 0, * 2..6
GB

2

Java 8, 65 55 ไบต์

นี่คือการแสดงออกแลมบ์ดาซึ่งจะใช้เวลาและการส่งกลับlong intไม่เคยเล่นกอล์ฟใน Java มาก่อนดังนั้นจึงควรเอาชนะได้ง่าย:

x->{int i=1;while(Math.pow(2,i)<=x)i<<=1+i%2;return i;}

ลองออนไลน์!


สำหรับ47 ไบต์เราสามารถมี:

x->{int i=1;while(1L<<i<=x)i<<=1+i%2;return i;}

อย่างไรก็ตาม1L<<iโอเวอร์โฟลว์สำหรับค่าส่งคืนมีขนาดใหญ่กว่า 32 ดังนั้นสิ่งนี้จึงล้มเหลวสำหรับ testcase สุดท้าย


1
ผลตอบแทนนี้4เมื่อทดสอบด้วย16เมื่อควรคืน 8 นอกจากนี้คุณยังสามารถตีกอล์ฟแก้ปัญหานี้ได้โดยการลบวงเล็บไปรอบ ๆi<<=1+i%2;โดยไม่ต้อง{}s ขณะที่ลูปจะดำเนินการในบรรทัดถัดไปเท่านั้น
Kritixi Lithos

@KritixiLithos ควรได้รับการแก้ไขแล้ว - ขออภัย Java ของฉันหายไปแล้ว ...
FlipTack

2

Mathematica ขนาด 30 ไบต์

2^(f=BitLength)[f@#-1]/. 2->4&

คำอธิบาย:

อนุญาตNเป็นชุดจำนวนเต็มไม่ใช่ค่าลบ กำหนดสองฟังก์ชั่นบนN, BitLengthและNextPowerดังต่อไปนี้:

BitLength(n) := min {x in N : 2^x - 1 >= n}
NextPower(n) := 2^(min {x in N : 2^x >= n})

วิธีการแก้ปัญหานี้เป็นหลักคำนวณให้เป็นจำนวนเต็มNextPower(BitLength(n)) n >= 0สำหรับn > 0เราจะเห็นว่าดังนั้นNextPower(n) = 2^BitLength(n-1)NextPower(BitLength(n)) = 2^BitLength(BitLength(n)-1)

ตอนนี้ Mathematica BitLengthในตัวก็เห็นด้วยกับคำจำกัดความที่ฉันให้n >= 0ไว้ สำหรับn < 0, ดังนั้นBitLength[n] == BitLength[BitNot[n]] == BitLength[-1-n] BitLength[-1] == BitLength[0] == 0ดังนั้นเราจึงได้คำตอบที่ต้องการสำหรับ1n==0

เนื่องจากเราข้ามตรงจากบิตเพื่อตอดเราต้องเปลี่ยนคำตอบของการมี24


1
สร้างขึ้นอย่างสวยงาม! (อัปยศว่าพื้นที่จำเป็น)
Greg Martin

2

bash, 49 ไบต์ 48 ไบต์

for((y=1;$[y==2|$1>=1<<y];$[y*=2])){ :;};echo $y

หรือ

for((y=1;$[y==2|$1>=1<<y];)){ y=$[y*2];};echo $y

บันทึกในสคริปต์และส่งหมายเลขที่จะทดสอบเป็นอาร์กิวเมนต์

แก้ไข: แทนที่ || กับ | ซึ่งใช้งานได้เนื่องจากอาร์กิวเมนต์มีค่าเป็น 0 หรือ 1 เสมอ

หมายเหตุ:สิ่งนี้ใช้ได้กับจำนวนเต็มจนถึงจำนวนเต็มบวกที่ใหญ่ที่สุดที่เวอร์ชันของ bash ของคุณสามารถจัดการได้ หากฉันมีเวลาฉันจะแก้ไขให้ทำงานได้มากถึง 2 ^ 64-1 ในเวอร์ชันทุบตีที่ใช้เลขคณิตแบบ 32 บิต

ในระหว่างนี้นี่เป็นโซลูชั่น 64- ไบต์ที่ใช้งานได้กับจำนวนที่มากตามอำเภอใจ (ในเวอร์ชันทุบตีใด ๆ ):

for((x=`dc<<<2o$1n|wc -c`;$[x==2||x&(x-1)];$[x++])){ :;};echo $x

2

ซ้อนกัน, 34 30 ไบต์

@n 1 2 6|>2\^,:n 2 log>keep 0#

หรือ

{!1 2 6|>2\^,:n 2 log>keep 0#}

คนแรกรับข้อมูลเกี่ยวกับ TOS และออกจาก TOS; ที่สองคือฟังก์ชั่น ลองที่นี่!

คำอธิบาย

@n 1 2 6|>2\^,:n 2 log>keep 0#
@n                               set TOS to `n`
   1 2 6|>2\^,                   equiv. [1, ...2 ** range(2, 6)]
              :                  duplicate it
               n                 push `n`
                 2 log           log base-2
                      >          element-wise `>`
                       keep      keep only truthy values
                            0#   yield the first element

นี่คือตัวอย่างของการทำงานกับตัวแทน :

> 8    (* input *)
(8)
> @n 1 2 6|>2\^,:n 2 log>keep 0#    (* function *)
(4)
>    (* output *)
(4)

กรณีทดสอบ

> {!1 2 6|>2\^,:n 2 log>keep 0#} @:f
()
> (0 1 2 15 16 123 260 131313 34359750709) $f map
((1 1 4 4 8 8 16 32 64))
> 

หรือเป็นโปรแกรมเต็มรูปแบบ:

{!1 2 6|>2\^,:n 2 log>keep 0#} @:f

(0 1 2 15 16 123 260 131313 34359750709) $f map

out

2

แร็กเก็ต 45 ไบต์

(findf(λ(x)(>(expt 2 x)m))'(1 4 8 16 32 64))

Ungolfed:

(define (f m)
  (findf (λ (x) (> (expt 2 x) m))          ; find first function
         '(1 4 8 16 32 64)))

รุ่นอื่น ๆ :

(define (f1 m)
  (for/last ((i '(1 4 8 16 32 64))         ; using for loop, taking last item
             #:final (> (expt 2 i) m))     ; no further loops if this is true
    i))

และการใช้ความยาวสตริง:

(define (f2 m)
  (for/last
      ((i '(1 4 8 16 32 64))
       #:final (<= (string-length
                    (number->string m 2))  ; convert number to binary string
                   i))
    i))

การทดสอบ:

(f 0)
(f 1)
(f 2)
(f 15)
(f 16)
(f 123)
(f 260)
(f 131313)
(f 34359750709)

เอาท์พุท:

1
1
4
4
8
8
16
32
64

1

คู่, 40 36 31 29 ไบต์

ฟังก์ชั่นที่ไม่ระบุชื่อง่าย สันนิษฐานว่าค่าที่ป้อนเป็นจำนวนเต็ม - ดูข้อแม้ที่ท้าย

@(a)(b=2.^[0 2:6])(a<2.^b)(1)

รหัสทำงานดังนี้:

  • แรกอาร์เรย์ของความยาวบิตได้รับอนุญาต (1,4,8,16,32,64) bถูกสร้างขึ้นและบันทึกไว้ใน

  • ต่อไปเราจะหาจำนวนบิตที่จำเป็นในการเก็บหมายเลขอินพุตaโดยเปรียบเทียบกับขนาดสูงสุดของแต่ละคอนเทนเนอร์bเพื่อดูว่ามีขนาดใหญ่พอ

  • จากนั้นเราจะใช้เวกเตอร์ดัชนีผลลัพธ์เพื่อแยกขนาดคอนเทนเนอร์จากbอีกครั้ง

  • ในที่สุดเราก็ใช้องค์ประกอบแรกในอาร์เรย์ผลลัพธ์ซึ่งจะเป็นคอนเทนเนอร์ที่เล็กที่สุดเท่าที่จะเป็นไปได้

คุณสามารถลองออนไลน์ได้ที่นี่ที่นี่

ans(x)เพียงแค่เรียกใช้รหัสต่อไปนี้และจากนั้นทำ


ข้อแม้เพียงข้อเดียวนี้คือความแม่นยำสองเท่าจะใช้สำหรับค่าคงที่โดยค่าเริ่มต้นซึ่งหมายความว่าจะใช้งานได้กับตัวเลขสูงสุดที่มีค่าสูงสุดซึ่งแสดงได้โดยการลอยความแม่นยำสองเท่าที่น้อยกว่า 2 ^ 64

สิ่งนี้สามารถแก้ไขได้โดยตรวจสอบให้แน่ใจว่าจำนวนที่ให้กับฟังก์ชันนั้นเป็นจำนวนเต็มแทนที่จะเป็นสองเท่า ans(uint64(x))นี้สามารถทำได้โดยการเรียกฟังก์ชั่นเช่นกับ:


1

PHP, 49 46 44 ไบต์

echo(2**ceil(log(log(1+$argn,2),2))-2?:2)+2;

ทำงานแบบนี้:

echo 16 | php -R 'echo(2**ceil(log(log(1+$argv[1],2),2))-2?:2)+2;';echo

คำอธิบาย

echo                       # Output the result of the expression
  (
    2**                    # 2 to the power
      ceil(log(            # The ceiling of the power of 2 of bitsize
        log(1+$argn,2),    # Number of bits needed
        2
      ))
      - 2 ?:               # Subtract 2 (will be added back again)
      2;                   # If that results in 0, result in 2 (+2=4).
  ) + 2                    # Add 2.

การปรับแต่ง

  • บันทึก 3 ไบต์ด้วยการกำจัดการ$r=มอบหมาย
  • บันทึก 2 ไบต์โดยใช้-Rเพื่อให้$argnพร้อมใช้งาน

1

CJam , 18 ไบต์

2ri2b,2mLm]_({)}|#

ลองออนไลน์!

คำอธิบาย

2                   Push 2
 ri                 Read an integer from input
   2b,              Get the length of its binary representation
      2mLm]         Take the ceiling of the base-2 log of the length
           _(       Duplicate it and decrement it
             {)}|   Pop the top element, if it's 0, increment the next element
                     Effectively, if ceil(log2(input)) was 1, it's incremented to 2,
                     otherwise it stays the same.
                 #  Raise 2 to that power

0

C, 71 52 ไบต์

i;f(long long n){for(i=1;n>>i;i*=2);return i-2?i:4;}

จะไม่มีการป้อนข้อมูลของ(1<<15)+1หรือมากกว่านี้ทำลายเพราะพฤติกรรมการลงนามของlong long? ประเภทที่คุณต้องการคือuint64_tสิ่ง#include <stdint.h>ที่จำเป็นซึ่งยังคงเป็นผู้แพ้เมื่อเทียบกับunsigned long long! ส่วนหัวเป็นความหายนะของการเล่นกอล์ฟในค
dmckee

@dmckee ฉันเดาว่ามันอาจจะพัง แต่ดูเหมือนว่ามันจะทำงานได้อย่างน้อยในคอมพิวเตอร์ของฉัน ไม่พบตัวอย่างที่ใช้ไม่ได้ ฉันคิดว่าจะใช้unsigned long longหรือuint64_tแต่เนื่องจากดูเหมือนว่าจะทำงานกับlong longฉันไปกับมัน
Steadybox

0

QBICขนาด 27 ไบต์

:~a<2|_Xq]{~a<2^t|_Xt\t=t*2

คำอธิบาย

:        Get cmd line parameter N, call it 'a'
~a<2     IF 'a' is 0 or 1 (edge case)
|_Xq]    THEN quit, printing 1 ('q' is auto-initialised to 1). ']' is END-IF
{        DO - infinite loop
    2^t  't' is our current number of bits, QBIC sets t=4 at the start of the program.
         2^t gives the maximum number storable in t bytes.
 ~a<     IF the input fits within that number,
|_Xt     THEN quit printing this 't'
\t=t*2   ELSE jump to the next bracket (which are spaced a factor 2 apart, from 4 up)
         DO-loop is auto-closed by QBIC.


0

PHP, 43 ไบต์

for(;1<<2**$i++<=$argn;);echo 2**$i-=$i!=2;

echo <number> | php -R '<code>'ทำงานด้วย

วนซ้ำ$iจนกว่า2**(2**$i)จะมีขนาดใหญ่กว่าอินพุต (Tweak: <<แทนที่จะ**กำจัด parens)
หลังจากลูป $ i นั้นสูงเกินไป จึงได้รับการลดลงก่อนที่จะคำนวณการส่งออก
- $i==2แต่ไม่ได้สำหรับ

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