Là số nhị phân nặng?


58

Một số nguyên nặng nhị phân nếu biểu diễn nhị phân của nó chứa nhiều 1s hơn 0s trong khi bỏ qua các số 0 đứng đầu. Ví dụ 1 là nặng nhị phân, vì biểu diễn nhị phân của nó đơn giản 1, tuy nhiên 4 không phải là nhị phân nặng, vì biểu diễn nhị phân của nó là 100. Trong trường hợp hòa (ví dụ 2, với biểu diễn nhị phân là 10), số này không được coi là nhị phân nặng.

Cho một số nguyên dương làm đầu vào, xuất giá trị trung thực nếu nó nặng nhị phân và giá trị falsey nếu không.

Tủ thử

Định dạng: input -> binary -> output

1          ->                                1 -> True
2          ->                               10 -> False
4          ->                              100 -> False
5          ->                              101 -> True
60         ->                           111100 -> True
316        ->                        100111100 -> True
632        ->                       1001111000 -> False
2147483647 ->  1111111111111111111111111111111 -> True
2147483648 -> 10000000000000000000000000000000 -> False

Chấm điểm

Đây là nên ít byte nhất trong mỗi ngôn ngữ sẽ thắng


Điều gì xảy ra nếu ngôn ngữ của tôi không thể xử lý trường hợp kiểm tra cuối cùng bởi vì nó nằm ngoài giới hạn của những gì được coi là số nguyên dương?
sĩ523

1
@ musicman523 afaik Quy tắc I / O tiêu chuẩn quy định rằng bạn chỉ phải chấp nhận các số có thể biểu thị theo định dạng số ngôn ngữ của bạn. Lưu ý rằng "chơi trò chơi" này bằng cách sử dụng một cái gì đó như boolfuck được coi là lỗ hổng tiêu chuẩn
Skidsdev

Có bất kỳ giá trị trung thực / giả mạo nào hoặc chúng ta cần hai giá trị riêng biệt?
Erik the Outgolfer

@EriktheOutgolfer bất kỳ giá trị nào
Skidsdev

6
Aka A072600 , nếu điều này giúp bất cứ ai.
dcsohl

Câu trả lời:


28

Mã máy x86, 15 14 byte

F3 0F B8 C1 0F BD D1 03 C0 42 2B D0 D6 C3

Đây là một hàm sử dụng quy ước gọi __fastcall của Microsoft (tham số đầu tiên và duy nhất trong ecx, giá trị trả về trong eax, callee được phép ghi đè edx), mặc dù nó có thể được sửa đổi một cách tầm thường cho các quy ước gọi khác chuyển các đối số trong các thanh ghi.

Nó trả về 255 là trung thực và 0 là falsey.

Nó sử dụng opcode không có giấy tờ (nhưng được hỗ trợ rộng rãi) salc.

Tháo gỡ dưới đây:

;F3 0F B8 C1 
  popcnt eax, ecx ; Sets eax to number of bits set in ecx

;0F BD D1
  bsr edx, ecx    ; Sets edx to the index of the leading 1 bit of ecx

;03 C0
  add eax, eax

;42
  inc edx

;2B D0
  sub edx, eax

  ; At this point, 
  ;   edx = (index of highest bit set) + 1 - 2*(number of bits set)
  ; This is negative if and only if ecx was binary-heavy.

;D6
  salc           ; undocumented opcode. Sets al to 255 if carry flag 
                 ; is set, and to 0 otherwise. 

;C3
  ret

Hãy thử trực tuyến!

Cảm ơn Peter Cordes đã đề nghị thay thế lzcntbằng bsr.


Đẹp. Tôi đã đi xa đến mức rõ ràng popcnttrước khi cuộn xuống để xem câu trả lời, nhưng tôi đã không nghĩ lzcntđến việc chỉ xử lý các chữ số có nghĩa theo yêu cầu của câu hỏi.
Peter Cordes

