Số lần nhảy tối thiểu


14

Đưa ra một chuỗi các số, tìm số lần nhảy tối thiểu để đi từ vị trí bắt đầu đến điểm cuối và quay lại vị trí bắt đầu một lần nữa.

Mỗi yếu tố của chuỗi biểu thị số lượng di chuyển tối đa mà người ta có thể di chuyển từ vị trí đó.

Tại bất kỳ vị trí nào, bạn có thể thực hiện bước nhảy ở mức tối đa k di chuyển, trong đó k là giá trị được lưu trữ tại vị trí đó. Sau khi kết thúc, bạn chỉ có thể sử dụng các vị trí đó để nhảy mà trước đây không được sử dụng để nhảy.

Đầu vào sẽ được đưa ra dưới dạng một chuỗi các số được phân tách bằng các khoảng trắng đơn. Đầu ra phải là một số duy nhất là số lần nhảy tối thiểu được sử dụng. Nếu không thể đi đến cuối và quay lại vị trí bắt đầu, sau đó in -1

Đầu vào:

2 4 2 2 3 4 2 2

Đầu ra:

6 (3 để đạt đến cuối và 3 để trở lại)

Đầu vào

1 0

Đầu ra

-1

Ghi chú

  • Giả sử tất cả các số của chuỗi là không âm

CHỈNH SỬA 1

Dòng "Vì vậy, cần phải rõ ràng rằng người ta luôn có thể nhảy từ vị trí cuối cùng." có thể gây nhầm lẫn, vì vậy tôi loại bỏ nó khỏi câu hỏi. Nó sẽ không có hiệu lực cho câu hỏi.

Tiêu chí chiến thắng:

Người chiến thắng sẽ là người có mã ngắn nhất.


3
Thus, it should be clear that one can always jump from the last position.- không phải 1 0là một ví dụ?
Daniel Lubarov

@Daniel Số Số lần nhảy sẽ bằng với giá trị được lưu trữ tại vị trí đó. Vị trí cuối cùng luôn là một ứng cử viên mà từ đó người ta có thể nhảy vì vị trí này trước đây không được sử dụng để nhảy.
Người đàn ông mã hóa

1
Mô tả này gây nhầm lẫn vì "nhảy" được sử dụng để chỉ hai điều khác nhau và chỉ với một ví dụ thực tế, thật khó để phân biệt ý nghĩa nào đi với việc sử dụng. Tôi thích một mô tả đề cập đến, nói, "nhảy" và "di chuyển". Với thuật ngữ này, bạn sẽ nói rằng mỗi lần di chuyển bao gồm một số lần nhảy. Các số trong đầu vào cung cấp số lần nhảy tối đa và đầu ra có thể được mô tả rõ ràng là báo cáo số lần di chuyển tối thiểu.
hộp bánh mì

1
Tiêu chí chiến thắng là gì? Khi bạn gắn thẻ mã golf cũng như thử thách mã, nó không rõ ràng.
Howard

@breadbox Có. Tôi đồng ý, nó mơ hồ. Tôi sẽ cập nhật câu hỏi sớm.
Người đàn ông mã hóa

Câu trả lời:


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

Các trường hợp thử nghiệm

      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

Tiếp cận

Cách tiếp cận là tìm kiếm vũ lực bằng cách sử dụng hàm đệ quy.

Bắt đầu từ vị trí 1, đặt giá trị ở vị trí hiện tại thành 0 và tạo một mảng các vị trí có thể được nhảy từ vị trí hiện tại. Vượt qua vị trí mới và mảng sửa đổi cho chính nó. Các trường hợp cơ sở là khi giá trị ở vị trí hiện tại là 0 (không thể nhảy) hoặc đến cuối.

Sau đó, đối với mỗi mảng được tạo, đảo ngược nó và thực hiện tìm kiếm lại. Vì các vị trí nhảy được đặt thành 0, chúng tôi không thể nhảy từ đó một lần nữa.

