Sự kết hợp giữa các chuỗi nhị phân và các cặp của chúng


8

Đầu vào : Một hoặc hai chuỗi '0' và '1'. Nếu có 2, chúng được phân cách bằng một khoảng trắng. Tất cả các chuỗi có độ dài ít nhất 1.

Đầu ra : Nếu một chuỗi là đầu vào, 2 là đầu ra. Nếu 2 là đầu vào, 1 là đầu ra. Các chuỗi đầu ra có thể là bất cứ thứ gì bạn thích, nhưng nếu chạy chương trình của bạn với đầu vào A cung cấp cho bạn B, thì việc chạy nó với B phải cung cấp cho A (nếu nhập vào 111 11cho 00000thì 00000phải nhập 111 11).

Điều đó có nghĩa là nếu bạn đặt chương trình của mình vào chính nó, bạn sẽ lấy lại bất cứ thứ gì bạn nhập vào. Nếu chương trình của bạn được gọi là foo, bạn có thể kiểm tra như thế này:

>echo 101 101|foo|foo
101 101

Để ngăn chặn việc sử dụng các kỹ thuật vũ phu, mã của bạn sẽ có thể chạy với chuỗi 1000 chữ số trong vòng dưới 10 giây. Giải pháp python của tôi cho việc này chỉ mất chưa đến 1 giây trên chuỗi 10.000 chữ số, vì vậy đây không phải là vấn đề.

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

Câu trả lời:


3

Con trăn, 183

Đồ lót được lưu trữ trên đĩa.

x=raw_input()
try:d=eval(open('d').read())
except:d={'':'','1 ':'1 '}
t='1 '*not' 'in x
if x not in d:
 while t in d:t+=`(id(t)/9)%2`
 d[t]=x;d[x]=t
 open(*'dw').write(`d`)
print d[x]

chỉnh sửa: Rất tiếc, có vẻ như đây không phải là câu trả lời thông minh đầu tiên. Của tôi nhất quán giữa các lần chạy!


Bạn có thể thay thế if x not in d:bằng if(x in d)-1:và lưu một byte.
Jonathan Frech

2

Con trăn, 326

s=lambda i,l:bin(i)[2:].zfill(l)
f=lambda n:2**n*(n-3)+4
g=lambda n:2**n-2
i=raw_input()
if' 'in i:
 a,b=i.split();n=len(a+b);r=f(n)+int(a+b,2)*(n-1)+len(a)-1;l=1
 while g(l+1)<=r:l+=1
 print s(r-g(l),l)
else:
 n=len(i);r=g(n)+int(i,2);l=2
 while f(l+1)<=r:l+=1
 r-=f(l);p=r%(l-1)+1;w=s(r/(l-1),l);print w[:p],w[p:]

Ví dụ đầu vào / đầu ra:

     input | output
-----------+-----------
         0 | 0 0
       0 0 | 0
     10 10 | 10101
     10101 | 10 10
0000000000 | 101 0100
  101 0100 | 0000000000

2

Perl 5, 197 ký tự

sub n{'0'x$_[0].sprintf'%b',$_[1]}sub N{/0*(?=.)/;length$&,oct"0b$'"}$_=<>;print/ /?n map{($a,$b)=N;($a+$b)*($a+$b+1)/2+$b}split:"@{[map{$w=int((sqrt(8*$_+1)-1)/2);$y=$_-($w*$w+$w)/2;n$w-$y,$y}N]}"

Với một số ngắt dòng:

sub n{'0'x$_[0].sprintf'%b',$_[1]}
sub N{/0*(?=.)/;length$&,oct"0b$'"}
$_=<>;print/ /?n map{
  ($a,$b)=N;($a+$b)*($a+$b+1)/2+$b
}split:"@{[map{
  $w=int((sqrt(8*$_+1)-1)/2);$y=$_-($w*$w+$w)/2;n$w-$y,$y
}N]}"

Chương trình này hoạt động bằng cách soạn hai phần:

  • Một cặp số tự nhiên có thể được ánh xạ thành một chuỗi nhị phân bằng cách chuyển đổi một số thành số cơ sở 2 và số còn lại thành các số 0 đứng đầu. nlà hàm này và Nlà nghịch đảo của nó (ngoại trừ Nsử dụng $_làm tham số của nó).

  • Một cặp số tự nhiên có thể được ánh xạ thành một số tự nhiên duy nhất bằng cách sử dụng chức năng ghép cặp Cantor . Khối đầu tiên maplà chức năng này và khối thứ hai là nghịch đảo.

