Bisakah angka tersebut dipecah menjadi kekuatan 2?


33

Kemarin saat bermain dengan anak saya, saya perhatikan nomor di kereta mainannya:

4281

Jadi kita memiliki

4281
yang dapat dibagi menjadi
4-2-8-1
atau
22-21-23-20

Jadi tantangan sederhana: diberi angka non-negatif sebagai input, kembalikan nilai kebenaran dan falsey yang konsisten yang mewakili apakah representasi string dari angka (di basis 10 dan tanpa nol di depan) dapat entah bagaimana dipecah menjadi angka yang merupakan kekuatan 2 .

Contoh:

4281      truthy (4-2-8-1)
164       truthy (16-4 or 1-64)
8192      truthy (the number itself is a power of 2)
81024     truthy (8-1024 or 8-1-02-4)
101       truthy (1-01)
0         falsey (0 cannot be represented as 2^x for any x)
1         truthy
3         falsey
234789    falsey
256323    falsey (we have 256 and 32 but then 3)
8132      truthy (8-1-32)

Tests for very large numbers (not really necessary to be handled by your code):
81024256641116  truthy (8-1024-256-64-1-1-16)
64512819237913  falsey

Ini adalah , jadi semoga kode terpendek untuk setiap bahasa menang!


2
@StewieGriffin awalnya saya berpikir tentang membatasi jumlah input ke kisaran inttipe standar (4 byte), tetapi sebenarnya saya tidak keberatan jika kode Anda tidak mendukung angka yang sangat besar. Cukup nyatakan dalam jawaban Anda keterbatasan kode Anda.
Charlie

3
Test case yang disarankan: 101(salah karena 0) ... atau apakah ini masih benar ( 1 - 01)?
Shieru Asakoto

1
@ShieruAsakoto Saya telah menguji 101kasus ini dengan jawaban saat ini dan semuanya kembali true, karena dapat dibagi menjadi 1-01dua kekuatan 2, jadi saya akan menganggap kasus itu benar.
Charlie

6
Meninggalkan ini di sini sebagai tip untuk semua orang. Berikut adalah tiga cara yang mungkin untuk memeriksa apakah angka adalah kekuatan 2: 1) Periksa apakah log2(n)tidak mengandung angka desimal setelah koma. 2) Periksa apakah n AND (n-1) == 0. 3) Buat daftar nr-square dan periksa apakah nada dalam daftar itu.
Kevin Cruijssen

1
" square-nrs " harus menjadi " kekuatan 2 " dalam komentar saya di atas tentu saja ..>.>
Kevin Cruijssen

Jawaban:


11

05AB1E , 9 8 byte

Ýos.œåPZ

-1 byte terima kasih kepada @Emigna dengan menggunakan Z(maks) untuk daftar 0s dan 1s untuk meniru anyperintah untuk 1(truey).

Cobalah secara online atau verifikasi semua kasus uji . (CATATAN: Di тheader adalah 100untuk hanya mendapatkan daya 100 pertama dari 2 angka, bukan jumlah input pertama dari kekuatan 2 angka. Ia bekerja dengan jumlah daya input 2 juga, tetapi cukup tidak efisien dan mungkin batas waktu pada TIO jika inputnya cukup besar.)

Penjelasan:

Ý            # Create a list in the range [0,n], where n is the (implicit) input
             # (or 100 in the TIO)
             #  i.e. 81024 → [0,1,2,3,...,81024]
 o           # Raise 2 to the `i`'th power for each `i` in the list
             #  → [1,2,4,8,...,451..216 (nr with 24391 digits)]
  s          # Swap to take the input
           # Create each possible partition of this input
             #  i.e. 81024 → [["8","1","0","2","4"],["8","1","0","24"],...,["8102","4"],["81024"]]
     å       # Check for each if it's in the list of powers of 2
             #  → [[1,1,0,1,1],[1,1,0,0],...,[0,1],[0]]
      P      # Check for each inner list whether all are truthy
             #  → [0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0]
       Z     # Take the maximum (and output implicitly)
             #  → 1 (truthy)

2
Bagus, solusi saya adalah .œ.²1%O0å(9 byte juga). Tambang gagal 0, namun.
Tn. Xcoder

