配列エスケープ-そこから出て


32

ある日、目を覚まして、自分がアレイに巻き込まれているのを見つけます。そこから出て、一度に1つのインデックスを取得しようとしますが、他のルールがあるようです。

配列は自然数で完全に埋められます。

  • インデックスに自分自身を見つけた場合 nにいる場合は、index array[n]に移動しますが、次の場合を除きます。
  • あなたがn素数であるインデックスに自分自身を見つけた場合、あなたはarray[n]戻ってステップを取る

例:4この配列のindex から開始します(開始インデックスは0):

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

現在のフィールドの値は8なので8、最初のステップとしてインデックスに移動します。着陸するフィールドには値が含まれています2。次に2、2番目のステップとしてインデックスに移動します。以下のよう2素数である、あなたはあなたの第三段階である、バックの5つのステップを取ります。インデックスがないため-3、合計3ステップで配列を正常にエスケープしました。

あなたの仕事は:

パラメータとして配列と開始インデックスを受け取り、配列をエスケープするためのステップ数を出力するプログラムまたは関数を作成します。配列をエスケープできない場合(たとえば[2,0,2]、start-index 2=>を使用すると、常にインデックスから移動します)2からに0)、偽の値を出力します。1ベースのインデックス付けまたはゼロベースのインデックス付けを使用できますが、使用するものを指定してください。

テストケース

入力: [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

最短の答えが勝ちです。


7
PPCGへようこそ!これはまずまずの挑戦です。:) 1ベースのインデックスも使用できますか?また、さらにいくつかのテストケースを用意しておくとよいでしょう。将来のチャレンジについては、サンドボックスを使用することも検討できます。サンドボックスでは、チャレンジが公開される前にコミュニティからフィードバックを得ることができます。
マーティンエンダー


1
@Martin Enderそれは質問とは関係ありません...しかし、モバイルユーザーとしての私は、サンドボックスを使用することは不可能だと思います。実際に質問を投稿する前に、質問に対するフィードバックを得るにはどうすればよいですか?
user6245072

1
@JerryJeremiahどうして3歩も戻れないの?あなたが5で開始し、バック3つのステップを取る場合は、インデックス2に着陸う
マイケル・クンスト

5
@ user902383はインデックス 2に進みます。これは素数であるため、2ステップ戻り、素数ではないインデックス 0に進みます。インデックス 0 の値は2なので、インデックス 2に移動します。これはプライム...リピート
edc65

回答:



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.


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


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

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


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


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.


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

@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

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

@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

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)


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?


1
@raznagul nonsense, you can't determine the length of an input parameter array. See answer 2 on the same question
edc65

@edc65: Sorry, I should have read beyond the first answer.
raznagul

@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

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


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.


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

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.


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.

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.