Cantidad mínima de saltos

14

Dada una secuencia de números, encuentre el número mínimo de saltos para ir desde la posición inicial hasta el final y volver a la posición inicial nuevamente.

Cada elemento de la secuencia denota el número máximo de movimientos que uno puede mover desde esa posición.

En cualquier posición, puede hacer un salto de al máximo k movimientos, donde k es el valor almacenado en esa posición. Después de llegar al final, puede usar solo aquellas posiciones para saltar que no se hayan usado previamente para saltar.

La entrada se dará como una secuencia de números separados por espacios individuales. La salida debe ser un número único, que es el número mínimo de saltos utilizados. Si no es posible ir al final y volver a la posición inicial, imprima -1

Entrada:

2 4 2 2 3 4 2 2

Salida:

6 (3 para llegar al final y 3 para volver)

Entrada

1 0

Salida

-1

Nota

  • Suponga que todos los números de la secuencia no son negativos

EDITAR 1

La línea "Por lo tanto, debe quedar claro que siempre se puede saltar desde la última posición". puede ser confuso, así que lo eliminé de la pregunta. No tendrá ningún efecto en la pregunta.

Criterios ganadores:

El ganador será el que tenga el código más corto.

Coding man
fuente
3
Thus, it should be clear that one can always jump from the last position.- ¿No es 1 0un contraejemplo?
Daniel Lubarov
@Daniel No. El número de saltos será igual al valor almacenado en esa posición. La última posición es siempre un candidato desde el cual se puede saltar ya que esta posición no se utilizó anteriormente para saltar.
Coding man
1
Esta descripción es confusa porque "saltos" se usa para significar dos cosas diferentes, y con solo un ejemplo real, es difícil desambiguar qué significado va con qué uso. Prefiero una descripción que se refiera, por ejemplo, a "saltos" y "movimientos". Con esta terminología, diría que cada movimiento consiste en un número de saltos. Los números en la entrada proporcionan el número máximo de saltos, y la salida se puede describir inequívocamente como un informe del número mínimo de movimientos.
breadbox
1
¿Cuál es el criterio ganador? Al etiquetar code-golf y code-challenge no está claro.
Howard
@breadbox Sí. Estoy de acuerdo, es ambiguo. Actualizaré la pregunta pronto.
Coding man

Respuestas:

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

Casos de prueba

      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

Acercarse

El enfoque es una búsqueda de fuerza bruta utilizando una función recursiva.

Comenzando desde la posición 1, establezca el valor en la posición actual en 0 y genere una matriz de las posiciones a las que se puede saltar desde la posición actual. Pase la nueva posición y la matriz modificada a sí mismo. Los casos base son cuando el valor en la posición actual es 0 (no se puede saltar) o llega al final.

Luego, para cada uno de los arreglos generados, inviértalo y realice la búsqueda nuevamente. Debido a que las posiciones saltadas se establecen en 0, no podemos saltar desde allí nuevamente.

Para aquellos arreglos que llegamos al final, encuentre los que tienen el número mínimo de 0. Restando de él, el número de 0 en la matriz inicial da el número real de saltos realizados.

TwiNight
fuente
4

Mathematica, 197193 caracteres

Fuerza bruta.

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 
alephalpha
fuente
Un trabajo muy impresionante. Puede ser fuerza bruta, pero es muy elegante, no obstante.
DavidC
3

Mathematica 351

[Nota: Esto aún no está totalmente golfizado; Además, la entrada debe ajustarse para ajustarse al formato requerido. Y la regla de no saltar en la misma posición dos veces debe implementarse. También hay algunos problemas de formato de código que deben abordarse. Pero es un comienzo.]

Se construye un gráfico con nodos correspondientes a cada posición, es decir, cada dígito de entrada que representa un salto. DirectedEdge[node1, node2]significa que es posible saltar del nodo1 al nodo 2. Las rutas más cortas se encuentran de principio a fin y luego de principio a fin.

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

Uso

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

6
3
-1

DavidC
fuente
Esto es parcialmente incorrecto ya que no impone la regla de no saltar en un número dos veces, pero es un comienzo, así que votaré por eso. No tenía idea si esto era posible :)
Pomo de la puerta
Estás en lo correcto. Pasé por alto la regla de no saltar sobre un número dos veces Mañana intentaré corregir eso.
DavidC
3

Python 304

Creo que este nuevo enfoque resuelve (¡espero!) Todos los problemas relacionados con el caso [2,0] y similares:

En esta versión, la secuencia de entrada se atraviesa (si es posible) hasta el final y luego comenzamos el proceso nuevamente con la secuencia invertida. Ahora podemos garantizar que para cada solución válida, uno de los saltos cae en el último elemento.

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