@ Mr.Xcoder Ah, .²1%O0cukup pintar juga. Saya berpikir untuk menggunakan log2seperti ini .²DïQ, tetapi akan membutuhkan peta di sekitarnya untuk melakukan ini untuk setiap nomor, dan memang tidak bekerja untuk kasus tepi 0.
Kevin Cruijssen


6

JavaScript (Node.js) , 69 64 58 byte

f=(x,m=10,q=!(x%m&x%m-1|!x))=>x<m?q:q&&f(x/m|0)||f(x,10*m)

Cobalah online!

Masukkan sebagai angka. Bagian logika cukup berbelit-belit, jadi tidak ada ide bagaimana menguraikannya dan menyingkirkannya q.

-11 byte dengan melakukan golf pada cek power-of-2.



5

Jelly , 9 byte

ŒṖḌl2ĊƑ€Ẹ

Lihat ruang tes!


Alternatif

Tidak berfungsi untuk kasus uji besar karena masalah presisi.

ŒṖḌæḟƑ€2Ẹ

Lihat ruang tes!

Bagaimana?

Program I

ŒṖḌl2ĊƑ€Ẹ     Full program. N = integer input.
ŒṖ            All possible partitions of the digits of N.
  Ḍ           Undecimal (i.e. join to numbers).
   l2         Log2. Note: returns (-inf+nanj) for 0, so it doesn't fail.
     ĊƑ€      For each, check if the logarithm equals its ceil.
        Ẹ     Any. Return 0 if there are no truthy elements, 1 otherwise.

Program II

ŒṖḌæḟƑ€2Ẹ     Full program. N = integer input.
ŒṖ            All possible partitions of the digits of N.
  Ḍ           Undecimal (i.e. join to numbers).
     Ƒ€       For each partition, check whether its elements are invariant under...
   æḟ  2      Flooring to the nearest power of 2.
        Ẹ     Any. Return 0 if there are no truthy elements, 1 otherwise.


5

JavaScript, 59 byte

s=>eval(`/^(${(g=x=>x>s?1:x+'|0*'+g(x+x))(1)})+$/`).test(s)

Cobalah online!

Membangun regex seperti /^(1|0*2|0*4|0*8|0*16|0*32|…|0*1)+$/kekuatan 2, dan mengujinyas .

Hanya bekerja hingga ketepatan angka JavaScript, tentu saja: akhirnya istilah dalam regex akan terlihat seperti 1.2345678e30(atau Inf). Tetapi karena kekuatan 2 mudah untuk diwakili secara akurat dalam floating-point, mereka tidak akan pernah salah bilangan bulat yang , yang akan lebih mendiskualifikasi, saya pikir.

@tsh menyimpan 14 byte. Neato!





3

APL (NARS), 154 karakter, 308 byte

∇r←f w;g;b;z;k
   g←{⍵≤0:1⋄t=⌊t←2⍟⍵}⋄→A×⍳∼w≤9⋄r←g w⋄→0
A: z←w⋄b←0⋄k←1
B: b+←k×10∣z⋄z←⌊z÷10
   →C×⍳∼g b⋄r←∇z⋄→0×⍳r
C: k×←10⋄→B×⍳z≠0
   r←0
∇
h←{⍵=0:0⋄f ⍵}

Fungsi untuk latihan itu adalah h. Algoritme tampaknya bukan uji eksponensial atau faktorial:

  h¨ 4281 164 8192 81024 101 
1 1 1 1 1 
  h¨ 0 1 3 234789 256323 8132
0 1 0 0 0 1 
  h 81024256641116
1
  h 64512819237913
0



2

Ruby , 55 byte

