Tìm số không


10

Thử thách

Cho một số nguyên ở định dạng bổ sung hai bit 32 bit , trả về chỉ số của chữ số 0 có ý nghĩa nhỏ thứ hai trong biểu diễn nhị phân, trong đó một chỉ số 0đại diện cho bit có trọng số thấp nhất và chỉ số 31đại diện cho bit có ý nghĩa nhất.

Nếu không có số 0 thứ hai, bạn có thể trả về 0, bất kỳ số âm nào, bất kỳ giá trị sai lệch nào hoặc báo cáo lỗi theo cách có ý nghĩa trong ngôn ngữ của bạn.

Bạn có thể sử dụng lập chỉ mục 1 nếu bạn thích, nhưng các trường hợp thử nghiệm bên dưới sẽ sử dụng lập chỉ mục 0.

Bạn có thể sử dụng số nguyên không dấu nếu bạn thích; nếu bạn làm như vậy, thì bạn phải xử lý các số nguyên trong phạm vi [0, 2^32). Nếu bạn sử dụng số nguyên đã ký, bạn phải xử lý số nguyên trong phạm vi [-2^31, 2^31). Các trường hợp thử nghiệm ở đây sẽ sử dụng số nguyên đã ký, nhưng lưu ý rằng -x(đã ký) là 2^32 - x(chưa ký).

Các trường hợp thử nghiệm

0 (0b00) -> 1
1 (0b001) -> 2
10 (0b1010) -> 2
11 (0b01011) -> 4
12 (0b1100) -> 1
23 (0b010111) -> 5
-1 (0b11..11) -> Không
-2 (0b11..10) -> Không
-4 (0b11..00) -> 1
-5 (0b11..1011) -> Không
-9 (0b11..10111) -> Không
2 ^ 31-2 (0b0111..1110) -> 31

Chấm điểm

Đây là , vì vậy câu trả lời ngắn nhất trong mỗi ngôn ngữ sẽ thắng!


Thay vào đó chúng ta có thể sử dụng một số nguyên không dấu?
Leaky Nun

Có, bạn có thể, miễn là bạn xử lý các số nguyên trong phạm vi [0, 2^32).
sĩ523

1
Chúng ta lấy số nguyên hoặc chuỗi 0b...làm đầu vào?
TheLethalCoder

1
@Jonathan ALLan Tôi đoán là không, vì tôi đã sửa câu trả lời Jelly của mình 2^32-1vì tôi không nên quay lại 33.
Erik the Outgolfer 17/07/17

1
@Jonathan ALLan Câu trả lời của Erik là chính xác. Tôi đã cập nhật thông số thử thách để phản ánh rằng bạn nên xử lý các số nguyên 32 bit cho dù bạn chọn lấy chúng dưới dạng đã ký hoặc chưa ký
Musicman523 17/07/17

Câu trả lời:


16

Python 2 , 45 byte

lambda n:[i for i in range(32)if n|1<<i>n][1]

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

Sử dụng lập chỉ mục 0, số không dấu và đưa ra lỗi không có số 0.

Đơn giản chỉ cần tạo một danh sách các chỉ số của các bit không được đặt, từ thấp nhất đến cao nhất và trả về mục nhập thứ hai.


5
Chào mừng đến với PPCG! Bài đăng đầu tiên rất hay!
Erik the Outgolfer 17/07/17

Cảm ơn! Tôi vẫn còn rất mới đối với trò đánh gôn trong Python, vì vậy tôi rất vui vì mã này đã không bị đánh gôn ngay lập tức.
Arnold Palmer

Tuyệt vời :) còn n = 2147483647 thì sao?
mdahmoune 17/07/17

@mdahmoune 2 ** 31-1 nên lỗi vì biểu diễn nhị phân của nó trong 32 bit là 0b01111111111111111111111111111111, không có giây thứ hai trừ khi tôi thiếu thứ gì đó ...
Arnold Palmer

