Array Escape - get out of there

32

One day you awake only to find yourself caught in an array. You try to just walk out of there, taking one index at the time, but it seems there are other rules:

The array is completely filled with natural numbers.

  • If you find yourself on an index n, you go to the index array[n], except:
  • If you find yourself on an index n which is a prime number, you take array[n] steps back

Example: You start on index 4, in this array (start index is 0):

array = [1,4,5,6,8,10,14,15,2,2,4,5,7];
-----------------^ you are here

As the value of the field you are on is 8, you go to the index 8 as the first step. The field you land on contains the value 2. You then go to index 2 as your second step. As2is a prime number, you take 5 steps back, which is your third step. As there is no index -3, you successfully escaped the array in a total of 3 steps.

Your task is:

To write a program or function, which accepts an array and a start index as parameter, and outputs the amount of steps to escape the array. If you can't escape the array (e.g. [2,0,2] with start-index 2 => you constantly go from index 2 to 0), output a falsy value. You may use one-based indexing or zero-based indexing, but please specify which you use.

Test cases

Input: [2,5,6,8,1,2,3], 3

Output: 1

Input: [2, 0, 2], 2

Output: false

Input: [14,1,2,5,1,3,51,5,12,3,4,41,15,4,12,243,51,2,14,51,12,11], 5;

Output: 6

The shortest answer wins.

Michael Kunst

Posted 2016-07-25T11:08:57.993

Reputation: 513

7

Welcome to PPCG! This is a decent first challenge. :) Can we use 1-based indexing as well? Also it might be good to have a few more test cases. For future challenges you can also consider using the sandbox where you can get feedback from the community before a challenge goes live.

– Martin Ender – 2016-07-25T11:18:03.737

Thanks for the feedback - to be honest I didn't read through the page much, so thanks for the sandbox advice, will do that next time :) I'll do an edit shortly. – Michael Kunst – 2016-07-25T11:24:50.057

Based on your second last paragraph I think I know the answer, but just in case: does "natural numbers" here mean > 0 or >= 0? – Sp3000 – 2016-07-25T11:26:03.523

@Sp3000 It means >= 0 – Michael Kunst – 2016-07-25T11:33:54.667

Can you put a testcase which outputs 0? Or, is the start index guaranteed to be valid? – Leaky Nun – 2016-07-25T12:07:45.517

You're speaking of natural numbers N and you use 0 in your test cases, so I assume you mean the set N= {0,1,2,...}, right? Is it correct that we have to assume N={1,2,3,...} for 1-based indexing? Can you add some 1-based indexing testcases? – flawr – 2016-07-25T12:18:29.093

@LeakyNun yes, you can expect that the startIndex is valid. @flawr: no, it's N={0,1,2,3..} for 1-based indexing aswell. You will have escaped the array if you land on index 0 however. – Michael Kunst – 2016-07-25T12:20:35.843

@LeakyNun no, you take array[n] steps back, so the value which is in index 2. In the example above this is the number 5 – Michael Kunst – 2016-07-25T12:27:43.047

@LeakyNun you're right, pasted the wrong array, it's fixed now – Michael Kunst – 2016-07-25T12:44:12.937

@MichaelKunst Please add some 1-indexed testcases. – flawr – 2016-07-25T12:55:23.780

1Very closely related – Peter Taylor – 2016-07-25T13:44:32.897

1@Martin Ender it's not related to the question... but me as a mobile user find it impossible to use the sandbox. What should I do to get a feedback on my questions before actually posting them? – user6245072 – 2016-07-25T18:52:26.397

What would using 1-based indexing look like? Does it affect only the initial index or all elements of the array? Would a value of 3 mean we go to the (1-based) index 3, but still go three steps back? If so, the current test cases don't cover 1-based indexing at all... – Dennis – 2016-07-25T23:37:13.777

I am confused. The third test case says start on index 5 which has the value 3 which is prime and since you can't take 3 steps back because this is the first step the answer should be 1 step, right? So how is the answer 6 and why am I the only one that is confused? – Jerry Jeremiah – 2016-07-26T01:05:49.113

1@JerryJeremiah why can't you take 3 steps back? you'll land on index 2 if you start at 5 and take 3 steps back – Michael Kunst – 2016-07-26T06:08:20.753

5@user902383 going to index 2, which is prime, so we do 2 steps back and go to index 0, which is not prime. The value at index 0 is 2, so we go to index 2, which is prime ... repeat – edc65 – 2016-07-26T09:27:07.203

