ジャンプの最小数


14

一連の数字が与えられたら、開始位置から終了まで移動して再び開始位置に戻るための最小ジャンプ数を見つけます。

シーケンスの各要素は、その位置から移動できる移動の最大数を示します。

任意の位置で、最大k移動でジャンプできます。kはその位置に保存されている値です。最後に到達すると、以前はジャンプに使用されていなかったジャンプの位置のみを使用できます。

入力は、単一のスペースで区切られた数字のシーケンスとして与えられます。出力は、使用されるジャンプの最小数である単一の数値でなければなりません。最後まで移動して開始位置に戻ることができない場合は、-1を出力します

入力:

2 4 2 2 3 4 2 2

出力:

6(最後に到達するには3、戻ってくるには3)

入力

1 0

出力

-1

注意

  • シーケンスのすべての数が負でないと仮定します

編集1

「したがって、常に最後の位置からジャンプできることは明らかです。」紛らわしいかもしれないので、質問から削除しました。質問には影響しません。

受賞基準:

勝者はコードが最も短いものになります。


3
Thus, it should be clear that one can always jump from the last position.- 1 0反例ではありませんか?
ダニエルルバロフ

@ダニエル番号。ジャンプの数は、その位置に保存された値と等しくなります。この位置は以前はジャンプに使用されていなかったため、最後の位置は常に、そこからジャンプできる候補です。
コーディング男

1
「ジャンプ」は2つの異なることを意味するために使用されるため、この説明は混乱を招きます。実際の例は1つだけなので、どの意味がどの用途に当てはまるかを明確にすることは困難です。たとえば、「ジャンプ」や「移動」に言及した説明を希望します。この用語では、各動きはいくつかのジャンプで構成されていると言えます。入力の数値はジャンプの最大数を提供し、出力は移動の最小数を報告していると明確に説明できます。
パンボックス

1
勝利基準は何ですか?code-golfcode-challengeをタグ付けしたので、明確ではありません。
ハワード

@breadboxはい。私は同意します、あいまいです。私はすぐに質問を更新します。
コーディング男

回答:


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←⎕

テストケース

      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

アプローチ

このアプローチは、再帰関数を使用したブルートフォース検索です。

位置1から開始して、現在の位置の値を0に設定し、現在の位置からジャンプできる位置の配列を生成します。新しい位置と変更された配列をそれ自体に渡します。基本的なケースは、現在の位置の値が0(ジャンプできない)または最後に達した場合です。

次に、生成された配列ごとに、その配列を逆にして再度検索します。ジャンプした位置は0に設定されているため、そこから再びジャンプすることはできません。

最後に到達した配列について、最小数の0を持つ配列を見つけます。それから初期配列の0の数を引くと、実際に実行されたジャンプの数がわかります。


4

Mathematica、197 193文字

強引な。

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 

非常に印象的な作品。総当たり攻撃かもしれませんが、それでも非常にエレガントです。
DavidC

3

Mathematica 351

[注:これはまだ完全にはゴルフされていません。また、入力は必要な形式に合うように調整する必要があります。また、同じ位置に2回ジャンプしないルールを実装する必要があります。また、対処が必要なコードフォーマットの問題もいくつかあります。しかし、それは始まりです。]

グラフは、各位置、つまりジャンプを表す各入力数字に対応するノードで構成されます。 DirectedEdge[node1, node2]は、node1からnode 2にジャンプできることを示します。最短パスは、開始から終了まで、次に終了から開始まで見つかります。

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})

使用法

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

6
3
-1


これは、2回の番号のジャンプのルールを強制しないため、部分的に間違っていますが、それは開始であり、そのために私は賛成します。これが可能かどうかは
わかり

あなたは正しいです。私は数二回のノー・ジャンピング・ルールを見落としていました明日、私はそれを修正しようとします。
DavidC

3

Python 304

この新しいアプローチは、[2,0]ケースなどに関するすべての問題を解決すると思います!

このバージョンでは、入力シーケンスが終了するまで(可能な場合)走査され、逆のシーケンスでプロセスが再び開始されます。これで、有効なソリューションごとに、ジャンプの1つが最後の要素に到達することが保証されます。

