Sự tương ứng một-một giữa các cặp số nguyên và số nguyên dương


8

Người ta biết rằng có các tương ứng một-một giữa các cặp số nguyên và số nguyên dương. Nhiệm vụ của bạn là viết mã xác định sự tương ứng như vậy (bằng cách xác định một cặp hàm / chương trình là nghịch đảo của nhau) bằng ngôn ngữ lập trình bạn chọn, cộng với kiểm tra tính chính xác (xem bên dưới) với số byte nhỏ nhất cho sự tương ứng định nghĩa (không tính đến tính chính xác).

Giải pháp phải bao gồm:

  • định nghĩa của hàm / chương trình f có hai đối số nguyên và trả về một số nguyên (đó là một hướng của mệnh đề).

  • hoặc định nghĩa của hàm / chương trình g có một đối số nguyên và trả về một cặp số nguyên (có thể là một mảng, một danh sách, nối hai số nguyên cách nhau bởi một số ...) hoặc hai hàm / chương trình a và b có một đối số nguyên và trả về một số nguyên (đó là hướng khác).

  • một đoạn mã bổ sung kiểm tra rằng đối với f và g (hoặc f và a, b) bạn đã xác định ở trên, bạn có g (f (x, y)) = (x, y) (hoặc a (f (x, y) ) = x và b (f (x, y)) = y) cho mọi số nguyên x, y trong phạm vi -100 <x <100, -100 <y <100. Lưu ý rằng f và g phải hoạt động cho các giá trị bên ngoài của phạm vi này là tốt.

Bạn có thể đổi tên a, b, f hoặc g tất nhiên. Hai giải pháp không phải được viết bằng cùng một ngôn ngữ.

Dưới đây là một giải pháp không tối ưu ở tất cả trong PARI / GP, với 597 ký tự cho các định nghĩa hàm.

plane_to_line(x,y)={
my(ax,ay,z);
ax=abs(x);
ay=abs(y);
if((ax<=ay)*(y<0),        z=4*y*y-2*y+x+2;);
if((ax<=ay)*(y>=0),       z=4*y*y-2*y-x+2;);
if((ay<=ax)*(x<0),        z=4*x*x    -y+2;);
if((ay<=ax)*(x>=0)*(y<0), z=4*x*x+4*x+y+2;);
if((ay<=ax)*(x>=0)*(y>=0),z=4*x*x-4*x+y+2;);
if((x==0)*(y==0),z=1;);
return(z);
}


line_to_plane(z)={
my(l,d,x,y);
l=floor((1+sqrt(z-1))/2);
d=z-(4*l*l-4*l+2);
if(d<=l,x=l;y=d;);
if((l<d)*(d<=3*l),x=2*l-d;y=l;);
if((3*l<d)*(d<=5*l),x=(-l);y=4*l-d;);
if((5*l<d)*(d<=7*l),x=d-6*l;y=(-l););
if((7*l<d)*(d<8*l) ,x=l;y=d-8*l;);
if(z==1,x=0;y=0;);
return([x,y]);
}

và mã kiểm tra tính chính xác:

accu=List([])
m=100;
for(x=-m,m,for(y=-m,m,if(line_to_plane(plane_to_line(x,y))!=[x,y],\
listput(accu,[x,y]);)))
Vec(accu)

1
Chúng tôi đã thực hiện phần thứ hai của vấn đề này nhưng tôi đoán rằng thực tế là cả hai chức năng cần phải nghịch đảo lẫn nhau có thể là tương tác đủ để biện minh cho một thách thức đa phần .
Martin Ender

@ MartinBüttner Tôi không chắc chắn hoạt động đa phần độc lập. Một phần của thử thách là chọn mã hóa cung cấp cho bạn các hàm ngắn nhất.
Cấp sông St

1
Chúng tôi có thể chỉ cung cấp một chương trình có thể được gọi là cả hai cách không?
Gây tử vong vào

1
@EwanDelanoy Tôi nghĩ Fatalize đã đề nghị đếm chương trình chỉ có thể làm cả hai việc một lần.
Martin Ender

2
@LevelRiverSt Để bổ sung cho nhận xét của Katenkyo, lý do Z^nlà viết tắt của n-tuples là toán tử bị bỏ qua không phải là phép nhân (cặp đôi) mà là sản phẩm của Cartesian. Z^2 = ZxZ.
Martin Ender

Câu trả lời:


7

MATL , 43 36 byte

Điều này sử dụng hàm spiral( 1YL), tạo ra một mảng 2D vuông có kích thước nhất định với các giá trị được sắp xếp theo hình xoắn ốc ra bên ngoài. Ví dụ, với đầu vào, 7nó tạo ra

43 44 45 46 47 48 49
42 21 22 23 24 25 26
41 20  7  8  9 10 27
40 19  6  1  2 11 28
39 18  5  4  3 12 29
38 17 16 15 14 13 30
37 36 35 34 33 32 31