Có cách nào để có được một khoản tiết kiệm ròng từ việc sử dụng bsrthay vì lzcnt(aka rep bsr) không? Bạn sẽ phải sử dụng subthay leavì nó cung cấp cho bạn 32-lzcnt. (Hoặc để dst không được sửa đổi cho src = 0, trên tất cả phần cứng Intel và AMD hiện có. AMD thậm chí còn ghi lại hành vi này, nhưng Intel nói không xác định ... Dù sao, OP nói tích cực , loại trừ 0.)
Peter Cordes

1
Tôi chắc chắn đã suy nghĩ theo cùng một dòng với @Peter, vì thách thức không giới hạn rõ ràng đầu vào đối với các số nguyên dương. Trong thực tế, tôi đã có một giải pháp được phác thảo bằng cách sử dụng popcntbsr, nhưng nó là 17 byte. Tôi đã nghĩ rằng nó khá tốt so với câu trả lời đầu tiên mà tôi thấy , nhưng leamẹo thông minh này đánh bại cái quần đó. Tôi cũng đã xem so sánh bsfpopcnt. Nhưng tôi không thấy bất kỳ cách nào giải pháp này có thể bị đánh bại, thậm chí có tính đến 1 byte mà bạn có thể lưu bằng cách bỏ reptiền tố.
Cody Gray

1
salckhông tương đương với setc al: bộ sau althành 1 nếu CF được đặt, không thành 255.
Ruslan

1
Tương đương thực tế salcsbb al, al, nhưng bạn có được khoản tiết kiệm 1 byte để mã hóa nó. Nhân tiện, nó được AMD ghi lại và nó được Intel hỗ trợ rộng rãi, với tính năng ghi nhớ thậm chí đến từ bản đồ opcode P6 của Intel. Vì vậy, cái này thực sự khá an toàn để sử dụng. Ngoài ra, cải thiện tốt đẹp ở đây để suy nghĩ để sử dụng hướng dẫn đó! Về cơ bản, đây là những gì bản nháp ban đầu của tôi đã làm, ngoại trừ (1) Tôi đã sử dụng mã x86-64, incthời gian mã hóa dài gấp đôi và (2) Tôi đã không nghĩ tới salc, vì vậy tôi đã làm công việc tương tự trong một con đường dài hơn. Quá tệ, tôi chỉ có thể upvote một lần.
Cody Grey

17

Thạch , 5 byte

Bo-SR

Mang lại đầu ra không trống (trung thực) hoặc đầu ra trống (giả).

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

Bo-SR  Main link. Argument: n

B      Binary; convert n to base 2.
 o-    Compute the logical OR with -1, mapping 1 -> 1 and 0 -> -1.
   S   Take the sum s. We need to check if the sum is strictly positive.
    R  Range; yield [1, ..., s], which is non-empty iff s > 0.

Đẹp. Tôi đã có Bo-S, nhưng tôi không thể tìm thấy một nguyên tử 1 byte nào có thể chuyển đổi tích cực / không tích cực thành sự thật / giả dối ...
ETHproductions

Hợp lý hay với −1, phải không?
Lynn

@Lynn Vâng, thực sự. Cảm ơn.
Dennis


@cairdcoinheringaahing Cảm ơn, nhưng Æṃsau đó không tồn tại.
Dennis

14

Python 2 , 35 byte

lambda n:max('10',key=bin(n).count)

Hãy thử trực tuyến!

Câu trả lời cũ, 38 byte

Đầu ra 0là giả và -2hoặc -1là sự thật

lambda n:~cmp(*map(bin(n).count,'10'))

Hãy thử trực tuyến!


2
Liệu 0 hàng đầu trong sự trở lại của binnguyên nhân giải pháp này có vấn đề?
Bóng tối

