Etrafında Sarılmış Alt Sıralar


11

Giriş

Bu zorlukta, göreviniz dizelerin genel dizilerini bulmaktır. Alt diziler bitişik olmak zorunda değildir ve ayrıca dizeyi "sarabilir", sonuna kadar gidebilir ve baştan başlayarak başlayabilirler. Yine de, sargı sayısını en aza indirmek istersiniz.

Daha resmen izin uve vherhangi iki dizeleri, ve olmayacak k ≥ 0bir tamsayı. Biz demek ubir olduğunu k-paketleme ve dozaj altdizi ait vfarklı indeksleri varsa, öyle ki , en az endeksleri tatmin . Bu, içeriden soldan sağa gidip, bazı karakterlerini yolda seçerek ve en fazla etrafı sararak (eşdeğer olarak, en fazla tarama yaparak ) bulunabileceği anlamına gelir. Bir karakterin, bir etrafa sarılmadan sonra bile bir kereden fazla seçilemeyeceğini ve sarma sarma dizilerinin tam olarak bildiğimiz sıradan diziler olduğunu unutmayın.i1, i2, ..., ilen(u)u == v[i1] v[i2] ... v[ilen(u)]kijij > ij+1uvkk+1v0

Görev

Kişisel girişler iki boş olmayan alfanümerik dizeleri uve vve çıktı tamsayı küçüğüdür kböyle ubir olduğu kbir -paketleme ve dozaj altdizi v. Eğer böyle bir şey kyoksa çıktı alınacaktır -1.

Misal

Girişleri u := xyzyxzzxyxve v := yxzzazzyxxxyz. Biz karakterler için seyir başlarsa uiçinde vaç gözlü bir şekilde, biz 3 kez etrafında kaydırılır:

 yxzzazzyxxxyz
>─x─────y────z┐
┌─────────────┘
└y───────x────┐
┌─────────────┘
└──zz─────x─y─┐
┌─────────────┘
└──────────x──>

Böylece doğru çıktı en fazla 3 olur. En soldaki karakterin xbir kez nasıl seçildiğine ve daha sonra tekrar kullanılamayacağından ikinci taramada nasıl yoksayıldığına dikkat edin. Bununla birlikte, sadece 2 sargı ile daha kısa bir yöntem vardır:

 yxzzazzyxxxyz
>──────────xyz┐
┌─────────────┘
└yxzz────x────┐
┌─────────────┘
└───────y─x───>

Bir sargı (yani iki tarama) yeterli olmadığı ortaya çıktı, bu yüzden doğru çıktı 2.

Kurallar ve Bonuslar

Bir işlev veya tam bir program yazabilir ve gerekirse girişlerin sırasını da değiştirebilirsiniz. En düşük bayt sayısı kazanır ve standart boşluklara izin verilmez.

Tüm test senaryolarının toplamının 10 saniyenin altında hesaplanması için % -10 bonusu vardır . Makinemdeki belirsiz vakaları test edeceğim; Python'daki referans uygulamam yaklaşık 0,6 saniye sürüyor. Dikkate almak isteyebileceğiniz 1,86 GHz çift çekirdekli CPU'ya sahip 7 yaşında bir dizüstü bilgisayarım var.

Test Durumları

"me" "moe" -> 0
"meet" "metro" -> -1
"ababa" "abaab" -> 1
"abaab" "baabaa" -> 1
"1c1C1C2B" "1111CCCcB2" -> 3
"reverse" "reserved" -> 2
"abcdefg" "gfedcba" -> 6
"xyzyxzzxyx" "yxzzazzyxxxyz" -> 2
"aasdffdaasdf" "asdfddasdfsdaafsds" -> 2

1
Bu da örnek için geçerli bir çözüm olabilir mi? Bu açgözlü bir yaklaşım.
orlp

@orlp Geçerli değil, çünkü birincisi xüç ayrı taramada kullanılıyor. Sadece bir kez kullanılabilir.
Zgarb

Ahhh, şimdi anlıyorum.
orlp

Yanıtlar:


4

Pyth, 34 bayt

