Chuyển đổi một số bit và có được một hình vuông


26

Cho một số nguyên , bạn phải tìm số bit tối thiểu cần được đảo trong để biến nó thành số vuông . Bạn chỉ được phép đảo ngược các bit dưới mức quan trọng nhất .N>3N

Ví dụ

  • 2 2 0N= =4 đã là một số vuông ( ), vì vậy đầu ra dự kiến ​​là .220
  • 11000 1100 1 25 = 5 2N= =24 có thể được biến thành một số vuông bằng cách đảo ngược 1 bit: ( ), vì vậy đầu ra dự kiến ​​là .110001100125= =521
  • 23 20 18 30 10110 10 0 0 0 16 = 4 2 2N= =22 thành số vuông bằng cách đảo ngược một bit đơn (kết quả có thể là , , và ) nhưng có thể được thực hiện bằng cách đảo ngược 2 bit: ( ), do đó, đầu ra dự kiến ​​là .23201830101101000016= =422

Quy tắc

  • Sẽ ổn nếu mã của bạn quá chậm hoặc gây ra lỗi cho các trường hợp thử nghiệm lớn hơn, nhưng ít nhất nó phải hỗ trợ trong vòng chưa đầy 1 phút.3<N<10000
  • Đây là !

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

    Input | Output
----------+--------
        4 | 0
       22 | 2
       24 | 1
       30 | 3
       94 | 4
      831 | 5
      832 | 1
     1055 | 4
     6495 | 6
     9999 | 4
    40063 | 6
   247614 | 7        (smallest N for which the answer is 7)
  1049310 | 7        (clear them all!)
  7361278 | 8        (smallest N for which the answer is 8)
100048606 | 8        (a bigger "8")

Hoặc ở dạng sao chép / dán thân thiện:

[4,22,24,30,94,831,832,1055,6495,9999,40063,247614,1049310,7361278,100048606]

Gần một nửa số câu trả lời không được thực hiện cho 100048606TIO, đó có phải là vấn đề không?
Bạch tuộc ma thuật Urn

@MagicOctopusUrn Cảm ơn, tôi đã cập nhật các quy tắc để làm rõ hơn rằng hỗ trợ là tùy chọn. N10000
Arnauld

1
Đây cũng sẽ là một câu hỏi mã nhanh nhất (không có giới hạn kích thước đầu vào)
qwr

@qwr Có, có lẽ. Hoặc nếu bạn muốn đi Hardcore: cho , tìm N nhỏ nhất sao cho f ( N ) = k . kNf(N)= =k
Arnauld

Câu trả lời:


14

Ruby, 74 byte

->n{(1..n).map{|x|a=(n^x*x).to_s 2;a.size>Math.log2(n)?n:a.count(?1)}.min}

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

Điều này chỉ đơn giản là tạo ra chuỗi (là quá đủ), XOR nó với n , và sau đó lấy số 1s trong biểu diễn nhị phân của nó nếu số bit ít hơn hơn hoặc bằng log 2 n , hoặc n khác. Sau đó, nó lấy số bit tối thiểu được lật. Trả về n thay vì số bit được lật khi lật bit cao nhất lớn hơn log 2 n ngăn các trường hợp này được chọn là tối thiểu, vì n[12,22,,n2]nlog2nnnlog2nn sẽ luôn luôn lớn hơn số bit mà nó có.

Cảm ơn Piccolo đã lưu một byte.


Bạn có thể lưu một byte bằng cách sử dụng (n^x*x).to_s 2;...thay vì(n^x*x).to_s(2);...
Piccolo

@Piccolo Không thể tin rằng tôi đã bỏ lỡ điều đó, cảm ơn!
Doorknob

6

Thạch , 12 byte

²,BẈEðƇ²^B§Ṃ

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

Kiểm tra một bộ thử nghiệm!

