Minimum Atlama Sayısı


14

Bir sayı dizisi verildiğinde, başlangıç ​​konumundan sonuna kadar gitmek için minimum atlama sayısını bulun ve tekrar başlangıç ​​konumuna geri dönün.

Dizinin her elemanı, bir kişinin o konumdan hareket edebileceği maksimum hareket sayısını belirtir.

Herhangi bir konumda, maksimum k hareketinde bir sıçrama yapabilirsiniz, burada k bu konumda depolanan değerdir. Sonuna ulaştıktan sonra, yalnızca atlama için daha önce atlama için kullanılmamış olan konumları kullanabilirsiniz.

Giriş, tek boşluklarla ayrılmış bir sayı dizisi olarak verilecektir. Çıktı, kullanılan minimum atlama sayısı olan tek bir sayı olmalıdır. Sona dönüp başlangıç ​​pozisyonuna geri dönmek mümkün değilse, -1 yazdırın

Giriş:

2 4 2 2 3 4 2 2

Çıktı:

6 (3 sona ulaşmak ve 3 geri dönmek için)

Giriş

1 0

Çıktı

-1

Not

  • Dizinin tüm sayılarının negatif olmadığını varsayalım

DÜZENLEME 1

"Bu nedenle, kişinin her zaman son konumdan atlayabileceği açık olmalıdır." kafa karıştırıcı olabilir, bu yüzden sorudan kaldırdım. Soru üzerinde hiçbir etkisi olmayacaktır.

Kazanan Kriterler:

Kazanan, en kısa koda sahip olacak.


3
Thus, it should be clear that one can always jump from the last position.- 1 0karşı örnek değil mi?
Daniel Lubarov

@Daniel No. Atlama sayısı, bu konumda depolanan değere eşit olacaktır. Son pozisyon her zaman atlayabileceği bir adaydır, çünkü bu pozisyon daha önce atlama için kullanılmamıştır.
Kodlama adam

1
Bu açıklama kafa karıştırıcıdır, çünkü "sıçramalar" iki farklı şey anlamına gelir ve sadece bir gerçek örnekle, hangi anlamın hangi kullanımla ilgili olduğunu belirsizleştirmek zordur. Diyelim ki, "zıplar" ve "hareketler" anlamına gelen bir açıklamayı tercih ederim. Bu terminoloji ile her hareketin birtakım sıçramalardan oluştuğunu söyleyebilirsiniz. Girişteki sayılar maksimum atlama sayısını sağlar ve çıkış net bir şekilde minimum hareket sayısını bildirerek tanımlanabilir.
ekmek kutusu

1
Kazanan kriter nedir? Eğer kod-golf yanı sıra kod meydan etiketli olarak açık değildir.
Howard

@breadbox Evet. Katılıyorum, belirsiz. Soruyu yakında güncelleyeceğim.
Kodlama adam

Yanıtlar:


4

APL (Dyalog), 116

f←{{⊃,/{2>|≡⍵:⊂⍵⋄⍵}¨⍵}⍣≡1{(⍴⍵)≤y←⊃⍺:⍵⋄⍵[y]=0:0⋄x←⍵⋄x[y]←0⋄∇∘x¨,∘⍺¨y+⍳y⌷⍵},⍵}
{0≡+/⍵:¯1⋄(⌊/+/0=⍵)-+/0=x}↑⊃,/f¨⌽¨f x←⎕

Test senaryoları

      2 4 2 2 3 4 2 2
6
      1 0
¯1
      1 1 1 1
¯1
      3 1 2 0 4
3
      1
0

Yaklaşmak

Yaklaşım özyinelemeli bir işlev kullanan kaba kuvvet aramadır.

Konum 1'den başlayarak, geçerli konumdaki değeri 0 olarak ayarlayın ve geçerli konumdan atlanabilen konumların bir dizisini oluşturun. Yeni konumu ve değiştirilmiş diziyi kendisine iletin. Temel durumlar, geçerli konumdaki değerin 0 olduğu (atlayamadığı) veya sona ulaştığı durumlardır.

Ardından, oluşturulan dizilerin her biri için diziyi tersine çevirin ve aramayı tekrar yapın. Atlanan konumlar 0 olarak ayarlandığından, oradan tekrar atlayamayız.

Sonuna ulaştığımız dizi için, minimum 0 olan dizileri bulun. İlk dizideki 0'ların çıkarılması, gerçekleştirilen gerçek atlama sayısını verir.


4

Mathematica, 197193 karakter

Kaba kuvvet.

