Numero minimo di salti


14

Data una sequenza di numeri, trova il numero minimo di salti per passare dalla posizione iniziale alla fine e tornare di nuovo alla posizione iniziale.

Ogni elemento della sequenza indica il numero massimo di mosse che si possono muovere da quella posizione.

In qualsiasi posizione, è possibile eseguire un salto di max k mosse, dove k è il valore memorizzato in quella posizione. Dopo aver raggiunto la fine, puoi usare solo quelle posizioni per saltare che non sono state usate in precedenza per saltare.

L'input verrà dato come una sequenza di numeri separati da spazi singoli. L'output dovrebbe essere un singolo numero che è il numero minimo di salti utilizzati. Se non è possibile andare alla fine e tornare alla posizione iniziale, quindi stampare -1

Ingresso:

2 4 2 2 3 4 2 2

Produzione:

6 (3 per raggiungere la fine e 3 per tornare indietro)

Ingresso

1 0

Produzione

-1

Nota

  • Supponiamo che tutti i numeri della sequenza non siano negativi

MODIFICA 1

La linea "Quindi, dovrebbe essere chiaro che si può sempre saltare dall'ultima posizione". potrebbe essere fonte di confusione, quindi l'ho rimosso dalla domanda. Non avrà alcun effetto sulla domanda.

Criteri vincenti:

Il vincitore sarà quello con il codice più breve.


3
Thus, it should be clear that one can always jump from the last position.- non è 1 0un controesempio?
Daniel Lubarov,

@Daniel No. Il numero di salti sarà uguale al valore memorizzato in quella posizione. L'ultima posizione è sempre un candidato da cui si può saltare poiché questa posizione non è stata utilizzata in precedenza per saltare.
Coding man

1
Questa descrizione è confusa perché "salti" è usato per significare due cose diverse, e con un solo esempio reale, è difficile chiarire quale significato sia associato a quale uso. Preferirei una descrizione che si riferisse, per esempio, a "salti" e "mosse". Con questa terminologia, diresti che ogni mossa consiste in un certo numero di salti. I numeri nell'input forniscono il numero massimo di salti e l'output può essere inequivocabilmente descritto come riportante il numero minimo di mosse.
breadbox il

1
Qual è il criterio vincente? Dato che hai taggato code-golf e code-challenge non è chiaro.
Howard,

@breadbox Sì. Sono d'accordo, è ambiguo. Aggiornerò presto la domanda.
Coding man,

Risposte:


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

Casi test

      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

Approccio

L'approccio è una ricerca della forza bruta che utilizza una funzione ricorsiva.

A partire dalla posizione 1, impostare il valore nella posizione corrente su 0 e generare un array delle posizioni che è possibile saltare dalla posizione corrente. Passa la nuova posizione e l'array modificato a se stesso. I casi base sono quando il valore nella posizione corrente è 0 (impossibile saltare) o raggiungere la fine.

Quindi, per ciascuno degli array generati, invertirlo e ripetere la ricerca. Poiché le posizioni saltate sono impostate su 0, non possiamo saltare di nuovo da lì.

Per quell'array che abbiamo raggiunto la fine, trova quelli che hanno il numero minimo di 0. Sottraendo da esso il numero di 0 nell'array iniziale si ottiene il numero effettivo di salti eseguiti.


4

Mathematica, 197 193 caratteri

Forza 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 

Lavoro davvero impressionante. Può essere una forza bruta ma è comunque molto elegante.
DavidC,

3

Mathematica 351

[Nota: questo non è ancora completamente giocato a golf; Inoltre, è necessario regolare l'input per adattarlo al formato richiesto. E la regola di non saltare sulla stessa posizione due volte deve essere implementata. Esistono anche alcuni problemi di formattazione del codice che devono essere risolti. Ma è un inizio.]

Un grafico è costruito con nodi corrispondenti a ciascuna posizione, ovvero ogni cifra di input che rappresenta un salto. DirectedEdge[node1, node2]significa che è possibile saltare dal nodo 1 al nodo 2. I percorsi più brevi si trovano dall'inizio alla fine e quindi dalla fine all'inizio.

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


Questo è parzialmente sbagliato dal momento che non impone il non saltare su una regola numero due volte, ma è un inizio, quindi voterò per quello. Non avevo idea se ciò fosse possibile :)
Maniglia della porta

Hai ragione. Ho trascurato la regola del non saltare su un numero due volte Domani proverò a correggerlo.
DavidC

3

Python 304

Penso che questo nuovo approccio risolva (spero!) Tutti i problemi riguardanti il ​​caso [2,0] e simili:

In questa versione la sequenza di input viene attraversata (se possibile) fino alla fine e quindi riprendiamo il processo con la sequenza invertita. Ora possiamo garantire che per ogni soluzione valida uno dei salti atterra sull'ultimo 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