Ahhh. So "X steps back" means "X indexes toward zero"? I read "As the value of the field you are on is 8, you go to the index 8 as the FIRST STEP. The field you land on contains the value 2. You then go to index 2 as your SECOND STEP." which clearly (to me) equated "step" with "move" so "X steps back" would mean "back to the index you were on X moves ago". I still think using "first step" to mean "first move" and "second step" to mean "second move" and "steps back" to mean "indexes toward zero" is confusing but at least I understand now. – Jerry Jeremiah – 2016-07-26T21:37:22.860

Answers

4

Pyth, 31 Bytes

KlQ%tl-.u?}NUK?P_N-N@QN@QNKQEKK

The test cases

It uses zero to indicate a false value, the number of hops otherwise.

Cameron McCluskie

Posted 2016-07-25T11:08:57.993

Reputation: 346

9

Python, 161 138 bytes

Credits for factorial.

g=lambda x:0**x or x*g(x-1)
f=lambda a,i,n=0,l=[]:(i<0)+(i>=len(a))and n or(0 if i in l else f(a,[a[i],i-a[i]][i and-g(i-1)%i],n+1,l+[i]))

Ideone it!

How it works

Wilson's theorem is used for prime checking.

Loop detection by storing seen indices to an array (l) and checking whether current index is in l.

Leaky Nun

Posted 2016-07-25T11:08:57.993

Reputation: 45 011

6

Python, 107 bytes

import sympy
f=lambda a,i,n=0:0if n>len(a)else f(a,[a[i],i-a[i]][sympy.isprime(i)],n+1)if 0<=i<len(a)else n

Usage: f(list, start) ex: f([2,5,6,8,1,2,3], 3)

Returns 0 for loops (detected when n > len(a))

RootTwo

Posted 2016-07-25T11:08:57.993

Reputation: 1 749

5

Matlab, 138 bytes

This a straighforward approach, using 1-based indices because Matlab uses 1-based indices by default. To count the number of steps we use a for loop counting from 1 to infinity(!). For the case were we cannot escape the array, we use a vector v to keep track of which entries we already visited. If we visit an entry twice, we know we are stuck in an unescapeable cycle. To see check whether we are outside of an array, we use the try/catch structure, which also catches out of bounds exceptions.

function r=f(a,i);v=a*0;v(i)=1;for k=1:Inf;if isprime(i);i=i-a(i);else;i=a(i);end;try;if v(i);r=0;break;end;v(i)=1;catch;r=k;break;end;end

flawr

Posted 2016-07-25T11:08:57.993

Reputation: 40 560

5

05AB1E, 32 bytes

ï[U¯Xåi0,q}²gL<Xå_#X²XèXDˆpi-]¯g

Explanation

ï                                 # explicitly convert input to int
 [                            ]   # infinite loop
  U                               # store current index in X
   ¯Xåi0,q}                       # if we've already been at this index, print 0 and exit
           ²gL<Xå_#               # if we've escaped, break out of infinite loop
                   X²XèXDˆpi-     # else calculate new index
                               ¯g # print nr of indices traversed

Try it online

Emigna

Posted 2016-07-25T11:08:57.993

Reputation: 50 798

4

CJam, 44 bytes

Expects index array on the stack.

