Bounce-modulo สองตัวเลข


12

กราฟของการดำเนินการโมดูโล ( y=xmodk ) มีลักษณะดังนี้:

กราฟของฟังก์ชันโมดูโล

นี่เป็นฟังก์ชั่นที่มีประโยชน์มากเพราะมันช่วยให้เราสร้างพฤติกรรม "การห่อ" อย่างไรก็ตามมันยุ่งยากมากเมื่อฉันต้องการใช้มันเพื่อสร้างรูปลักษณ์ของ "แสง" ระหว่างกำแพงทั้งสอง กราฟของฟังก์ชั่น "เด้ง" ( y=bounce(x,k) ) มีลักษณะดังนี้:

กราฟของฟังก์ชัน "bounce-modulo"

ระยะเวลาของกราฟของมีkระยะเวลาของกราฟของคือเนื่องจากมันเลื่อนขึ้นสำหรับหน่วยแล้วเลื่อนลงไปอีกหน่วยก่อนที่จะกลับไปที่จุดเริ่มต้น สำหรับทั้งสองฟังก์ชั่นค่าต่ำสุดสำหรับคือ 0 และสูงสุดคือ (ที่จริงแล้วสำหรับฟังก์ชั่นโมดูลัสที่มีอินพุทอินทิกรัลคือ ) นอกจากนี้สำหรับทั้งสองฟังก์ชันค่าที่คือ 0k y = bounce ( x , k ) 2 k k k y k k - 1 x = 0y=xmodkky=bounce(x,k)2kkkykk1x=0

ความท้าทาย

ได้รับจำนวนเต็มและเป็นจำนวนเต็มบวกกลับจำนวนเต็มหรือทศนิยมประมาณของk)k y = การตีกลับ( x , k )xky=bounce(x,k)

นี่คือดังนั้นการส่งที่ถูกต้องที่สั้นที่สุด (นับเป็นไบต์) ชนะ

กรณีทดสอบ

  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

คะแนนโบนัสสำหรับฟูริเยร์เบสวิธีการในฟูริเยร์


" สำหรับทั้งสองฟังก์ชั่นค่าต่ำสุดของ x คือ 0 และค่าสูงสุดคือ k " นั้นผิดธรรมดา
Peter Taylor

@ PeterTaylor อ๊ะ ฉันหมายถึงผลลัพธ์
ผลไม้แยกแยะ

1
โอ๊ะนั่นคือสิ่งที่ฉันคิดว่าพูดไปแล้ว มันยังคงผิด k % k = 0
Peter Taylor

@ PeterTaylor โอ้ฉันเข้าใจคำถามของคุณ ตอนแรกฉันออกแบบมันโดยคำนึงถึงจุดลอยตัวแล้วเปลี่ยนไปใช้คำสั่งหลังจากนั้น จะแก้ไข
ผลไม้แยกแยะ

1
@PeterTaylor หากอาร์กิวเมนต์เป็นแบบลอยตัวค่าสูงสุดคือตัวเลขที่อยู่ใกล้k
ผลไม้แยกแยะ

คำตอบ:


7

x86-64 รหัสเครื่อง, 18 ไบต์

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

รหัสนี้กำหนดฟังก์ชั่นในภาษาเครื่อง x86-64 ที่คำนวณbounce(x, k) หลังจากการประชุมการเรียกใช้System V AMD64 ที่ใช้กับระบบ Gnu / Unix xพารามิเตอร์จะถูกส่งผ่านในEDIรีจิสเตอร์ขณะที่kพารามิเตอร์ถูกส่งผ่านในESIรีจิสเตอร์ เช่นเดียวกับการประชุมแบบเรียก x86 ทั้งหมดผลลัพธ์จะถูกส่งคืนในEAXรีจิสเตอร์

ในการเรียกสิ่งนี้จาก C คุณจะต้องสร้างต้นแบบดังต่อไปนี้:

int Bounce(int x, int k);

ลองออนไลน์!

คำย่อของชุดประกอบ Ungolfed:

