Bounce-modulo iki sayı


12

Modulo işleminin grafiği ( ) şöyle görünür:y=xmodk

Modulo fonksiyonunun grafiği

"Sarma" davranışı yaratmamıza izin verdiği için bu çok kullanışlı bir işlevdir. Ancak, iki duvar arasında "zıplayan" bir görünüm oluşturmak için kullanmak istediğim zaman çok hantal. "Sıçrama" fonksiyonunun grafiği ( y=bounce(x,k) ) şöyle görünür:

"Bounce-modulo" fonksiyonunun grafiği

Süresi grafiğinin isimli . Grafiğinin süresi bir bunun için yukarı doğru hareket eder, çünkü, birimi ve daha sonra başka bir aşağı doğru hareket eder başladığı yere geri dönmeden önce, birim. Her iki işlev için de için minimum değer 0 ve maksimum değer (Aslında, tümleşik girişli modül işlevi için ). Ayrıca, her iki işlev için değerinin olduğu değer .y=xmodkky=bounce(x,k)2kkkykk1x=0

Meydan okuma

tamsayısı ve pozitif tamsayısı verildiğinde , tamsayısı veya kayan nokta yaklaşımı .k y = hemen çıkma ( x , k )xky=bounce(x,k)

Bu , bu nedenle (bayt cinsinden sayılan) en kısa geçerli gönderim kazanır.

Test Durumları

  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

Bir bonus puan Fourier yaklaşımı tabanlı Fourier .


" Her iki işlev için, x için minimum değer 0 ve maksimum k'dir " yalnızca yanlıştır.
Peter Taylor

@PeterTaylor Whoops. Sonuç demek istiyorum.
Esolanging Fruit

1
Hata! Bunu zaten söylediğini sanıyordum. Hala yanlış. k % k = 0
Peter Taylor

@PeterTaylor Oh, sorunuzu anlıyorum. Başlangıçta bunu kayan nokta düşünülerek tasarlamıştım, sonra sadece ints'a geçtim. Düzenleyecek.
Esolanging Fruit

1
@PeterTaylor Bağımsız değişkenler değişiyorsa, maksimum sayı keyfi olarak yakın bir sayıdır k.
Esolanging Fruit

Yanıtlar:


7

x86-64 Makine Kodu, 18 bayt

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

Bu kod, x86-64 makine dilinde hesaplanan bir işlevi tanımlar bounce(x, k). Gnu / Unix sistemlerinde kullanılan System V AMD64 çağrı kuralını takiben xparametre EDIkayıt defterine kgeçirilirken parametre ESIkayıt defterine geçirilir . Tüm x86 çağrı kurallarında olduğu gibi, sonuç EAXkayıt defterine döndürülür .

Bunu C'den çağırmak için, prototipini şu şekilde prototiplersiniz:

int Bounce(int x, int k);

Çevrimiçi deneyin!

Ungolfed montaj anımsatıcıları:

; 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

İlk bölümün (mutlak değeri alan) eşzamanlı olarak yazılabileceğini unutmayın:

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

aynı bayt sayısıdır (6). Performans benzer olmalı, belki biraz daha hızlı olmalıdır ( koşullu hareketlerin yavaş olduğu bazı Intel yongaları hariç ).

XCHGtabii ki, nispeten yavaştır ve MOVkod golfü haricinde tercih edilmez (işlenenlerden biri akümülatör olduğunda birincisi 1 bayttır, oysa bir yazmaç-kayıt MOVher zaman 2 bayttır).


6

Jöle , 3 bayt

æ%A

Çevrimiçi deneyin!

Dahili ftw.

açıklama

æ%burada yararlı bir yerleşiktir. Nasıl tanımlayacağımı bilmiyorum, bu yüzden sadece bazı girdiler için çıktı sağlayacağım:

Gibi xgider 0sonsuza, xæ%4gider 0,1,2,3,4,(-3,-2,-1,0,1,2,3,4,)parantez içinde bölüm iki yönde sonsuza tekrarlanır nerede.




3

Yakut, 40 bayt 32 bayt

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

Çevrimiçi deneyin!

açıklama

Merhaba, bu sitedeki ilk cevabım! Bu kod, gözleme dayalı olduğu dönen fonksiyonu davranır tam modülo gibi zaman ( n -1) k <= x < nk ve n garip ve bir ters modülo işlemi gibi davranır , n ve eşitlenir. (x/k+1)daha küçük tam sayı olduğu X / k (ki x / k bir tamsayı +1 yuvarlak aşağı). Bu nedenle, yukarıda belirtilen n'yi(x/k+1) bulur . n'nin tek mi yoksa çift mi olduğunu kontrol eder . Eğer n 2> 0 mod, daha sonra n garip. Eğer n%2>0mod 2 = 0, o zaman n eşittir. Eğer n garip, daha sonra sıçrama fonksiyonu eşit olmalıdır x mod k . Eğer n bile olduğunu, sıçrama fonksiyonu ters olmalıdır için eşit k - x mod k . Tüm ifade n'yi(x/k+1)%2>0?x%k:k-x%k bulur , sonra tekse x mod k yürütür ve aksi takdirde k - x mod k yürütür .

Cevap, Cyoce'un bir önerisine dayanarak geliştirildi .


Bunu lambda'ya dönüştürebilirsiniz. Yerine def b(x,k) ... endkullanımı->x,k{...}
Cyoce

Ve tamsayılarla uğraştığınız için .to_igerekli değil.
Cyoce



1

J, 25 bayt

İpucu:

Bu, merdiven sayıları üzerindeki düzenli modülondur. Örneğin, 5 durumunda:0 1 2 3 4 5 4 3 2 1