Mh+Smssm>.ukC,dtdfqGsm@HkT.PUHlG_1

Bu bir işlevi tanımlar g parametre olarak iki dizeyi alan . Çevrimiçi deneyin: Pyth Derleyici / Yönetici

Bu kod çok verimsiz. Zaman ve hafıza karmaşıklığına sahiptir len(v)!/(len(v)-len(u))!. Daha uzun test vakalarını 10 saniyenin altında çözemez. (Ayrıca bellek yetersiz kaldığı için büyük olasılıkla çökecektir.)

M                                    define g(G, H): return _
                          .PUHlG        all permutations of [0, 1, ..., len(H)-1] of length len(G)
                 fqGsm@HkT              filter the permutations which form the string G
    mssm>.ukC,dtd                       compute the number of wraps for each of the remaining permutations
  +S                            _1      sort the numbers and append -1
 h                                      return the first element

4

Haskell, 160 * 0.9 = 144 bayt

a#(-1)=a
a#b=min a b
f y=w(y++" ")0$length y
w _ n _[]=n
w(c:d)n o g@(a:b)|n>o=(-1)|a==c=z#w y n z g|c==' '=w y(n+1)o g|1<2=w y n o g where z=w d n o b;y=d++[c]

Tüm test senaryoları için zamanlama (not: bağımsız değişkenler ters çevrilir):

*Main> map (uncurry f) [
             ("moe", "me"),
             ("metro", "meet"),
             ("abaab", "ababa"),
             ("baabaa", "abaab"),
             ("1111CCCcB2", "1c1C1C2B"),
             ("reserved", "reverse"),
             ("gfedcba", "abcdefg"),
             ("yxzzazzyxxxyz", "xyzyxzzxyx"),
             ("asdfddasdfsdaafsds", "aasdffdaasdf")]
[0,-1,1,1,3,2,6,2,2]
(0.08 secs, 25794240 bytes)

Nasıl çalışır (kısa versiyon): Eşleşen bir karakteri kullanmak ve atlamak için minimum olan basit kaba kuvvet. Aramayı bitirdiğimde (döngü sayısını döndürdüğünüzde) veya şu ana kadar minimumdan daha fazla çevrildiğinde (-1 döndürdüğümde) aramayı durdururum.

İlk sürüme kıyasla çok fazla bayt kaydettim, çünkü tam bir programdan bir işleve geçtim.

Bazı yorumlar ve uygun aralıklarla golf Haskell oldukça okunabilir:

-- a minimum function that ignores a -1 in the right argument to prevent
-- "not solvable" cases in parts of the recursive search to dominate low numbers
-- of solvable parts. If the case isn't solvabale at all, both arguments are
-- -1 and are carried on.
a # (-1) = a
a # b    = min a b

-- the main function f calls the worker funktion w with arguments
-- * the string to search in (STSI), appended by a space to detect cycles
-- * the number of cycles so far
-- * the minimum of cycles needed so far, starting with the length of STSI
-- * the string to search for (STSF) (partial applied away and therefore invisible)
f y = w (y++" ") 0 (length y)

-- the worker function 
w _ n _ [] = n          -- base case: if STSF is empty the work is done and the 
                        -- number of cycles is returned

w (c:d) n o g@(a:b)     -- "c" is first char of STSI, "d" the rest
                        -- "n" number of cycles, "o" minimum of cycles so far
                        -- "g" is the whole STSF, "a" the 1st char, "b" the rest
  | n>o    = (-1)             -- if current cycle is more than a previous result,
                              -- indicate failure
  | a==c   = z # w y n z g    -- if there's a character match, take the min of
                              -- using it and skipping it
  | c==' ' = w y (n+1) o g    -- cycle detected, repeat and adjust n
  | 1<2    = w y n o g        -- otherwise try next char in STSI

  where                 -- just some golfing: short names for common subexpressions
  z = w d n o b;        -- number of cycles if a matching char is used
  y = d ++ [c]          -- rotated STSI

Referans için: eski sürüm, tam program, 187 bayt