6

JavaScript (ES6), 34 byte

Trả về chỉ mục dựa trên 0 hoặc -1nếu không tìm thấy số 0 thứ hai.

n=>31-Math.clz32((n=~n^~n&-~n)&-n)

Các trường hợp thử nghiệm

Biểu thức thay thế

n=>31-Math.clz32((n=~n^++n&-n)&-n)

Phiên bản đệ quy, 42 byte

Trả về chỉ mục dựa trên 0 hoặc falsenếu không tìm thấy số 0 thứ hai.

f=(n,p=k=0)=>n&1||!k++?p<32&&f(n>>1,p+1):p

Làm sao?

f=(n,p=k=0)=>                               // given n, p, k
             n&1||                          // if the least significant bit of n is set
                  !k++?                     // or this is the 1st zero (k was not set):
                       p<31&&               //   return false if p is >= 31
                             f(n>>1,p+1)    //   or do a recursive call with n>>1 / p+1
                                        :p  // else: return p

Các trường hợp thử nghiệm

Phiên bản thay thế được đề xuất bởi Neil, 41 byte

Trả về chỉ mục dựa trên 0 hoặc đưa ra lỗi đệ quy quá nhiều nếu không tìm thấy số 0 thứ hai.

f=(n,c=1)=>n%2?1+f(~-n/2,c):c&&1+f(n/2,0)

Phiên bản đệ quy 41 byte:f=(n,c=1)=>n%2?1+f(~-n/2,c):c&&1+f(n/2,0)
Neil

5

Thạch , 7 byte

|‘‘&~l2

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

Nó xuất ra thứ gì đó không nằm trong phạm vi [1,31] nếu không có số 0 thứ hai. Điều này bao gồm 32 33(-inf+nanj). Tôi đoán điều đó có ý nghĩa.

Nó tính toán log(((x|(x+1))+1)&~x)/log(2).


1
-inf+nanjTôi đã không nghĩ rằng điều đó thậm chí có thể tồn tại
Luis Mendo

Nó không xuất ra (-inf+nanj)một đầu vào 2147483647có đại diện nhị phân 31 1 giây, do đó không có số 0 thứ hai trong ký hiệu 32 bit (đây là lý do tại sao nó ngắn hơn nhiều so với câu trả lời của tôi và Erik).
Jonathan Allan

Trên thực tế, khi nào nó sản xuất (-inf+nanj)?
Jonathan Allan

... ah Tôi nghĩ đã giải quyết xong, bạn đang sử dụng tùy chọn đã ký?
Jonathan Allan

4

Java, ... 194 191 186 byte

static int f(int n){char[] c=Integer.toBinaryString(n).toCharArray();int j=0,o=2^32-2,i=c.length,l=i-1;if(n<0|n>o)return 0;for(;j<2&i>0;j+=c[--i]==48?1:0);if(j==2)return l-i;return 0;}

-159 Byte để sử dụng tên biến nhỏ hơn và xóa khoảng trắng
-25 Byte, sau khi lấy các biến thậm chí ngắn hơn và nhờ các mẹo @KevinCruijssen
-18 Byte, nhiều khoảng trắng hơn, tên hàm
-3 Byte, nhờ @KevinCruijssen, rút ​​ngắn nếu điều kiện
-5 Byte , Cảm ơn @Arnold Palmer, @KevinCruijssen, rút ​​ngắn vòng lặp

Ung dung

public static int getPosSecondZero2(int number){
    int overflow = 2^32-2;
    if(number < 0 || number > overflow){
        return 0;
    }    
    String binaryString = Integer.toBinaryString(number);   
    char[] binaryCharArray = binaryString.toCharArray();    
    int count = 0;
    int idx = binaryCharArray.length;
    int length = binaryCharArray.length -1;
    while(count < 2 && idx>0){
        idx--;
        if(binaryCharArray[idx] == '0'){
            count++;
        }   
    }
    if(count == 2)
        return length-idx;
    return 0;
}

