Kafiye düzenlerini numaralandır


26

Bir "kafiye düzeni" harflerin bir dize akadar zbaşlayarak karakterlerin ilk oluşumları (boşluklar olmadan) artan sırada olacak şekilde, a. Örneğin (ilk kez işaretlendiğinde):

abccdbebdcfa
^^^ ^ ^   ^

Uzunluk kafiye şemalarının sayısı Bell numaralarıN tarafından verilmektedir . ( OEIS A000110 ) B(N)

Meydan okuma

Göreviniz, bu kafiye planlarının bir numaralandırmasını, yani tamsayılardan kafiye planlarına kadar bir sıfat eşlemesini uygulamaktır. Sen pozitif bir tamsayı verilen konum N <= 26, hem de negatif olmayan bir tamsayı 0 <= i < B(N). Alternatif olarak, aralığı kullanabilirsiniz 1 <= i <= B(N). Her birinin farklı bir dizge vereceği şekilde N, bir kafiye şeması çıkarmalısınız i.

STDIN (veya en yakın alternatif), komut satırı argümanı veya işlev argümanı yoluyla giriş alarak ve sonucu STDOUT (veya en yakın alternatif), fonksiyon dönüş değeri veya function (out) parametresi ile çıktı alarak bir program veya işlev yazabilirsiniz.

Küçük veya büyük harf kullanabilirsiniz (sürekli olarak).

Kodunuz herhangi bir geçerli girişi makul bir süre içinde ele almalıdır (örn . En kötü durum için birkaç saatten fazla değil ). Bu , yavaş dillerde bile (küçük bazlar için) üssel olarak ölçeklendirilen çözümlere izin vermeli , ancak (yani ) ile doğrusal olarak ölçeklendirilen çözümleri yasaklamalıdır . Özellikle, bu, planları atana kadar geçerli olan tüm geçerli kafiyeli şemalarını yineleyemeyeceğiniz anlamına gelir .N = 26iNiB(N)Ni

Standart kuralları geçerlidir.

Örnekler

Şemalara tam olarak atanması i(yani verilen şemaların sırası N) size bağlıdır. Ancak, sözlük sırasını seçtiğinizi söyleyin, çözümünüz aşağıdaki tabloya uymalıdır ( -geçersiz girdilerle birlikte):

N\i 1    2    3    4    5    6    7    8    9    10   11   12   13   14   15
1   a    -    -    -    -    -    -    -    -    -    -    -    -    -    -
2   aa   ab   -    -    -    -    -    -    -    -    -    -    -    -    -
3   aaa  aab  aba  abb  abc  -    -    -    -    -    -    -    -    -    -
4   aaaa aaab aaba aabb aabc abaa abab abac abba abbb abbc abca abcb abcc abcd