Queste sono le versioni golfate:

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

E alcuni esempi:

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

Ha un enorme potenziale per ulteriori golf. Ma non c'è gestione di input e output, che è parte di questo problema.
Ripristina Monica il

1
hai tonnellate di spazi bianchi non necessari ...
Maniglia della porta

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)

Simulazione:

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-giocato a 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

2

Python 271

questa è la mia soluzione:

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

Esempi:

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

E queste sono le versioni (parzialmente ormai) del golf:

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

Qualche esempio:

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

Sbagliato. All'ingresso [1], l'output dovrebbe essere 0 (l'output è 1). All'ingresso [3,0,0,1,4], l'output dovrebbe essere 3 (l'output è -1)
Coding man

@Coding man: Oops, scusa. C'è stato un controllo del salto exrtra. if (i> = len (L) -1): S.append (n) sembra risolvere il problema
Triadico

Dare ancora risultati errati. Es: [2,0] ---> 1 (dovrebbe essere -1).
Coding man,

@Coding man: Penso che la mia soluzione sia in conflitto con "Quindi, dovrebbe essere chiaro che si può sempre saltare dall'ultima posizione.", Poiché considero [2,0] ---> 1 una soluzione valida, dal momento che salta attraverso la fine.
Triadic,

1
Mi scuso per tutti questi errori. La linea "Quindi, dovrebbe essere chiaro che si può sempre saltare dall'ultima posizione". è stato rimosso. È stato usato solo per indicare che l'ultima posizione non è mai stata usata quando ci muoviamo in avanti nella sequenza. Quindi, può sempre essere usato per saltare quando ci spostiamo all'indietro. Ma in [2,0] il valore nell'ultima posizione è 0, puoi fare un salto di massimo 0 mosse. Quindi, non puoi mai raggiungere la posizione di partenza. La domanda è stata aggiornata
Coding man,

2

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

Simulazione:

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

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

0
-1

1
0

2

Rubino - circa 700 golf. Ho iniziato una versione golf, con nomi a carattere singolo per variabili e metodi, ma dopo un po 'mi sono interessato più all'algoritmo che al golf, quindi ho smesso di cercare di ottimizzare la lunghezza del codice. Né mi sono preoccupato di ottenere la stringa di input. Il mio sforzo è al di sotto.

Per aiutarti a capire come funziona ho incluso commenti che mostrano come viene manipolata una particolare stringa (u = "2 1 4 3 0 3 4 4 3 5 0 3"). Elenco le combinazioni di "rocce nel flusso" che sono disponibili per salire. Questi sono rappresentati con una stringa binaria. Fornisco l'esempio 0b0101101010 nei commenti e mostro come sarebbe usato. I 1 corrispondono alle posizioni delle rocce disponibili per il viaggio iniziale; gli 0 per il viaggio di ritorno. Per ciascuna di tali allocazioni, utilizzo la programmazione dinamica per determinare il numero minimo di salti richiesti in ciascuna direzione. Eseguo anche alcune semplici ottimizzazioni per eliminare alcune combinazioni all'inizio.

L'ho eseguito con le stringhe fornite in altre risposte e ottengo gli stessi risultati. Ecco alcuni altri risultati che ho ottenuto:

"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

Sarei interessato a sapere se gli altri ottengono gli stessi risultati per queste stringhe. Le prestazioni sono ragionevolmente buone. Ad esempio, ci è voluto meno di un minuto per ottenere una soluzione per questa stringa:

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

Il codice segue.

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 in GHCi

Ecco la versione normale:

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

Ecco la risposta GHCi (metti la riga una alla volta):

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 forza bruta. Genera la possibile risposta. (es. permutazione di [0..n-1] con zero e seguente elemento scartato. Quindi controlla se la risposta è corretta. Ottieni la lunghezza minima e aggiungi di una (poiché gli zero iniziale e finale sono eliminati).

Come usare: j[3,4,0,0,6]->3


Data.List.permutationsnon funziona in GHC, ma solo in GHCi. Secondo la nostra guida alle regole del golf a Haskell , è necessario aggiungere l'importazione o contrassegnare la risposta come "Haskell GHCi". La prima opzione è generalmente preferita dai golfisti di Haskell su questo sito.
Laikoni,

Invece di a<-permutations[0..t l-1],let f=takeWhile(/=0)a, puoi scrivere f<-map(takeWhile(/=0))(permutations[0..t l-1]), che può essere nuovamente giocato a golf f<-fst.span(>0)<$>permutations[0..t l-1]. Con questo sei tornato a 166 byte anche aggiungendo l'importazione: provalo online!
Laikoni,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.