Array Escape - убирайся оттуда


32

Однажды ты просыпаешься только для того, чтобы оказаться пойманным во множестве. Вы пытаетесь просто уйти оттуда, взяв один индекс за раз, но, похоже, существуют другие правила:

Массив полностью заполнен натуральными числами.

  • Если вы попали в индекс n, вы переходите в индекс array[n], кроме:
  • Если вы попадаете в индекс, nкоторый является простым числом, вы делаете array[n]шаги назад

Пример: вы начинаете с индекса 4в этом массиве (индекс запуска равен 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=> вы постоянно переходите от индекса 2к 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? Также было бы хорошо иметь еще несколько тестовых случаев. Для будущих задач вы также можете рассмотреть возможность использования песочницы, где вы можете получить обратную связь от сообщества, прежде чем задача будет запущена.
Мартин Эндер


1
@Martin Ender, это не связано с вопросом ... но я, как мобильный пользователь, считаю невозможным использование песочницы. Что я должен сделать, чтобы получить обратную связь по моим вопросам перед тем, как отправлять их?
user6245072

1
@JerryJeremiah, почему ты не можешь сделать 3 шага назад? Вы попадете в индекс 2, если начнете с 5 и сделаете 3 шага назад
Майкл Кунст,

5
@ user902383 идет к индексу 2, который является простым, поэтому мы делаем 2 шага назад и идем к индексу 0, который не является простым. Значение по индексу 0 равно 2, поэтому мы переходим к индексу 2, который является простым ... повторить
edc65

Ответы:



9

Python, 161 138 байт

кредиты для факториала.

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

Идео это!

Как это работает

Теорема Вильсона используется для простой проверки.

Обнаружение цикла путем сохранения видимых индексов в array ( 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)ex: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, 229 218 байт

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

Благодаря Кевину, 11 байтов кусает пыль.


Несколько вещей для игры в гольф еще немного: Stack<Integer>i=new Stack<>();могут быть изменены Stack i=new Stack();и return 1==2;могут быть изменены return 0>1;. Кроме того, вы можете упомянуть, что это Java 7 вместо Java в целом.
Кевин Круйссен

@KevinCruijssen Я не уверен, стоит ли упоминать, что это Java 7, так как особенно сейчас это решение совместимо с большинством Java-версий.
user902383

Что ж, в Java 8 вы можете использовать лямбды, которые короче: a,b->{...}вместо этого Object e(int[]a,int b){...}, поэтому я лично упоминаю Java 7, чтобы люди знали, что я специально не использовал лямбды Java 8, но решать вам.
Кевин Круйссен

@ KevinCruijssen, если честно, когда я использую lamda, я указываю версию java, но когда решение работает с java 7, обычно оно работает и с java 8, поэтому добавлять версию бессмысленно. Но вы можете быть правы, я должен указать минимальную версию.
user902383

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является ли простое число или нет. Кредит на это идет к @ Линн и его ответу Для этого числа простое число?


1
@raznagul ерунда, вы не можете определить длину массива входных параметров. Смотрите ответ 2 на тот же вопрос
edc65

@ edc65: Извините, я должен был прочитать после первого ответа.
Разнагул

@Jasmes - В коде гольф, функция должна вызываться несколько раз, чтобы получить один и тот же результат. Ваш код требует сброса cдля повторного вызова функции.
owacoder

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

Ракетка, 183 156 байт

Возможно, больше байтов будет сохранено при дальнейшей игре в гольф, но это все для меня. :)

(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, 163 160 байт

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)для функции escape. Использование:

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)условие), последовательность конечна; в противном случае индексы вращаются бесконечно.

Эта последовательность передается внутренней анонимной функции:

{ .[+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 (пусто), если список неизбежен.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.