Estas son las versiones de golf:

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

Y algunos ejemplos:

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
Triadic
fuente
Tiene un enorme potencial para seguir jugando al golf. Pero no hay manejo de entrada y salida, que es parte de este problema.
Vuelva a instalar a Monica el
1
tienes toneladas de espacios en blanco innecesarios ...
Pomo de la puerta
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)

Simulación:

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-golf:

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
flodel
fuente
2

Python 271

Esta es mi solución:

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

Ejemplos:

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

Y estas son las versiones de golf (en parte por ahora):

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

Algunos ejemplos:

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])
Triadic
fuente
Incorrecto. En la entrada [1], la salida debe ser 0 (su salida es 1). En la entrada [3,0,0,1,4], la salida debe ser 3 (su salida es -1)
Coding man
@Coding man: Vaya, lo siento. Hubo una prueba de salto exrtra. if (i> = len (L) -1): S.append (n) parece resolver el problema
Triadic
Todavía dando salidas incorrectas. Ej: [2,0] ---> 1 (debería ser -1).
Coding man
@Coding man: creo que mi solución está en conflicto con el "Por lo tanto, debe quedar claro que uno siempre puede saltar desde la última posición", ya que considero que [2,0] ---> 1 es una solución válida, ya que salta al otro lado del final.
Triadic
1
Pido disculpas por todos estos errores. La línea "Por lo tanto, debe quedar claro que siempre se puede saltar desde la última posición". ha sido removido. Se usó solo para significar que la última posición nunca se usó cuando avanzamos en la secuencia. Por lo tanto, siempre se puede usar para saltar cuando nos movemos hacia atrás. Pero, en [2,0] el valor en la última posición es 0, puede hacer un salto de máximo 0 movimientos. Por lo tanto, nunca puede alcanzar la posición inicial. La pregunta ha sido actualizada.
Coding man
2

Rubí - 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

Simulación:

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

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

0
-1

1
0
Thaha kp
fuente
2

Ruby: unos 700 jugadores de golf. Comencé una versión de golf, con nombres de un solo carácter para variables y métodos, pero después de un tiempo me interesé más en el algoritmo que el golf, así que dejé de intentar optimizar la longitud del código. Tampoco me preocupé por obtener la cadena de entrada. Mi esfuerzo está abajo.

Para ayudarlo a comprender cómo funciona, he incluido comentarios que muestran cómo se manipula una cadena en particular (u = "2 1 4 3 0 3 4 4 3 5 0 3"). Enumero combinaciones de "rocas en la corriente" que están disponibles para subir. Estos se representan con una cadena binaria. Doy el ejemplo 0b0101101010 en los comentarios y muestro cómo se usaría. Los 1 corresponden a las posiciones de rocas disponibles para el viaje inicial; los 0 para el viaje de regreso. Para cada asignación, uso la programación dinámica para determinar el número mínimo de saltos requeridos en cada dirección. También realizo algunas optimizaciones simples para eliminar algunas combinaciones desde el principio.

Lo ejecuté con las cadenas dadas en otras respuestas y obtuve los mismos resultados. Aquí hay algunos otros resultados que obtuve:

"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

Me interesaría saber si otros obtienen los mismos resultados para estas cadenas. El rendimiento es razonablemente bueno. Por ejemplo, tardó menos de un minuto en obtener una solución para esta cadena:

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

El código sigue.

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
Cary Swoveland
fuente
0

Haskell, 173 166 bytes, 159 bytes de GHCi

Aquí está la versión normal:

importar datos Lista

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

Aquí está la respuesta de GHCi (ponga la línea de una en una):

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

Solo una fuerza bruta. Genera la posible respuesta. (es decir, la permutación de [0..n-1] con cero y el elemento siguiente descartado. Luego verifique si la respuesta es correcta. Obtenga la longitud mínima y agregue por uno. (Dado que los ceros iniciales y finales se eliminan).

Cómo usar: j[3,4,0,0,6]->3

Akangka
fuente
Data.List.permutationsno funciona en GHC, sino solo en GHCi. De acuerdo con nuestra Guía de reglas de golf en Haskell , debe agregar la importación o marcar su respuesta como "Haskell GHCi". La primera opción es generalmente preferida por los golfistas de Haskell en este sitio.
Laikoni
En lugar de a<-permutations[0..t l-1],let f=takeWhile(/=0)a, puedes escribir f<-map(takeWhile(/=0))(permutations[0..t l-1]), que de nuevo se puede jugar f<-fst.span(>0)<$>permutations[0..t l-1]. Con esto, vuelve a 166 bytes incluso agregando la importación: ¡ Pruébelo en línea!
Laikoni