최소 점프 수


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반례가 아닙니까?
Daniel Lubarov

@Daniel No. 점프 횟수는 해당 위치에 저장된 값과 같습니다. 마지막 위치는이 위치가 이전에 점프에 사용되지 않았기 때문에 항상 점프 할 수있는 후보입니다.
코딩 남자

1
이 설명은 "점프"가 서로 다른 두 가지를 의미하는 데 사용되기 때문에 혼란스럽고 실제 예를 하나만 사용하면 어떤 의미가 어떤 사용법과 관련이 있는지 명확하게하기가 어렵습니다. "점프"와 "이동"이라고하는 설명을 선호합니다. 이 용어를 사용하면 각 움직임은 몇 번의 점프로 구성됩니다. 입력의 숫자는 최대 점프 수를 제공하며 출력은 최소 이동 수를보고하는 것으로 명확하게 설명 될 수 있습니다.
breadbox

1
이기는 기준은 무엇입니까? code-golfcode-challenge에 태그를 달았 으므로 명확하지 않습니다.
Howard

@breadbox 예. 동의합니다. 질문을 곧 업데이트하겠습니다.
코딩 남자

답변:


4

APL (다이아 로그), 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

매스 매 티카 351

[참고 : 이것은 아직 완전히 골프되지 않은; 또한 필요한 형식에 맞게 입력을 조정해야합니다. 그리고 동일 위치에 두 번의 점프가없는 규칙을 구현해야합니다. 해결해야 할 코드 형식 문제도 있습니다. 하지만 시작이야.]

그래프는 각 위치, 즉 점프를 나타내는 각 입력 숫자에 해당하는 노드로 구성됩니다. 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


이것은 두 번의 규칙에 대한 점프를 강요하지 않기 때문에 부분적으로 잘못되었지만 시작이기 때문에 이에 찬성합니다. 이것이 가능한지 전혀 몰랐습니다 :)
Doorknob

당신이 올바른지. 나는 두 번의 두 번 째 규칙을 간과했습니다. 내일 나는 그것을 고치려고 노력할 것입니다.
DavidC

3

파이썬 304

나는이 새로운 접근법이 [2,0] 사건과 유사한 모든 문제를 해결한다고 생각한다.

이 버전에서는 입력 시퀀스가 ​​끝날 때까지 (가능한 경우) 통과 한 다음 반대 순서로 프로세스를 다시 시작합니다. 이제 모든 유효한 솔루션에 대해 점프 중 하나가 마지막 요소에 도달한다는 것을 보증 할 수 있습니다.

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

추가 골프를 할 수있는 잠재력이 큽니다. 그러나이 문제의 일부인 입력 및 출력 처리는 없습니다.
복원 Monica Monica

1
당신은 t ... 불필요한 공백의를
손잡이

3

제 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

파이썬 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입니다)
Coding man

@ 코딩 담당자 : 죄송합니다. 엑스트라 점프 점검이있었습니다. if (i> = len (L) -1) : S.append (n)이 문제를 해결하는 것으로 보입니다
Triadic

여전히 잘못된 출력을 제공합니다. 예 : [2,0] ---> 1 (-1이어야 함).
코딩 남자

@ 코딩 맨 : 내 솔루션이 "따라서 항상 마지막 위치에서 벗어날 수 있다는 것이 분명해야합니다."라고 생각합니다. [2,0] ---> 1은 유효한 솔루션입니다. 그것은 점프 를 통해 말.
Triadic

1
이 모든 실수에 대해 사과드립니다. "따라서 항상 마지막 위치에서 점프 할 수 있다는 것이 분명해야합니다." 제거 되었어. 시퀀스에서 앞으로 나아갈 때 마지막 위치가 사용되지 않았 음을 의미하기 위해 사용되었습니다. 따라서 뒤로 이동할 때 항상 점프에 사용할 수 있습니다. 그러나 [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 골프. 변수와 메소드의 단일 문자 이름으로 골프 버전을 시작했지만 잠시 후 골프보다 알고리즘에 더 관심이 생겼으므로 코드 길이 최적화를 중단했습니다. 입력 문자열을 얻는 것에 대해 걱정하지 않았습니다. 내 노력은 아래와 같습니다.

작동 방식을 이해하는 데 도움이되도록 특정 문자열 (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 분도 걸리지 않았습니다.

"34 34 34 34 5 34 5 34 34 3 3 5 34 34 31 5 34 5 34 34 5678 5 34 34 5 5 1 4 3 5 4 34 5 5 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

하스켈, 173 GHCi 166 바이트, 159 바이트

일반적인 버전은 다음과 같습니다.

Import 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 답변입니다 (한 번에 한 줄씩 입력).

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을 더하십시오. (앞과 뒤의 0은 삭제되므로).

사용 방법 : j[3,4,0,0,6]->3


Data.List.permutationsGHC에서는 작동하지 않지만 GHCi에서만 작동합니다. Haskell의 골프 규칙 가이드 에 따르면 수입을 추가하거나 답변을 "Haskell GHCi"로 표시해야합니다. 첫 번째 옵션은 일반적으로이 사이트의 Haskell 골퍼가 선호합니다.
Laikoni

대신 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 바이트로 돌아갑니다. 온라인으로 사용해보십시오!
Laikoni
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.