Sabırsız bölünebilirlik testi


14

Göreviniz, bir sayının diğeri tarafından bölünebilir olup olmadığını belirleyen bir program veya işlev yazmaktır. Yakalama, sayının tüm rakamları verilmemiş olsa bile , mümkün olan en kısa zamanda bir cevap vermesi gerektiğidir .

Programınız D D 2 tamsayısını ve ardından girdi olarak bir dizi rakam almalıdır . Bunlar , en az anlamlı basamaktan başlayarak başka bir N ≥ 1 tamsayısının rakamlarını temsil eder . İlk aşamada olduğunu N ya gerekir veya olmamalıdır tarafından divisble olmak D , programınız çıkış gerektiği uygun bir cevap ve çıkış. Girişin sonuna ulaşılırsa, tam N'nin D ile bölünebilir olup olmadığı çıktı vermelidir .

N için kabul edilebilir giriş biçimlerinin bir listesi ( dahil edilmeyen bir şeye izin verilmesi gerektiğini düşünüyorsanız yorum bırakın):

  • Standart giriş : rakamlar ayrı satırlarda verilir; giriş sonu EOF veya özel bir değerdir; çıkış , işlevin geri döndüğü veya programın çıktığı anlamına gelir.

  • Analog giriş : örn. Her basamağı temsil eden tuş vuruşları veya on düğme aracılığıyla; giriş sonu özel bir değerdir; çıkış , işlevin geri döndüğü veya programın çıktığı anlamına gelir.

  • Küresel durum ile fonksiyon : art arda rakamlarla tekrar tekrar çağrılır; giriş sonu özel bir değerdir; çıkış , işlevin boş olmayan bir değer döndürdüğü anlamına gelir. Genel durumu kullanırsanız, bir değer döndürüldükten sonra silinmesi veya işlevin birden çok kez çalışacağı şekilde sıfırlanması gerekir .

  • Curried işlevi : bir sonraki basamakla ya da bir değerle çağrılacak başka bir işlevi döndürür; giriş sonu özel bir değerdir veya işlevi bağımsız değişken olmadan çağırır; çıkış , işlevin başka bir işlev yerine bir yanıt döndürdüğü anlamına gelir.

  • GUI istemi veya benzeri : tekrar tekrar görüntülenir; giriş sonu "iptal" veya eşdeğeri veya özel bir değerdir; çıkış , istemlerin görünmeyi durdurması anlamına gelir.

  • Yineleyici işlevi : girdi, çağrıldığında bir sonraki basamağı döndüren durum bilgisi olan bir nesne veya işlevdir; girdinin sonu bir istisna veya özel değerdir; çıkış , yineleyicinin çağrılmasını durdurduğu anlamına gelir.

D için giriş ve çıkış kabul edilebilir herhangi bir standart yöntemle yapılabilir .

Test senaryoları:

2;   6               => true
5;   6               => false
20;  0 3             => false
20;  0 4             => true
100; 1               => false
100; 0 0             => true
100; 0 2             => false
4;   2 4             => false
4;   2 5             => true
4;   2 [eof]         => false
4;   4 [eof]         => true
625; 5 5             => false
625; 5 7 2           => false
625; 5 7 3 6         => false
625; 5 7 3 4         => true
7;   9 3 4 [eof]     => false
7;   9 3 4 5 [eof]   => true
140; 0 3             => false
140; 0 4 5 [eof]     => false
140; 0 4 5 1 [eof]   => true
14;  4 5 1 4 [eof]   => false
14;  4 5 1 4 1 [eof] => true