İşte J'de (henüz iyi golf oynamamış) bir çözüm: Yarın gelişmeye çalışacağız:

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

sıkıştırılmış: [((|~#){])(i.@>:,}:@i.@-)@]

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

Çevrimiçi deneyin!


i:Burada kullanılabileceğini hissediyorum , ama henüz bir çözüm denemedim
Conor O'Brien

@ ConorO'Brien sıkıştırılmış2 sürümüme göz atın, kullanarak birkaç bayt kaydeder i:. Ana olanı güncellemek ve bir açıklama yapmak için zamanım olmadı. Bir uzmanın en azından başka bir 4 veya 5 bayt tıraş edebileceğini düşünüyorum ...
Jonah

((|~#){])]-|@}:@i:18 bayt için
mil

@miles güzel, tyvm
Jonah

1

QBIC , 25 30 27 bayt

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

Biraz yeniden yapılanma yaptım ...

açıklama

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 işlemleri için diğer Temel uygulamalardan farklı bir şey yapar mı? Diğer Temel Bilgiler, temettü ile aynı işaretle MOD'u döndürür; x-13 ve k14 olduğunda başarısız olur .
Cody Gray

@CodyGray Hayır, -13 verdi. Şimdi düzeltildi.
steenbergh

absİki kere de ihtiyacınız yok mu?
Neil

@Neil bunun için bir test çantanız var mı?
steenbergh

@Neil nvm, her şeyi yeniden yapılandırarak düzelttim.
steenbergh

1

C89, 40 bayt

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

Benim x86 makine kodu yanıtının AC bağlantı noktası , bu fparametreler için bounce-modulo xvek .

C89'un örtük-int kuralını kullanır, böylece her iki parametrenin, global değişkenin tve işlevin dönüş değerinin tümü örtük olarak türdedir int. Global değişkent , koşullu operatörün her iki tarafında hesaplamanın tekrarlanmasına kıyasla, bayt tasarrufu sağlayan geçici bir değeri tutmak için kullanılır.

absFonksiyonu (mutlak değer) sağlanan <stdlib.h>başlığında, ama biz burada tekrar, (işlev dolaylı ilan ve karşılığında kabul edilir C89 örtülü-int kural sayesinde dahil gerekmez int).

Çevrimiçi deneyin!

Ungolfed sürümü:

#include <stdlib.h>

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

Buna elle ayarlanmış makine kodum ışığında bakıldığında , derleyiciler aslında bunun için oldukça iyi bir çıktı üretir . Yani, yapmalılar; optimize etmek oldukça basit bir işlev! GCC'nin x86-64 optimizer'ında küçük bir hatayı ortaya çıkardım , burada , hız için optimize etmenizi söylediğinizde merakla daha büyük kod üretiyor ve hız için optimize etmenizi söylediğinizde daha küçük kod üretiyordum .


m;f(x,k){m=abs(x%k);x=x/k%2?k-m:m;}daha kısa
user41805

Gerçekte bir değer döndürmemesi dışında, @cows, x86 hedeflerindeki GCC kod üreticisinin garip olması nedeniyle belirli kötü tanımlanmış koşullar dışında. İnsanların burada kullandığını gördüğüm bir şablon, ama benim için işe yaramıyor, sadece doğru cevap olan yığıntan rastgele çöp atmaktan başka bir şey değil.
Cody Gray

1

Haskell, 37 Bayt

Çevrimiçi deneyin!

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

: Nasıl kullanılır
olarak Çağrı 15#14negatif olmayan sol argümanlar için ve aynı (-13)#14Haskell yorumlamak çünkü negatif için, argümanlar sol -13#14olarak -(13#14)gibi bir şey kullanıyorsanız ghci. TIO bağlantısı iki komut satırı argümanı alır.

Açıklama:
İlk olarak ikili infix işlecini !ile aynı olacak şekilde yeniden tanımlar mod. Haskell'in modher zaman negatif olmayan bir değer üretir, bu nedenle absburadaki diğer çözümlerin yapmasına gerek yoktur. Daha sonra x/k(tamsayı bölümünün) tek olup olmadığını kontrol eder ve eğer öyleyse, geri döner k-x mod k(yani geri sekme) veya geri döner x mod k.


Bu muhtemelen sadece bir zevk meselesidir, ancak şahsen tanımlamamayı tercih ediyorum !çünkü hiçbir bayt x#k|odd$x`div`k=k-x`mod`k|1<2=x`mod`k
Mark S.

1

PHP, 40 50 bayt

lanet olası dolar. lanet ithalat yükü. :)

tamsayı sürümü:

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

veya

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

kayan sürüm, 56 bayt:

Değiştir abs($x)%$kile fmod(abs($x),$k).


edit: negatif için sabit sonuçlar x


4
"Kahretsin dolar". Evet, para kokuyor ...
steenbergh

2
Nasıl ya €argvda £argv? Bunlar güzel görünecekti: x
Ismael Miguel

1

JavaScript (ES6), 36 32 bayt

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

Recursively sıçramalar xkarşı 0ve kbu nedenle çok zorluk ruhu içinde,.



0

C (gcc), 43 53 bayt

Düzenleme: Sabit negatif sorun

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

Çevrimiçi deneyin!


2
Bu (-13, 14) (13 yerine -13) için yanlış cevap verir. Modül ve geri kalan işlemler negatif sayılar üzerinde farklı davranır.
CAD97

0

R, 28 bayt

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

Hangi işlevi değerlendirir:

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

Bu, çoğu çözümün kullandığı yöntem gibi görünüyor. Bunu yapmadan önce onlara bakmadım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.