Minimal kalan diziyi oluşturun


21

Her sayı sonsuz uzun bir kalan sekans kullanılarak gösterilebilir. Örneğin, 7 sayısını alırsak ve uygularsak 7mod2, o zaman 7mod3, o zaman 7mod4, vb. Alırız 1,1,3,2,1,0,7,7,7,7,.....

Bununla birlikte, onu tüm düşük sayılardan ayırmak için hala mümkün olan en kısa kalan geri kalanlar grubuna ihtiyacımız var . Yine 7'yi kullanmak [1,1,3], en kısa sonuçtur, çünkü önceki başlıkların tümü ile başlamaz [1,1,3]:

0: 0,0,0,0...
1: 1,1,1,1...
2: 0,2,2,2...
3: 1,0,3,3...
4: 0,1,0,4...
5: 1,2,1,0...
6: 0,0,2,1...

Not [1,1] gelmez aynı zamanda Ancak 1. temsil etmek için kullanılabilir, çünkü çalışmak yapmanız gerekir çıktı, 7 temsil etmek [1]1'lik bir girişi olan.

Giriş çıkış

Girişiniz negatif olmayan bir tamsayıdır. Yukarıda tanımlandığı gibi asgari uzunluktaki bir dizi sıranın bir dizisini veya listesini çıkarmalısınız.

Test durumları:

0: 0
1: 1
2: 0,2
3: 1,0
4: 0,1
5: 1,2
6: 0,0,2
7: 1,1,3
8: 0,2,0
9: 1,0,1
10: 0,1,2
11: 1,2,3
12: 0,0,0,2
30: 0,0,2,0
42: 0,0,2,2
59: 1,2,3,4
60: 0,0,0,0,0,4
257: 1,2,1,2,5,5
566: 0,2,2,1,2,6,6
1000: 0,1,0,0,4,6,0,1
9998: 0,2,2,3,2,2,6,8,8,10
9999: 1,0,3,4,3,3,7,0,9,0

İşte ilk 10.000 dizileri size (satır numaraları 1 ile kapalıdır) ilgilenen durumda.

Bu bir , bu yüzden en sevdiğiniz dilde olabildiğince kısa yapın. Hızlı olan herhangi bir cevap için sahte bonus puan!



@ nimi bunu sohbette konuştuk ve dizilerin en az 1 eleman olması gerektiğine karar verdim.
Nathan Merrill,

1
Asıl kalanları sınırlamadığına biraz şaşırdım.
Neil

Çıktı bir listeye döndürülürse sorun olur mu?
R. Kap,

@neil, ben de düşündüm, ama geri kalanlar bileşik sayılardan farklı olduğu için onu tutmak için oy kullandım
Nathan Merrill

Yanıtlar:


5

Mathematica, 60 53 bayt

#~Mod~FirstCase[2~Range~#&/@Range[#+2],x_/;LCM@@x>#]&

Biraz hızlı (10000 ~ 0,1 saniyede çalışır, ancak muhtemelen 100000 için bellek tükenir).

Kod bir hata atar ancak sonucu doğru hesaplar.

açıklama

Daha önce sohbette, gerekli bölenlerin her zaman en {1, 2, ..., n}az ortak katları girişi geçen en kısa liste olarak belirlenebileceğini bulduk . Bunun nedeninin kısa bir argümanı: eğer LCM girişden azsa, LCM'yi girişden çıkarmak tüm bölenleri değiştirmeden bırakacaktır, bu yüzden gösterim benzersiz değildir. Bununla birlikte, LCM'den daha küçük olan tüm girdiler için, kalanlar benzersiz olacaktır, aksi takdirde eşit kalanlar ile iki sayı arasındaki fark, tüm bölenlerin daha küçük bir katı olacaktır.

Kod gelince ... her zamanki gibi golf oynayan Mathematica'nın okuma sırası biraz eğlenceli.

