Bounce-modulo hai số


12

Đồ thị của phép toán modulo ( ) trông như thế này:y=xmodk

Đồ thị của hàm modulo

Đây là một chức năng rất hữu ích, vì nó cho phép chúng ta tạo ra hành vi "gói". Tuy nhiên, nó rất cồng kềnh khi tôi muốn sử dụng nó để tạo ra vẻ ngoài "nảy" giữa hai bức tường. Biểu đồ của hàm "nảy" ( ) trông như thế này:y=bounce(x,k)

Đồ thị của hàm "nảy-modulo"

Chu kỳ của đồ thị k . Chu kỳ của đồ thị y = nảy ( x , k ) 2 k , vì nó di chuyển lên trên chođơn vị k , và sau đó di chuyển xuống dưới chođơn vị k khác, trước khi quay lại nơi bắt đầu. Đối với cả hai hàm, giá trị tối thiểu của y là 0 và tối đa là k (Trên thực tế, đối với hàm mô đun có đầu vào tích phân, nó là k - 1 ). Ngoài ra, đối với cả hai hàm, giá trị trong đó x = 0 là 0.y=xmodkky=bounce(x,k)2kkkykk1x=0

Các thách thức

Cho một số nguyên và một số nguyên dương k , trả về một xấp xỉ số nguyên hoặc dấu phẩy động của y = nảy ( x , k ) .xky=bounce(x,k)

Đây là , vì vậy bài nộp hợp lệ ngắn nhất (tính bằng byte) sẽ thắng.

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

  x,  k -> bounce(x, k)
  0, 14 ->            0
  3,  7 ->            3
 14, 14 ->           14
 15, 14 ->           13
-13, 14 ->           13 (12.999997 etc would be an acceptable answer)
-14, 14 ->           14
191,  8 ->            1
192,  8 ->            0

Điểm thưởng cho một Fourier dựa trên cách tiếp cận trong Fourier .


" Đối với cả hai hàm, giá trị tối thiểu của x là 0 và tối đa là k " hoàn toàn sai.
Peter Taylor

@PeterTaylor Rất tiếc. Tôi có nghĩa là kết quả.
Trái cây Esolanging

1
Rất tiếc, đó là những gì tôi nghĩ nó đã nói. Nó vẫn sai. k % k = 0
Peter Taylor

@PeterTaylor Ồ, tôi hiểu câu hỏi của bạn. Ban đầu tôi đã thiết kế điều này với ý tưởng nổi, sau đó chuyển sang chỉ ints sau. Sẽ chỉnh sửa.
Trái cây Esolanging

1
@PeterTaylor Nếu các đối số là float, thì mức tối đa là một số tùy ý gần với k.
Trái cây Esolanging

Câu trả lời:


7

Mã máy x86-64, 18 byte

97
99
31 D0
29 D0
99
F7 FE
29 D6
A8 01
0F 45 D6
92
C3 

Mã này xác định một hàm trong ngôn ngữ máy x86-64 tính toán bounce(x, k). Theo quy ước gọi AMD V của Hệ thống V được sử dụng trên các hệ thống Gnu / Unix, xtham số được truyền vào thanh EDIghi, trong khi ktham số được truyền trong thanh ESIghi. Như với tất cả các quy ước gọi x86, kết quả được trả về trong thanh EAXghi.

Để gọi nó từ C, bạn sẽ tạo nguyên mẫu như sau:

int Bounce(int x, int k);

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

Ma thuật lắp ráp bất khả xâm phạm:

; Take absolute value of input 'x' (passed in EDI register).
; (Compensates for the fact that IDIV on x86 returns a remainder with the dividend's sign,
; whereas we want 'modulo' behavior---the result should be positive.)
xchg   eax, edi      ; swap EDI and EAX (put 'x' in EAX)
cdq                  ; sign-extend EAX to EDX:EAX, effectively putting sign bit in EDX
xor    eax, edx      ; EAX ^= EDX
sub    eax, edx      ; EAX -= EDX

; Divide EDX:EAX by 'k' (passed in ESI register).
; The quotient will be in EAX, and the remainder will be in EDX.
; (We know that EAX is positive here, so we'd normally just zero EDX before division,
; but XOR is 2 bytes whereas CDQ is 1 byte, so it wins out.)
cdq
idiv   esi

; Pre-emptively subtract the remainder (EDX) from 'k' (ESI),
; leaving result in ESI. We'll either use this below, or ignore it.
sub    esi, edx

; Test the LSB of the quotient to see if it is an even number (i.e., divisible by 2).
; If not (quotient is odd), then we want to use ESI, so put it in EDX.
; Otherwise (quotient is even), leave EDX alone.
test   al, 1
cmovnz edx, esi

; Finally, swap EDX and EAX to get the return value in EAX.
xchg   eax, edx
ret

Lưu ý rằng phần đầu tiên (có giá trị tuyệt đối) có thể được viết tương đương:

; Alternative implementation of absolute value
xchg    eax, edi
neg     eax
cmovl   eax, edi

