Số nhị phân ngắn nhất trong phạm vi


8

Với hai tùy tiện chính xác thập phân số 0 ≤ x < y ≤ 1, tính toán (trong chữ số) ngắn nhị phân số bxb < y .

Xuất các chữ số nhị phân của b sau điểm nhị phân dưới dạng một mảng hoặc một chuỗi các số 0 và một. Lưu ý rằng mảng trống có nghĩa là 0,0, nhờ vào việc xóa các số 0 ở cuối. Điều này cũng đảm bảo rằng có một câu trả lời đúng duy nhất cho bất kỳ phạm vi nào.

Nếu bạn không quen thuộc với các số phân số nhị phân, chúng hoạt động giống như các số thập phân:

Base 10   0.625 = 0.6 + 0.02 + 0.005 = 6 x 10^-1  +  2 x 10^-2  +  5 x 10^-3
Base  2   0.101 = 0.1 + 0.00 + 0.001 = 1 x  2^-1  +  0 x  2^-2  +  1 x  2^-3
                                          |             |             |
                                          v             v             v
Base 10                        0.625 =   0.5      +     0       +   0.125

Được xây dựng mà tầm thường hóa vấn đề này không được phép.

Ví dụ:

0.0, 1.0 -> ""
0.1, 1.0 -> "1"
0.5, 0.6 -> "1"
0.4, 0.5 -> "0111"

Mã ngắn nhất sẽ thắng.


3
"Chính xác tùy ý" có nghĩa là "trong giới hạn loại ngôn ngữ của bạn", hay chúng ta phải hỗ trợ đầu vào (0.98983459823945792125172638374187268447126843298479182647, 0.98983459823945792125172638374187268447126843298479182648)? Ngoài ra, các trường hợp thử nghiệm sẽ hữu ích.
Doorknob

@Doorknob Chính xác một cách tùy tiện có nghĩa là câu trả lời của bạn sẽ hoạt động cho mọi đầu vào, đến giới hạn của máy vật lý (bộ nhớ). Vì vậy, có, đầu vào đó phải được hỗ trợ.
orlp


@ MartinBüttner Rất gần (không biết về nó), nhưng câu hỏi này đòi hỏi độ chính xác và đầu ra tùy ý dưới dạng bit.
orlp

1
Aaaah khoảng thời gian nửa mở nửa trên x y b <y rất khó đối phó, sẽ dễ dàng hơn nhiều với x <b ≤ y.
xnor

Câu trả lời:


2

CJam, 46

q'.-_,:M;S/{3a.+M'0e]~GM#*AM(#/(2b}/_@.=0#)<2>

Dùng thử trực tuyến

Giải trình:

Ý tưởng chung là: nhân cả hai số với 10 số mũ đủ lớn để lấy số nguyên, nhân lại với 2 số mũ đủ lớn khác để "tạo khoảng trống" cho các chữ số nhị phân ở dạng số nguyên, chia số nguyên cho 10 số mũ đầu tiên , giảm số nguyên số (để đến trường hợp "x <b ≤ y") và chuyển đổi kết quả sang cơ sở 2. Tìm chữ số khác nhau đầu tiên (nó sẽ là 0 trong số thứ nhất và 1 trong số thứ hai) và in tất cả các chữ số từ số thứ hai lên đến và bao gồm số đó.

Trước khi bắt đầu với phép nhân, tôi thêm 3 vào các phần nguyên để đảm bảo rằng kết quả có cùng số chữ số nhị phân (không có số 0 đứng đầu) sau khi giảm. Cuối cùng, tôi bỏ qua 2 chữ số nhị phân đầu tiên để bù.

