数组转义-离开那里


32

有一天,您醒来只是发现自己陷入了阵列。您尝试走出那里,同时获取一个索引,但是似乎还有其他规则:

该数组完全用自然数填充。

  • 如果发现自己在索引上n,请转到该索引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质数,您需要向后退5步,这是您的第三步。由于没有索引-3,您总共分了3个步骤成功地对数组进行了转义。

您的任务是:

编写一个程序或函数,该程序或函数接受一个数组和一个起始索引作为参数,并输出逃逸该数组的步骤数。如果无法转义数组(例如,[2,0,2]使用start-index 2=>,则不断从index 2转到0),则输出错误的值。您可以使用基于1的索引或基于0的索引,但是请指定要使用的索引。

测试用例

输入: [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的索引吗?另外,拥有更多的测试用例可能也很好。对于未来的挑战,您还可以考虑使用沙盒,在挑战发布之前,您可以在其中获得社区的反馈。
Martin Ender


1
@Martin Ender与问题无关...但是作为移动用户,我发现无法使用沙箱。在实际发布问题之前,我应该怎么做才能获得反馈?
user6245072 '16

1
@JerryJeremiah为什么您不能退后三步?如果您从5开始并向后退3步,您将进入索引2
Michael Kunst

5
@ user902383转到索引 2,它是素数,所以我们往后退了2步,转到索引 0,它不是素数。索引 0 的值是2,因此我们转到索引 2,它是质数...重复
edc65 '16

Answers:



9

Python,161138字节

学分为阶乘。

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

伊迪恩!

怎么运行的

威尔逊定理用于素数检验。

通过将可见索引存储到数组(l)并检查当前索引是否位于中来进行循环检测l


6

Python,107个字节

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

用法:f(list, start)例如:f([2,5,6,8,1,2,3], 3)

返回0循环(在时检测到n > len(a)


5

Matlab,138个字节

这是直接使用基于1的索引的方法,因为Matlab默认使用基于1的索引。要计算步数,我们使用for从1到无穷(!)的循环。对于无法逃脱数组的情况,我们使用向量v来跟踪已经访问过的条目。如果我们两次访问一个条目,就会知道我们陷入了不可逃避的循环。要查看是否在数组之外,我们使用try/catch结构,该结构还捕获了超出范围的异常。

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字节

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

说明

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

在线尝试


4

JavaScript(ES6),100

索引基数为0。注意:此函数修改输入数组

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

少打高尔夫球

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

测试

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,229218字节

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

多亏了凯文(Kevin),11个字节才尘土飞扬。


Stack<Integer>i=new Stack<>();可以进行更多操作的一些事项:可以更改为Stack i=new Stack();return 1==2;也可以更改为return 0>1;。另外,您可能要提到的是Java 7,而不是一般的Java。
凯文·克鲁伊森

@KevinCruijssen我不确定要指出它是Java 7,因为现在尤其是此解决方案与大多数Java版本兼容。
user902383 '16

好吧,在Java 8中,您可以使用较短的lambda:a,b->{...}代替Object e(int[]a,int b){...},这就是为什么我亲自提到Java 7来让人们知道我故意没有使用Java 8 lambda,但这取​​决于您。
凯文·克鲁伊森

@KevinCruijssen足够公平,当我使用lamda时,我指定的是Java版本,但是当解决方案与java 7一起使用时,它通常也与java 8一起使用,因此添加版本毫无意义。但是您可能是对的,我应该指定最低版本。
user902383 '16

4

CJam,44个字节

期望index array在堆栈上。

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

在线尝试!

我的第一个CJam答案,因此为什么它如此可怕和迫切...

: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

(在打印正确的输出后,可以认为它可以崩溃,这是此处程序的作用)


3

C,121字节

函数f接受数组,起始索引(从0开始)和数组中的元素数,因为没有办法在C语言中测试数组的结尾(至少我不知道)。

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

ideone尝试!

注意: function p(n)测试是否n为素数。值得赞扬的 @Lynn,他的回答是这个数字是素数吗?


1
@raznagul废话,您无法确定输入参数数组的长度。看到关于同一问题的答案2
edc65 '16

@ edc65:对不起,我应该已经阅读了第一个答案以外的内容。
raznagul

@James-在代码高尔夫中,应该可以多次调用一个函数以获取相同的输出。您的代码需要重置c才能再次调用该函数。
owacoder '16

3

JavaScript中,121个 132字节

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

编辑1:糟糕,错过了有关返回步数的信息。立即修复。

编辑2:固定


3

球拍,183156字节

可能在进一步打高尔夫球时可以节省更多字节,但这对我来说就是这样。:)

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

带有测试套件的完整模块,具有更清洁的功能:

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

像这样运行 raco test e.rkt

@cat 发现未记录prime?功能的主要荣誉。


2

Java 163160字节

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)用于主要测试,f(a,n)用于转义功能。用法:

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

非高尔夫版本:

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个字节

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

说明:

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

这是根据规则遍历的索引的惰性序列。如果索引最终超出了输入数组的范围(!(0 <= * < a)条件),则序列是有限的;否则,序列为0。否则,索引将无限循环。

该序列被提供给内部匿名函数:

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

如果序列是在输入数组的大小给定的索引处定义的,则它必须已进入一个无限循环,因此0将其返回。否则,将+$_返回序列的大小。


1

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

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

在线尝试!

基于0的列表。如果列表无法转义,则返回false(空白)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.