main=interact$show.f.lines
a#(-1)=a
a#b=min a b
f[x,y]=w x(y++" ")0 0
w[]_ n _=n
w g@(a:b)(c:d)n m|a==c=w b d n 1#y|c==' '&&m==1=w g(d++" ")(n+1)0|c==' '=(-1)|1<2=y where y=w g(d++[c])n m

@Zgarb: çözümümü yeniden düzenledi. Artık daha hızlı ve daha kısa.
nimi

Yorumlandığında 0.6 saniye, derlendiğinde 0.01 saniye içinde çalışır.
Zgarb

2

JavaScript (ES6) 174 (193-10%)

@ Nimi'nin cevabı gibi, yinelemeli arama, minileri sarar. Çözüm alanı büyüktür (her şeyden önce son örnek için), ancak şu anda bulunan min'de aramayı kesmek zamanı düşük tutar. Edit 1 Eksik bir test örneği ekleyin, biraz kısaltın Edit 2 Param w'yi geçmeye gerek yok, düzeltildi

K=(w,s,x)=>
  ~-(R=(r,l,p=0,q=1,z=w[p],i=0)=>
  {
    if(z&&!(q>x)){
      if(~(r+l).indexOf(z))
        for(t=l?R(l+r,'',p,q+1):x;x<t?0:x=t,i=~r.indexOf(z,-i);)
          t=R(r.slice(-i),l+r.slice(0,~i),p+1,q);
      q=x
    }
    return q
  })(s,'')

Ungolfed

K=(word, astring)=>
{
  var minWraps // undefined at first. All numeric comparison with undefined give false 
  var R=(right, left, pos, wraps)=>
  {
    var cur = word[pos]
    var i,t;
    if (! cur) // when all chars of word are managed
      return wraps;
    if (wraps > minWraps) // over the minimum wrap count already found, stop search
      return wraps; 
    if ( (right+left).indexOf(cur) < 0 ) // if the current char is not found in the remaining part of the string
      return minWraps; // return the current min, could still be undefined (that means 'no way')
    if ( left ) // if there is a left part, try a wrapping search with the current char
    {
      t = R(left+right, '', pos, wraps+1)
      if ( !(minWraps < t)) minWraps = t; // set current min if t is less than current min or current min is still undefined
    }
    // find all occurrences of current char in the remaining part
    // for each occurrence, start a recursive search for the next char
    for(i = 0; (i = right.indexOf(cur, i)) >= 0; i++)
    {
      var passed = right.slice(0,i) // the passed chars go in the left part
      var rest = right.slice(i+1) 
      t = R(rest, left+passed, pos+1, wraps) // try next char in the remaining part, no wrap
      if ( !(minWraps < t)) minWraps = t; // set current min if t is less than current min or current min is still undefined
    }
    return minWraps
  }
  var result = R(astring, '', 0, 1) // start with right=string and left empty
  return ~-result; // decrement. convert undefined to -1
}

Firefox / FireBug konsolunda test et

time=~new Date;
[['me','moe']
,['meet','metro']
,['ababa','abaab']
,['abaab','baabaa']
,['1c1C1C2B','1111CCCcB2']
,['reverse','reserved']
,['abcdefg','gfedcba']
,['xyzyxzzxyx','yxzzazzyxxxyz']
,['aasdffdaasdf','asdfddasdfsdaafsds']]
.forEach(s=>console.log(s,r=K(...s)))
time-=~new Date

Çıktı (son satır ms cinsinden yürütme süresidir)

["ben", "moe"] 0
["buluş", "metro"] -1
["ababa", "abaab"] 1
["abaab", "baabaa"] 1
["1c1C1C2B", "1111CCCcB2"] 3
["ters", "ayrılmış"] 2
["abcdefg", "gfedcba"] 6
["xyzyxzzxyx", "yxzzazzyxxxyz"] 2
["aasdffdaasdf", "asdfddasdfsdaafsds"] 2
116


Firebug ile test edildi, makinemde 175ms'de çalışıyor.
Zgarb

@Zgarb o zaman iyileştirmeler için yer var: Daha yavaş ve daha kısa yapmaya çalışacağım
edc65
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.