Sedikit, gigitan atau byte?


45

Terinspirasi oleh tantangan ini

Diberikan bilangan bulat dalam kisaran 0 <= n < 2**64, output wadah ukuran minimum yang bisa masuk

  • bit: 1
  • menggigit: 4
  • byte: 8
  • pendek: 16
  • int: 32
  • panjang: 64

Testcases:

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

Ini adalah , jadi jawaban tersingkat dalam byte menang.


10
Ini akan jauh lebih mudah jika 2merupakan output juga ...
ETHproduk

1
@ ETHproductions Akan tetapi sayangnya, itu tidak (butuh waktu lama untuk menulis algoritma yang melakukannya)
Blue

Saya berharap saya mengerti masalahnya. ... tunggu, yang diinginkannya adalah jumlah bit yang diperlukan untuk memuat angka, dibulatkan ke struktur fundamental berikutnya?
Z0rberg

2
Terima kasih! Saya menyadarinya ketika saya menulis komentar dan mengeditnya terlambat. Kurasa aku butuh bebek karet untuk diajak bicara ...
Z0rberg

2
@Aniel jawaban di sini mengambil pendekatan yang sama sekali berbeda untuk pertanyaan lain. Ketika saya mengatakan 'terinspirasi oleh' itu tidak berarti 'duplikat'. Tidak ada jawaban yang bisa dimodifikasi untuk menjadi sepele untuk pertanyaan ini
Biru

Jawaban:


3

05AB1E , 10 byte

bg.²îD1Q+o

Penjelasan

bg         Push the length of the binary representation of input without leading zeros
  .²î      Push x = ceil(log2(length))
     D1Q+  Add 1 if x == 1 or add 0 otherwise
         o Push pow(2,x) and implicitly display it

Cobalah online!


22

Python, 39 byte

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

Menghitung berapa kali seseorang harus mengambil akar kuadrat untuk nberada di bawah 16, dengan beberapa casing khusus untuk menghindari output 2.

Jika 2 dimasukkan, kita bisa melakukannya

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

dengan True untuk 1.


41 byte:

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

Berulang kali eksponen ihingga dua kali lipat 2**i>n. Melompat dari i=1ke i=4dengan menggeser sedikit tambahan saat iganjil.

Alt 45 byte:

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

7
Tidak pernah berhenti membuat saya takjub bagaimana Anda dapat menemukan begitu banyak solusi untuk suatu masalah. Pada dasarnya sebagai seorang programmer saya telah belajar untuk menemukan solusi untuk suatu masalah dan bekerja dengannya hingga berhasil. Kira saya masih harus belajar banyak tentang golf! Menghormati.
ElPedro

@ xnor, bagaimana jawaban pertama Anda dihasilkan 1ketika akar kuadrat dari 0 atau 1 selalu 1 (tak terhingga berulang dalam or 2*f(n**.5))?
dfernan

2
@dfernan Saya percaya bagian setelah orhanya dievaluasi jika bagian sebelum dievaluasi untuk sesuatu yang palsu (nol). Untuk n = 0, dan untuk n = 1, n>1dievaluasi menjadi False, yang diperlakukan sebagai nol dalam ekspresi numerik, dan n<16dievaluasi menjadi True, yang diperlakukan sebagai satu dalam ekspresi numerik. Begitu 4**(n>1)*(n<16)juga 1.
trichoplax

1
@trichoplax, itu benar. Terima kasih untuk penjelasannya.
dfernan

12

J, 19 byte

Kata kerja monadik mengambil angka di sebelah kanan dan meludahkan ukuran wadah. Ada beberapa cara yang setara untuk menulisnya sehingga saya memasukkan keduanya.

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

Dijelaskan oleh ledakan:

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

Apa yang keren adalah kita melihat dua cara berbeda untuk mengambil basis log 2 dalam J. Yang pertama adalah yang jelas 2^., yang merupakan logaritma numerik. Yang kedua adalah #@#:, yang dapat dibaca sebagai "panjang representasi basis-2". Ini hampir setara dengan one-plus-floor-of-log-base-2, kecuali itu #:0adalah daftar satu-elemen 0, yang persis seperti yang kita inginkan. Ini berdetak 1+2<.@^.1&>.8 byte.

Digunakan di 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

Solusi 20 byte yang terlalu pintar.

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

Python, 53 50 49 byte

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]lebih pendek satu byte
Biru

Baru saja memposting sesuatu yang serupa. +1
ElPedro

8

Mathematica, 44 39 38 byte

Terima kasih @orlp untuk 5 byte dan @MartinEnder untuk 1 byte.

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

Temukan elemen pertama dalam daftar {1, 4, 8, 16, 32, 64}sehingga angka 2 ^ lebih besar dari input.


8

Pip , 19 byte

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

Cobalah online!

Bagaimana itu bekerja

                     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 byte

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