Liên kết đơn âm. Nên chơi golf. Nhưng tôi quá ngu ngốc khi nghĩ ra một cách để thoát khỏi ³s. Đó là câu trả lời đầu tiên của tôi trong đó tôi sử dụng thành công lọc / ánh xạ / vòng lặp nói chung cùng với chuỗi dyadic \ o /

Giải trình

², BẈEðƇ² ^ B §Ṃ - Chương trình đầy đủ / Liên kết đơn âm. Gọi đối số N.
     ðƇ - Bộ lọc giữ [1 ... N] với chuỗi dyadic sau:
², BẈE - Hình vuông của vật phẩm hiện tại có cùng độ dài bit với N.
² - Quảng trường.
 , - Ghép đôi với N.
  B - Chuyển đổi cả hai thành nhị phân.
   - Lấy chiều dài của chúng.
    E - Và kiểm tra xem chúng có bằng nhau không.
       ² ^ - Sau khi lọc, bình phương kết quả và XOR chúng với N.
         B - Đại diện nhị phân của mỗi.
          § - Tổng của mỗi. Đếm số lượng 1s trong hệ nhị phân.
           Ṃ - Tối thiểu.

5

Husk , 20 byte

▼mΣfo¬→S↑(Mo¤ż≠↔ḋİ□ḋ

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

Giải trình

▼mΣf(¬→)S↑(M(¤ż≠↔ḋ)İ□ḋ) -- example input n=4
        S↑(           ) -- take n from n applied to (..)
                     ḋ  -- | convert to binary: [1,0,0]
                   İ□   -- | squares: [1,4,9,16,...]
           M(     )     -- | map with argument ([1,0,0]; example with 1)
                 ḋ      -- | | convert to binary: [1]
             ¤  ↔       -- | | reverse both arguments of: [1] [0,0,1]
              ż≠        -- | | | zip with inequality (absolute difference) keeping longer elements: [1,0,1]
                        -- | : [[1,0,1],[0,0,0],[1,0,1,1],[0,0,1,0,1],[1,0,1,1,1],....
                        -- : [[1,0,1],[0,0,0],[1,0,1,1],[0,0,1,0,1]]
    f(  )               -- filter elements where
       →                -- | last element
      ¬                 -- | is zero
                        -- : [[0,0,0]]
 mΣ                     -- sum each: [0]
▼                       -- minimum: 0

▼mΣfo¬←ṠMz≠ȯfo£İ□ḋπŀ2Lḋtiết kiệm 2 byte. RIP bạn điểm vuông hoàn hảo.
Ông Xcoder

@ Mr.Xcoder: Xấu hổ về tỷ số .. Nhưng tôi đã thoát khỏi một số chi tiết, bây giờ nhắm mục tiêu 16; P
ბიმო

5

Perl 6 , 65 byte

{min map {+$^a.base(2).comb(~1) if sqrt($a+^$_)!~~/\./},^2**.msb}

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

Tôi cảm thấy hơi bẩn khi kiểm tra một hình vuông hoàn hảo bằng cách tìm kiếm một khoảng thời gian trong biểu diễn chuỗi của căn bậc hai của số, nhưng ... bất cứ điều gì để loại bỏ byte.


4

05AB1E , 20 15 byte

Lnʒ‚b€gË}^b€SOß

-5 byte nhờ @ Mr.Xcoder sử dụng một cổng câu trả lời Jelly của anh ấy .

Dùng thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm (ba trường hợp thử nghiệm lớn nhất bị xóa vì hết thời gian sau 60 giây; vẫn mất khoảng 35-45 giây với các trường hợp thử nghiệm khác).

Giải trình:

L            # Create a list in the range [1, input]
             #  i.e. 22 → [0,1,2,...,20,21,22]
 n           # Take the square of each
             #  i.e. [0,1,2,...,20,21,22] → [0,1,4,...,400,441,484]
  ʒ     }    # Filter this list by:
   ,         #  Pair the current value with the input
             #   i.e. 0 and 22 → [0,22]
             #   i.e. 25 and 22 → [25,22]
    b        #  Convert both to binary strings
             #   i.e. [0,22] → ['0','10110']
             #   i.e. [25,22] →  ['10000','11001']
     g      #  Take the length of both
             #   i.e. ['0','10110'] → [1,5]
             #   ['10000','11001'] → [5,5]
       Ë     #  Check if both are equal
             #   i.e. [1,5] → 0 (falsey)
             #   i.e. [5,5] → 1 (truthy)