Chào mừng đến với PPCG! Có khá nhiều thứ bạn có thể chơi golf: static có thể loại bỏ; if(n<0||n>o){return 0;}có thể if(n<0|n>o)return 0;( |thay vì ||và không có dấu ngoặc); bs, bsav.v ... tất cả đều có thể là các ký tự đơn (không bao giờ sử dụng tên biến / phương thức nhiều byte trong mã golf); Bạn có thể kết hợp ints, như thế này : int o=2^32-2,c=0,i=x.length,l=i-1;. Và có một số điều nữa để chơi golf. Mẹo chơi golf trong JavaMẹo chơi golf ở tất cả các ngôn ngữ có thể thú vị để đọc. Một lần nữa chào mừng, và tận hưởng kỳ nghỉ của bạn! :)
Kevin Cruijssen

Tôi nghĩ rằng vẫn còn một vài khoảng trống bạn có thể loại bỏ trong khai báo biến của bạn. Chào mừng bạn :)
sĩ523

@ musicman523 Cảm ơn, yeah đã sửa nó. 194 bây giờ :)
0x45

1
if(c[i]=='0'){j++;}vẫn có thể được đánh gôn thành if(c[i]==48)j++;-3 byte :) EDIT: Hoặc tốt hơn nữa: while(j<2&&i>0){i--;if(c[i]=='0'){j++;}}có thể for(;j<2&i>0;j+=c[i--]==48?1:0);cho -8 byte.
Kevin Cruijssen

1
@ 0x45 Tôi tin rằng nếu bạn thay đổi mã của @ KevinCruijssen thành mã for(;j<2&i>0;j+=c[--i]==48?1:0);sẽ hoạt động. Lỗi xuất phát từ iđộ dài của chuỗi, vì vậy ban đầu bạn đang cố gắng lập chỉ mục vượt qua giới hạn của mảng. Nếu bạn thực hiện giảm trước (như được hiển thị trong đoạn mã được cập nhật), thì lần đầu tiên bạn sử dụng nó sẽ truy cập c[c.length-1]như trong mã gốc của bạn.
Arnold Palmer


3

Mã máy IA-32, 14 13 byte

Hexdump:

F7 D1 0F BC C1 0F B3 C1 0F BC C9 91 C3

Danh sách tháo gỡ:

0:  f7 d1                   not    ecx
2:  0f bc c1                bsf    eax,ecx
5:  0f b3 c1                btr    ecx,eax
8:  0f bc c1                bsf    ecx,ecx
b:  91                      xchg   eax, ecx
c:  c3                      ret

Nhận đầu vào trong ecx; đầu ra là trong al. Trả về 0 khi lỗi.

Trước hết, nó đảo ngược đầu vào, vì vậy nó có thể sử dụng các hướng dẫn quét bit để tìm kiếm các bit được thiết lập. Nó tìm kiếm bit set ít quan trọng nhất, đặt lại nó, tìm bit set ít quan trọng nhất một lần nữa và trả về kết quả.

Nếu hướng dẫn quét bit không tìm thấy bất kỳ bit nào được đặt, tài liệu Intel cho biết đầu ra không được xác định. Tuy nhiên, trong thực tế, tất cả các bộ xử lý đều giữ nguyên thanh ghi đích trong trường hợp này (như được lưu ý bởi Cody Gray, tài liệu AMD mô tả hành vi này là bắt buộc).

Vì vậy, có những trường hợp sau:

  1. Không có bit nào (nhị phân 111 ... 1): ecx được đặt thành 0 by notvà vẫn là 0
  2. Một bit 0: ecx được đặt thành 0 by btrvà vẫn là 0 saubsf
  3. Hai bit 0: ecx được đặt thành giá trị phù hợp theo bsf