Min[Length/@Select[Join[{1},#,{n},Reverse@#2]&@@@Tuples[Subsets@Range[3,n=Length[i=FromDigits/@StringSplit@InputString[]]]-1,2],{}⋃#==Sort@#∧And@@Thread[i[[#]]≥Abs[#-Rest@#~Append~1]]&]]/.∞->-1 

Çok etkileyici bir çalışma. Kaba kuvvet olabilir ama yine de çok zariftir.
DavidC

3

Mathematica 351

[Not: Bu henüz tam olarak golf oynamamıştır; Ayrıca, girişin gerekli biçime uyacak şekilde ayarlanması gerekir. Ve aynı pozisyonda iki kez zıplamama kuralının uygulanması gerekir. Adresleme gerektiren bazı kod biçimlendirme sorunları da vardır. Ama bu bir başlangıç.]

Her konuma karşılık gelen düğümlerle, yani her bir giriş basamağını bir sıçramayı temsil eden bir grafik oluşturulur. DirectedEdge[node1, node2]düğüm 1'den düğüm 2'ye atlamanın mümkün olduğunu gösterir. En kısa yollar baştan sona ve sonra baştan sona bulunur.

f@j_:=
(d={v=FromCharacterCode/@(Range[Length[j]]+96),j}\[Transpose];
w[n_,o_:"+"]:={d[[n,1]],FromCharacterCode/@(ToCharacterCode[d[[n,1]]][[1]]+Range[d[[n,2]]]  
If[o=="+",1,-1])};

y=Graph[Flatten[Thread[DirectedEdge[#1,#2]]&@@@(Join[w[#]&/@Range[8],w[#,3]&/@Range[8]])]];

(Length[Join[FindShortestPath[y,v[[1]],v[[-1]]],FindShortestPath[y,v[[-1]],v[[1]]]]]-2)
/.{0-> -1})

kullanım

f[{2,4,2,2,3,4,2,2}]
f[{3,4,0,0,6}]
f[{1,0}]

6
3
-1


Bu kısmen yanlıştır, çünkü iki kez bir kurala atlamayı zorlamaz, ancak bir başlangıçtır, bu yüzden bunun için oy vereceğim. Bu bile mümkün olsaydı hiçbir fikrim yoktu :)
Kapı Tokmağı

Haklısın. Atlama yapmadan iki katına çıkma kuralını gözden kaçırdım Yarın bunu düzeltmeye çalışacağım.
DavidC

3

Python 304

Bu yeni yaklaşımın [umarım!] [2,0] dava ve benzeri tüm sorunları çözdüğünü düşünüyorum:

Bu versiyonda giriş dizisi sonuna kadar geçilir (mümkünse) ve sonra işlemi ters çevrilmiş diziyle tekrar başlatırız. Şimdi her geçerli çözüm için atlamalardan birinin son elemente indiğini garanti edebiliriz.

## Back and forward version

# Changed: now the possible jumps from a given L[i] position  
# are at most until the end of the sequence 
def AvailableJumps(L,i): return range(1,min(L[i]+1,len(L)-i))

# In this version we add a boolean variable bkw to keep track of the
# direction in which the sequence is being traversed
def Jumps(L,i,n,S,bkw):
    # If we reach the end of the sequence...
    # ...append the new solution if going backwards
    if (bkw & (i == len(L)-1)): 
            S.append(n)
    else:
        # ...or start again from 0 with the reversed sequence if going forward
        if (i == len(L)-1):
            Jumps(L[::-1],0,n,S,True)    
        else:
            Laux = list(L)
            # Now we only have to disable one single position each time
            Laux[i] = 0
            for j in AvailableJumps(L,i):
                Jumps(Laux,i+j,n+1,S,bkw)

def MiniJumpBF(L):
    S = []        
    Jumps(L,0,0,S,False)
    return min(S) if (S) else -1

Bunlar golf versiyonları:

def J(L,i,n,S,b):
    if (i == len(L)-1):
        S.append(n) if b else J(L[::-1],0,n,S,True)
    else:
        L2 = list(L)
        L2[i] = 0
        for j in range(1,min(L[i]+1,len(L)-i)):
            J(L2,i+j,n+1,S,b)
def MJ(L):
    S = []        
    J(L,0,0,S,False)
    return min(S) if (S) else -1

Ve bazı örnekler:

MJ( [2, 4, 2, 2, 3, 4, 2, 2] ) -->  6
MJ( [0, 2, 4, 2, 2, 3, 4, 2, 2] ) -->  -1
MJ( [3, 0, 0, 1, 4] ) -->  3
MJ( [2, 0] ) -->  -1
MJ( [1] ) -->  0
MJ( [10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 10] ) -->  4
MJ( [3, 2, 3, 2, 1] ) -->  5
MJ( [1, 1, 1, 1, 1, 1, 6] ) -->  7
MJ( [7, 1, 1, 1, 1, 1, 1, 7] ) -->  2

Daha fazla golf için büyük bir potansiyele sahiptir. Ancak bu sorunun bir parçası olan giriş ve çıkış işlemleri yoktur.
Monica'yı

1
Sahip olduğunuz ton ... gereksiz edilmiş boşluğa
Doorknob

3

R - 195

x=scan(nl=1)
L=length
n=L(x)
I=1:(2*n-1)
P=n-abs(n-I)
m=0
for(l in I)if(any(combn(I,l,function(i)all(P[i[c(1,k<-L(i))]]==1,n%in%i,L(unique(P[i]))==k-1,diff(i)<=x[P][i[-k]])))){m=l;break}
cat(m-1)

Simülasyon:

1: 2 4 2 2 3 4 2 2   # everything after 1: is read from stdin
6                    # output is printed to stdout

1: 1 0               # everything after 1: is read from stdin
-1                   # output is printed to stdout

De-golfed:

x = scan(nlines = 1)       # reads from stdin
n = length(x)
index    = 1:(2*n-1)       # 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
position = c(1:n, (n-1):1) # 1  2  3  4  5  6  7  8  7  6  5  4  3  2  1
value    = x[position]     # 2  4  2  2  3  4  2  2  2  4  3  2  2  4  2
is_valid_path = function(subindex) {
  k = length(subindex)
  position[subindex[1]] == 1                  & # starts at 1
  position[subindex[k]] == 1                  & # ends at 1
  n %in% subindex                             & # goes through n (end of vector)
  length(unique(position[subindex])) == k - 1 & # visits each index once (except 1)
  all(diff(subindex) <= value[subindex[-k]])
}
min_length = 0
for(len in index) {
  valid_paths = combn(index, len, FUN = is_valid_path)
  if (any(valid_paths)) {
    min_length = len
    break
  }
}
min_jumps = min_length - 1
cat(min_jumps)             # outputs to stout

2

Python 271

bu benim çözümüm:

## To simplify the process we unfold the forward-backward sequence
def unfold(L): return L + L[:-1][::-1]

## Possible jumps from a given L[i] position
def AvailableJumps(L,i): return range(1,L[i]+1)

# To disable a used position, in the forward and backward sites
# (the first one is not really necessary)
def Use(L,i):
    L[i] = 0
    L[ len(L) - i - 1] = 0
    return L

def Jumps(L,i,n,S):
    if (i >= len(L)-1): 
        S.append(n)
    else:
        Laux = list(L)
        Use(Laux,i)
        for j in AvailableJumps(L,i):
            Jumps(Laux,i+j,n+1,S)

def MiniJump(L):
    S = []        
    Jumps(unfold(L),0,0,S)
    return min(S) if (S) else -1

Örnekler:

print MiniJump([2,4,2,2,3,4,2,2])
print MiniJump([0,2,4,2,2,3,4,2,2])

Ve bunlar (şimdiye kadar) golf edilmiş versiyonlardır:

def J(L,i,n,S):
    if (i >= len(L)-1): S.append(n)
    else:
        La = list(L)
        La[len(La) - i - 1] = 0
        for j in range(1,L[i]+1):
            J(La,i+j,n+1,S)

def MJ(L):
     S = []        
     J(L + L[:-1][::-1],0,0,S)
     return min(S) if (S) else -1

Bazı örnekler:

print MJ([2,4,2,2,3,4,2,2])
print MJ([0,2,4,2,2,3,4,2,2])
print MJ([3,4,0,0,6])

Yanlış. [1] girişinde çıkış 0 olmalıdır (çıkışınız 1'dir). [3,0,0,1,4] girişinde çıkış 3 olmalıdır (çıktınız -1'dir)
Kodlama adamı

@Kodlama adam: Hata! Bir exrtra atlama kontrolü yapıldı. eğer (i> = len (L) -1): S.append (n) sorunu çözüyor gibi görünüyor
Triadic

Hala yanlış çıktılar veriyor. Örn: [2,0] -> 1 (-1 olmalı).
Kodlama adam

@Kodlama adam: Bence çözümüm "Bu nedenle, her zaman son konumdan atlayabileceği açık olmalıdır.", [2,0] ---> 1'i geçerli bir çözüm olarak gördüğüm için, o atlar karşısında sonuna.
Triadic

1
Tüm bu hatalar için özür dilerim. "Bu nedenle, kişinin her zaman son konumdan atlayabileceği açık olmalıdır." Kaldırıldı. Sadece dizide ileri doğru hareket ettiğimizde son konumun asla kullanılmadığı anlamına geliyordu. Böylece, geriye doğru hareket ettiğimizde her zaman zıplamak için kullanılabilir. Ancak, [2,0] 'da son konumdaki değer 0'dır, en fazla 0 hamlede bir sıçrama yapabilirsiniz. Böylece, asla başlangıç ​​pozisyonuna ulaşamazsınız. Soru güncellendi.
Kodlama adam

2

Yakut - 246

a=gets.split.map &:to_i
L=a.size;r=[];a.collect!{|v|([1,v].min..v).to_a};S=a[0].product *a[1..-1];S.each{|s|i=0;b=L==1&&s[i]!=0 ?0:1;(L*2).times{|c|r<<c if i==L-1&&b==0;break if !s[i]||s[i]==0;if i==L-1;b=i=0;s.reverse!end;i+=s[i]}}
puts r.min||-1

Simülasyon:

2, 4, 2, 2, 3, 4, 2, 2
6

0, 2, 4, 2, 2, 3, 4, 2, 2
-1

0
-1

1
0

2

Ruby - yaklaşık 700 golf oynadı. Değişkenler ve yöntemler için tek karakterli isimlerle golf edilmiş bir versiyona başladım, ancak bir süre sonra algoritmaya golften daha fazla ilgi duydum, bu yüzden kod uzunluğunu optimize etmeye çalıştım. Ben de girdi dizesini almak için endişe ettim. Çabalarım aşağıda.

Nasıl çalıştığını anlamanıza yardımcı olmak için belirli bir dizenin (u = "2 1 4 3 0 3 4 4 3 5 0 3") nasıl işlendiğini gösteren yorumlar ekledim. Ben atlamak için kullanılabilir "dere kaya" kombinasyonlarını numaralandırmak. Bunlar ikili bir dize ile temsil edilir. Yorumlarda 0b0101101010 örneğini veriyorum ve nasıl kullanılacağını gösteriyorum. 1'ler ilk yolculuk için mevcut kaya pozisyonlarına karşılık gelir; 0 dönüş yolculuğu için. Bu tür her tahsis için, her bir yönde gereken minimum atlama sayısını belirlemek için dinamik programlama kullanıyorum. Ayrıca bazı kombinasyonları erkenden ortadan kaldırmak için birkaç basit optimizasyon yapıyorum.

Ben diğer cevaplarda verilen dizeleri ile çalıştırın ve aynı sonuçları almak. İşte elde ettiğim diğer bazı sonuçlar:

"2 1 4 3 0 3 4 4 3 5 0 3"                             # =>  8
"3 4 3 5 6 4 7 4 3 1 5 6 4 3 1 4"                     # =>  7
"2 3 2 4 5 3 6 3 2 0 4 5 3 2 0 3"                     # => 10
"3 4 3 0 4 3 4 4 5 3 5 3 0 4 3 3 0 3"                 # => 11
"2 3 2 4 5 3 6 3 2 0 4 5 3 2 0 3 4 1 6 3 8 2 0 5 2 3" # => 14

Başkalarının bu dizeler için aynı sonuçları alıp almadığını duymak isterim. Performans makul. Örneğin, bu dizeye bir çözüm bulmak bir dakikadan az sürdü:

"3 4 3 0 4 3 4 4 5 3 5 3 0 4 3 3 0 3 4 5 3 2 0 3 4 1 6 3 2 0 4 5 3 2 0 3 4 1 6 3 0 4 3 4 4 5 0 1"

Kod aşağıdaki gibidir.

I=99 # infinity - unlikely we'll attempt to solve problems with more than 48 rocks to step on

def leap!(u)
  p = u.split.map(&:to_i) # p = [2,1,4,3,0,3,4,4,3,5,0,3]
  s = p.shift        # s=2, p =   [1,4,3,0,3,4,4,3,5,0,3] # start
  f = p.pop          # f=3, p =   [1,4,3,0,3,4,4,3,5,0]   # finish
  q = p.reverse      #      q =   [0,5,3,4,4,3,0,3,4,1]   # reverse order
  # No path if cannot get to a non-zero rock from s or f
  return -1 if t(p,s) || t(q,f) 
  @n=p.size                  # 10 rocks in the stream
  r = 2**@n                  # 10000000000 - 11 binary digits 
  j = s > @n ? 0 : 2**(@n-s) #   100000000 for s = 2 (cannot leave start if combo number is smaller than j)
  k=r-1                      #  1111111111 - 10 binary digits

  b=I # best number of hops so far (s->f + f->s), initialized to infinity
  (j..k).each do |c|
    # Representative combo: 0b0101101010, convert to array
    c += r                     # 0b10 1 0 1 1 0 1 0 1 0
    c = c.to_s(2).split('').map(&:to_i)
                               # [1,0,1,0,1,1,0,1,0,1,0]
    c.shift                    #   [0,1,0,1,1,0,1,0,1,0] s->f: rock offsets available: 1,3,4,6,8
    d = c.map {|e|1-e}.reverse #   [1,0,1,0,1,0,0,1,0,1] f->s: rock offsets available: 0,2,5,7,9
    c = z(c,p)                 #   [0,4,0,0,3,0,4,0,5,0] s->f: max hops by offset for combo c
    d = z(d,q)                 #   [0,0,3,0,4,0,0,3,0,1] f->s: max hops by offset for combo c
    # Skip combo if cannot get from to a rock from f, or can't
    # get to the end (can always get to a rock from s if s > 0).
    next if [s,f,l(c),l(d)].max < @n && t(d,f)
    # Compute sum of smallest number of hops from s to f and back to s,
    # for combo c, and save it if it is the best solution so far.
    b = [b, m([s]+c) + m([f]+d)].min
  end
  b < I ? b : -1 # return result
end

# t(w,n) returns true if can conclude cannot get from sourch n to destination  
def t(w,n) n==0 || (w[0,n].max==0 && n < @n) end
def l(w) w.map.with_index {|e,i|i+e}.max end
def z(c,p) c.zip(p).map {|x,y| x*y} end

def m(p)
  # for s->f: p = [2,0,4,0,0,3,0,4,0,5,0] - can be on rock offsets 2,5,7,9
  # for f->s: p = [3,0,0,3,0,4,0,0,3,0,1] - can be on rock offsets 3,5,8,10
  a=[{d: 0,i: @n+1}]
  (0..@n).each do |j|
    i=@n-j
    v=p[i] 
    if v > 0
      b=[I]
      a.each{|h| i+v < h[:i] ? break : b << (1 + h[:d])}
      m = b.min
      a.unshift({d: m,i: i}) if m < I
    end
  end
  h = a.shift
  return h[:i]>0 ? I : h[:d]
end

0

Haskell'in 173 GHCi 166 bayt, 159 bayt

İşte normal sürüm:

Data.List'i içe aktar

t=length
j[_]=0
j l=y[t f|f<-fst.span(>0)<$>permutations[0..t l-1],u<-f,u==t l-1,all(\(a,b)->abs(b-a)<=l!!a)$zip(0:f)$f++[0]]
y[]=0-1
y l=minimum l+1

İşte GHCi cevabı (her seferinde bir tane koyun):

t=length
y[]=0-1;y l=minimum l+1
j[_]=0;j l=y[t f|f<-fst.span(>0)<$>Data.List.permutations[0..t l-1],u<-f,u==t l-1,all(\(a,b)->abs(b-a)<=l!!a)$zip(0:f)$f++[0]]

Sadece bir kaba kuvvet. Olası cevabı üretin. (örn. [0..n-1] 'in sıfır ve aşağıdaki eleman düştüğü permütasyon. Ardından cevabın doğru olup olmadığını kontrol edin. Minimum uzunluğu alın ve bir tane ekleyin. (Baştaki ve sondaki sıfırlar silindiğinden).

Nasıl kullanılır: j[3,4,0,0,6]->3


Data.List.permutationsGHC'de değil, sadece GHCi'de çalışır. Haskell'deki Golf Kuralları Rehberi'ne göre , içe aktarmayı eklemeniz veya yanıtınızı "Haskell GHCi" olarak işaretlemeniz gerekir. İlk seçenek genellikle bu sitedeki Haskell golfçüler tarafından tercih edilir.
Laikoni

Yerine a<-permutations[0..t l-1],let f=takeWhile(/=0)ayazabilirsiniz f<-map(takeWhile(/=0))(permutations[0..t l-1])tekrar etmek golfed edilebilir, f<-fst.span(>0)<$>permutations[0..t l-1]. Bununla içe aktarma ekleyerek 166 bayta geri dönersiniz: Çevrimiçi deneyin!
Laikoni
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.