^            # After we've filtered, Bitwise-XOR each with the input
             #  i.e. [16,25] and 22 → [6,15]
 b           # Convert each to a binary string again
             #  i.e. [6,15] → ['110','1111']
  S         # Change the binary strings to a list of digits
             #  i.e. ['110','1111'] → [['1','1','0'],['1','1','1','1']]
    O        # Take the sum of each
             #  i.e. [['1','1','0'],['1','1','1','1']] → [2,4]
ß            # And then take the lowest value in the list
             #  i.e. [2,4] → 2

1
Được rồi, 15 -terter hợp lệ : Lnʒ‚b€gË}^b€SOß. Tuy nhiên, nó không may phá vỡ bộ kiểm tra của bạn
Ông Xcoder

1
@ Mr.Xcoder Cảm ơn! Và bộ kiểm tra của tôi hầu như luôn bị hỏng sau khi tôi chơi thứ gì đó .. XD Nhưng giờ nó cũng đã được sửa.
Kevin Cruijssen

Tôi đoán tôi không giỏi trong việc viết các bộ kiểm tra trong 05AB1E \ _ () _ /, thật tuyệt khi bạn đã sửa nó :)
Ông Xcoder


3

Gaia , 18 byte

Gần cổng câu trả lời Jelly của tôi .

s¦⟪,b¦l¦y⟫⁇⟪^bΣ⟫¦⌋

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

Phá vỡ

s¦⟪, b¦l¦y⟫⁇ ⟪^ bΣ⟫¦⌋ - Chương trình đầy đủ. Hãy gọi đầu vào là N.
s¦ - Bình phương mỗi số nguyên trong phạm vi [1 ... N].
  ⟫ - Chọn những điều kiện đáp ứng một điều kiện nhất định, khi chạy qua
                     một khối dyadic. Sử dụng một khối dyadic tiết kiệm một byte vì
                     đầu vào, N, được sử dụng hoàn toàn như là một đối số khác.
   , - Ghép phần tử hiện tại và N trong danh sách.
    b¦ - Chuyển đổi chúng thành nhị phân.
      l¦ - Nhận độ dài của chúng.
        y - Sau đó kiểm tra xem chúng có bằng nhau không.
           ⟪⟫¦ - Chạy tất cả các số nguyên hợp lệ thông qua một khối dyadic.
            ^ - XOR mỗi người với N.
             bΣ - Chuyển đổi thành nhị phân và tổng (đếm 1s trong nhị phân)
                 ⌋ - Tối thiểu.

2

Brachylog , 56 41 byte

Nó sẽ không phá vỡ bất kỳ hồ sơ chiều dài nhưng nghĩ rằng tôi sẽ đăng nó

⟨⟨{⟦^₂ᵐḃᵐ}{h∋Q.l~t?∧}ᶠ{ḃl}⟩zḃᶠ⟩{z{∋≠}ᶜ}ᵐ⌋

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


Chỉ cần nhận ra nén là một điều. Tôi sẽ rút ngắn nó sau khi tôi trở về từ quán ăn
Kroppeb

1
@Arnauld Vâng, vấn đề chính là với mỗi i trong phạm vi (0, n + 1) tôi đã tính toán lại phạm vi, bình phương nó và thành nhị phân. Đặt cái này bên ngoài đã thu được thêm một vài byte nhưng giờ nó đã nhanh hơn
Kroppeb

2

lắp ráp x86-64, 37 byte