Range[#+2]

Bu bize [1, 2, 3, ..., n+2]giriş için bir liste getirir n. +2Onun için doğru çalıştığından emin olmak için 0ve 1.

2~Range~#&/@...

Bu listedeki Harita 2~Range~#(sözdizimi şekeri Range[2,#]),

{{}, {2}, {2,3}, ..., {2,3,...,n+2}}

Bunlar aday bölen listeleridir (elbette genel olarak ihtiyacımız olandan çok daha fazlası). Şimdi, LCM'leri girişi aşan ilkini bulduk:

FirstCase[...,x_/;LCM@@x>#]

Diğer sözdizimi: x_listelerden herhangi biriyle eşleşen ve onu çağıran bir kalıptır x. /;Ekler bu forma bir koşul ekler. Bu durumdur LCM@@x>#nerede @@ geçerlidir listeye, yani işlevi LCM@@{1,2,3}aracı LCM[1,2,3].

Nihayet biz sadece gerçeği yararlanarak, bütün kalanlar almak Modolduğunu Listableargümanlardan biri bir liste ise otomatik olarak bir liste üzerinde eşler, yani (veya her ikisi aynı uzunluktaki listeleri varsa):

#~Mod~...

5

Jöle , 14 bayt

‘Ræl\>iṠ2»2r⁸%

Bu, bir doğrusal eşgüdüm sisteminin (eğer varsa) çözümünün, modüllerin LCM'sinin benzersiz bir modulo olduğu gerçeğini kullanır. Çevrimiçi deneyin! veya tüm test durumlarını doğrulayın .

Nasıl çalışır

‘Ræl\>iṠ2»2r⁸%  Main link. Argument: n

‘               Increment; yield n+1.
 R              Range; yield [1, ..., n+1].
  æl\           Cumulatively reduce by LCM.
                This yields [LCM(1), ..., LCM(1, ..., n+1)].
     >          Compare all LCMs with n.
      iṠ        Find the first index of sign(n).
                This yields the first m such that LCM(2, ..., m) > n if n > 0, and
                0 if n == 0.
        2»      Take the maximum of the previous result and 2, mapping 0 to 2.
          2r    Yield the range from 2 up to and including the maximum.
            ⁸%  Compute n modulo each integer in that range.

5

MATL , 24 bayt

Bu cevabın önceki sürümündeki bir hatayı işaret ettiği için @nimi sayesinde (şimdi düzeltildi)

Q:qtQ!\t0Z)tb=YpsSP2):Q)

Bu, en büyük iki sınama durumu için çevrimiçi derleyicideki belleği yetersiz tutar (ancak 4 GB RAM'e sahip bir bilgisayarda çalışır).

Çevrimiçi deneyin!

açıklama

Bu, tanımı basit bir şekilde uygular. Giriş için nbu ihtiva eden bir 2D dizi hesaplar mod(p,q)ile pgelen 0için nve qgelen 1için n+1. Her pbiri bir sütundur ve her qbiri bir satırdır. Örneğin, giriş ile n=7bu dizi

0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1
0 1 2 0 1 2 0 1
0 1 2 3 0 1 2 3
0 1 2 3 4 0 1 2
0 1 2 3 4 5 0 1
0 1 2 3 4 5 6 0
0 1 2 3 4 5 6 7

Artık, kalanları içeren son sütun, nbu dizinin her bir sütunu ile karşılaştırıldığında, eleman şeklindedir. Bu verim

1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1
0 1 0 0 1 0 0 1
0 0 0 1 0 0 0 1
0 0 1 0 0 0 0 1
0 1 0 0 0 0 0 1
1 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1

nerede 1eşitliği gösterir. Son sütun açıkça kendisine eşittir ve bu nedenle hepsini içerir. Son sütundan başka en fazla ilk sütuna sahip olan sütunu bulmamız ve bu ilk ağaçların sayısını not almamız gerekir m. (Bu durumda, ilkleri içeren ikinci sütun m=3). Bu amaçla, her bir sütunun toplam ürününü hesaplıyoruz:

1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1
0 1 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1

sonra her sütunun toplamı

1 3 1 2 1 2 1 8

ve sonra giderek artan bir şekilde sıralama ve ikinci olanı al 3. İstenen budur m, bu, kaç tane geri kalanımızı seçmemiz gerektiğini gösterir.

Q:q    % take input n implicitly. Generare row array [0 1 ... n]
tQ!    % duplicate. Transform into column array [1; 2; ...; n-1]
\      % modulo, element-wise with broadcast. Gives the 2D array
t0Z)   % duplicate. Take last column
tb     % duplicate, bubble up
=      % test for equality, element-wise with broadcast
Yp     % cumumative product of each column
s      % sum of each column. This gives the number of initial coincidences
SP2)   % sort in decreasing order and take second value: m
:Q     % generate range [2 3 ... m+1]
)      % apply as index into array of remainders of n. Implicitly display

4

Jöle , 13 11 bayt

r¬µ%€R‘$ḟ/Ṫ