Đây chỉ là tài liệu của Intel cho biết quét bit trên 0 là không xác định. Tài liệu của AMD tài liệu rõ ràng rằng đích đến không thay đổi. Nếu bạn muốn tránh hành vi này, thông thường bạn sẽ thêm tiền tố REP để nhận LZCNT hoặc TZCNT, nhưng điều đó làm tăng số byte, điều này không mong muốn đối với môn đánh gôn.
Cody Grey

1
Bạn đang thực sự làm quá nhiều việc ở đây. Thử thách không yêu cầu bạn phân biệt giữa trường hợp không có bit 0 và trường hợp chỉ có 1 bit 0. Nó cho phép bạn trả về 0 (hoặc bất kỳ giá trị âm) trong cả hai trường hợp. Vì vậy, mặc dù là 1 byte SALC+ DECcực kỳ thông minh, bạn có thể cạo ra một byte bằng cách chỉ sử dụng bất cứ thứ gì trong ECXtính đến thứ hai BSFhướng dẫn. Điều duy nhất yêu cầu là 1 byte XCHGđể có kết quả EAXđể có thể trả về. Nói cách khác,not ecx; bsf eax, ecx; btr ecx, eax; bsf ecx, ecx; xchg eax, ecx; ret
Cody Grey

1
Đây là một liên kết "thử trực tuyến" cho ở trên . Vì bạn đang sử dụng ECXlàm thanh ghi đầu vào, chúng tôi cần nói với GCC để sử dụng quy ước gọi fastcall.
Cody Grey

2

APL Dyalog, 20 byte

{2⊃(⍳32)/⍨~⌽⍵⊤⍨32⍴2}

Sử dụng 1 chỉ mục, ném INDEX ERRORtrong trường hợp không có giây thứ hai.

Làm sao?

⍵⊤⍨- mã hóa dưới dạng

32⍴2 - chuỗi nhị phân có độ dài 32

- đảo ngược

~ - phủ định (0 → 1, 1 → 0)

(⍳32)/⍨ - nén với phạm vi 1-32 (để lại các chỉ số 0)

2⊃ - chọn phần tử thứ hai


Bạn có thể tiết kiệm rất nhiều byte bằng Where ( )
TwiNight

@TwiNight Tôi sử dụng dyalog 14
Uriel

TIO có Dyalog 16 nếu bạn cần
TwiNight 18/07/17


1

Thạch , 12 byte

,4BUFḣ32¬TḊḢ

Một liên kết đơn, lấy một số nguyên, sử dụng tùy chọn không dấu và trả về kết quả 1 chỉ mục (trả về 0 khi không tồn tại).

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

hoặc là

32Ḷ2*|€n⁸TḊḢ

Hãy thử nó

Làm sao?

1.

,4BUFḣ32¬TḊḢ - Link: number, n   e.g. 14
,4           - pair with 4            [14,4]
  B          - to binary              [[1,1,1,0],[1,0,0]]
   U         - upend                  [[0,1,1,1],[0,0,1]]
    F        - flatten                [0,1,1,1,0,0,1]
     ḣ32     - head to 32             [0,1,1,1,0,0,1] (truncates the right if need be)
        ¬    - not (vectorises)       [1,0,0,0,1,1,0]
         T   - truthy indexes         [1,5,6]
          Ḋ  - dequeue                [5,6]
           Ḣ - head                   5
             -   if the dequeued list is empty the head yields 0

2.

32Ḷ2*|€n⁸TḊḢ - Link: number, n   e.g. 14
32Ḷ          - lowered range of 32    [ 0, 1, 2, 3, 4, 5, ...,31]
   2*        - 2 exponentiated        [ 1, 2, 4, 8,16,32, ...,2147483648]
     |€      - bitwise or for €ach    [15,14,14,14,30,46, ...,2147483662]
        ⁸    - chain's right argument 14
       n     - not equal?             [ 1, 0, 0, 0, 1, 1, ..., 1]
         T   - truthy indexes         [ 1, 5, 6, ..., 32]
          Ḋ  - dequeue                [ 5, 6, ..., 32]
           Ḣ - head                   5
             -   if the dequeued list is empty the head yields 0