đó là cùng một số byte (6). Hiệu suất phải tương tự nhau, có lẽ nhanh hơn một chút (ngoại trừ một số chip Intel nhất định, trong đó các bước di chuyển có điều kiện chậm ).

XCHGtất nhiên là tương đối chậm và sẽ không được ưa thích hơn MOVngoại trừ trong việc chơi golf mã (trước đây là 1 byte khi một trong các toán hạng là bộ tích lũy, trong khi thanh ghi đăng ký MOVluôn là 2 byte).


6

Thạch , 3 byte

æ%A

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

Được xây dựng ftw.

Giải trình

æ%là một tích hợp hữu ích ở đây. Tôi không biết làm thế nào để mô tả nó, vì vậy tôi sẽ chỉ cung cấp đầu ra cho một số đầu vào:

Như xđi từ 0vô tận, xæ%4đi đến 0,1,2,3,4,(-3,-2,-1,0,1,2,3,4,)nơi phần trong ngoặc được lặp lại đến vô cùng theo cả hai cách.




3

Ruby, 40 byte 32 byte

b=->(x,k){(x/k+1)%2>0?x%k:k-x%k}

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

Giải trình

Xin chào, đây là câu trả lời đầu tiên của tôi trên trang web này! Mã này dựa trên quan sát rằng hàm nảy hoạt động chính xác như modulo khi ( n -1) k <= x < nk và n là số lẻ và hoạt động như một phép toán modulo đảo ngược khi n chẵn. (x/k+1)là số nguyên nhỏ nhất lớn hơn x / k (là x / k +1 được làm tròn xuống một số nguyên). Do đó, (x/k+1)tìm thấy n được đề cập ở trên. %2>0kiểm tra xem n là số lẻ hay số chẵn Nếu n mod 2> 0, thì n là số lẻ. Nếu nmod 2 = 0, thì n chẵn. Nếu n là số lẻ thì hàm nảy phải bằng x mod k . Nếu n chẵn, hàm nảy phải ngược lại, bằng k - x mod k . Toàn bộ biểu thức (x/k+1)%2>0?x%k:k-x%ktìm thấy n , sau đó thực hiện x mod k nếu nó là số lẻ và thực thi k - x mod k nếu không.

Câu trả lời đã được cải thiện dựa trên một gợi ý từ Cyoce .


Bạn có thể chuyển đổi nó thành lambda. Thay vì def b(x,k) ... endsử dụng->x,k{...}
Cyoce

Và vì bạn đang làm việc với số nguyên, .to_ikhông cần thiết.
Cyoce



1

J, 25 byte

Dấu:

Đây chỉ là modulo thông thường trên các số bậc thang. Ví dụ: trong trường hợp 5:0 1 2 3 4 5 4 3 2 1

Đây là một giải pháp (chưa được chơi tốt) trong J. Sẽ cố gắng cải thiện vào ngày mai:

[ ((|~ #) { ]) (i.@>:,}:@i.@-) @ ]

nén: [((|~#){])(i.@>:,}:@i.@-)@]

nén2: [((|~#){])(<:|.|@}.@i:)@]

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


Tôi cảm thấy như i:có thể được sử dụng ở đây, nhưng tôi chưa thử một giải pháp nào
Conor O'Brien

@ ConorO'Brien kiểm tra phiên bản nén2 của tôi, nó tiết kiệm một vài byte bằng cách sử dụng i:. Chỉ cần không có thời gian để cập nhật cái chính và đưa ra lời giải thích. Tôi hy vọng một chuyên gia có thể loại bỏ ít nhất 4 hoặc 5 byte nữa ...
Jonah

((|~#){])]-|@}:@i:18 byte
dặm

@miles xinh đẹp, tyvm
Jonah

1

QBIC , 25 30 27 byte

g=abs(:%:)~a'\`b%2|?b-g\?g

Đã làm một chút tái cấu trúc ...

Giải trình

g=abs(   )  let g be the absolute value of 
       %    the (regular) modulo between
      : :   input a read from cmd line, and input b read from cmd line
~a \ b%2    IF the int division of A and B mod 2 (ie parity test) yields ODD
  ' `         (int divisions need to be passed to QBasic as code literals, or ELSE...)
|?b-g       THEN print bouncy mod
\?g         ELSE print regular mod

QBIC có làm điều gì đó khác biệt cho các hoạt động MOD so với các triển khai Cơ bản khác không? Các vấn đề cơ bản khác trả lại MOD có cùng dấu với cổ tức; điều đó sẽ thất bại khi xlà -13 và klà 14.
Cody Gray

@CodyGray Không, nó đã cho -13. Đã sửa bây giờ.
steenbergh

Bạn không cần abscả hai lần?
Neil

@Neil bạn có một testcase cho điều đó?
steenbergh

@Neil nvm, tôi đã sửa nó bằng cách tái cấu trúc toàn bộ.
steenbergh

1

C89, 40 byte

t;f(x,k){t=abs(x%k);return x/k%2?k-t:t;}

Cổng AC của câu trả lời mã máy x86 của tôi , điều này xác định một hàm, ftính toán độ nảy cho các tham số xk .

Nó sử dụng quy tắc ngầm định của C89, sao cho cả hai tham số, biến toàn cục tvà giá trị trả về của hàm đều là kiểu ngầm int. Biến toàn cụct chỉ được sử dụng để giữ một giá trị tạm thời, kết thúc việc lưu byte, so với việc lặp lại tính toán ở hai bên của toán tử điều kiện.

Các abschức năng (giá trị tuyệt đối) được cung cấp trong <stdlib.h>tiêu đề, nhưng chúng tôi không cần phải bao gồm nó ở đây, một lần nữa nhờ vào quy tắc ngầm-int C89 của (nơi hàm được ngầm tuyên bố và giả định trở lại int).

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

Phiên bản bị đánh cắp:

#include <stdlib.h>

int Bounce(int x, int k)
{
    int mod = abs(x % k);
    return (x/k % 2) ? k-mod : mod;
}

Nhìn vào điều này dưới ánh sáng của mã máy được điều chỉnh bằng tay của tôi , trình biên dịch thực sự tạo ra đầu ra khá tốt cho việc này. Ý tôi là, họ nên; đó là một chức năng khá đơn giản để tối ưu hóa! Tuy nhiên, tôi đã phát hiện ra một lỗi nhỏ trong trình tối ưu hóa x86-64 của GCC , nơi nó tò mò tạo ra mã lớn hơn khi bạn bảo nó tối ưu hóa kích thước và mã nhỏ hơn khi bạn bảo nó tối ưu hóa tốc độ .


m;f(x,k){m=abs(x%k);x=x/k%2?k-m:m;}ngắn hơn
Kritixi Lithos

Ngoại trừ việc nó không thực sự trả về một giá trị, @cows, ngoại trừ trong một số trường hợp không xác định rõ ràng do sự giải thích của trình tạo mã GCC trên các mục tiêu x86. Đó là một mẫu mà tôi thấy mọi người sử dụng ở đây, nhưng nó không hoạt động đối với tôi, bất kể việc rút rác ngẫu nhiên ra khỏi ngăn xếp là câu trả lời chính xác.
Cody Grey

1

Haskell, 37 byte

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

(!)=mod;x#k|odd$x`div`k=k-x!k|1<2=x!k

Cách sử dụng:
Gọi như 15#14đối với các đối số bên trái không âm và (-13)#14đối với các đối số bên trái phủ định, bởi vì Haskell sẽ diễn giải -13#14như -(13#14)thể bạn đang sử dụng một cái gì đó như ghci. Liên kết TIO đơn giản chỉ cần hai đối số dòng lệnh.

Giải thích:
Đầu tiên xác định lại toán tử infix nhị phân !giống như mod. Haskell modluôn đưa ra một giá trị không âm, vì vậy chúng tôi không cần abscác giải pháp khác ở đây làm. Sau đó, nó kiểm tra xem x/k(phép chia số nguyên) có phải là số lẻ hay không và nếu có, trả về k-x mod k(tức là trả lại) hoặc nếu không nó sẽ trả về x mod k.


Đây có lẽ chỉ là vấn đề của hương vị, nhưng cá nhân tôi không muốn xác định !vì nó không lưu bất kỳ byte nàox#k|odd$x`div`k=k-x`mod`k|1<2=x`mod`k
Mark S.

1

PHP, 40 50 byte

đô la chết tiệt. nhập khẩu chết tiệt. :)

phiên bản số nguyên:

[,$x,$k]=$argv;$y=abs($x)%$k;echo$x/$k&1?$k-$y:$y;

hoặc là

[,$x,$k]=$argv;echo[$y=abs($x)%$k,$k-$y][$x/$k&1];

phiên bản float, 56 byte:

Thay thế abs($x)%$kbằng fmod(abs($x),$k).


chỉnh sửa: kết quả cố định cho âm tính x


4
"Đô la chết tiệt". Vâng, tiền bốc mùi ...
steenbergh 16/07/17

2
Thế còn €argvhay £argv? Trông thật tuyệt: x
Ismael Miguel

1

JavaScript (ES6), 36 32 byte

k=>f=x=>x<0?f(-x):x>k?k-f(k-x):x

Đệ quy trả xlại 0k, rất nhiều trong tinh thần của thách thức.



0

C (gcc), 43 53 byte

Chỉnh sửa: Đã sửa vấn đề tiêu cực

int f(int x,int y){return x/y%2?abs(y-x%y):abs(x%y);}

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


2
Điều này cung cấp câu trả lời sai cho (-13, 14) (-13 thay vì 13). Các mô đun và các hoạt động còn lại hoạt động khác nhau trên các số âm.
CAD97

0

R, 28 byte

pryr::f(abs((x-k)%%(2*k)-k))

Mà đánh giá chức năng:

function (k, x) 
abs((x - k)%%(2 * k) - k)

Mà dường như là phương pháp mà hầu hết các giải pháp sử dụng. Tôi đã không nhìn vào họ trước khi làm điều này.

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.