Bu herhangi bir hız brownie puanı kazanmayacak ... Çevrimiçi deneyin! veya daha küçük test durumlarını doğrulayın .

Nasıl çalışır

r¬µ%€R‘$ḟ/Ṫ  Main link. Argument: n

r¬           Range from n to (not n).
             This yields [n, ..., 0] if n > 0 and [0, 1] otherwise.

  µ          Begin a new, monadic chain. Argument: A (range)

       $     Combine the previous two links into a monadic chain:
     R         Range; turn each k in A into [1, ..., k] or [] if k == 0.
      ‘        Increment to map k to [2, ..., k+1].
   %€        Take each k in A modulo all the integers in the 2D list to the right.
        ḟ/   Reduce by filter-not; sequentially remove all remainder sequences of
             n-1, ..., (not n) from the remainder sequences of n.
          Ṫ  Tail; take the last remainder sequence.
             This gives the shortest sequence for descending A and the longest one
             (i.e., [0]) for ascending A.

Neden iki cevap ekledin ???
Outgolfer Erik,

Çünkü onlar tamamen farklı iki yaklaşım. Bu açık 3 bayt daha kısa olsa da, diğeri aslında tüm test durumlarını hesaplamak için yeterince hızlı.
Dennis,

Yerinde olsam, yukarı / aşağı oylama olayı hariç ... yapmazdım.
Outgolfer Erik


3

Python 3.5, 117 95 78 bayt

import sympy
r=lambda n,m=2,M=1,*l:M>n and l or r(n,m+1,sympy.lcm(m,M),*l,n%m)

Python 3.5 ve sympy ( python3 -m pip install --user sympy) gerektirir . Python 3.5'in *lnumarayı varsayılan argümanlarla sağladığını bildirmek için @Dennis'e teşekkür et .


SymPy 0.7.5 ile, kısaltabilirsiniz M>n and liçin l*(M>n).
Dennis,

3

Python 2, 73 70 69 65 bayt

i=l=1
n=input()
while l<=n|1:
 i+=1;a=l;print n%i
 while l%i:l+=a

Tam bir program. @Dennis, sıfırın işlenme biçimini geliştirerek 4 bayt kurtardı.


3

Haskell, 66 60 51 50 bayt

f i=mod i<$>[2..2+sum[1|l<-scanl1 lcm[2..i],l<=i]]

Kullanım örneği: f 42-> [0,0,2,2]. Martin Büttner'ın cevabında açıklanan algoritma .

Referans için önceki sürümü tutacağım, çünkü oldukça hızlı:

Haskell, 51 bayt

f i=mod i<$>[[2..x]|x<-[2..],foldl1 lcm[2..x]>i]!!0

f (10^100)Beş yaşındaki dizüstü bilgisayarımda 0.03 sn sürüyor .

Düzenleme: @xnor kaydetmek için bir bayt buldu. Teşekkürler!


Lcm çok yükselene kadar endeksleri sayarak bir bayt kaydetme:h i=mod i<$>[2..2+sum[1|l<-scanl1 lcm[2..i],l<=i]]
xnor

2

Pyth, 51 Bayt 66 Bayt