Mã byte:

53 89 fb 89 f9 0f bd f7 89 c8 f7 e0 70 12 0f bd
d0 39 f2 75 0b 31 f8 f3 0f b8 c0 39 d8 0f 42 d8
e2 e6 93 5b c3

Độc đáo, điều này tính toán ngay cả ví dụ cao nhất trong chưa đầy một giây.

Trái tim của thuật toán là xor / popcount như bình thường.

    push %rbx
    /* we use ebx as our global accumulator, to see what the lowest bit
     * difference is */
    /* it needs to be initialized to something big enough, fortunately the
     * answer will always be less than the initial argument */
    mov %edi,%ebx
    mov %edi,%ecx
    bsr %edi,%esi
.L1:
    mov %ecx,%eax
    mul %eax
    jo cont     /* this square doesn't even fit into eax */
    bsr %eax,%edx
    cmp %esi,%edx
    jnz cont    /* can't invert bits higher than esi */
    xor %edi,%eax
    popcnt %eax,%eax
    cmp %ebx,%eax   /* if eax < ebx */
    cmovb %eax,%ebx
cont:
    loop .L1
    xchg %ebx,%eax
    pop %rbx
    retq

Đề nghị thay thế ít nhất một trong các chiến movs với mộtxchg
ceilingcat

Theo như tôi có thể nói chỉ có một cái sẽ tiết kiệm một byte ( mov %ecx,%eax) và tôi không thể để% ecx chết ở đó.
Ob ObiousNewt


1

Than , 31 byte

NθI⌊EΦEθ↨×ιι²⁼LιL↨θ²ΣE↨責⁼λ§ιμ

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Giải trình:

Nθ                              Input N
       θ                        N
      E                         Map over implicit range
          ιι                    Current value (twice)
         ×                      Multiply
        ↨   ²                   Convert to base 2
     Φ                          Filter over result
               ι                Current value
                  θ             N
                 ↨ ²            Convert to base 2
              L L               Length
             ⁼                  Equals
    E                           Map over result
                       θ        N
                      ↨ ²       Convert to base 2
                     E          Map over digits
                           λ    Current base 2 digit of N
                             ι  Current base 2 value
                              μ Inner index
                            §   Get digit of value
                          ⁼     Equals
                         ¬      Not (i.e. XOR)
                    Σ           Take the sum
   ⌊                            Take the minimum
  I                             Cast to string
                                Implicitly print




1

C (gcc) ,  93  91 byte

g(n){n=n?n%2+g(n/2):0;}m;i;d;f(n){m=99;for(i=0;++i*i<2*n;m=g(d=i*i^n)<m&d<n/2?g(d):m);n=m;}

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


Chỉnh sửa: Tôi nghĩ rằng giải pháp ban đầu của tôi ( Dùng thử trực tuyến! ) Không hợp lệ, vì một trong các biến m, toàn cầu để lưu một vài byte bằng cách không chỉ định loại, đã được khởi tạo bên ngoài f(n)và do đó phải được khởi tạo lại giữa các cuộc gọi


Mã xác nhận và nhận xét:

g(n){n=n?n%2+g(n/2):0;} // returns the number of bits equal to 1 in n
m; //miminum hamming distance between n and a square
i; //counter to browse squares
d; //bitwise difference between n and a square
f(n){m=99; //initialize m to 99 > size of int (in bits)
    for(
        i=0;
        ++i*i<2*n; //get the next square number, stop if it's greater than 2*n
        g(d=i*i^n)<m&&d<n/2&&(m=g(d)) //calculate d and hamming distance
//      ^~~~~~~~~~~^ if the hamming distance is less than the minimum
//                    ^~~~^ and the most significant bit of n did not change (the most significant bit contains at least half the value)
//                           ^~~~~~~^ then update m
       );
    n=m;} // output m

Chỉnh sửa:

  • Đã lưu 2 byte nhờ vào trần nhà
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.