Burada, belirli bir uzunluk için geçerli tüm kafiye düzenlerini üreten kısa bir CJam betiği bulunmaktadır (ancak 10'dan fazla denemeyin yoksa bir süre beklersiniz).

İlgili Zorluklar


5
NOldukça önemsiz olmadığı ve onu bulamayacak kadar aptal olduğum sürece (iyi) bir polinom-zaman çözümüne (in ) bir ödül verebilirim .
Martin Ender

Her ne kadar ödül polinom zaman çözümleri için hazır olsa da, zaman sınırını karşılayan üssel-zaman çözümlerini görmek isterim. (Kendi Mathematica referans başvurum şu anda hala mücadeleyi kazanacaktır.)
Martin Ender

B (26), 64 bit bir tam sayıya uymayan en küçük Bell sayısıdır. Meanie. :-(
Anders Kaseorg,

Yanıtlar:


3

CJam, 68 66 bayt

r~:W)1a*{__(;\);_,,.*.+}W(*r~{X@\=_2$\/:CX<!{X:C):X;}&C*-C'a+o}W*;

Çevrimiçi deneyin.

Bu benim ilk CJam programım. Hayata Perl çözümümün bir limanı olarak başladı ve başlangıçta 130 bayttan uzun sürdü. Diğer golf önerileri açıktır.

Perl programımda olduğu gibi iki bölümden oluşuyor.

Part 1:
r~:W                                         | Read the first input (n) and store it in W
    )1a*                                     | Create an array of n+1 1s
        {              }W(*                  | Repeat n-1 times:
         __                                  | Duplicate array twice
           (;\);                             | Remove first element of 1st array. Swap
                                             | arrays. Remove last element of 2nd array
                _,,                          | Duplicate array. Count items. Create range
                   .*.+                      | Multiply arrays. Add 1st array to result

Part 2:
r~                                           | Read the second input (i)
   {                                  }W*    | Repeat n times:
    X@                                       | Push y (initially 1). Bring item 2 (last array) to top
     \=                                      | Swap top two items. Pop array[y] (v)
       _2$                                   | Duplicate v. Copy item 2 (i) to top
          \/:CX                              | Swap i & v. i/v. Store in C (c). Push y
               <!{       }&                  | If !(i/v < c):
                  X:C):X;                    | c = y. ++y (store in X)
                           C*-C'a+o          | i -= c * v. Push y. Push "a". Add c. Print
                                         ;   | Discard top item (integer 0)

Bölüm 1 eklenti tarafından oluşturulan dizileri hata ayıklamak için ]_`o~n ise 1 ve 2. Parça arasındaki 5, diziler aşağıdaki gibi görünecektir: [[1 1 1 1 1 1] [1 2 3 4 5] [2 5 10 17] [5 15 37] [15 52]]. Her dizinin 0 endeksi kullanılmaz, sadece ofsetleri hesaplamak zorunda kalmadan işleri kolaylaştırır. Diziler şöyle hesaplanır:

[2 5 10 17] [2 5 10 17] [2 5 10 17]        | Duplicate twice
[2 5 10 17] [2 5 10 17] [5 10 17]          | Discard first item of array
[2 5 10 17] [5 10 17] [2 5 10 17]          | Swap last two arrays
[2 5 10 17] [5 10 17] [2 5 10]             | Discard last item of array
[2 5 10 17] [5 10 17] [2 5 10] [2 5 10]    | Duplicate array
[2 5 10 17] [5 10 17] [2 5 10] 3           | Count items in array
[2 5 10 17] [5 10 17] [2 5 10] [0 1 2]     | Integer to range 0 - n-1
[2 5 10 17] [5 10 17] [0 5 20]             | Multiply arrays [2*0 5*1 10*2]
[2 5 10 17] [5 15 37]                      | Add arrays [5+0 10+5 17+20]

Bir sonrakini hesaplarken eski dizinin bir kopyasını tutar. Diziler, Bölüm 2 tarafından ters sırayla okunur ve atılır.


13

Python 2, 153

u=[1]*999;i=60;exec"u[i]=i%30*u[i-30]+u[i-29];i+=1;"*900
def x(l,n,a=0):m=u[30*l+a];c=n>=a*m;return'.'*l and chr(65+min(n/m,a))+x(l-1,[n%m,n-m*a][c],a+c)

Alfabetik sıra ve 0 tabanlı indeksleme kullanır.

Izin lharfler bir ekinin uzunluğu belirtmek ve aönceki kısmında kullanılan farklı harflerin sayısını gösterir. Ardından p(l,a), kalan harfleri seçme yollarının sayısını hesaplayan bir fonksiyon 40 byte olabilir:

p=lambda l,a:l<1or a*p(l-1,a)+p(l-1,a+1)

Bununla birlikte, bu zorluk için çok yavaştır, bu nedenle gerekli değerler önceden hesaplanır ve udizide depolanır . Harf biri olup olmadığını hesaplama her aşamada, adaha önce kullanılmış, n = k * p (I 1 -, a) + n ' burada k, alfabenin 0 endeksli harf ve n' olduğu nKalan harflerle ilgili bilgileri içeren bir sonraki işlev çağrısının değeri . Yeni bir harf kullanılırsa, n = a * p (l - 1, a) + n ' .


1
En kötü durum girişi için ne kadar sürer?
Michael Klein,

1
@MichaelKlein İhmal edilebilir bir süre.
feersum

Bu yapmayı planladığım şeydi (JS ile yapmam dışında). İyi iş! +1
ETHProductions

11

Haskell (GHC 7.10), 150 bayt

s=(1,\_->[]):s
k!((y,b):l@((x,a):_))|let h i|i<x=k:a i|(p,q)<-divMod(i-x)y=p:b q=(x+k*y,h):(k+1)!l
n#i=(['a'..]!!).fromEnum<$>snd(iterate(0!)s!!n!!0)i

Operatör , uzunluğu th (sıfır indeksli) kafiye şemasını n # ihesaplar . Haskell'in tembel sonsuz listelerinden yararlanarak, otomatik kayıt için O (n²) (büyük-tamsayı) işlemlerinde çalışır. Örnek çalışır:in

*Main> 26 # 0
"abcdefghijklmnopqrstuvwxyz"
*Main> 26 # 1
"abcdefghijklmnopqrstuvwxya"
*Main> 26 # 2
"abcdefghijklmnopqrstuvwxyb"
*Main> 26 # 49631246523618756271
"aaaaaaaaaaaaaaaaaaaaaaaabb"
*Main> 26 # 49631246523618756272
"aaaaaaaaaaaaaaaaaaaaaaaaab"
*Main> 26 # 49631246523618756273
"aaaaaaaaaaaaaaaaaaaaaaaaaa"
*Main> [1 # i | i <- [0..0]]
["a"]
*Main> [2 # i | i <- [0..1]]
["ab","aa"]
*Main> [3 # i | i <- [0..4]]
["abc","aba","abb","aab","aaa"]
*Main> [4 # i | i <- [0..14]]
["abcd","abca","abcb","abcc","abac","abaa","abab","abbc","abba","abbb","aabc","aaba","aabb","aaab","aaaa"]

(Maksimum N 26 yerine 25 ise, .fromEnumkaldırılabilir, çünkü B (25) 64-bit'e sığar Int.)


1
Harika görünüyor. Daha kolay dinleme için daha az golf oyunu ekler misiniz?
Michael Klein

4

Perl 257 + 1 (-p bayrağı) = 258

Perl 182 + 10 (-pMbignum bayrakları) = 192

($n,$i)=split;@m=[@a=(1)x($n+1)];while($a[2]){push@m,[@a=map{$a[$_]*$_+$a[$_+1]}0..$#a-1]}$_='';$y=1;while($w=pop@m){$c=int($i/($v=$$w[$y]));$c=$y++if($c>=$y);$i-=$c*$v;$_.=chr$c+65}

Birçok baytı kurtardığın için teşekkür ederim ! Şimdi CJam sürümünü yaparken öğrendiklerime dayanarak yeniden yazdım.

Tekerlemeyi artan alfabetik sırada, 0 endeksli olarak hesaplar.

İki bölüm: Bölüm 1 128 90 bayttır ve Bölüm 2 için bir matris hesaplar. Bölüm 2 129 92 bayttır ve her harfi hesaplamak için bazı basit matematik işlemleri yapar. Eğer matristen kurtulabilsem ve iki basit sayı ile değiştirebilseydim, her bir sayı için matristen tek bir yol hesaplayabilir ve çok sayıda bayt biriktirebilirdim! Görünüşe göre bu fikir işe yaramadı!

Ne yazık ki, i9007199254740992'den daha yüksek değerler için doğru tekerlemeler vermiyor , ancak düşük değerler için güzel çalışıyor! Bignum kütüphanesini 11 byte ekledim. Komut satırından ile çalıştırılır perl -pMbignum bell-rhyme.pl. -pMbignum = 10 bayt. Herhangi bir giriş değeri için de çok hızlı.


2

Oracle SQL 11.2, 412 284 283 bayt

WITH a AS(SELECT CHR(96+LEVEL)d,LEVEL b FROM DUAL CONNECT BY LEVEL<=:i),v(s,c,n)AS(SELECT d,1,1 FROM a WHERE b=1 UNION ALL SELECT s||d,b,LENGTH(REGEXP_REPLACE(s||d,'([a-z])\1+','\1'))FROM v,a WHERE(b<=n OR b=c+1)AND LENGTH(s)<:n)SELECT s FROM v WHERE:n=LENGTH(s)AND:i<=:n ORDER BY 1;

Ne yazık ki, yalnızca 8 uzunluğa kadar çalışır. Herhangi bir daha büyük değere neden olur: ORA-01489: string birleştirme sonucu çok uzun

Un-golfed

WITH a AS(SELECT CHR(96+LEVEL)d,LEVEL b FROM DUAL CONNECT BY LEVEL<=:i),
v(s,c,n) AS
(
  SELECT d,1,1 FROM a WHERE b=1
  UNION ALL
  SELECT s||d,b,LENGTH(REGEXP_REPLACE(s||d,'([a-z])\1+','\1')) 
  FROM v,a 
  WHERE (b<=n OR b=c+1) AND LENGTH(s)<:n
)
SELECT s FROM v WHERE LENGTH(s)=:n AND :i<=:n ORDER BY 1;

Bu görünüm: a sütunundaki harfleri ve b deki değerlerini oluşturur.

Özyinelemeli görünüm v, v parametresi, c'de kullanılan son harfin değeri ve n'de kullanılan en büyük harfin değeri olarak oluşturulan dizeyi alır. N parametresi, yinelenen bir harf içermeyen dizgenin uzunluğuna eşittir, yani, regex bunun içindir.

Bir harf, değeri <= kullanılmış en büyük harfin değeri veya kullanılacak bir sonraki harf ise geçerlidir.

Her nasılsa, sorgunun çalışması için LENGTH (s) <: n kısmına ihtiyaç duyuluyor, sorgunun nasıl çalıştığına dair bir şey eksik olmalı.

Ana SELECT, geçersiz girişleri ve hedeflenen uzunluğa ulaşılmadan önce oluşturulan kısa dizeleri filtrelemeye özen gösterir.

412 bayt sürümü

WITH a AS(SELECT * FROM(SELECT d,b,ROW_NUMBER()OVER(PARTITION BY b ORDER BY d)l FROM(SELECT CHR(64+DECODE(MOD(LEVEL,:i),0,:i,MOD(LEVEL,:i)))d,CEIL(LEVEL/:i)b FROM DUAL CONNECT BY LEVEL<=:i*:n))WHERE l<=b),v(s,c,p)AS(SELECT d,1,l FROM a WHERE b=1 UNION ALL SELECT s||d,c+1,l FROM v,a WHERE c+1=b AND(l<=LENGTH(REGEXP_REPLACE(s,'([A-Z])\1+','\1'))OR l=p+1))SELECT s FROM v WHERE LENGTH(s)=:n AND :i<=:n ORDER BY 1;

412 baytlık sorguyu 26 ile deneme İş yerinde exadata'yı deneyebilirim, ama ne yazık ki hala yaşamak için çalışmam gerekiyor.


0

Mathematica, 136 bayt

(For[j=2^#-1;t=#2,c=1;m=0;x=t;r=If[#>0,++m,c*=m;d=x~Mod~m+1;x=⌊x/m⌋;d]&/@j~IntegerDigits~2;;c<=t,t-=c;--j];FromCharacterCode[r+64])&

Tamamlanması için, işte benim golf referans uygulaması Mevcut cevapların aksine, bu polinom zamanlarında ( N2 numaralı üssünde üstel olarak bulunmuyor) sürmüyor, ancak zaman kısıtlamasını sağlıyor (en kötü durum hala yarım saatten az sürüyor).

Fikir şudur:

  • Her kafiye şeması için, şu ana kadar maksimum karakterin arttığı pozisyonları belirleyebiliriz:

    ABCDEFGHDIJDEKBBIJEIKHDFII
    ^^^^^^^^ ^^  ^
    

    Bu işaretleri, bu tür yapılar üzerinde yinelemeyi kolaylaştıran ikili bir sayı olarak değerlendirebiliriz. Üstel zaman karmaşıklığının geldiği 2 n-1 ila 2 n (veya tam tersi yönde) yinelememiz gerekir .

  • Bu tür her bir yapı için, bu gibi kaç tane karakter dizisi bulunduğunu belirlemek kolaydır: sadece işaretler arasındaki boşluklar serbestçe seçilebilir ve aralığın önündeki maksimum değer bize her pozisyonda kaç farklı karakterin geçerli olduğunu söyler. Bu basit bir ürün. Bu sayı daha küçükse i, onu çıkarırız i. Aksi takdirde, istenen kafiye planının yapısını bulduk.
  • Verilen yapıdaki şemaları numaralandırmak için i, basamakların ağırlıklarının kalan konumlardaki izin verilen karakter sayısı ile belirlendiği karışık temel bir sayı olarak basitçe (veya geriye kalanları) temsil ediyoruz .

Bunun, herhangi bir hatıra veya ön hesap gerektirmediğinden gönderilen diğer dillerde daha kısa bir çözüme izin verip vermeyeceğini merak ediyorum.

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.