2
Versi rekursif seperti f=(n,b=1)=>2**b>n&&b-2?b:f(n,b*2)harus sedikit lebih pendek.
Arnauld

6

Mathematica, 46 43 38 byte

Terima kasih kepada JungHwan Min dan Martin Ender karena telah menghemat 3 byte! Terima kasih kepada ngenisis untuk penghematan 5 byte yang besar!

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

Fungsi tanpa nama mengambil integer non negatif sebagai input dan mengembalikan integer positif. BitLength@#menghitung jumlah bit dalam input, dan kemudian 2^⌈Log2@...⌉menghitung kekuatan terkecil 2 yang setidaknya sama besar dengan jumlah bit. Akhirnya, /.{2->4,0->1}urus kasus khusus yang tidak ada "niblit" antara bit dan nybble, dan juga memperbaiki jawaban untuk input aneh 0.


2
Hemat 3 byte dengan menggunakan BitLength@#bukan ⌊1+Log2@#⌋. Kemudian alih-alih mengganti dengan 1Anda dapat mengganti 0, menyimpan 2 byte lain dan Anda terikat untuk yang pertama.
ngenisis

1
Ini sebenarnya bisa dilakukan sepenuhnya dengan BitLength. Lihat jawaban saya
ngenisis

4

Julia, 40 byte

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

Ini adalah fungsi anonim yang menghasilkan array kekuatan 2 dari 0 hingga 6, tidak termasuk 2, dan memfilternya hanya untuk elemen-elemen x sedemikian rupa sehingga 2 x lebih besar dari input. Unsur seperti pertama adalah jawabannya. Sayangnya ini membutuhkan promosi 2 ke a BigIntuntuk menghindari overflow pada x = 64.

Ini sebenarnya sangat mirip dengan jawaban Python orlp, meskipun saya tidak melihatnya sebelum meramu pendekatan ini.

Cobalah online!


4

Perl 6 , 30 byte

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

+<adalah operator bit shift kiri Perl 6, yang disebut banyak bahasa lain <<.


4

Haskell, 31 byte

f n=[2^i|i<-0:[2..],2^2^i>n]!!0

Alt 32-byte:

f n|n<2=1|n<16=4|1>0=2*f(sqrt n)

2

Java, 143 byte.

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
Saya tahu saya bisa membuat ini lebih pendek, Io melakukannya ketika saya di depan komputer.
Pavel

2
hemat 50 byte: return a<2?1:a<5?4:a<9?8:a<17?16:a<33?32:64;
Mindwin

@Mindwin saya tahu, tapi saya bepergian dan tidak akan memiliki akses ke komputer untuk sementara waktu. Saya akan menyiasatinya.
Pavel

Apakah skor menjadikannya ... byte cinta ?
Engineer Toast

2

Haskell, 43 byte

f x=head$filter((>x).(2^))$[1,4,8,16,32,64]

2

Ruby, 39 36 byte

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

Terima kasih GB untuk membantu golf


Seharusnya juga berfungsi tanpa tanda kurung. Juga, daftarnya bisa 0,2,3,4,5,6 dan menggunakan 1 << 2 ** p.
GB

... karena Anda dapat menggunakan 0, * 2..6.
GB

2

Java 8, 65 55 byte

Ini adalah ekspresi lambda yang mengambil longdan mengembalikan sebuah int. Tidak pernah bermain golf di Jawa sebelumnya, jadi ini seharusnya mudah dikalahkan:

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

Cobalah online!


Untuk 47 byte , kita dapat memiliki:

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

Namun, 1L<<iluapan untuk nilai pengembalian lebih besar dari 32, jadi ini gagal untuk testcase akhir.


1
Ini kembali 4ketika diuji dengan 16ketika seharusnya mengembalikan 8. Juga Anda masih dapat golf solusi ini dengan menghapus tanda kurung sekitar i<<=1+i%2;karena tanpa {}s, loop sementara hanya akan mengeksekusi baris berikutnya
Kritixi Lithos

@KritixiLithos harus diperbaiki sekarang - maaf, Java saya sudah karatan ...
FlipTack

2

Mathematica, 30 byte

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

Penjelasan:

Membiarkan Nmenjadi himpunan bilangan bulat negatif. Tentukan dua fungsi aktif N, BitLengthdan NextPowersebagai berikut:

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

Solusi ini pada dasarnya menghitung NextPower(BitLength(n))diberi bilangan bulat n >= 0. Karena n > 0, kita bisa melihatnya NextPower(n) = 2^BitLength(n-1), jadi NextPower(BitLength(n)) = 2^BitLength(BitLength(n)-1).

Sekarang BitLengthbuilt-in Mathematica setuju dengan definisi yang saya berikan n >= 0. Untuk n < 0, BitLength[n] == BitLength[BitNot[n]] == BitLength[-1-n], jadi BitLength[-1] == BitLength[0] == 0. Dengan demikian kami mendapatkan jawaban yang diinginkan 1untukn==0 .