->n{a=*b=1;a<<b*=2until b>n;n.to_s=~/^(0*(#{a*?|}))*$/}

Cobalah online!

Output adalah 0jika benar dan niljika salah.


2

Ruby , 49 byte

->n{n.to_s=~/^(0*(#{(0..n).map{|x|2**x}*?|}))*$/}

Cobalah online!

Hanya bekerja secara teori. Dibutuhkan selamanya untuk nilai besarn


2

PHP, 101 byte

Tampaknya tidak bisa mendapatkan ini di bawah 100; tapi aku bisa mendapatkannya untuk 100 jika 101adalah kasus falsy.

function f($s){for($x=.5;$s>=$x*=2;)if(preg_match("/^$x(.*)$/",$s,$m)?!~$m[1]||f(+$m[1]):0)return 1;}

NUL.L.1

variasi:

for($x=.5;$s>=$x*=2;)
while($s>=$x=1<<$i++)   # yields notices "undefined variable $i"

?!~$m[1]||f(+$m[1]):0
?~$m[1]?f(+$m[1]):1:0

PHP 5 atau lebih tua, 95 byte

function f($s){while($s>=$x=1<<$i++)if(ereg("^$x(.*)$",$s,$m)?$m[1]>""?f(+$m[1]):1:0)return 1;}

2

Merah , 212 211 byte

func[n][g: func[x][(log-2 do x)% 1 = 0]repeat i 2 **((length? s: form n)- 1)[b: a:
copy[] k: i foreach c s[append b c if k % 2 = 0[alter a g rejoin b
b: copy[]]k: k / 2]append a g form c if all a[return on]]off]

Cobalah online!

Satu lagi pengajuan panjang, tapi saya sama sekali tidak puas, karena tidak ada built-in untuk menemukan semua substring di Red.

Lebih mudah dibaca:

f: func [ n ] [
    g: func [ x ] [ (log-2 do x) % 1 = 0 ]
    repeat i 2 ** ((length? s: form n) - 1) [
        b: a: copy []
        k: i
        foreach c s [
            append b c
            if k % 2 = 0 [ 
                append a g rejoin b
                b: copy []
            ]
            k: k / 2 
        ]
        append a g form c
        if all a[ return on ]
    ]
    off
]

2

Aksioma, 198 byte

G(a)==(a<=1=>2>1;x:=log_2 a;x=floor x)
F(n)==(n<=9=>G n;z:=n;b:=0;k:=1;repeat(b:=b+k*(z rem 10);z:=z quo 10;if G b and F z then return 2>1;k:=k*10;z<=0=>break);1>1)
H(n:NNI):Boolean==(n=0=>1>1;F n)

ungolf dan tes

g(a)==(a<=1=>2>1;x:=log_2 a;x=floor x)
f(n)==
   n<=9=>g n
   z:=n;b:=0;k:=1
   repeat
      b:=b+k*(z rem 10);z:=z quo 10;
      if g b and f z then return 2>1
      k:=k*10
      z<=0=>break
   1>1
h(n:NNI):Boolean==(n=0=>1>1;f n)

(15) -> [[i,h i] for i in [4281,164,8192,81024,101]]
   (15)  [[4281,true],[164,true],[8192,true],[81024,true],[101,true]]
                                                      Type: List List Any
(16) -> [[i,h i] for i in [0,1,3,234789,256323,8132]]
   (16)  [[0,false],[1,true],[3,false],[234789,false],[256323,false],[8132,true]]
                                                      Type: List List Any
(17) -> [[i,h i] for i in [81024256641116, 64512819237913]]
   (17)  [[81024256641116,true],[64512819237913,false]]
                                                      Type: List List Any
(18) -> h 44444444444444444444444444
   (18)  true
                                                            Type: Boolean
(19) -> h 44444444444444444128444444444
   (19)  true
                                                            Type: Boolean
(20) -> h 4444444444444444412825444444444
   (20)  false
                                                            Type: Boolean
(21) -> h 2222222222222244444444444444444412822222222222210248888888888882048888888888888888
   (21)  true
                                                            Type: Boolean
(22) -> h 222222222222224444444444444444441282222222222225128888888888882048888888888888888
   (22)  true
                                                            Type: Boolean

1

Japt -! , 12 byte

Mengambil input sebagai string.

ÊÆòXÄÃex_&ZÉ

Cobalah


The 0kasus output truedan karenanya kasus seperti 1010juga keluaran true.
Charlie

1

C # 157 byte

bool P(string s,int i=1)=>i>=s.Length?((Func<ulong,bool>)((x)=>(x!=0)&&((x&(x-1))==0)))(ulong.Parse(s)):(P(s,i+1)||(P(s.Substring(0,i))&&P(s.Substring(i))));

Anda dapat mencobanya secara online


1

APL (NARS), 70 karakter, 140 byte

P←{k←↑⍴⍵⋄x←11 1‼k k⋄y←⍵⋄∪{x[⍵;]⊂y}¨⍳↑⍴x}
f←{⍵=0:0⋄∨/∧/¨y=⌊y←2⍟⍎¨¨P⍕⍵}

uji:

  f¨ 4281 164 8192 81024 101
1 1 1 1 1 
  f¨ 0 1 3 234789 256323 8132
0 1 0 0 0 1 
  f 126
0

saya tidak mencoba untuk melakukan angka lebih besar lainnya ... saya harus mencatat bahwa P bukan partisi normal, tetapi itu adalah satu partisi di mana semua elemen adalah himpunan bagian yang memiliki anggota semua berturut-turut, misalnya

  ⎕fmt P 'abc'
┌4──────────────────────────────────────────────────┐
│┌1─────┐ ┌2─────────┐ ┌2─────────┐ ┌3─────────────┐│
││┌3───┐│ │┌2──┐ ┌1─┐│ │┌1─┐ ┌2──┐│ │┌1─┐ ┌1─┐ ┌1─┐││
│││ abc││ ││ ab│ │ c││ ││ a│ │ bc││ ││ a│ │ b│ │ c│││
││└────┘2 │└───┘ └──┘2 │└──┘ └───┘2 │└──┘ └──┘ └──┘2│
│└∊─────┘ └∊─────────┘ └∊─────────┘ └∊─────────────┘3
└∊──────────────────────────────────────────────────┘

perhatikan bahwa tidak ada elemen ((ac) (b)) atau lebih baik ,, ¨ ('ac') 'b'

  ⎕fmt ,,¨('ac')'b'
┌2─────────┐
│┌2──┐ ┌1─┐│
││ ac│ │ b││
│└───┘ └──┘2
└∊─────────┘

1

POSIX ERE, 91 byte

(0*([1248]|16|32|64|128|256|512|1024|2048|4096|8192|16384|32768|65536|131072|262144|524288))+

Ini benar-benar curang, berdasarkan teks angka besar (tidak benar-benar perlu ditangani oleh kode Anda) dalam pertanyaan; ini menangani semua nilai dalam rentang ukuran contoh. Jelas dapat diperpanjang hingga jangkauan penuh tipe integer 32 atau 64-bit dengan mengorbankan ukuran. Saya terutama menulisnya sebagai demonstrasi bagaimana masalah itu secara alami cocok dengan alat itu. Latihan yang menyenangkan akan menulis ulangnya sebagai program yang menghasilkan ERE untuk rentang sewenang-wenang kemudian cocok dengan itu.


1

C (gcc) , -DA=asprintf(&c,+ 108 = 124 byte

p,c;f(a,i){c="^(0*(1";for(i=0;i<31;)A"%s|%d",c,1<<++i);A"%s))+$",c);regcomp(&p,c,1);a=!regexec(&p,a,0,0,0);}

Cobalah online!

Ini membangun regex dari kekuatan 2 hingga 2 ** 32, dan kemudian mencocokkan string input dengan itu.


1

Powershell, 56 byte

$x=(0..63|%{1-shl$_})-join'|0*'
"$args"-match"^(0*$x)+$"

Skrip uji:

$f = {

    $x=(0..63|%{1-shl$_})-join'|0*'
    "$args"-match"^(0*$x)+$"

}

@(
    ,(4281            ,$true)
    ,(164             ,$true)
    ,(8192            ,$true)
    ,(81024           ,$true)
    ,(101             ,$true)
    ,(0               ,$false)
    ,(1               ,$true)
    ,(3               ,$false)
    ,(234789          ,$false)
    ,(256323          ,$false)
    ,(8132            ,$true)
    ,("81024256641116"  ,$true)
    ,("64512819237913"  ,$false)
) | % {
    $n, $expected = $_
    $result = &$f $n
    "$($result-eq$expected): $result <- $n"
}

Keluaran:

True: True <- 4281
True: True <- 164
True: True <- 8192
True: True <- 81024
True: True <- 101
True: False <- 0
True: True <- 1
True: False <- 3
True: False <- 234789
True: False <- 256323
True: True <- 8132
True: True <- 81024256641116
True: False <- 64512819237913

Penjelasan:

Membangun regex seperti ^(0*1|0*2|0*4|0*8|0*16|0*32|…)+$kekuatan 2, dan mengujinya pada argumen.


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.