Çözümümüzün her girdi istediğinde bir rakam verileceğini düşünmeliyiz, değil mi? Ve bu tam bir program olmalı, çünkü girdinin basamak basamak verilmesini sağlamanın nesnel yolu bu değil mi? (
Zorluk

1
@EriktheOutgolfer Giriş biçimi, sorudaki madde işaretli listede ayrıntılı olarak açıklanmaktadır.
Kapı tokmağı

1
Sadece bu formatların ne kadar objektif olabileceğini düşünüyordum ... Sanırım sadece nitpicking'dan çıkacağım ve aslında bunu çözmeye başlayacağım . :-)
Outgolfer Erik

1
Bir listeyi digitsEOF için özel bir değere sahip girdi olarak almakta bir sorun mu var?
Jonathan Allan

1
@EriktheOutgolfer bir EOF değeri olup olmadığını, bir şeyi yanlış anlamadığım sürece olmaz. Örnek olsun için en tüm değer 132 olduğunu söylemek ve potansiyel böleni 4 daha sonra []ve [2]başka dönüş şey falseya true(vb fonksiyonu kendisi ... dahil) iken [2,3], [2,3,1]ve [2,3,1,EOF]dönüş true. Küresel devlet seçeneğine çok yakın.
Jonathan Allan

Yanıtlar:


9

JavaScript (ES6), 70 bayt

Giriş formatı: Kıvrımlı fonksiyon

101

p=>(q='',g=(d,t=k=z=!~d||(q=d+q,p))=>k--?g(d,t-=(k+q)%p<1):t?t-z&&g:1)

Çevrimiçi deneyin!

Nasıl?

pqn0k<p

(1)k×10n+q(modp)

Herhangi biri için vardır ve , öyle ki , giden:xpm10k<px=mp+k

x×10n+q(modp)=(mp+k)×10n+q(modp)=(mp×10n(modp))+(k×10n+q(modp))(modp)=0+(k×10n+q(modp))(modp)=k×10n+q(modp)

Bu nedenle, eğer eşittir tümü için , o da eşit olacaktır herhangi biri için ve cevap doğrudur .0 0 k < p 0 k p(1)00k<p0kp

Aynı nedenle, eğer için büyükse , cevap yanlıştır .0 0 k < p(1)00k<p

in sonuçları karışıksa, henüz karar veremeyiz ve daha fazla basamağı veya EOF bildirimi gerekir.q(1)q

Yorumlananlar

p => (                       // p = divisor
  q = '',                    // q = dividend stored as a string, initially empty
  g = (                      // g() = curried function taking:
    d,                       //   d = next digit
    t =                      //   t = number of iterations yielding a non-zero value
    k =                      //   k = total number of iterations to process
    z =                      //   z = copy of k
      !~d ||                 //   if d == -1 (meaning EOF), use only 1 iteration
                             //   so that we simply test the current value of q
      (q = d + q, p)         //   otherwise, prepend d to q and use p iterations
  ) =>                       //
    k-- ?                    //   decrement k; if it was not equal to zero:
      g(                     //     do a recursive call to g():
        d,                   //       pass the current value of d (will be ignored anyway)
        t -= (k + q) % p < 1 //       test (k + q) % p and update t accordingly
      )                      //     end of recursive call
    :                        //   else:
      t ?                    //     if t is greater than 0:
        t - z && g           //       return 0 if t == z, or g otherwise
      :                      //     else:
        1                    //       return 1
)                            //

2

Toplu, 177 169 bayt

@set n=
@set g=1
:l
@set/ps=
@if %s%==- goto g
@set n=%s%%n%
@set/ae=%1/g,g*=2-e%%2,g*=1+4*!(e%%5),r=n%%g
@if %g% neq %1 if %r%==0 goto l
:g
@cmd/cset/a!(n%%%1)

Alır dbir komut satırı parametresi olarak ve basamak okur nayrı hatlarında -EOF markeri olarak. Varsa 1bölünebilir çıktılar 0. Açıklama:

@set n=

nBoş dizeyi başlangıç durumuna getirin .

@set g=1

g dır-dir gcd(d, 10**len(n))

:l

Rakamları okuyarak bir döngü başlatın.

@set/ps=

Sonraki basamağı okuyun.

@if %s%==- goto g

EOF'da işlemeyi durdurun.

@set n=%s%%n%

Sonraki basamağın başına n.

@set/ae=%1/g,g*=2-e%%2,g*=1+4*!(e%%5),r=n%%g

Artan ve hesaplanan gşimdi güncelleyin .len(n)n%g

@if %g% neq %1 if %r%==0 goto l

Eğer ro zaman olmayan sıfır dkesinlikle bu değildir bölün nçünkü gbir faktör, dbunu dikkate almaz. Eğer rsıfır o zaman sadece olmadığını bilmek dböler neğer geşittir d, öyle değil mi eğer öyleyse, döngü devam eder.

:g

EOF'daki rakam okuma döngüsünden çıkın.

@cmd/cset/a!(n%%%1)

Sonucu hesaplayın ve dolaylı olarak çıktı alın.

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.