1

mã máy x86_64, 34 32 byte

Không chắc đây có phải là cách tiếp cận đúng hay không, khá nhiều byte (hóa ra không phải vậy ):

31 c0 83 c9 ff 89 fa 83 e2 01 83 f2 01 01 d1 7f 09 ff c0 d1 ef eb ee 83 c8 ff 83 f8 1f 7f f8 c3

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

second_zero:
  # Set eax = 0
  xor  %eax, %eax
  # Set ecx = -1
  xor %ecx,%ecx
  not %ecx

  # Loop over all bits
Loop:
  # Get current bit
  mov %edi, %edx
  and $0x1, %edx
  # Check if it's zero and possibly increment ecx
  xor $0x1, %edx
  add %edx, %ecx
  # If ecx > 0: we found the position & return
  jg Return
  # Increment the position
  inc %eax
  # Shift the input and loop
  shr %edi
  jmp Loop

Fix:
  # If there's not two 0, set value to -1
  xor %eax,%eax
  not %eax

Return:
  # Nasty fix: if position > 31 (e.g for -1 == 0b11..11)
  cmp $31, %eax
  jg  Fix

  ret

Cảm ơn @CodyGray cho -2byte.


1
Xoay vòng qua tất cả các bit có lẽ không phải là cách tiếp cận phù hợp, cho việc chơi golf mã hoặc cho thế giới thực. Bước đột phá sản sẽ được sử dụng một trong những hướng dẫn cho phép bạn thao tác tất cả 32 (hoặc 64) bit cùng một lúc, như BSF, BSR, POPCNT, BTvv Anatolyg đã đệ trình một giải pháp cùng những dòng này . Tôi vẫn chưa xác định nếu nó có thể bị đánh bại. :-p
Cody Grey

1
Nhân tiện, một mẹo đánh gôn mã có khả năng hữu ích để đặt thanh ghi thành -1 là HOẶC nó với -1. Ví dụ , or ecx, -1. Đó là 3 byte, ngắn hơn 1 byte so với XOR + NEG. Đây không phải là một mẹo hay khi không chơi gôn vì nó giới thiệu một phụ thuộc đọc sai vào thanh ghi đích, nhưng ở đó bạn chỉ cần sử dụng mov ecx, -1và chi tiêu 5 byte.
Cody Grey

1

8 , 149 byte

2 base swap >s nip decimal s:len 32 swap n:- ( "0" s:<+ ) swap times s:rev null s:/ a:new swap ( "0" s:= if a:push else drop then ) a:each swap 1 a:@

Mã nhận xét

: f \ n -- a1 a2 n 

  \ decimal to binary conversion
  2 base swap >s nip decimal     

  \ 32bit formatting (padding with 0)            
  s:len 32 swap n:- ( "0" s:<+ ) swap times  

  \ put reversed binary number into an array 
  s:rev null s:/

  \ build a new array with position of each zero 
  a:new swap ( "0" s:= if a:push else drop then ) a:each

  \ put on TOS the position of the 2nd least least-significant zero digit
  swap 1 a:@
;

Sử dụng và đầu ra

ok> : f 2 base swap >s nip decimal s:len 32 swap n:- ( "0" s:<+ ) swap times s:rev null s:/ a:new swap ( "0" s:= if a:push else drop then ) a:each swap 1 a:@ ;

ok> [0, 1, 10, 11, 12, 23, -1, -2, -4, -5, -9, 2147483646]

ok> ( dup . " -> " .  f . 2drop cr ) a:each
0 -> 1
1 -> 2
10 -> 2
11 -> 4
12 -> 1
23 -> 5
-1 -> null
-2 -> null
-4 -> 1
-5 -> null
-9 -> null
2147483646 -> 31

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.