3
@shadow Không có vấn đề gì, vì cách maxlàm việc. Trong trường hợp hòa, max sẽ trả về giá trị đầu tiên trong lần lặp có giá trị tối đa. Mã này sử dụng thực tế đó để đảm bảo rằng 1 được trả về trong trường hợp hòa, điều này thực sự có nghĩa là có nhiều số hơn số không, vì thêm một số 0 được thêm vào bin. Nó thực sự sẽ không chính xác khi được viết theo cách này nếu không có thêm 0.
FryAmTheEggman

@FryAmTheEggman điều này cũng đúng với câu trả lời cũ, nơi cmptrả về 0khi cả hai đều bằng nhau
Rod

11

Octave , 18 byte

@(n)mode(de2bi(n))

TIO không hoạt động vì không bao gồm hộp công cụ truyền thông. Nó có thể được thử nghiệm trên Octave-Online .

Cách thức hoạt động:

de2bichuyển đổi một số thập phân thành một vectơ số nhị phân, không phải là một chuỗi như dec2bin.

modetrả về chữ số thường xuyên nhất trong vector. Nó mặc định ở mức thấp nhất trong trường hợp hòa.

@(n)                % Anonymous function that takes a decimal number as input 'n'
    mode(        )  % Computes the most frequent digit in the vector inside the parentheses
         de2bi(n)   % Converts the number 'n' to a binary vector

Là hộp công cụ truyền thông là một phần tiêu chuẩn của Octave, hay nó gần giống với một thư viện trong các ngôn ngữ khác?
dcsohl

Đây là một gói đi kèm với việc cài đặt. Bạn phải tải cụ thể trong một số cài đặt và nó sẽ tự động được tải theo tiêu chuẩn trong các cài đặt khác. Đó là một phần của tiêu chuẩn trên Octave-Online.net, vì vậy tôi đang sử dụng nó làm tài liệu tham khảo. (Mã phải hoạt động trong ít nhất một trình thông dịch tồn tại trước thử thách).
Stewie Griffin

9

JavaScript (ES6), 36 34 byte

f=(n,x=0)=>n?f(n>>>1,x+n%2-.5):x>0

f=(n,x=0)=>n?f(n>>>1,x+=n%2-.5):x>0cho 35 byte.
trứng

Sử dụng n>>1thay vì n>>>1để lưu một byte vì đầu vào không bao giờ âm.
kamoroso94

@ kamoroso94 Cảm ơn, nhưng sau đó nó sẽ thất bại vào ngày 2147483648.
ETHproductions

@ETHproductions Darn, và n/2|0không tốt hơn: /
kamoroso94



7

Brachylog , 6 byte

ḃọtᵐ>₁

Hãy thử trực tuyến!

Giải trình

Example input: 13

ḃ        Base (default: binary): [1,1,0,1]
 ọ       Occurences:             [[1,3],[0,1]]
  tᵐ     Map Tail:               [3,1]
    >₁   Strictly decreasing list

sẽ không bao giờ thống nhất đầu ra của nó với một danh sách các chữ số có các số 0 đứng đầu, chúng tôi biết rằng các lần xuất hiện 1sẽ luôn là đầu tiên và các lần xuất hiện 0sẽ luôn là thứ hai sau .



6

C (gcc) , 51 48 41 40 byte

i;f(n){for(i=0;n;n/=2)i+=n%2*2-1;n=i>0;}

Hãy thử trực tuyến!


Dựa trên sự làm rõ của OP, bạn có thể xóaunsigned
Musicman523

Vì nnn là tích cực, bạn có thể thay đổi n>>=1thành n/=2. Tôi cũng nghĩ rằng bạn có thể sử dụng ~nthay vì n^-1, điều này cũng sẽ cho phép bạn thay đổi &&thành&
Musicman523

Những điều kỳ lạ xảy ra khi tôi chỉnh sửa nhận xét - "nnn" có nghĩa là nvà không bao giờ bận tâm đến việc thay đổi &&thành &, tôi không nghĩ rằng nó sẽ hoạt động. Nhưng việc thay đổi nó *có vẻ hiệu quả
sĩ523