Trung tâm của mảng, chứa 1, tương ứng với bộ dữ liệu [0 0]. Góc trên bên trái tương ứng với [-3 -3]vv Vì vậy, ví dụ f (-3, -3) sẽ là 43 và g (43) sẽ là [-3 -3].

Mã tạo ra một mảng 2D với ma trận xoắn ốc này, lớn đến mức cần thiết để thực hiện chuyển đổi. Lưu ý rằng kích thước lớn hơn luôn cho kết quả tương tự đối với các mục đã được bao gồm trong kích thước nhỏ hơn.

Từ Z 2 đến N (18 byte):

|X>tEQ1YLGb+QZ}3$)

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

|X>   % input is a 2-tuple. Take maximum of absolute values
tEQ   % duplicate. Multiply by 2 and increase by 1. This gives necessary size of spiral
1YL   % generate spiral
G     % push input 2-tuple again
b+Q   % bubble up, add, increase by 1. This makes the center correspont to [0 0]
Z}    % split tuple into its values
3$)   % use those two value as indices into the spiral array to obtain result

Từ N đến Z 2 ( 25 18 byte)

Eqt1YLG=2#fhw2/k-q

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

Eq      % input is a number. Multiply by 2, add 1. This assures size is enough and odd
t1YL    % duplicate. Generate spiral of that size
G=      % compare each entry with the input value
2#fh    % 2-tuple of row and column indices of matching entry
w2/k-q  % swap. Offset values so that center corresponds to [0 0]

Đoạn trích để kiểm tra

Lưu ý rằng Gcần phải được sửa đổi để phù hợp với thực tế là chúng ta không có một đầu vào duy nhất. Mã chậm, vì vậy liên kết chỉ kiểm tra các bộ dữ liệu với các giá trị từ -9 đến 9. Đối với -99 đến 99 chỉ cần thay thế dòng đầu tiên.

Mã kiểm tra từng bộ với các giá trị trong phạm vi được xác định. Nó thực hiện chuyển đổi thành một số, sau đó từ số đó trở lại một tuple, và sau đó kiểm tra xem bộ dữ liệu gốc và bộ thu hồi có bằng nhau không. Tất cả các kết quả nên được 1, chỉ ra rằng tất cả các so sánh đưa ra true.

Phải mất một lúc để chạy.

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

-9:9                     % Or use -99:99. But it takes long
HZ^!"@                   % Cartesian power: gives tuples [-9 -9] ... [9 9].
                         % For each such tuple
|X>tEQ1YL@b+QZ}3$)       % Code from Z^2 to N with `G` replaced by `@` (current tuple)
XJ                       % Copy result into clipboard J
Eqt1YLJ=2#fhw2/k-q       % Code from N to Z^2 with `G` replaced by `J`
@!X=                     % Compare original tuple with recovered tuple: are they equal?

4

JavaScript (ES6), 171 byte

(x,y)=>(h=x=>parseInt((x^x>>31).toString(2)+(x>>>31),4),h(x)*2+h(y))
x=>(h=x=>parseInt(x.toString(2).replace(/.(?!(..)*$)/g,''),2),i=x=>x<<31>>31^x>>>1,[i(h(x>>>1)),i(h(x))])

Bit twiddling: số âm có bit của chúng bị lật; mỗi số nguyên sau đó được nhân đôi và thêm 1 nếu nó ban đầu là âm; các bit từ các số nguyên sau đó được xen kẽ. Thao tác ngược sẽ xóa các bit thay thế, chia cho 2 và lật tất cả các bit nếu giá trị âm. Tôi có thể lưu 3 byte bằng cách giới hạn bản thân ở các giá trị 15 bit thay vì giá trị 16 bit.


3

Thạch, 50 48 46 45 43 40 39 byte

Mặt phẳng tới dòng ( 18 17 16 byte ):

AḤ_<0$
+RS+
,Ñç/

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

Đường thẳng đến mặt phẳng ( 32 30 29 27 24 23 byte ):

HĊN⁸¡
³R‘R’U⁹¡F³ịÇ
ç1,¢

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

Giải trình:

Tôi sẽ chỉ giải thích plane to line, bởi vì line to planenó chỉ là đối diện của nó.

Đầu tiên, chúng ta chuyển đổi mỗi số nguyên thành một số tự nhiên, theo hàm f(x) = 2*|x| - (x<0).

Sau đó, chúng ta chuyển đổi hai số tự nhiên thành hai số tự nhiên khác, theo hàm g(x,y) = (x+y,y).

Cuối cùng, chúng ta chuyển đổi chúng thành một số tự nhiên, theo hàm h(x,y) = (x+1)C2 + y


@LuisMendo Có, và bây giờ đầu vào của các liên kết thử trực tuyến là7
Leaky Nun

Điều này có vẻ tốt hơn :-) Tôi giả sử bạn đang làm việc trên đoạn kiểm tra
Luis Mendo

@LuisMendo Đoạn kiểm tra có được tính vào điểm số không?
Leaky Nun

Không, thách thức nói rằng không xem xét tính chính xác
Luis Mendo
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.