; 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

โปรดทราบว่าส่วนแรก (ที่ใช้ค่าสัมบูรณ์) อาจถูกเขียนอย่างเท่าเทียมกัน:

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

ซึ่งเป็นจำนวนไบต์เดียวกันแน่นอน (6) ประสิทธิภาพควรใกล้เคียงกันอาจจะเร็วกว่าเล็กน้อย (ยกเว้นสำหรับชิป Intel บางรุ่นที่การเคลื่อนที่แบบมีเงื่อนไขช้า )

XCHGแน่นอนว่าค่อนข้างช้าและจะไม่ได้รับความนิยมมากกว่าMOVยกเว้นในการตีกอล์ฟ (ที่อดีตคือ 1 ไบต์เมื่อหนึ่งในตัวถูกดำเนินการคือตัวสะสมในขณะที่ register-register MOVจะมี 2 ไบต์เสมอ)


6

เยลลี่ 3 ไบต์

æ%A

ลองออนไลน์!

Built-ins ftw

คำอธิบาย

æ%มีประโยชน์ในตัวที่นี่ ฉันไม่ทราบวิธีอธิบายดังนั้นฉันจะให้ผลลัพธ์สำหรับอินพุตบางอย่าง:

ในฐานะที่เป็นxไปจาก0อินฟินิตี้xæ%4ไป0,1,2,3,4,(-3,-2,-1,0,1,2,3,4,)ที่ส่วนในวงเล็บจะทำซ้ำไปไม่มีที่สิ้นสุดทั้งสองวิธี




3

Ruby, 40 ไบต์ 32 ไบต์

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

ลองออนไลน์!

คำอธิบาย

สวัสดีนี่เป็นคำตอบแรกของฉันในเว็บไซต์นี้! รหัสนี้จะขึ้นอยู่กับการสังเกตว่าพฤติกรรมของฟังก์ชั่นการตีกลับเหมือนแบบโมดูโลเมื่อ ( n -1) k <= x < NKและ n เป็นเลขคี่และพฤติกรรมเช่นมอดุโลตรงกันข้ามเมื่อnคือแม้ (x/k+1)เป็นจำนวนเต็มที่น้อยที่สุดที่มากกว่าx / k (ซึ่งคือx / k +1 จะถูกปัดเศษลงเป็นจำนวนเต็ม) ดังนั้นจึง(x/k+1)ค้นหาn ที่กล่าวถึงข้างต้น %2>0ตรวจสอบเพื่อดูว่าnเป็นเลขคี่หรือคู่ ถ้าn mod 2> 0 ดังนั้นnจะเป็นเลขคี่ ถ้าnmod 2 = 0 แล้วnคือเลขคู่ ถ้าnเป็นเลขคี่แล้วฟังก์ชั่นการตีกลับควรจะเท่ากับx mod k ถ้าnคือแม้ฟังก์ชั่นการตีกลับควรจะย้อนกลับเท่ากับk - x mod k นิพจน์ทั้งหมด(x/k+1)%2>0?x%k:k-x%kค้นหาnจากนั้นเรียกใช้x mod kหากมันเป็นเลขคี่และเรียกใช้k - x mod k เป็นอย่างอื่น

คำตอบที่ได้รับการปรับปรุงตามข้อเสนอแนะจากCyoce


คุณสามารถแปลงเป็นแลมบ์ดา แทนที่จะdef b(x,k) ... endใช้->x,k{...}
Cyoce

และเนื่องจากคุณกำลังติดต่อกับจำนวนเต็ม.to_iจึงไม่จำเป็น
Cyoce



1

J, 25 ไบต์

คำแนะนำ:

นี่เป็นเพียงโมดูโล่ปกติบนหมายเลขบันได ตัวอย่างเช่นในกรณีของ 5:0 1 2 3 4 5 4 3 2 1

ต่อไปนี้เป็นวิธีแก้ปัญหาที่ยังไม่ได้ผลนักกอล์ฟในเจจะพยายามปรับปรุงในวันพรุ่งนี้:

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