Đối với những mảng mà chúng ta đã đạt đến cuối, hãy tìm những mảng có số lượng tối thiểu là 0. Trừ đi số 0 của nó trong mảng ban đầu sẽ cho số lần nhảy thực sự được thực hiện.


4

Toán học, 197 193 ký tự

Lực lượng vũ phu.

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 

Công việc rất ấn tượng. Nó có thể là vũ phu nhưng dù sao cũng rất thanh lịch.
DavidC

3

Toán học 351

[Lưu ý: Điều này chưa được đánh gôn hoàn toàn; Ngoài ra, đầu vào cần phải được điều chỉnh để phù hợp với định dạng cần thiết. Và quy tắc không nhảy-trên-cùng-hai-vị trí cần phải được thực hiện. Ngoài ra còn có một số vấn đề định dạng mã cần giải quyết. Nhưng đó là một sự khởi đầu.]

Một biểu đồ được xây dựng với các nút tương ứng với từng vị trí, tức là mỗi chữ số đầu vào biểu thị một bước nhảy. DirectedEdge[node1, node2]biểu thị rằng có thể nhảy từ nút1 sang nút 2. Các đường dẫn ngắn nhất được tìm thấy từ đầu đến cuối và sau đó từ đầu đến cuối.

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

Sử dụng

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

6
3
-1


Điều này là một phần sai vì nó không thực thi quy tắc không nhảy vào số hai lần, nhưng đó là một sự khởi đầu, vì vậy tôi sẽ ủng hộ điều đó. Tôi không biết điều này có khả thi hay không :)
Doorknob

Bạn nói đúng. Tôi đã bỏ qua quy tắc không nhảy hai lần vào ngày mai Tôi sẽ cố gắng sửa nó.
DavidC

3

Con trăn 304

Tôi nghĩ rằng cách tiếp cận mới này giải quyết (tôi hy vọng!) Tất cả các vấn đề liên quan đến trường hợp [2.0] và tương tự:

Trong phiên bản này, chuỗi đầu vào được dịch chuyển (nếu có thể) cho đến khi kết thúc và sau đó chúng ta bắt đầu lại quá trình với chuỗi đảo ngược. Bây giờ chúng ta có thể đảm bảo rằng đối với mọi giải pháp hợp lệ, một trong những bước nhảy sẽ rơi vào phần tử cuối cùng.

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

Đây là những phiên bản chơi gôn:

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

Và một số ví dụ:

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

Có tiềm năng lớn để chơi gôn hơn nữa. Nhưng không có xử lý đầu vào và đầu ra, đó là một phần của vấn đề này.
Phục hồi lại

1
bạn có tấn của khoảng trắng không cần thiết ...
tay nắm cửa

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)

Mô phỏng:

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

Bỏ chơi gôn:

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

Con trăn 271

đây là giải pháp của tôi:

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

Ví dụ:

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

Và đây là các phiên bản golf (một phần bây giờ):

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

Vài ví dụ:

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

Sai lầm. Ở đầu vào [1], đầu ra phải là 0 (đầu ra của bạn là 1). Ở đầu vào [3,0,0,1,4], đầu ra phải là 3 (đầu ra của bạn là -1)
Mã hóa người đàn ông

@Coding man: Rất tiếc, xin lỗi. Có một kiểm tra nhảy exrtra. if (i> = len (L) -1): S.append (n) dường như giải quyết vấn đề
Triadic

Vẫn đưa ra kết quả đầu ra sai. Ví dụ: [2,0] ---> 1 (nên là -1).
Người đàn ông mã hóa

@Coding man: Tôi nghĩ rằng giải pháp của tôi mâu thuẫn với "Vì vậy, rõ ràng là người ta luôn có thể nhảy từ vị trí cuối cùng.", Vì tôi coi [2,0] ---> 1 là một giải pháp hợp lệ, vì nó nhảy qua cuối
Triadic

