g | x | w | all
Bytes Lang Time Link
053Charcoal250606T085606ZNeil
757C++ gcc250604T190626ZDavid G.
070JavaScript Node.js250604T060541Zl4m2
066Brachylog250603T230939ZDLosc
316Python3250603T164429ZAjax1234
074JavaScript ES6250603T150427ZArnauld
017Pyth250603T142828ZCursorCo

Charcoal, 53 bytes

FLθ⊞υEθ∧⁻ιλκFυ«≔⌕ι⁰η§≔ιη±¹FΦLθ⁼§ικ↔⁻ηκ⊞υEι∧⁻κμλ»›⁰⌈⊟υ

Try it online! Link is to verbose version of code. Explanation: Lots of brute force, working backwards from the end. (I tried to write a faster version, but I wasn't getting anywhere even with the 100 size test case.)

FLθ⊞υEθ∧⁻ιλκFυ«

Start a breadth-first search using each possible index as the end of the traversal.

≔⌕ι⁰η

Get the earliest hop of this traversal.

§≔ιη±¹

Mark it as visited.

FΦLθ⁼§ικ↔⁻ηκ

Find all unvisited indices that can hop here. (Because visited indices have been replaced with -1 they will never match a successful hop.)

⊞υEι∧⁻κμλ

Add another traversal with this as the new earliest hop.

»›⁰⌈⊟υ

Check that the last traversal visited all of the indices.

C++ (gcc), 757 bytes

#define R (i+v)
#define L (i-v)
#define V int v=I[i];
#define D B[i]
struct A{int C;int E;int G;int F;int H;};A B[10000];int M(int I[],int N,int i,int Q){if(Q==0)return 1;V
#define TRY(x)if(!B[x].H){B[x].H=1;if(M(I,N,(x),Q-1))return 1;B[x].H=0;}
if(D.C)TRY(L);if(D.E)TRY(R);return 0;}int T(int I[],int N){int K=0,J=0,i;for(i=0;i<N;i++){V
D.C=L>=0;D.E=R<N;D.G=0;D.F=0;D.H=0;if(D.C){K++;}else{if(D.E){K++;}else{D.F=1;J++;}}}if(J>1)return 0;int P=1;while(P&&(K>0)){P=0;for(i=0;i<N;i++){V
if(D.F)continue;int O=0;if(D.C&&B[L].G){D.C=0;O=1;}if(D.E&&B[R].G){D.E=0;O=1;}if(O)P=1;if(D.C){if(!D.E){if(J){B[L].G=1;D.F=1;P=1;}}}else{if(D.E){if(J){B[R].G=1;D.F=1;P=1;}}else{D.F=1;J++;}}}if(J>1)return 0;}for(i=0;i<N;i++){D.H=1;if(M(I,N,i,N-1))return 1;D.H=0;}return 0;}

Try it online!

This does all the test data, including the two 10Ks, plus a few of my own, in under 6 seconds on TIO.

Fitting it in a SE answer took work, since I include the 10Ks in the TIO. (I never knew there was a 64k limit.)

I started with a brute-force program, but my C++ version is now almost 37 hours into the first 10010K length (the 100 took 1.5 seconds). So I revised to find the entries that can be the final entry, and then (if there is one) have other entries "speak for" the only one they can go to. This repeats until I can't make progress, and then I do a brute force pass on what is left.

The ungolfed body:

#define R (i+v)
#define L (i-v)
#define V int v=array[i];
#define D data[i]

struct datum { 
    bool can_go_left  : 1;
    bool can_go_right : 1;
    bool spoken_for   : 1;
    bool speaks_for   : 1;
    bool used         : 1;
};

datum data[10000];

int attempt(int const array[], int length, int i, int needed)
{
    if (needed == 0) return 1;
    V
    #define TRY(x) if (!data[x].used) { data[x].used=true; if (attempt(array,length,(x),needed-1)) return 1; data[x].used=false; }
    if (D.can_go_left) TRY(L);
    if (D.can_go_right) TRY(R);
    return 0;
}

int test(int const array[], int length)
{
    //memset(data, 0, sizeof(data));

    int pending = 0,
        final = 0,
    i;

    // initial setup.  Sets up the data array, and pending and final
    for (i=0; i<length; i++) {
        V
        D.can_go_left = L>=0;
        D.can_go_right = R < length;
        D.spoken_for = false;
        D.speaks_for = false;
        D.used = false;
        if (D.can_go_left) {
        pending++;
            //if (D.can_go_right) {
            //    pending++;
            //} else {
            //    //ok... speak for or final?
            //    pending++;
            //}
        } else {
            if (D.can_go_right) {
                //ok... speak for or final?
                pending++;
            } else {
        D.speaks_for = true;
                final++;
            }
        }
    }

    dump_array(array,length,"initial setup",pending,final);

    if (final>1) return false;

    // passes trying to improve.  Generatlly needs final...
    bool dirty = true;
    while (dirty && (pending>0)) {
        dirty = false;
        for (i=0; i<length; i++) {
            V
            if (D.speaks_for) continue;
            bool changed = false;
            if (D.can_go_left && data[L].spoken_for) { D.can_go_left=0; changed=true; }
            if (D.can_go_right && data[R].spoken_for) { D.can_go_right=0; changed=true; }
            if (changed) dirty = true;
            if (D.can_go_left) {
                if (!D.can_go_right) {
                //if (D.can_go_right) {
                //    //still pending
                //} else {
                    if (final) {
                        data[L].spoken_for=true;
                        D.speaks_for=true;
                        dirty=true;
                    }
                }
            } else {
                if (D.can_go_right) {
                    if (final) {
                        data[R].spoken_for=true;
                        D.speaks_for=true;
                        dirty=true;
                    }
                } else {
            D.speaks_for = true;
                    final++;
                }
            }
        }
        dump_array(array,0,"after pass",pending,final);
        if (final>1) return 0;
    }
    dump_array(array,length,"after all pass",pending,final);

    //do the brute force...
    for (i=0; i<length; i++) {
        D.used = true;
        if (attempt(array,length,i,length-1)) return 1;
        D.used = false;
    }

    return 0;
}

JavaScript (Node.js), 70 bytes

f=(a,i)=>a.some((c,j)=>c*c-i*i--?!/\d/.test(a):f(c=[...a],j,c[j]=1/0))

Try it online!

Don't get how xor of Arnauld work but whatever

Brachylog, 66 bytes

~c₂↰₁
kʰc+0|htℕ₁J&{k,0}ʰ;[J]z{↰₅|↔{↔ʰ}ᵐ↰₅↔ᵐ↔}↰
⟨⟨hⁱ²c{th₎}⟩≡{tb₎}⟩

Try it online!

Explanation

Performs an actual traversal of the list, replacing visited numbers with 0s and using Brachylog's non-determinism to pick directions.

Entry point (takes a list of integers as input):

~c₂↰₁
~c₂    Un-concatenate the input list into two parts
   ↰₁  Call the below predicate

Main, recursive predicate:

kʰc+0|htℕ₁J&{k,0}ʰ;[J]z{↰₅|↔{↔ʰ}ᵐ↰₅↔ᵐ↔}↰
                                         EITHER:
kʰ                                       Remove the last element of the first part
  c                                      Concatenate all remaining elements in one list
   +0                                    The sum is 0
                                         (in which case, return success)
     |                                   OR:
      ht                                 The last element of the first part
        ℕ₁                               must be a positive integer (not 0)
          J                              Store that as J, the jump distance
           &                             And
            {   }ʰ                       Modify the first part as follows:
             k                            Remove the last element
              ,0                          Concatenate a 0 in its place
                  ;[J]                   Pair the modified list with [J]
                      z                  Zip, pairing each of the two parts with J
                       {              }  Either:
                        ↰₅                Call the below predicate directly
                          |              Or:
                           ↔              Swap the two parts
                            {↔ʰ}ᵐ         and reverse each part
                                 ↰₅       Then call the below predicate
                                   ↔ᵐ     Afterwards, reverse each part
                                     ↔    and swap the two parts back
                                       ↰ Call this predicate recursively

Helper predicate that does the jumps (slightly ungolfed so it's easier to explain):

⟨⟨{hh}c{th₎}⟩≡{tb₎}⟩
 {hh}              The first part
      {th₎}        The first J elements of the second part
 ⟨    c    ⟩        Concatenate those two lists
                   This is the new first part
             {tb₎} The second part without the first J elements
                   This is the new second part
⟨           ≡     ⟩ Wrap both parts in a list and return it

A partial worked example: Suppose our input list is [5,3,2,6,1,4] and we are starting at the 2. After splitting the list at that point, we have [[5,3,2],[6,1,4]]. The main predicate saves off the 2 in J and replaces it with 0, giving [[5,3,0],[6,1,4]]. Pairing with [J] gives [[[5,3,0],[6,1,4]],[2]]. Zipping gives [[[5,3,0],2],[[6,1,4],2]]. Then we call the helper predicate:

{h }    First element: [[5,3,0],2]
{ h}    First element of that: [5,3,0]

{t  }   Last element: [[6,1,4],2]
{ h₎}   If that is of the form [A,B], take the first B elements of A: [6,1]

⟨  c  ⟩  Concatenate those two: [5,3,0,6,1]

{t  }   Last element: [[6,1,4],2]
{ b₎}   If that is of the form [A,B], remove the first B elements from A: [4]

⟨  ≡  ⟩  Pair those two: [[5,3,0,6,1],[4]]

This represents a jump 2 spots to the right, onto the 1. The recursion continues from here, backtracking when it hits a dead end.

Python3, 316 bytes

E=enumerate
def f(l):
 if(O:=[i for i,a in E(l)if i-a<0 and i+a>=len(l)]):
  q,s=[(O[0],[O[0]])],[]
  for i,L in q:
   if len(L)==len(l):return 1
   T={}
   for I,a in E(l):
    if any(I+a*j==i for j in[1,-1])and I not in L:T[I]=sum(0<=I+j*a<len(l)for j in[1,-1])
   q+=[(K,L+[K])for K in T if T[K]==min(T.values())]

Try it online!

JavaScript (ES6), 74 bytes

Returns a Boolean value.

a=>a.some(g=(v,i)=>(v=a[i])?v^=a[i]^=g(a[i]=0,i-v)|g(0,i+v):!a.some(v=>v))

Try it online!


JavaScript (ES6), 71 bytes

Similar but much slower.

a=>a.some(g=(v,i)=>(v=a[i])?v^=a[i]^=g(a[i]=0,i-v)|g(0,i+v):!+a.join``)

Try it online!

Pyth, 17 bytes

sqVmaVtdd.pUQPM.p

Try it online!

Takes input as a list, outputs the number of valid traversal paths (0 is falsy in pyth, >=1 is truthy). Link will time out for any inputs of length greater than about 9.

Explanation

sqVmaVtdd.pUQPM.pQ    # implicitly add Q
                      # implicitly assign Q = eval(input())
             PM       # remove the last element of each of
               .pQ    # all permutations of Q
   maVtdd             # get the absolute differences between adjacent elements of
         .pUQ         # all permutations of range(len(Q))
 qV                   # vectorized equality, look for elements that are equal across these two lists
s                     # sum