## 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

これらはゴルフバージョンです:

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

そしていくつかの例:

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

さらにゴルフをする大きな可能性を秘めています。しかし、この問題の一部である入出力の処理はありません。
モニカを復活させる

1
あなたは持っているトン ...不要な空白のを
ドアノブを

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)

シミュレーション:

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

脱ゴルフ:

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

これは私の解決策です:

## 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

例:

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

そして、これらは(現在までに)ゴルフされたバージョンです:

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

いくつかの例:

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])

違う。入力[1]では、出力は0である必要があります(出力は1です)。入力[3,0,0,1,4]では、出力は3(出力は-1)である必要があります
コーディングマン

@コーディングマン:おっと、すみません。余分なジャンプチェックがありました。if(i> = len(L)-1):S.append(n)は問題を解決しているようです
Triadic

まだ間違った出力を与えています。例:[2,0] ---> 1(-1である必要があります)。
コーディング男

@コーディングマン:私の解決策は「したがって、常に最後の位置からジャンプできることは明らかである」と矛盾していると思います。端を越えてジャンプます。
トライアディック

1
これらすべての間違いをおaびします。「このように、常に最後の位置からジャンプできることは明らかです。」削除されました。これは、シーケンスを進めるときに最後の位置が使用されなかったことを意味するためだけに使用されました。そのため、後方に移動するときにジャンプに常に使用できます。ただし、[2,0]の最後の位置の値は0であり、最大0の移動でジャンプできます。したがって、開始位置に到達することはできません。質問が更新されました。
コーディング男

2

ルビー-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

シミュレーション:

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

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

0
-1

1
0

2

ルビー-約700のゴルフ。変数とメソッドに1文字の名前を付けたゴルフバージョンを開始しましたが、しばらくしてから、ゴルフよりもアルゴリズムに興味を持つようになったため、コード長を最適化しようとはしませんでした。入力文字列を取得することも心配しませんでした。私の努力は以下です。

仕組みを理解しやすくするために、特定の文字列(u = "2 1 4 3 0 3 4 4 3 5 0 3")の操作方法を示すコメントを記載しました。飛び乗ることができる「ストリーム内のロック」の組み合わせを列挙します。これらはバイナリ文字列で表されます。コメントで例0b0101101010を示し、それがどのように使用されるかを示します。1は、最初の旅行で利用可能な岩の位置に対応しています。復路の0 そのような割り当てごとに、動的プログラミングを使用して、各方向に必要な最小ホップ数を決定します。また、いくつかの単純な最適化を実行して、いくつかの組み合わせを早期に排除します。

私は他の答えで与えられた文字列でそれを実行し、同じ結果を得ました。ここに私が得た他の結果があります:

"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

他の人がこれらの文字列に対して同じ結果を得るかどうかを聞いてみたいです。パフォーマンスは妥当です。たとえば、この文字列の解決策を得るのに1分もかかりませんでした。

「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」

コードは次のとおりです。

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、173 166バイト、GHCiで159バイト

通常のバージョンは次のとおりです。

Data.Listのインポート

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

GHCiの答えは次のとおりです(一度に1行ずつ入力してください)。

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]]

ただのブルートフォース。可能な答えを生成します。(つまり、0と後続の要素が削除された[0..n-1]の順列。答えが正しいかどうかを確認します。最小長を取得し、1ずつ加算します(先頭と末尾のゼロは削除されるため)。

使用方法:j[3,4,0,0,6]->3


Data.List.permutationsGHCでは機能せず、GHCiでのみ機能します。Haskellのゴルフ規則ガイドに従って、インポートを追加するか、回答を「Haskell GHCi」としてマークする必要があります。このサイトのHaskellゴルファーは、一般的に最初のオプションを好んでいます。
ライコニ

代わりにa<-permutations[0..t l-1],let f=takeWhile(/=0)a、書くf<-map(takeWhile(/=0))(permutations[0..t l-1])ことができますf<-fst.span(>0)<$>permutations[0..t l-1]。これにより、インポートを追加しても166バイトに戻ります。オンラインで試してください!
ライコニ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.