1
Tôi xin lỗi vì tất cả những sai lầm này. Dòng "Vì vậy, cần phải rõ ràng rằng người ta luôn có thể nhảy từ vị trí cuối cùng." đã bị loại bỏ. Nó được sử dụng chỉ có nghĩa là vị trí cuối cùng không bao giờ được sử dụng khi chúng ta tiến lên phía trước trong chuỗi. Vì vậy, nó luôn có thể được sử dụng để nhảy khi chúng ta di chuyển lùi. Nhưng, trong [2,0] giá trị ở vị trí cuối cùng là 0, bạn có thể thực hiện bước nhảy ở mức tối đa 0 di chuyển. Do đó, bạn không bao giờ có thể đạt đến vị trí bắt đầu. Câu hỏi đã được cập nhật.
Người đàn ông mã hóa

2

Hồng ngọc - 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

Mô phỏng:

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 - khoảng 700 golf. Tôi đã bắt đầu một phiên bản chơi gôn, với các tên ký tự đơn cho các biến và phương thức, nhưng sau một thời gian tôi đã quan tâm đến thuật toán hơn so với golf, vì vậy đã ngừng cố gắng tối ưu hóa độ dài mã. Tôi cũng không lo lắng về việc nhận được chuỗi đầu vào. Nỗ lực của tôi là dưới đây.

Để giúp bạn hiểu cách thức hoạt động của nó, tôi đã bao gồm các nhận xét cho thấy cách thức một chuỗi cụ thể (u = "2 1 4 3 0 3 4 4 3 5 0 3") được thao tác. Tôi liệt kê các kết hợp của "đá trong dòng" có sẵn để nhảy vào. Chúng được biểu diễn bằng một chuỗi nhị phân. Tôi đưa ra ví dụ 0b0101101010 trong các bình luận và chỉ ra cách sử dụng nó. Số 1 tương ứng với vị trí của các tảng đá có sẵn cho chuyến đi ban đầu; 0 giây cho chuyến trở về. Đối với mỗi phân bổ như vậy, tôi sử dụng lập trình động để xác định số bước nhảy tối thiểu cần thiết cho mỗi hướng. Tôi cũng thực hiện một vài tối ưu hóa đơn giản để loại bỏ một số kết hợp sớm.

Tôi đã chạy nó với các chuỗi được đưa ra trong các câu trả lời khác và nhận được kết quả tương tự. Dưới đây là một số kết quả khác tôi thu được:

"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

Tôi sẽ quan tâm đến việc liệu những người khác có nhận được kết quả tương tự cho các chuỗi này hay không. Hiệu suất là hợp lý tốt. Ví dụ: mất ít hơn một phút để có được giải pháp cho chuỗi này:

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

Các mã sau.

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 byte, 159 byte trong GHCi

Đây là phiên bản bình thường:

nhập dữ liệu.

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

Đây là câu trả lời GHCi (đặt dòng một tại một thời điểm):

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

Chỉ là một bruteforce. Tạo câu trả lời có thể. (tức là hoán vị của [0..n-1] với phần tử 0 và sau bị bỏ đi. Sau đó kiểm tra xem câu trả lời có đúng không. Lấy độ dài tối thiểu và thêm một. (Vì các số 0 đứng đầu và dấu cuối bị xóa).

Cách sử dụng: j[3,4,0,0,6]->3


Data.List.permutationskhông hoạt động trong GHC, mà chỉ trong GHCi. Theo Hướng dẫn về Quy tắc chơi gôn của chúng tôi trong Haskell , bạn nên thêm phần nhập hoặc đánh dấu câu trả lời của mình là "Haskell GHCi". Tùy chọn đầu tiên thường được ưa thích bởi những người chơi golf Haskell trên trang web này.
Laikoni

Thay vì a<-permutations[0..t l-1],let f=takeWhile(/=0)a, bạn có thể viết f<-map(takeWhile(/=0))(permutations[0..t l-1]), một lần nữa có thể được chơi golf f<-fst.span(>0)<$>permutations[0..t l-1]. Với điều này, bạn trở lại 166 byte ngay cả bằng cách thêm nhập: Hãy thử trực tuyến!
Laikoni
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.