q          read the input as a string
'.-        remove the dots
_,         duplicate and get the string length
:M;        store in M and pop; M-1 will be the first exponent
S/         split by space
{…}/       for each number (in string form)
  3a.+     add 3 to the first digit (vectorized-add [3] to the string)
  M'0e]    pad to the right with '0's up to length M
            this is like multiplying the decimal number with 10^(M-1)
            but done as a string operation
  ~        evaluate the result as an integer
  GM#*     multiply by 16^M (G=16) = 2^(4*M) -- 4*M is the second exponent
  AM(#/    divide by 10^(M-1) (A=10)
  (2b      decrement and convert to base 2 (array of digits)
_          duplicate the 2nd array
@          bring the first array to the top
.=         vectorized-compare the arrays (digit by digit)
0#         find the position of the first 0 (meaning digits are not equal)
)<         increment and slice the other copy of the 2nd array before that position
2>         discard the first 2 digits

2

Ruby, 138 132 byte

->x,y{d,*a=->{a.map.with_index{|n,i|n/BigDecimal.new(2)**(i+1)}.inject(:+)||0};[a+=[1],a[-1]=d[]>=y ?0:1]while d[]<x;a}

13 byte được thêm cho -rbigdecimalcờ. Dự kiến ​​đầu vào là hai BigDecimals.

Chạy mẫu:

irb(main):029:0> f=->x,y{d,*a=->{a.map.with_index{|n,i|n/BigDecimal.new(2)**(i+1)}.inject(:+)||0};[a+=[1],a[-1]=d[]>=y ?0:1]while d[]<x;a}
=> #<Proc:0x00000001053a10@(irb):29 (lambda)>
irb(main):030:0> f[BigDecimal.new('0.98983459823945792125172638374187268447126843298479182647'),BigDecimal.new('0.98983459823945792125172638374187268447126843298479182648')]
=> [1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1]

Giải trình:

->x,y{
d,*a=   # sets d to the following, and a to [] with fancy splat operator
->{     # lambda...
 a.map.with_index{|n,i|       # map over a with indices
  n/BigDecimal.new(2)**(i+1)  # this will return:
                              #  - 0 [ /2**(i+1) ] if n is 0
                              #  - 1   /2**(i+1)   if n is 1
 }.inject(:+)                 # sum
 ||0                          # inject returns nil on empty array; replace with 0
};      # this lambda turns `[0, 1, 1]' into `BigDecimal(0b0.011)'
[       # `[...]while x' is a fancy/golfy way to say `while x;...;end'
 a+=[1],            # add a digit 1 to the array
 a[-1]=d[]>=y ?0:1  # replace it with 0 if we exceeded upper bound
]while d[]<x;       # do this while(below the lower bound)
a       # return the array of digits
}

2

Toán học, 72 byte

IntegerDigits[#2[[-1,-1]],2,Log2@#]&@@Reap[1//.a_/;Sow@⌈a#⌉>=a#2:>2a]&

Giải trình

Phương pháp là tìm hệ số nhân nhỏ nhất của biểu mẫu 2^nmở rộng khoảng cách giữa hai số đầu vào để nó chứa một số nguyên.

Ví dụ, 16*{0.4,0.5} = {6.4,8.}có chứa 7, vì vậy câu trả lời là 7/16.

Trường hợp thử nghiệm

%[0.4,0.5]
(* {0,1,1,1} *)

Nice và gieo hạt!
Một Simmons

0

JavaScript (ES6), 144 byte

f=(x,y,b='',d=s=>s.replace(/\d/g,(n,i)=>(i&&n*2%10)+(s[i+1+!i]>4)).replace(/[.0]+$/,''),n=d(x),m=d(y))=>n?n>'1'||(m||2)<='1'?f(n,m,b+n[0]):b+1:b

Giả sử đầu vào ở dạng 0.<digits>(hoặc 1.<zeros>được chấp nhận cho y). dlà một hàm lấy phần thập phân của một số và nhân đôi nó, sau đó cắt các số 0 ở cuối. Chữ số hàng đầu phải có mặt nhưng nó bị bỏ qua. Thuận tiện d("0.0")là trống rỗng, và do đó điều này được sử dụng như một thử nghiệm để xem liệu đó có phải xlà một phần nhị phân chính xác hay không; trong trường hợp này bđã giữ kết quả. Mặt khác, có một thử nghiệm hơi phức tạp để xác định xem có phải là một 1để bphục vụ để phân biệt giữa xy; nếu vậy được trả lại. Mặt khác, MSB của xhậu tố được kết hợp với hàm và hàm tự gọi đệ quy để xử lý bit tiếp theo.

Nếu thay vào đó, chúng ta mong muốn x < b ≤ ychức năng đơn giản hơn nhiều, một cái gì đó như thế này (chưa được kiểm tra):

f=(x,y,b='',d=s=>s.replace(/\d/g,(n,i)=>(i&&n*2%10)+(s[i+1+!i]>4)),n=d(x),m=d(y))=>n>='1'||m<'1'?f(n,m,b+n[0]):b+1
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.