IqQZ[Z).q)IqQ1[1))IqQ2,0 1))FdhhQJu/*GHiGHtUd1I>JQVQ aY%QhN)<tYd.q

Denemek!

Çok daha yüksek hızlı 39 bayt sürümü (0-2 için çalışmıyor):

FdhhQJu/*GHiGHtUd1I>JQVtd aY%QhN)<tYd.q

10 10 3 gibi saçma sapan büyük rakamlar için işe yarayacak

Not: Bu cevap 0, 1 ve 2 için çalışmaz. Sabit!


2

JavaScript (ES6), 81 77 bayt

f=(n,r=[n%2],l=i=2,g=(j,k)=>j?g(k%j,j):k)=>l>n?r:f(n,[...r,n%++i],i/g(i,l)*l)

LCM orijinal numarayı geçinceye kadar bu tekrarlı olarak cevabı oluşturur. GCD elbette özyinelemeli olarak da hesaplanır.

Düzenleme: @ user81655 sayesinde 4 bayt kaydedildi.


@ user81655 Bu sadece underhanded ...
Neil

2

Ruby, 52 bayt

->n{m=t=1;a=[];(a<<n%m)until n<t=t.lcm(m+=1);a<<n%m}

Bu çözüm m, sırayı benzersiz kılan 2'den başlayarak mümkün olan her şeyi kontrol eder . Sonuncuyu mbenzersiz yapan şey, geri kalanın kendisi değil, o maralığın (2..m)en az ortak katının (LCM) büyük olduğu en küçük aralığın son üyesi olmasıdır n. Bu benzersiz sayı belirlemek için Çinli Kalan Teoremi, kaynaklanmaktadır nkalıntıların bir dizi olduğunu, bu kalıntıların LCM daha büyük olmalıdır n(eğer seçme nden (1..n); seçiyorsanız ngelen a..b, LCM sadece daha büyük ihtiyacı b-a)

Not:a<<n%m Kodun sonuna koydum , çünkü daha until n<t=t.lcm(m+=1)önce kısa devre ayapılması onu benzersiz yapan son elemanı aldı.

Herhangi bir golf önerisi varsa, lütfen yorumlarda veya PPCG sohbetinde bana bildirin .

Ungolfing:

def remainder_sequence(num)
  # starting with 1, as the statements in the until loop immediately increments divisor
  divisor = 1
  # starts with 1 instead of 2, as the statements in the until loop
  # immediately change product to a new lcm
  product = 1
  remainders = []

  # this increments divisor first then checks the lcm of product and divisor
  # before checking if num is less than this lcm
  until num < (product = product.lcm(divisor = divisor + 1))
    remainders << num % divisor
  end

  # until always short circuits before the last element is entered
  # so this enters the last element and returns
  return remainders << num % divisor
end


1

Python 3.5, 194 181 169 152 149 146 bayt:

( 2 bayt için @ Sherlock9'a teşekkürler! )

def r(o,c=0):
 y=[[j%i for i in range(2,100)]for j in range(o+1)]
 while 1:
  c+=1;z=y[-1][:c]
  if z not in[f[:c]for f in y[:-1]]:break
 print(z)

Mükemmel çalışıyor ve aynı zamanda oldukça hızlı. 100000Çıkışların minimum kalan dizisi için hesaplanması [0, 1, 0, 0, 4, 5, 0, 1, 0, 10, 4, 4]ve sadece yaklaşık 3 saniye sürdü. Girdi 1000000(1 milyon), çıktının sırasını bile hesaplayabildi [0, 1, 0, 0, 4, 1, 0, 1, 0, 1, 4, 1, 8, 10, 0, 9]ve yaklaşık 60 saniye sürdü.

açıklama

Temelde bu işlev öncelikle bir liste oluşturmak olduğunu ne yaptığını, ytüm ile j mod inerede jaralığında her tamsayıdır 0=>7(7 dahil) ve iserideki tüm tamsayıdır 0=>100. Program daha sonra sonsuz bir gider whiledöngü ve ikinci-en son sublists vasıtasıyla birinci içindeki her alt liste içeriğinin aynı sayısını, y( y[:-1:]son alt liste (öğe, aynı sayı ile) y[-1]listenin) y. Alt liste zaman y[-1]olan farklı başka bir alt liste daha döngü üzerinden bozuldu ve doğru minimum kalan dizi döndürülür.

Örneğin, giriş 3 ise y:

[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]]

Daha sonra, while döngüsüne girdiğinde, listedeki her alt listeyi y[:-1:], alt listedeki aynı sayıda öğeyle karşılaştırır y[-1]. Örneğin, ilk önce [[0],[1],[0]]ve karşılaştırırdı [1]. Son alt liste geri kalanında yolduğu için devam edip sonra [[0,0],[0,1],[0,2]]ve ile karşılaştır [1,0]. Yana [1,0]geri kalanında şimdi değil y bu sırayla , yani asgari hatırlatma dizisidir ve bu nedenle, [1,0]doğru döndürülür.


Baytları kurtarmak y[:c:]için aynıy[:c]
Sherlock9

0

C89, 105 bayt

g(a,b){return b?g(b,a%b):a;}main(n,m,M){scanf("%d",&n);for(m=M=1;(M=++m*M/g(m,M))<=n;)printf("%d ",n%m);}

Kullanarak derler (uyarılarla birlikte) gcc -std=c89. Stdin üzerinde tek bir sayı alır ve stdout'taki boşluklarla ayrılmış kalan diziyi çıkarır.


1
Bu n = 0
xsot

0

C, 89 bayt

a,i=2;main(l,n){for(n=atoi(gets(n))?:!puts(n);n/l;printf("%d ",n%i++))for(a=l;l%i;l+=a);}

Gcc ile derleyin. Çevrimiçi deneyin: n = 59 , n = 0 .

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.