Karena kita lewati langsung dari bit ke nibble, kita harus mengganti jawaban 2dengan 4.


1
Dibangun dengan baik! (Malu bahwa ruang itu diperlukan.)
Greg Martin

2

bash, 49 byte, 48 byte

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

atau

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

Simpan dalam skrip dan berikan nomor untuk diuji sebagai argumen.

Sunting: Diganti || dengan |, yang berfungsi karena argumen selalu 0 atau 1.

Catatan: Ini berfungsi untuk bilangan bulat hingga bilangan bulat positif terbesar yang dapat ditangani versi bash Anda. Jika saya punya waktu, saya akan memodifikasinya untuk bekerja hingga 2 ^ 64-1 dalam versi bash yang menggunakan aritmatika bertanda 32-bit.

Sementara itu, berikut ini adalah solusi 64-byte yang berfungsi untuk jumlah besar yang sewenang-wenang (dalam versi bash apa pun):

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

2

Ditumpuk, 34 30 byte

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

atau

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

Yang pertama mengambil input pada TOS dan meninggalkan output pada TOS; yang kedua adalah fungsi. Coba di sini!

Penjelasan

@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

Berikut ini contohnya yang bekerja pada repl :

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

Uji kasus

> {!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))
> 

Atau, sebagai program lengkap:

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

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

out

2

Racket 45 byte

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

Tidak Disatukan:

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

Versi lain:

(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))

dan menggunakan panjang string:

(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))

Pengujian:

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

Keluaran:

1
1
4
4
8
8
16
32
64

1

Oktaf, 40 36 31 29 byte

Fungsi anonim sederhana. Diasumsikan bahwa nilai input adalah bilangan bulat - lihat peringatan di bagian akhir.

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

Kode kerjanya sebagai berikut:

  • Pertama array dari panjang bit yang diizinkan (1,4,8,16,32,64) dibuat dan disimpan b.

  • Selanjutnya kita menemukan jumlah bit yang diperlukan untuk menyimpan nomor input adengan membandingkan dengan ukuran maksimum setiap wadah buntuk melihat mana yang cukup besar.

  • Kami kemudian menggunakan vektor indeks yang dihasilkan untuk mengekstrak ukuran wadah dari blagi.

  • Akhirnya kita mengambil elemen pertama dalam array yang dihasilkan yang akan menjadi wadah sekecil mungkin.

Anda dapat mencobanya online di sini .

Cukup jalankan kode berikut, lalu lakukan ans(x).


Satu-satunya peringatan dengan ini adalah bahwa presisi ganda digunakan untuk konstanta secara default yang berarti bahwa itu hanya bekerja dengan angka hingga nilai tertinggi yang diwakili oleh pelampung presisi ganda yang kurang dari 2 ^ 64.

Ini dapat diperbaiki dengan memastikan bahwa angka yang dipasok ke fungsi adalah bilangan bulat bukan ganda. Hal ini dapat dicapai dengan memanggil fungsi misalnya dengan: ans(uint64(x)).


1

PHP, 49 46 44 byte

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

Jalankan seperti ini:

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

Penjelasan

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.

Tweaks

  • Disimpan 3 byte dengan menyingkirkan $r=tugas
  • Disimpan 2 byte dengan menggunakan -Ragar $argntersedia

1

CJam , 18 byte

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

Cobalah online!

Penjelasan

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 byte

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

Bukankah masukan (1<<15)+1atau lebih merusak ini karena perilaku yang ditandatangani long long? Jenis yang Anda inginkan adalah uint64_tyang mengharuskan #include <stdint.h>yang masih kalah dibandingkan unsigned long long! Header adalah kutukan bermain golf di c.
dmckee

@ dmckee Saya kira itu bisa memecahkannya, tetapi tampaknya berfungsi setidaknya di komputer saya. Belum menemukan contoh yang tidak akan berfungsi. Saya berpikir untuk menggunakan unsigned long longatau uint64_t, tetapi karena tampaknya berfungsi dengan baik, long longsaya menggunakannya.
Steadybox

0

QBIC , 27 byte

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

Penjelasan

:        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

Pyke, 13 byte

7Zm@2-#2R^<)h

Coba di sini!

7Zm@          -   [set_bit(0, i) for i in range(7)] <- create powers of 2
    2-        -  ^.remove(2)
      #    )h - filter(^, V)[0]
       2R^    -   2 ** i
          <   -  input < ^

0

PHP, 43 byte

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

Jalankan dengan echo <number> | php -R '<code>'.

loop $ihingga 2**(2**$i)lebih besar dari input. (Tweak: <<bukannya **menghilangkan parens)
Setelah loop, $ i adalah salah satu yang terlalu tinggi; sehingga mendapat pengurangan sebelum menghitung output
- tetapi tidak untuk $i==2.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.