@ musicman523 &&Chỉ để xử lý trường hợp chưa ký nhưng vì tôi chỉ cần xử lý các số nguyên dương nên tôi có thể loại bỏ tất cả cùng nhau. Mặc dù vậy, pouint tốt về /=việc ngắn hơn >>=, Cảm ơn!
cleblanc

Bạn có thể lưu một byte thay đổi n&1?++i:--1thành i+=n%2*2-1. Bạn cũng có thể thoát khỏi >0bằng cách tuyên bố rằng bạn sẽ tạo ra số 0 cho hạng nặng và số khác không nặng
sĩ523

6

R , 54 53 51 byte

-1 byte nhờ Max Lawnboy

n=scan();d=floor(log2(n))+1;sum(n%/%2^(0:d)%%2)*2>d

đọc từ stdin; trả về TRUEcho số nặng nhị phân. dlà số chữ số nhị phân; sum(n%/%2^(0:d)%%2tính tổng các chữ số (nghĩa là số lượng).

Hãy thử trực tuyến!


Chỉ thấy câu trả lời của bạn sau khi đăng bài của tôi ... Dù sao, bạn có thể sử dụng log2(n)thay vì log(n,2)để tiết kiệm 1 byte
Maxim Mikhaylov

@MaxLawnboy ah, tất nhiên rồi. Cảm ơn!
Giuseppe


6

mã máy x86_64, 23 22 21 byte

31 c0 89 fa 83 e2 01 8d 44 50 ff d1 ef 75 f3 f7 d8 c1 e8 1f c3

Đã tháo rời:

  # zero out eax
  xor  %eax, %eax
Loop:
  # copy input to edx
  mov  %edi, %edx
  # extract LSB(edx)
  and  $0x1, %edx
  # increment(1)/decrement(0) eax depending on that bit
  lea -1(%rax,%rdx,2), %eax
  # input >>= 1
  shr  %edi
  # if input != 0: repeat from Loop
  jnz  Loop

  # now `eax < 0` iff the input was not binary heavy,
  neg %eax
  # now `eax < 0` iff the input was binary heavy (which means the MSB is `1`)
  # set return value to MSB(eax)
  shr  $31, %eax
  ret

Cảm ơn @Ruslan, @PeterCordes cho -1byte!

Hãy thử trực tuyến!


Có bất kỳ lý do cụ thể tại sao bạn sử dụng 8d 1fthay vì 89 fb?
Ruslan

2
Câu hỏi thực sự là, có lý do cụ thể nào khiến bạn sử dụng cú pháp AT & T gớm ghiếc đó không?!? Ngoài ra, việc tháo gỡ và tháo gỡ của bạn đều đồng ý rằng bạn có add eax, 2+ dec eax, nhưng ý kiến ​​của bạn cho thấy bạn muốn tăng ebxchứ không phải eax.
Cody Grey

1
Bạn có thể thay thế jnz Next/ add/ dec(7 byte) bằng lea -1(%rax, %rbx, 2), %eax(4 byte) để làm eax += 2*ebx - 1(như trong câu trả lời mã máy x86 khác ). Sau đó, bên ngoài vòng lặp, neg %eax(2 byte) trước khi chuyển bit dấu xuống phía dưới. Tiết kiệm ròng 1 byte. Hoặc test %eax,%eax/ setge %alcũng sẽ hoạt động, nếu giá trị trả về của bạn là một boolhoặc int8_t.
Peter Cordes

1
@PeterCordes Tôi nghĩ rằng tôi biết chuyện gì đã xảy ra, nhưng tôi không chắc: Tôi có thể đã không thử lea -1(%rax,rbx,2)nhưng chỉ lea -1(%eax,%eax,2)lãng phí byte theo cách này .. Dù sao, cả hai bạn đều đúng, tôi có thể lưu một byte như thế này. Cảm ơn rất nhiều (đổi lại tôi sẽ thay đổi điều đó leathành một movlúc tôi đang ở đó)!
18 giờ 01 phút

1
@ moonheart08: Lúc đó tôi không biết về điều đó, nhưng ai đó đã đăng một câu trả lời lưu 7 byte.
ბიმო

5

Perl 6 ,  32  30 byte

{[>] .base(2).comb.Bag{qw<1 0>}}

Kiểm tra nó

{[>] .polymod(2 xx*).Bag{1,0}}

Kiểm tra nó

Mở rộng:

{      # bare block lambda with implicit parameter 「$_」

  [>]  # reduce the following with &infix:« > »

    .polymod(2 xx *) # turn into base 2 (reversed) (implicit method call on 「$_」)
    .Bag\            # put into a weighted Set
    { 1, 0 }         # key into that with 1 and 0
                     # (returns 2 element list that [>] will reduce)
}


5

Haskell, 41 34

g 0=0
g n=g(div n 2)+(-1)^n
(<0).g

Nếu nlà số lẻ, hãy lấy -1số chẵn, lấy một 1. Thêm một cuộc gọi đệ quy với n/2và dừng nếu n = 0. Nếu kết quả nhỏ hơn 0số nhị phân nặng.

Hãy thử trực tuyến!

Chỉnh sửa: @ rjan Johansen tìm thấy một số phím tắt và lưu 7 byte. Cảm ơn!


mod n 2có thể chỉ là n, và nó ngắn hơn một byte mà không cần bộ tích lũy. Hãy thử trực tuyến!
Ørjan Johansen

5

Võng mạc , 37 34 byte

.+
$*
+`(1+)\1
$1@
@1
1
+`.\b.

1+

Hãy thử trực tuyến! Liên kết bao gồm các trường hợp thử nghiệm nhỏ hơn (những trường hợp lớn hơn có thể sẽ hết bộ nhớ). Chỉnh sửa: Đã lưu 3 byte nhờ @MartinEnder. Giải thích: Giai đoạn đầu tiên chuyển đổi từ thập phân sang đơn nguyên và hai giai đoạn tiếp theo chuyển đổi từ đơn phương sang nhị phân (điều này gần như thoát khỏi trang số học đơn nhất trên wiki Retina, ngoại trừ việc tôi đang sử dụng @thay vì 0). Giai đoạn thứ ba tìm kiếm các cặp nhân vật không giống nhau, có thể là @1hoặc 1@, và xóa chúng cho đến khi không còn lại. Giai đoạn cuối cùng sau đó kiểm tra 1s còn lại.


${1}có thể $+. Hoặc bạn có thể sử dụng !thay cho 0và sau đó rút ngắn 01|10tới .\b..
Martin Ender

@MartinEnder Huh, có $+làm đúng khi mẫu chứa a |không? Tôi tự hỏi liệu tôi có thể sử dụng nó trước đây không ...
Neil

2
không, $+là siêu ngu ngốc và chỉ đơn giản là sử dụng nhóm với số lượng lớn nhất, cho dù nó đã được sử dụng hay không. Nó chỉ hữu ích khi chơi golf khi bạn có hơn chín nhóm hoặc trong tình huống như nhóm ở đây và tôi không biết tại sao tôi lại sử dụng nó trong chế độ sản xuất.
Martin Ender

5

R , 43 byte

max(which(B<-intToBits(scan())>0))/2<sum(B)

Hãy thử trực tuyến!

             intToBits(scan())              # converts to bits
          B<-                 >0            # make logical and assign to B
max(which(                      ))/2        # get the length of the trimmed binary and halve
                                    <sum(B) # test against the sum of bits

Giải pháp gọn gàng +1! Tôi thậm chí còn không biết vềintToBits
Giuseppe


5

Kotlin , 50 byte

{i:Int->i.toString(2).run{count{it>'0'}>length/2}}

Lambda của loại ngầm (Int) -> Boolean. Phiên bản 1.1 trở lên chỉ do sử dụng Int.toString(radix: Int).

Thật không may, thời gian chạy Kotlin của TIO dường như là 1.0.x, vì vậy đây là một con chó buồn thay vì liên kết TIO:



4

R, 39 37 byte

sum(intToBits(x<-scan())>0)>2+log2(x)

Đây là sự kết hợp của các phương thức được sử dụng bởi @MickyT và @Giuseppe, tiết kiệm một vài byte khác.

sum(intToBits(x) > 0)đếm số lượng 1bit và 2+log2(x)/2bằng một nửa tổng số bit, khi làm tròn xuống. Chúng ta không phải làm tròn vì hành vi khi hai giá trị bằng nhau.



4

Regex (ECMAScript), 85 73 71 byte

^((?=(x*?)\2(\2{4})+$|(x*?)(\4\4xx)*$)(\2\4|(x*)\5\7\7(?=\4\7$\2)\B))*$

Hãy thử trực tuyến!

giải thích bởi Deadcode

Phiên bản 73 byte trước đó được giải thích bên dưới.

^((?=(x*?)\2(\2{4})+$)\2|(?=(x*?)(\4\4xx)*$)(\4|\5(x*)\7\7(?=\4\7$)\B))+$

Do những hạn chế của biểu thức chính của ECMAScript, một chiến thuật hiệu quả thường là biến đổi bước số một tại một thời điểm trong khi vẫn giữ bất động sản cần thiết ở mọi bước. Ví dụ, để kiểm tra một hình vuông hoàn hảo hoặc công suất là 2, hãy giảm số lượng kích thước trong khi vẫn giữ cho hình vuông hoặc công suất là 2 (tương ứng) ở mỗi bước.

Đây là những gì giải pháp này làm ở mỗi bước:

111100101oviết sai rồieS>zeroeS1

oviết sai rồieS>zeroeSoviết sai rồieS-1>zeroeS-1

Khi các bước lặp lại này không thể tiến xa hơn, kết quả cuối cùng sẽ là một chuỗi 1bit liền kề , rất nặng và chỉ ra rằng số ban đầu cũng nặng, hoặc lũy thừa bằng 2, cho thấy số ban đầu không nặng.

Và tất nhiên, mặc dù các bước này được mô tả ở trên về mặt thao tác chính tả trên biểu diễn nhị phân của số, chúng thực sự được thực hiện dưới dạng số học đơn phương.

# For these comments, N = the number to the right of the "cursor", a.k.a. "tail",
# and "rightmost" refers to the big-endian binary representation of N.
^
(                          # if N is even and not a power of 2:
    (?=(x*?)\2(\2{4})+$)   # \2 = smallest divisor of N/2 such that the quotient is
                           # odd and greater than 1; as such, it is guaranteed to be
                           # the largest power of 2 that divides N/2, iff N is not
                           # itself a power of 2 (using "+" instead of "*" is what
                           # prevents a match if N is a power of 2).
    \2                     # N = N - \2. This changes the rightmost "10" to a "01".
|                          # else (N is odd or a power of 2)
    (?=(x*?)(\4\4xx)*$)    # \4+1 = smallest divisor of N+1 such that the quotient is
                           # odd; as such, \4+1 is guaranteed to be the largest power
                           # of 2 that divides N+1. So, iff N is even, \4 will be 0.
                           # Another way of saying this: \4 = the string of
                           # contiguous 1 bits from the rightmost part of N.
                           # \5 = (\4+1) * 2 iff N+1 is not a power of 2, else
                           # \5 = unset (NPCG) (iff N+1 is a power of 2), but since
                           #   N==\4 iff this is the case, the loop will exit
                           #   immediately anyway, so an unset \5 will never be used.
    (
        \4                 # N = N - \4. If N==\4 before this, it was all 1 bits and
                           # therefore heavy, so the loop will exit and match. This
                           # would work as "\4$", and leaving out the "$" is a golf
                           # optimization. It still works without the "$" because if
                           # N is no longer heavy after having \4 subtracted from it,
                           # this will eventually result in a non-match which will
                           # then backtrack to a point where N was still heavy, at
                           # which point the following alternative will be tried.
    |
        # N = (N + \4 - 2) / 4. This removes the rightmost "01". As such, it removes
        # an equal number of 0 bits and 1 bits (one of each) and the heaviness of N
        # is invariant before and after. This fails to match if N is a power of 2,
        # and in fact causes the loop to reach a dead end in that case.
        \5                 # N = N - (\4+1)*2
        (x*)\7\7(?=\4\7$)  # N = (N - \4) / 4 + \4
        \B                 # Assert N > 0 (this would be the same as asserting N > 2
                           # before the above N = (N + \4 - 2) / 4 operation).
    )
)+
$       # This can only be a match if the loop was exited due to N==\4.

2
Mặc dù điều này được lấy cảm hứng từ câu trả lời của Deadcode , thuật toán này đủ khác để tôi cảm thấy nó xứng đáng có một câu trả lời riêng hơn là một nhận xét.
Grimmy

2
Đây là một hiện tượng, và chính xác những gì tôi muốn thấy (ai đó thổi regex của tôi ra khỏi nước với một thuật toán ngắn gọn hơn nhiều). Nhưng các bình luận của bạn thực sự không giải thích được gì cả, và phiên bản regex 73 byte được bình luận thậm chí không hoạt động (các backrefs \5trở đi bị tắt bởi một). Tôi đã nghiên cứu điều này và giải thích và nhận xét nó trong câu trả lời của mình (vì StackExchange không cho phép trả lời nhiều dòng).
Deadcode

4

Regex (ECMAScript), 183 byte

Đây là một vấn đề thú vị khác để giải quyết với regex ECMA. Cách "rõ ràng" để xử lý việc này là đếm số 1bit và so sánh với tổng số bit. Nhưng bạn không thể đếm trực tiếp mọi thứ trong biểu thức ECMAScript - việc thiếu các phản hồi liên tục có nghĩa là chỉ một số có thể được sửa đổi trong một vòng lặp và ở mỗi bước chỉ có thể giảm đi.

Thuật toán đơn nguyên này hoạt động như sau:

  1. Lấy căn bậc hai có công suất lớn nhất bằng 2 phù hợp với N và lưu ý xem căn bậc hai là hoàn hảo hay phải làm tròn xuống. Điều này sẽ được sử dụng sau.
  2. Trong một vòng lặp, di chuyển từng 1bit có ý nghĩa nhất đến vị trí ít quan trọng nhất trong đó có một 0bit. Mỗi bước này là một phép trừ. Ở cuối vòng lặp, số còn lại (như được biểu thị dưới dạng nhị phân) là một chuỗi 1s không có 0s. Các hoạt động này thực sự được thực hiện trong unary; Về mặt khái niệm, chúng chỉ được thực hiện ở dạng nhị phân.
  3. So sánh "chuỗi nhị phân 1s" này với căn bậc hai thu được trước đó. Nếu căn bậc hai phải được làm tròn xuống, hãy sử dụng phiên bản nhân đôi của nó. Điều này đảm bảo rằng "chuỗi nhị phân của 1s" được yêu cầu phải có hơn một nửa số chữ số nhị phân như N để có kết quả khớp cuối cùng.

Để có được căn bậc hai, một biến thể của thuật toán nhân được mô tả ngắn gọn trong bài đăng regex số Rocco của tôi được sử dụng. Để xác định 0bit có ý nghĩa nhỏ nhất, thuật toán phân chia được mô tả ngắn gọn trong bài regex số giai thừa của tôi được sử dụng. Đây là những kẻ phá hoại . Vì vậy, đừng đọc thêm nữa nếu bạn không muốn một số phép thuật regex unary tiên tiến được làm hỏng cho bạn . Nếu bạn thực sự muốn tự mình tìm ra phép thuật này, tôi khuyên bạn nên bắt đầu bằng cách giải quyết một số vấn đề trong danh sách các vấn đề được đề xuất liên quan đến spoiler trong bài đăng trước đó và cố gắng đưa ra những hiểu biết toán học một cách độc lập.

Không có thêm rắc rối, regex:

^(?=.*?(?!(x(xx)+)\1*$)(x)*?(x(x*))(?=(\4*)\5+$)\4*$\6)(?=(((?=(x(x+)(?=\10$))*(x*))(?!.*$\11)(?=(x*)(?=(x\12)*$)(?=\11+$)\11\12+$)(?=.*?(?!(x(xx)+)\14*$)\13(x*))\16)*))\7\4(.*$\3|\4)

Hãy thử trực tuyến!

# For the purposes of these comments, the input number = N.
^
# Take the floor square root of N
(?=
    .*?
    (?!(x(xx)+)\1*$)    # tail = the largest power of 2 less than tail
    (x)*?               # \3 = nonzero if we will need to round this square root
                        #      up to the next power of two
    (x(x*))             # \4 = potential square root; \5 = \4 - 1
    (?=
        (\4*)\5+$       # Iff \4*\4 == our number, then the first match here must result in \6==0
    )
    \4*$\6              # Test for divisibility by \4 and for \6==0 simultaneously
)
# Move all binary bits to be as least-significant as possible, e.g. 11001001 -> 1111
(?=
    (                                 # \7 = tool for making tail = the result of this move
        (
            (?=
                (x(x+)(?=\10$))*(x*)  # \11 = {divisor for getting the least-significant 0 bit}-1
            )
            (?!.*$\11)                # Exit the loop when \11==0
            (?=
                (x*)                  # \12 = floor((tail+1) / (\11+1)) - 1
                (?=(x\12)*$)          # \13 = \12+1
                (?=\11+$)
                \11\12+$
            )
            (?=
                .*?
                (?!(x(xx)+)\14*$)     # tail = the largest power of 2 less than tail
                \13                   # tail -= \13
                (x*)                  # \16 = tool to move the most-significant 1 bit to the
                                      # least-significant 0 bit available spot for it
            )
            \16
        )*
    )
)
\7                  # tail = the result of the move
\4                  # Assert that \4 is less than or equal to the result of the move
(
    .*$\3
|
    \4              # Double the value of \4 to compare against if \3 is non-empty,
                    # i.e. if we had an even number of total digits.
)



3

J , 12 byte

(+/>-:@#)@#:

J thực hiện các động từ từ phải sang trái, vì vậy chúng ta hãy bắt đầu ở cuối và làm theo cách của chúng ta về đầu.

Giải trình

         #:       NB. Convert input to list of bits
       -:@#       NB. Half (-:) the (@) length (#)
          >       NB. Greater than 
         +/       NB. Sum (really plus (+) reduce (/)

1
(#<2*+/)@#:nên lưu 1 trừ khi tôi thiếu thứ gì đó
FrownyFrog





2

C #, 82 byte

n=>{var s=System.Convert.ToString(n,2);return s.Replace("0","").Length>s.Length/2}

Bạn có thể cắt bớt một số chi tiết bằng cách xử lý chuỗi dưới dạng <char>. n=>{var s=Convert.ToString(n,2);return s.Count(c=>c=='1')>s.Length/2;}
GalacticCowboy

@GalacticCowboy Điều đó thêm 11 byte vì bạn phải đủ điều kiện Convertvà bao gồm using System.Linq;(viết ngắn hơn là namespace System.Linq{}). Ý tưởng tuyệt vời chỉ không cạo đi đủ để đảm bảo tiết kiệm trong trường hợp này.
TheLethalCoder
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.