Kaosun Düşmesi (Minimal Aperiodik Bir Dizinin Oluşturulması)


9

Buradaki fikir, neredeyse tekrar eden bir model üretmektir . Yani, inşa edilmekte olan dizi, bir sonraki alt dizinin tekrarını önlemek için son anda değişir. AA ve ABA tipi alt sıralardan kaçınılmalıdır (burada B, A'dan uzun değildir).

Örnekler:

Devam edeceğim ve açıklamamı daha net hale getirmek için tüm küçük örnekleri listeleyerek başlayacağım. 0 ile başlayalım.

Geçerlilik: 0

Geçersiz: 00 (AA modeli)
Geçerlilik: 01

Geçersiz: 010 (ABA şablonu)
Geçersiz: 011 (AA modeli)
Geçerlilik: 012

Geçerlilik: 0120
Geçersiz: 0121 (ABA şablonu)
Geçersiz: 0122 (AA modeli)

Geçersiz: 01200 (AA modeli)
Geçersiz: 01201 (ABA deseni; 01-2-01)
Geçersiz: 01202 (ABA şablonu)
Geçerlilik: 01203

Şimdi, 4bir kanıtım olmamasına rağmen a'nın hiçbir zaman gerekli olmadığına şiddetle inanıyorum , çünkü sadece sadece yüzlerce karakter uzunluğunda diziler buldum 0123. (Muhtemelen AA kalıbı olmayan sonsuz dizgilere sahip olmak için sadece üç karakterin nasıl gerekli olduğu ile yakından ilgilidir. Bunun üzerinde bir Wikipedia sayfası var.)

Giriş çıkış

Giriş tek, pozitif, sıfır olmayan bir tamsayıdır n. Bunu varsayabilirsin n <= 1000.

Çıktı, nyasaklanmış modelle (AA veya ABA) eşleşen hiçbir alt karakteri olmayan bir karakter dizisidir.

Örnek giriş ve çıkışlar

>>> 1
0

>>> 2
01

>>> 3
012

>>> 4
0120

>>> 5
01203

>>> 50
01203102130123103201302103120132102301203102132012

kurallar

  • Yalnızca karakterlere 0123izin verilir.
  • B A. Bu durumu önlemek için daha artık 012345tarafından takip edilecek olan 6çünkü 0123451bu vardır: 1-2345-1. Başka bir deyişle, dizi önemsiz ve ilgisiz olacaktır.
  • nsert kodlama haricinde istenen herhangi bir yöntemle girilebilir .
  • Çıktı, hangisinin daha kolay olduğuna bağlı olarak bir liste veya dize olabilir.
  • Kaba kuvvet yok ; çalışma süresi gerçekten yavaş bir makinede dakikalar, en fazla bir saat olmalıdır n=1000. (Bu, tüm nuzunluk permütasyonları arasında dolaşan {0,1,2,3}, hile ve benzer numaralara izin verilmeyen çözümleri diskalifiye etmeyi amaçlamaktadır .)
  • Standart boşluklara her zamanki gibi izin verilmez.
  • Puanlama bayt cinsindendir. Bu, bu yüzden en kısa giriş kazanır (muhtemelen - bonusa bakın).
  • Bonus: her adımda izin verilen en düşük rakamı seçin. Dizideki bir sonraki basamak için 1ve varsa 3olası seçeneklerse, öğesini seçin 1. Çıkar 5 puanınızı bayt. Ancak, aşağıdaki notu not edin.

Not!

Çıkmaz sokaklar mümkündür. Programınız veya işleviniz bunlardan kaçınmalıdır. İşte bir örnek:

Güdük: 012031021301231032013021031201321023012031021320123021031201302310320123021320310230120321023120130210312301320310213012032102301320312302103203303203203203
Güdük: 012031021301231032013021031201321023012031021320123021031201302310320123021320310230120321023120130210312301320310213012032102301320312302103203303203203203
Güdük: 012031021301231032013021031201321023012031021320123021031201302310320123021320310230120321023120130210312301320310213012032102301320312302103203203203203203203203203203203203
Güdük: 012031021301231032013021031201321023012031021320123021031201302310320123021320310230120321023120130210312301320310213012032102301320312302103203303203203203203

Bu sekansların her biri daha fazla genişletilemez (a kullanılmadan 4). Ancak, ilk iki ile ikinci ikisi arasında önemli bir fark olduğunu da unutmayın. Bunu Xnetleştirmek için paylaşılan ilk alt diziyi bir ile değiştireceğim .

Güdük: X2130120
Güdük: X2130123
Güdük: X320
Güdük: X321301203102130

Son iki basamak Xvardır 10, bu yüzden bir sonraki basamağı için tek olası seçeneklerdir 2ve 3. Seçmek 2, dizinin sona ermesi gereken bir duruma yol açar . Açgözlü algoritma olacak değil burada çalışıyorum. (Yine de geri izleme olmadan değil.)


Gerçekçi zamanda çıktı vermese bile olası her dizeyi test etmek için kaba kuvvet stratejisi kullanılabilir mi? Herkes için bir çözüm olacağını biliyor musunuz n? Birisi sezgisel yarı açgözlü algoritma verirse, çok büyük bir süre için sorunlara yol açıp açmadığını nasıl kontrol edersiniz? Genel problem ilginç bir sorundur ve desenden kaçınmak için modelin bir kısmının uzunluğunu kısıtladığımız hiçbir şey bulamadım. Birisi genel bir tarif üretebilirse, bunun en iyi yaklaşım olmasını bekliyorum.
xnor

Kurallarda kaba kuvvete izin vermediğime inanıyorum. Muhtemelen bunu vurgulamalıyım. Herkes için bir çözüm olduğuna dair bir kanıtım yok n, ancak programımın bulduğu kütüklerin her seferinde ortalama 10 basamak uzadıkları göz önüne alındığında, sonsuz bir dizinin var olduğundan eminim. Yarı açgözlü bir algoritmanın keyfi olarak büyük diziler için nasıl test edilebileceğinden emin değilim. Ben sınırlayabilir gereksinimi için n= 1000 ve daha yüksek ilgili değil endişe n.
El'endia Starman

4
Herhalde AAgerçekten tip olduğu ABAyerlerde Bboş. Bu belki de bazı çözümleri kolaylaştırmaya yardımcı olabilir.
mathmandan

Yanıtlar:


6

Retina , 86 bayt - 5 = 81

$
_
(r`^(?<-2>.)+_((.)+)\b$
$1!
\b$
0
3#
#
0#
1
1#
2
2#
3
)r`\1(?<-2>.)*((.)+)$
$0#
!
<empty>

Burada <empty>boş bir sondaki çizgiyi temsil eder. Yukarıdaki kodu -sbayraklı tek bir dosyadan çalıştırabilirsiniz .

Giriş tekli olarak verilmelidir , örn 111111. Henüz binlerce sipariş için test etmedim - regex'lerin ikisi bir süre sonra biraz yavaşlayabilir - ancak birkaç saniyede birkaç yüz kolayca işleyebilir.

açıklama

Bu basit bir geri izleme çözümüdür.

  1. Ekleme a 0.
  2. Geçerli sıra geçersizken, sondaki tüm 3'leri kaldırın ve son olmayanı artırın 3.
  3. İstenen uzunlukta geçerli bir sıraya sahip olana kadar tekrarlayın.

Bu geri izleme, ip tek bir yinelemeyle değişmeden kaldığında iptal edilen bir regex ikameleri döngüsü tarafından uygulanır.

$
_

Bu _, tekli girdiyi oluşturduğumuz diziden ayırmak için kullanılan girişe bir ekler .

(r`^(?<-2>.)+_((.)+)\b$
$1!

Bu, döngüdeki ilk ikame (öncü ile gösterilir (). Regex, a) dizenin sonunda bir kelime karakteri (yani bir rakam) varsa eşleşir (bu, dizenin geçerli olduğu anlamına gelir - geçersiz dizilerin bir izle işaretlendiğini aşağıda göreceğiz #) ve b) en azından sırayla girişte olduğu kadar çok karakter (bu dengeleme grupları kullanılarak kontrol edilir ). Bu durumda, girdiyi kaldırır ve a ekleriz !. Bu !, döngüdeki tüm regex'lerin başarısız olmasını sağlar, böylece sonlanır.

\b$
0

Sonunda bir kelime karakteri varsa (yani, dizi geçerliyse ve döngü önceki adımla sonlandırılmamışsa), a ekleyin 0.

3#
#

(Bunun yerine) dizi geçersiz olarak işaretlenmiş ve sonlandırılmışsa 3, bunu kaldırırız 3(ancak diziyi geçersiz olarak bırakırız, çünkü geçerli önek için olası bir devam yoktur ... bu nedenle bir sonraki karakterin de geri izlenmesi gerekir).

0#
1
1#
2
2#
3

Sekans geçersiz olarak işaretlenmişse ve sonunda olmayan herhangi bir rakam varsa, 3rakamı arttırır ve işaretçiyi kaldırırız.

)r`\1(?<-2>.)*((.)+)$
$0#

Döngüdeki son ikame (ile gösterildiği gibi )). Dizenin bitip bitmediğini ABA( Bdaha uzun Adeğil, potansiyel olarak boş olan) kontrol eder. Bağıl uzunlukları Ave Btekrar dengeleme grupları kullanılarak kontrol edilir ve tekrarları Abasit bir geri başvuru ile kontrol edilir.

Bu normal ifade eşleşirse, diziyi ekleyerek geçersiz olarak işaretleriz #.

!
<empty>

Döngü sona erdiğinde, tek yapmamız gereken, kaldırmaktır !ve daha sonra istenen çıktıyla bırakılır.


2

Python 2,175 - 5 = 170 bayt

n=input();s='';u=j=-1
while n>len(s):
 while u>2:u=int(s[0]);s=s[1:]
 u+=1;t=`u`+s;m=c=0
 while t[c:]*0**m:c+=1;i=t[c:].find(t[:c]);m=j<i<=c
 if c>=len(t):s=t;u=j
print s[::j]

Bu, geri izlemeli açgözlü algoritmadır. Keşke daha kısa olsaydı. Umarım doğrudur (aşağıya bakınız).

Dizeyi her seferinde bir basamak oluşturur. dZaten bulmuş olduğu bir basamak dizisi verildiğinde 0, (d+1)st basamağı olarak a eklemeye çalışır . Bu işe yaramazsa, o zaman a 1, sonra a 2, sonra a dener 3. Bunların hiçbiri işe yaramazsa, dth basamağına geri döner ve (daha küçükse 3) arttırır veya kaldırır (eşitse 3, bu durumda öncekini arttırır, vb.).

Geçerlilik kontrolü, içindeki satırdır .find. Vaka kimse kodumu okumak karar, ben bu program aslında basamak ekleyen yani dize geriye doğru saklamak olduğunu demeliyim önünde . Bu nedenle kontrol, ilk c rakamların daha sonra dizede (ilk crakamlardan sonra herhangi bir yerde) tekrar göründüğü yerleri aramayı ve böyle bir yer varsa, araya giren uzunluğun en fazla olup olmadığını içerir c.

(Tabii ki yazdırmadan önce ipi tersine çevirir.)

Ayrıca kolayca daha hızlı olabilir; Başlangıçta verimlilik için çeşitli döngülerden çıkmayı başardım, ama bu değerli değerli bayt. Yine de aralığında hala Tamam n=1000.

Her neyse, program daha küçük basamaklar için bir tercih gösteriyor gibi görünüyor, ancak çok güçlü bir tercih değil. Örneğin, onu çalıştırmak n=2000bana 523sıfırlar, 502birler, 497iki ve 478üçler ile biten bir dize verdi 30210312013021. Bu yüzden başka biri açgözlü bir algoritma üzerinde çalışıyorsa, belki bu sonucu doğrulayabilirler. Ya da sayılar için rakamları n=1000aldım [263, 251, 248, 238].

Son olarak, bu sayımların bir tür simetriyi düşündürdüğünü söyleyebilirim, neredeyse (tam olarak olmasa da) tekdüze bir dağılımla başlamış ve daha sonra bazı 3'ları 0' s 've 2' s 1' s. Ama belli ki bu sadece tesadüf olabilir. Hiç bir fikrim yok!


1

Haskell, 115 (120 bayt - 5 bonus)

x?_|or[t x==t(drop i x)|i<-[1..length x],t<-[take$div(i+1)2]]=[]
x?0=[x]
x?n=(?(n-1)).(:x)=<<"0123"
f=reverse.head.([]?)

Ideone'da çevrimiçi koş

Örnek çalışma:

*Main> f 40
"0120310213012310320130210312013210230120"
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.