Do đó, hai chuỗi nhị phân được chia thành bốn số, kết hợp thành hai số và sau đó kết hợp thành một chuỗi nhị phân - hoặc ngược lại.

Đã thử nghiệm trên 100 đầu vào ngẫu nhiên của từng loại với chuỗi dài tối đa 8 ký hiệu. Tôi đã tìm ra nhiều cách để làm cho nó ngắn hơn một chút, nhưng tôi sẽ dừng lại và đăng nó. Nếu có chỗ để tối ưu hóa hơn nữa, có lẽ đó là trong các biểu thức số học.


Đầu vào của 1111111111111111111111111111111111111111111111111111111111111111(64 1giây) dường như bị sập, và đầu vào của cặp 0và 50 1giây cho kết quả tương tự như 0và 51 1giây, cả hai đều xuất ra 64 1giây. Tôi nghĩ rằng có một số loại tràn với số lượng 0s hàng đầu , vì vậy một giải pháp có thể là lấy Ngiá trị đầu ra từ một cặp Ngiá trị đầu vào Cantor và ngiá trị từ một cặp ngiá trị (hoặc ngược lại cho nghịch đảo). Tôi là một người không biết gì cả, vì vậy tôi có thể đã làm sai điều gì đó.
tông_box

Có, chương trình này sẽ không hoạt động đối với các chuỗi nhị phân có phần chứa 1 quá lớn để Perl hoạt động với tư cách là số nguyên. Tôi cảm thấy đó là một giới hạn thực hiện hợp lý để đổi lấy sự thanh lịch của thuật toán. Về nguyên tắc, tất cả các hoạt động số có thể được thay thế bằng các hoạt động lớn.
Kevin Reid

1

Perl, 56 ký tự

đã thêm +1 char cho -pchuyển đổi dòng lệnh

$s.=1;$h{$h{$_}||=(split>1?$s:"$s $s").$/}=$_;$_=$h{$_}

Có lẽ tôi đã không đủ rõ ràng. Tôi muốn chương trình của bạn lấy một số đầu vào, in một số đầu ra, và sau đó chấm dứt. Sau đó chạy lại chương trình với đầu ra là đầu vào sẽ trả lại những gì bạn nhập đầu tiên.
tông_box

@cardboard_box ánh xạ nên tồn tại giữa nhiều lần chạy? bạn thực sự nên thêm nó vào mô tả vấn đề
ardew

0

Con trăn, 394

Tôi chắc chắn rằng điều này có thể được chơi gôn hơn nữa, nhưng khối đá nguyên khối này sử dụng Chức năng ghép nối Cantor và nghịch đảo của nó.

import math
s=lambda n:n*(n+1)/2
p=lambda a:'0'*a[0]+bin(a[1])[2:]
q=lambda t:t.index('1')
B=raw_input().split()
def f(x,y):r=x+y+1;return s(r)-[y,x][r%2]-1
def g(z):r=int(math.ceil((2*(z+1)+1/4.)**(1/2.)-1/2.))-1;d=s(r+1)-z-1;return [(d,r-d),(r-d,d)][r%2]
if len(B)<2:a=[g(q(B[0])),g(int(B[0],2))];print p(a[0])+' '+p(a[1])
else:print p([f(q(B[0]),int(B[0],2)),f(q(B[1]),int(B[1],2))])

Giải trình

Có một liên kết tự nhiên giữa một chuỗi nhị phân và một cặp số tự nhiên: số thứ nhất của hình ảnh là số không đứng đầu và số thứ hai là giá trị nguyên của số nhị phân. Biết rằng chúng ta có:

S ~ N^2

và với trang phục Cantor

N ~ N^2

vì thế:

S ~ N^2 ~ N^4 ~ S^2

S ~ S^2

Trong đó S được đặt của tất cả các chuỗi nhị phân. Giải pháp này thực hiện các mệnh đề giữa S và S ^ 2.


Chỉ cần lưu ý rằng điều này không thành công trên bất kỳ đầu vào nào là 0, tôi sẽ sửa nó vào ngày mai, tôi cảm thấy mệt mỏi với con trăn ngay bây giờ -_-
scleaver
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.