การบีบอัด: [((|~#){])(i.@>:,}:@i.@-)@]

compressed2: [((|~#){])(<:|.|@}.@i:)@]

ลองออนไลน์!


ฉันรู้สึกเหมือนi:สามารถใช้ที่นี่ แต่ฉันยังไม่ได้ลองวิธีแก้ปัญหา
Conor O'Brien

@ ConorO'Brien ตรวจสอบรุ่น compressed2 i:ของฉันก็จะบันทึกไม่กี่ไบต์ใช้ เพิ่งไม่มีเวลาอัปเดตหลักและให้คำอธิบาย ผมคาดว่าผู้เชี่ยวชาญสามารถโกนอีก 4 หรือ 5 ไบต์อย่างน้อย ...
โจนาห์

((|~#){])]-|@}:@i:สำหรับ 18 ไบต์
ไมล์

@miles สวยงาม, tyvm
Jonah

1

QBIC , 25 30 27 ไบต์

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

ทำการปรับโครงสร้างเล็กน้อย ...

คำอธิบาย

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 ทำสิ่งต่าง ๆ สำหรับการดำเนินงานของ MOD มากกว่าการใช้งานพื้นฐานอื่น ๆ หรือไม่? ความรู้พื้นฐานอื่น ๆ กลับมา MOD ที่มีเครื่องหมายเช่นเดียวกับเงินปันผล ที่จะล้มเหลวเมื่อx-13 และk14 คือ
Cody Gray

@CodyGray Nope ให้ -13 แก้ไขแล้ว
steenbergh

คุณไม่ต้องการabsทั้งสองครั้งเหรอ?
Neil

@ ไม่มีคุณมี testcase สำหรับสิ่งนั้นใช่ไหม
steenbergh

@ Neil nvm ฉันได้รับการแก้ไขโดยการปรับโครงสร้างทั้งหมด
steenbergh

1

C89, 40 ไบต์

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

พอร์ต AC ของx86 คำตอบรหัสเครื่องของฉันนี้กำหนดฟังก์ชั่นfที่คำนวณตีโมดูโลสำหรับพารามิเตอร์และxk

จะใช้กฎนัย-int C89 ของเพื่อให้ทั้งสองพารามิเตอร์ตัวแปรส่วนกลางและค่าตอบแทนของฟังก์ชั่นที่มีทั้งหมดโดยปริยายประเภทt intตัวแปรโกลบอลtใช้เพื่อเก็บค่าชั่วคราวซึ่งจบลงด้วยการบันทึกไบต์เปรียบเทียบกับการคำนวณซ้ำที่ด้านใดด้านหนึ่งของโอเปอเรเตอร์เงื่อนไข

absฟังก์ชั่น (ค่าสัมบูรณ์) ให้ไว้ใน<stdlib.h>ส่วนหัว แต่เราไม่ได้มีการรวมไว้ที่นี่อีกครั้งขอบคุณกฎนัย-int C89 (โดยฟังก์ชั่นที่มีการประกาศโดยปริยายและสันนิษฐานว่าจะกลับมาint)

ลองออนไลน์!

เวอร์ชันที่ไม่ถูกปรับแต่ง:

#include <stdlib.h>

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

เมื่อมองดูสิ่งนี้ตามรหัสเครื่องที่ปรับด้วยมือของฉันคอมไพเลอร์จะสร้างผลลัพธ์ที่ดีงามสำหรับเรื่องนี้ ฉันหมายความว่าพวกเขาควร; มันเป็นฟังก์ชั่นที่ใช้งานง่ายเพื่อเพิ่มประสิทธิภาพ! ฉันได้ค้นพบข้อผิดพลาดเล็ก ๆ น้อย ๆ ในการเพิ่มประสิทธิภาพ x86-64 ของ GCCแต่ที่มันอยากรู้อยากเห็นการผลิตขนาดใหญ่รหัสเมื่อคุณบอกว่าเพื่อเพิ่มประสิทธิภาพสำหรับขนาดและขนาดเล็กรหัสเมื่อคุณบอกว่าเพื่อเพิ่มประสิทธิภาพสำหรับความเร็ว


m;f(x,k){m=abs(x%k);x=x/k%2?k-m:m;}สั้นกว่า
user41805

ยกเว้นว่ามันจะไม่ส่งคืนค่าจริง @cows นอกเหนือจากภายใต้สถานการณ์ที่กำหนดไว้อย่างไม่แน่นอนเนื่องจากความแปลกประหลาดของตัวสร้างรหัส GCC บนเป้าหมาย x86 มันเป็นเทมเพลตที่ฉันเห็นคนใช้อยู่ที่นี่ แต่มันไม่ได้ผลสำหรับฉันมากกว่าการดึงขยะสุ่มออกจากสแต็กที่เพิ่งเกิดขึ้นเพื่อเป็นคำตอบที่ถูกต้อง
Cody Grey

1

Haskell, 37 ไบต์

ลองออนไลน์!

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

วิธีใช้:
call เหมือน15#14ไม่ใช่เชิงลบที่เหลือข้อโต้แย้งและเป็น(-13)#14เชิงลบที่เหลือข้อโต้แย้งเพราะ Haskell จะแปลความหมาย-13#14เป็นถ้าคุณกำลังใช้สิ่งที่ต้องการ-(13#14) ghciTIO-link ใช้เวลาเพียงสองอาร์กิวเมนต์บรรทัดคำสั่ง

คำอธิบาย:
แรกนิยามใหม่ของผู้ประกอบการมัดไบนารีที่จะเป็นเช่นเดียวกับ! modHaskell ให้modผลลัพธ์ที่ไม่เป็นลบเสมอดังนั้นเราจึงไม่ต้องการabsวิธีแก้ปัญหาอื่นที่นี่ จากนั้นจะตรวจสอบว่าx/k(จำนวนเต็มหาร) เป็นเลขคี่และถ้าเป็นเช่นนั้นผลตอบแทนk-x mod k(เช่นหลังตีกลับ) x mod kหรือผลตอบแทนอื่นมัน


นี่อาจเป็นเพียงเรื่องของรสนิยม แต่โดยส่วนตัวแล้วฉันไม่ต้องการกำหนด!เพราะมันไม่ได้ช่วยประหยัดไบต์เลยx#k|odd$x`div`k=k-x`mod`k|1<2=x`mod`k
Mark S.

1

PHP, 40 50 ไบต์

ด่าดอลลาร์ ค่าใช้จ่ายในการนำเข้าแช่ง :)

รุ่นจำนวนเต็ม:

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

หรือ

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

รุ่นลอย 56 ไบต์:

แทนที่ด้วยabs($x)%$kfmod(abs($x),$k)


แก้ไข: ผลลัพธ์คงที่สำหรับเชิงลบ x


4
"ดอลลาร์ด่า" ใช่เงินเหม็น ...
steenbergh

2
วิธีการเกี่ยวกับ€argvหรือ£argv? สิ่งเหล่านั้นจะดูดี: x
Ismael Miguel

1

JavaScript (ES6), 36 32 ไบต์

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

ตีกลับซ้ำxกับ0และkเพื่อให้เป็นอย่างมากในจิตวิญญาณของความท้าทาย



0

C (gcc), 43 53 ไบต์

แก้ไข: แก้ไขปัญหาเชิงลบ

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

ลองออนไลน์!


2
นี่เป็นคำตอบที่ผิดสำหรับ (-13, 14) (-13 แทนที่จะเป็น 13) การทำงานของโมดูลัสและส่วนที่เหลือจะทำงานแตกต่างกันในจำนวนลบ
CAD97

0

R, 28 ไบต์

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

ซึ่งประเมินการทำงาน:

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

ซึ่งดูเหมือนจะเป็นวิธีการที่โซลูชันส่วนใหญ่ใช้ ฉันไม่ได้ดูพวกเขาก่อนทำสิ่งนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.