:G\{_G,,&{G=_L#)0{_L+:L;_mp3T?-F}?}L,?}:F~o@

Try it online!

My first CJam answer, hence why it's so terrible and imperative...

:G\{_G,,&{G=_L#)0{_L+:L;_mp3T?-F}?}L,?}:F~o@
:G                                              Store the array as G
  \                                             Put the index first
   {                                  }:F~      The recursive F function
     G,,                                        Generate a 0..length(G) sequence
    _   &                            ?          Check that the index is contained
         {                        }             If so, then...
          G=                                    Get the value at the index
            _L#)                 ?              If the value is in L (`-1)` gives `0` which is falsy)
                0                               Return 0 (infinite loop)
                 {              }               Otherwise...
                  _L+:L;                        Store the value we're accessing in L (infinite loop check)
                        _mp3T?-                 Remove 3 if the number is prime
                               F                Then recursively call F
                                   L,           We escaped! Return the size of "L" (number of steps)
                                          o     Print the top value of the stack
                                           @    Tries to swap 3 elements, which will error out

(it is considered okay to crash after the correct output as printed, which is what the program here does)

Ven

Posted 2016-07-25T11:08:57.993

Reputation: 3 382

4

JavaScript (ES6), 100

Index base 0. Note: this function modifies the input array

(a,p)=>eval("for(s=0;1/(q=a[p]);++s,p=p>1&&p%i||p==2?p-q:q)for(a[p]=NaN,i=1;p%++i&&i*i<p;);q==q&&s")

Less golfed

(a,p)=>
{
  for(s = 0; 
      1/ (q = a[p]); 
      ++s)
  {
    a[p] = NaN; // mark visited position with NaN to detect loops
    for(i = 1; p % ++i && i*i < p;); // prime check
    p = p > 1 && p % i || p == 2 ? p-q : q;
  }
  return q==q && s // return false if landed on NaN as NaN != NaN
}

Test

F=
(a,p)=>eval("for(s=0;1/(q=a[p]);++s,p=p>1&&p%i||p==2?p-q:q)for(a[p]=NaN,i=1;p%++i&&i*i<p;);q==q&&s")

;[
 [[2,5,6,8,1,2,3], 3, 1]
,[[2, 0, 2], 2, false]
,[[14,1,2,5,1,3,51,5,12,3,4,41,15,4,12,243,51,2,14,51,12,11], 5, 6]
].forEach(t=>{
  var [a,b,k]=t, i=a+' '+b,r=F(a,b)
  console.log(r==k?'OK':'KO',i+' -> '+r)
  
})  

edc65

Posted 2016-07-25T11:08:57.993

Reputation: 31 086

4

JAVA, 229 218 Bytes

Object e(int[]a,int b){Stack i=new Stack();int s=0;for(;!(a.length<b|b<0);s++){if(i.contains(b))return 1>2;i.add(b);b=p(b)>0?b-a[b]:a[b];}return s;}int p(int i){for(int j=2;j<i/2;j++)if(i%j<1)return 0;return i<2?0:1;}

Thanks to Kevin, 11 bytes bites the dust.

user902383

Posted 2016-07-25T11:08:57.993

Reputation: 1 360

A few things to golf it down some more: Stack<Integer>i=new Stack<>(); can be changed to Stack i=new Stack(); and return 1==2; can be changed to return 0>1;. Also, you might want to mention it's Java 7 instead of Java in general. – Kevin Cruijssen – 2016-07-27T11:40:16.320

@KevinCruijssen I'm not sure is it point to mention that it is java 7, as especially now this solution is compatible with most java versions. – user902383 – 2016-07-28T13:21:51.177

Well, in Java 8 you can use a lambdas which is shorter: a,b->{...} instead of Object e(int[]a,int b){...}, which is why I personally mention Java 7 to let people know I purposely haven't used Java 8 lambdas, but it's up to you. – Kevin Cruijssen – 2016-07-28T14:25:35.360

@KevinCruijssen fair enough, when I'm using lamda, I'm specifying java version, but when solution works with java 7, it's usually works with java 8 as well, so it was pointless to add version. But you might be right, i should specify minimum version. – user902383 – 2016-07-28T14:39:37.263

3

C, 121 bytes

Function f accepts array, starting index (0-based) and number of elements in the array, since there is no way how to test the end of an array in C (at least I don't know any).

p(n,i,z){return--i?p(n,i,z*i*i%n):z%n;}c;f(a,i,n)int*a;{return i<0||i/n?c:c++>n?0:i&&p(i,i,1)?f(a,i-a[i],n):f(a,a[i],n);}

Try it on ideone!

Note: function p(n) tests if n is prime or not. Credit for this goes to @Lynn and his answer for Is this number a prime?

Jasmes

Posted 2016-07-25T11:08:57.993

Reputation: 131

1@raznagul nonsense, you can't determine the length of an input parameter array. See answer 2 on the same question – edc65 – 2016-07-26T09:58:10.000

@edc65: Sorry, I should have read beyond the first answer. – raznagul – 2016-07-26T10:01:22.203

@Jasmes - In code golf, a function should be able to be called multiple times to get the same output. Your code requires resetting c to call the function again. – owacoder – 2016-07-26T12:09:15.787

3

JavaScript, 121 132 bytes

p=n=>t=i=>n%i&&n>i?t(i+1):(0<n&&n<=i?1:0),c=-1,a=>r=s=>(++c,0<=s&&s<a.length?(p(s)(2)?r(s-a[s]):0||([a[s],s]=[0,a[s]])[1]?r(s):0):c)

f=(p=n=>t=i=>n%i&&n>i?t(i+1):(0<n&&n<=i?1:0),c=-1,a=>r=s=>(++c,0<=s&&s<a.length?(p(s)(2)?r(s-a[s]):0||([a[s],s]=[0,a[s]])[1]?r(s):0):c));

let test_data = [[[1,4,5,6,8,10,14,15,2,2,4,5,7],4],
                 [[2,5,6,8,1,2,3],3],
                 [[2,0,2],2],
                 [[14,1,2,5,1,3,51,5,12,3,4,41,15,4,12,243,51,2,14,51,12,11],5]];
for (test of test_data) {
    c = -1;
    console.log(f(test[0])(test[1]));
}

edit 1: oops, missed the bit about returning number of steps. fix coming soonish.

edit 2: fixed

Yay295

Posted 2016-07-25T11:08:57.993

Reputation: 650

3

Racket, 183 156 bytes

Probably more bytes savable with further golfing, but that's it for me. :)

(require math)(define(e l i[v'()][g length])(cond[(memq i v)#f][(not(< -1 i(g l)))(g v)][else(e l((λ(a)(if(prime? i)(- i a)a))(list-ref l i))(cons i v))]))

Complete module with test suite with cleaner function:

#lang racket

(require math)

(define (e l i [v'()] [g length])
  (cond
    [(memq i v) #f]
    [(not (< -1 i (g l))) (g v)]
    [else (e l
             ((λ (a) (if (prime? i)
                         (- i a)
                         a))
              (list-ref l i))
             (cons i v))]))

(module+ test
  (require rackunit)
  (define escape-tests
    '((((2 5 6 8 1 2 3) 3) . 1)
      (((2 0 2) 2) . #f)
      (((14 1 2 5 1 3 51 5 12 3 4 41 15 4 12 243 51 2 14 51 12 11) 5) . 6)))
  (for ([t escape-tests])
    (check-equal? (apply e (car t)) (cdr t) (~a t))))

Run it like raco test e.rkt

Major kudos for @cat discovering the undocumented prime? function.

Winny

Posted 2016-07-25T11:08:57.993

Reputation: 1 120

2

Java, 163 160 bytes

boolean p(int n){for(int i=2;i<n;)if(n%i++==0)return 0>1;return 1>0;}
int f(int[]a,int n){return n<0||n>=a.length?1:p(n)?n<a[n]?1:1+f(a,a[n-a[n]]):1+f(a,a[n]);}

p(n) is for prime testing, f(a,n) is for the escape function. Usage:

public static void main(String[] args) {
    int[] array = {14,1,2,5,1,3,51,5,12,3,4,41,15,4,12,243,51,2,14,51,12,11};
    System.out.println(f(array, 5));
}

Ungolfed version:

static boolean isPrime(int n) {
    for (int i = 2; i < n; i++) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

static int escape(int[] array, int n) {
    if (n < 0 || n >= array.length) {
        return 1;
    } else if (isPrime(n)) {
        if (n < array[n]) {
            return 1;
        } else {
            return 1 + escape(array, array[n - array[n]]);
        }
    } else {
        return 1 + escape(array, array[n]);
    }
}

Justin

Posted 2016-07-25T11:08:57.993

Reputation: 417

1

Perl 6, 85 bytes

->\n,\a{{.[+a].defined??0!!+$_}(lazy n,{.is-prime??$_- a[$_]!!a[$_]}...^!(0 <=* <a))}

Explanation:

lazy n, { .is-prime ?? $_ - a[$_] !! a[$_] } ...^ !(0 <= * < a)

This is a lazy sequence of the indices traversed according to the rule. If the index eventually exceeds the input array bounds (the !(0 <= * < a) condition), the sequence is finite; otherwise, the indices cycle infinitely.

That sequence is fed to the internal anonymous function:

{ .[+a].defined ?? 0 !! +$_ }

If the sequence is defined at the index given by the size of the input array, it must have entered an infinite cycle, so 0 is returned. Otherwise, the size of the sequence +$_ is returned.

Sean

Posted 2016-07-25T11:08:57.993

Reputation: 4 136

1

Perl 5, 107 + 1 (-a) = 108 bytes

for($i=<>;!$k{$i}++&&$i>=0&&$i<@F;$s++){$f=0|sqrt$i||2;1while$i%$f--;$i=$f?$F[$i]:$i-$F[$i]}say$k{$i}<2&&$s

Try it online!

0-based list. Returns false (blank) if the list is unescapable.

Xcali

Posted 2016-07-25T11:08:57.993

Reputation: 7 671