Перевірте мої тунельні масиви


18

Уявіть, що у вас є масив цілих чисел, чиї негативні значення є вказівниками на інші позиції в тому ж масиві, лише що ці значення представляють тунелі, тож якщо значення в позиції A додатне і вказує на позицію B, то значення в позиції B також повинен бути позитивним і вказувати на положення A, щоб представляти обидва кінці тунелю. Так:

Виклик

  • Дано масив цілих чисел, перевірте, чи відповідає масив обмеженням тунельний масив і поверніть два чіткі, когерентні значення для truthy та falsey.
  • Значення масиву будуть нижчими за нуль для позицій, які не є тунелями, і нульові або вище для позицій тунелю. Якщо ваш масив є 1-індексованим, то нульове значення являє собою не тунельну позицію. Значення без тунелю не потрібно перевіряти.
  • Якщо позитивне значення в клітині вказує на себе, це фальсифікація. Якщо A вказує на B, B на C і C на A, це фальсифікація. Якщо додатне значення вказує за межі масиву, це фальсифікація.

Приклади

Наступні приклади індексуються 0:

[-1, -1, -1, 6, -1, -1, 3, -1, -1]  Truthy (position 3 points to position 6 and vice versa)
[1, 0]                              Truthy (position 0 points to position 1 and vice versa)
[0, 1]                              Falsey (positions 0 and 1 point to themselves)
[4, 2, 1, -1, 0, -1]                Truthy
[2, 3, 0, 1]                        Truthy
[1, 2, 0]                           Falsey (no circular tunnels allowed)
[-1, 2, -1]                         Falsey (tunnel without end)
[]                                  Truthy (no tunnels, that's OK)
[-1, -2, -3]                        Truthy (no tunnels, that's OK)
[1, 0, 3]                           Falsey (tunnel goes beyond limits)
[1]                                 Falsey (tunnel goes beyond limits)
[1, 0, 3, 7]                        Falsey (tunnel goes beyond limits)

Це , тому може виграти найкоротший код для кожної мови!


3
за що нам повернутись [0]?
ngn

1
Розширюючись на запитання ngn, чи дозволяються самостійні тунелі? Що б справи [0,1]і [0,-1,2]дали?
ділнан

1
@dylnan [0,1]є в прикладах. "Якщо позитивне значення в комірці вказує на себе, це фальсифікація"
ngn

1
запропонований тест:[2,3,0,1]
ngn

1
@JonathanAllan значення тунелю - це значення, що вказують на можливі положення масиву. Якщо ваш масив індексується 0, то кожне значення нижче 0 не є тунельним значенням. Якщо це 1-індексується, то кожне значення нижче 1 не є тунельним значенням.
Чарлі

Відповіді:


8

R , 47 байт

function(v,a=v[v>0],b=sort(a))all(v[a]==b&a!=b)

Спробуйте в Інтернеті!


Нерозкручений код та пояснення:

f=
function(v){          # v vector of tunnel indexes (1-based) or values <= 0

  a = v[v>0]          # get the tunnel positions

  b = sort(a)         # sort the tunnel positions ascending

  c1 = v[a]==b        # get the values of 'v' at positions 'a'
                      # and check if they're equal to the sorted positions 'b'
                      # (element-wise, returns a vector of TRUE/FALSE)

  c2 = a != b         # check if positions 'a' are different from sorted positions 'b' 
                      # (to exclude tunnels pointing to themselves, element-wise,
                      #  returns a vector of TRUE/FALSE)

  all(c1 & c2)        # if all logical conditions 'c1' and 'c2' are TRUE then
                      # returns TRUE otherwise FALSE
}

Я дуже вдячний за пояснення цієї відповіді. :-)
Чарлі

3
@Charlie: додано пояснення
digEmAll


5

APL (Dyalog Unicode) , 19 24 байти

×/<∘≢⍨×≠∘⍳∘≢⍨×0∘>∨⊢=⊢⍳⍳⍨

Спробуйте в Інтернеті!

Префікс анонімного лямбда, повернення 1 для truthy та 0 для фальшивого. Посилання TIO містить "попередньо попередньо" версію виводу для тестових випадків.

Вигуки до @ngn та @ Adám для економії приблизно мільйона байтів.

Додатковий вигук на @ngn за допомогою щодо виправлення відповіді на деякі тестові випадки та переведення її на поїзд.

Оновлена ​​відповідь використовує ⎕IO←0, встановлюючи I ndex O на 0.

Як:

×/<∘≢⍨×≠∘⍳∘≢⍨×0∘>∨⊢=⊢⍳⍳⍨  Prefix lambda, argument   4 2 1 ¯1 0 ¯1.
                       ⍳⍨  Index of (⍳)  in ⍵. ⍵⍳⍵  0 1 2 3 4 3
                     ⊢⍳    Index of that in  (returns the vector length if not found). 
                           ⍵⍳⍵⍳⍵  4 2 1 6 0 6
                  ⊢=       Compare that with ⍵. ⍵=⍵⍳⍵⍳⍵  1 1 1 0 1 0
                           This checks if positive indices tunnel back and forth correctly.
                          Logical OR with
              0∘>          0>⍵  0 0 0 1 0 11 1 1 0 1 0  1 1 1 1 1 1
                           Removes the zeroes generated by negative indices
             ×             Multiply that vector with
                          (using  as both arguments)
         ⍳∘≢               Generate the range [0..length(⍵)-1]
       ≠∘                  And do ⍵≠range; this checks if any          
                           element in  is tunneling to itself.
                           ⍵≠⍳≢⍵  4 2 1 ¯1 0 ¯10 1 2 3 4 5  1 1 1 1 1 1  
      ×                    Multiply that vector with
                          (using  as both arguments)
  <∘≢                       < length(⍵)  4 2 1 ¯1 0 ¯1 < 6  1 1 1 1 1 1
                           This checks if any index is out of bounds
×/                         Finally, multiply and reduce.
                           ×/1 1 1 1 1 1  1 (truthy)

Я думаю, що це не працює для (1), (3 2 1), (5 4 3 2 1).
nwellnhof

0<×Я думаю
Уріель

4

JavaScript (ES6), 35 байт

Збережено 1 байт завдяки @Shaggy

a=>a.every((v,i)=>v<0|v!=i&a[v]==i)

Спробуйте в Інтернеті!

Прокоментував

a =>                // a[] = input array
  a.every((v, i) => // for each value v at position i in a[]:
    v < 0 |         //   force the test to succeed if v is negative (non-tunnel position)
    v != i &        //   make sure that this cell is not pointing to itself
    a[v] == i       //   check the other end of the tunnel
  )                 // end of every()

Добре, що я перевірив рішення, перш ніж розміщувати порт мого рішення Japt, який майже ідентичний цьому. Ви можете зберегти байт за допомогою a=>a.every((v,i)=>v<0|v!=i&a[v]==i).
Кудлатий



3

Perl 6 , 36 байт

{!.grep:{2-set $++,$^v,.[$v]xx$v+1}}

Спробуйте в Інтернеті!

Основна ідея полягає в тому, щоб перевірити безліч чи { i, a[i], a[a[i]] }містить рівно два різних елемента для кожного індексу iз a[i] >= 0. Якщо елемент вказує на себе, набір містить лише один окремий елемент. Якщо інший кінець не вказує назад i, набір містить три різних елемента. Якщо a[i] < 0, xxкоефіцієнт дорівнює нулю або від’ємному, значить множина є { i, a[i] }також з двома різними елементами.


3

MATL , 19 18 байт

-1 байт завдяки Луїсу

n:G=GGG0>f))7M-|hs

Спробуйте в Інтернеті!, тільки для першого, тому що я не знаю, як їх зробити!

Дає 0чи truthy, нульове ціле число , якщо falsey, наприклад. для тестового випадку 6 дає4 .

Пам'ятайте, що як і MATLAB, MATL є 1-індексованою, тому 1 слід додати до тестових випадків!

Ніколи раніше не займався гольфом в Езоланг, тому пораду чудово отримав!

Пояснили:

n:G=GGG0>f))7M-|hs
                        Implicit - input array
n                       Number of values in array
 :                      Make array 1:n
  G                     Push input
   =                    Equality
n:G=                    Makes non-zero array if any of the tunnels lead to themselves
    GGG                 Push input 3x
       0                Push literal 0
        >               Greater than
      G0>               Makes array of ones where input > 0
         f              Find - returns indeces of non-zero values
                        Implicit - copy this matrix to clipboard
          )             Indeces - returns array of positive integers in order from input
           )            Ditto - Note, implicit non-zero any above maximum
            7M          Paste from clipboard
              -         Subtract
    GGG0>f))7M-         Makes array of zeros if only two-ended tunnels evident
               |        Absolute value (otherwise eg. [3,4,2,1] -> '0')
                h       Horizontal concat (ie. joins check for self tunnels and wrong tunnels)
                 s      Sum; = 0 if truthy, integer otherwise                 

Моє пояснення занадто багатослівне? Я хочу зробити це очевидним, не переходячи за борт.
Луї

3

05AB1E , 16 15 14 байт

εèNQyNÊ*y0‹~}P

-1 байт завдяки @Dorian .

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Пояснення:

ε               # Map each value `y` of the (implicit) input-list to:
 è              #   If the current value indexed into the (implicit) input-list
  NQ            #   is equal to the index
       *        #   And
    yNÊ         #   If the current value is not equal to the current index
           ~    #  Or if:
        y0     #   The current value is negative
            }P  # After the map: check if everything is truthy
                # (after which the result is output implicitly)

Моя спроба була такою ж, за винятком фільтра. Я не бачу способу покращити це.
Емінья

1
14 байт . Ви можете натиснути на поточне значення εз y. Тож не потрібно ©, і кожен ®замінюється наy
Доріан

@ Доріан Ах, звичайно .. Це було неможливо в спадщині, коли я розмістив цю відповідь, але я повинен був подумати про це, коли я зробив свій гольф раніше сьогодні. Спасибі! :)
Кевін Круїссен




2

Haskell , 48 байт

(all=<< \u(x,y)->y<0||x/=y&&elem(y,x)u).zip[0..]

Перевірте всі тести!

Пояснення

Давайте спочатку трохи скажемо код. Як f =<< gі те саме \x -> f (g x) x, код еквівалентний

(\u->all(\(x,y)->y<0||x/=y&&elem(y,x)u)u).zip[0..]

що трохи зрозуміліше.

(\u ->                                  -- given u, return
    all (\(x, y) ->                     -- whether for all elements (x, y) of u
            y < 0 ||                    -- either y < 0, or
            x /= y && elem (y, x) u     -- (x /= y) and ((y, x) is in u)
        )
    u
) . zip [0..]                           -- given the array a (implicitly via point-free style),
                                        -- return the array augmented with indices (it's the u above)

Це рішення базується на простому спостереженні: нехай aбуде вхідний масив та uсписок пар, (i, a[i])де iє індекс. Тоді aє дійсним масив, якщо і тільки якщо для кожного (x, y)з uз y >= 0, пара також (y, x)належить u.


2

Java (JDK) , 89 байт

a->{int l=a.length,i=l;for(;i-->0;)i=a[i]<1||a[i]<l&&a[i]!=i&a[a[i]]==i?i:-2;return-2<i;}

Спробуйте в Інтернеті!

Кредити


Можливо, це було б 87 байт, якби не це прискіпливе IndexOutOfBoundsException. Можливо, ви бачите щось, щоб це легко виправити?
Kevin Cruijssen

@KevinCruijssen Я бачу, як це виправити на 102 байти . Ще нічого коротшого :(
Олів'є Грегоар,

1
-3 байти - опустіть rі
вирвіться

1

Вугілля деревне , 22 байти

¬Φθ∨⁼ικ¬∨‹ι⁰∧‹ιLθ⁼κ§θι

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Вихідні дані -для правди і нічого для фальшивих. Примітка: Введення порожнього масиву, схоже, руйнує вугілля, але поки ви можете ввести пробіл, який знаходиться досить близько. Пояснення:

  θ                     Input array
 Φ                      Filter elements
     ι                  Current value
    ⁼                   Equals
      κ                 Current index
   ∨                    Or
       ¬                Not
          ι             Current value
         ‹ ⁰            Is less than zero
        ∨               Or
              ι         Current value
             ‹          Is less than
               L        Length of
                θ       Input array
            ∧           And
                  κ     Current index
                 ⁼      Equals
                   §θι  Indexed value
¬                       Logical Not (i.e. is result empty)
                        Implicitly print

Це здається не дуже шаленим викликом ... :-)
Чарлі

1

Паскаль (FPC) , 165 155 153 байт

function f(a:array of int32):byte;var i:int32;begin f:=1;for i:=0to length(a)-1do if a[i]>-1then if(a[i]=i)or(a[i]>length(a))or(a[a[i]]<>i)then f:=0;end;

Спробуйте в Інтернеті!

Цього разу зроблено функцією, оскільки вхід є масивом. Повертається 1до трити та 0фальси.


1

Чисто , 60 байт

import StdEnv
@l=and[v<0||l%(v,v)==[i]&&v<>i\\v<-l&i<-[0..]]

Спробуйте в Інтернеті!

Чистота , 142 байти

Величезна надмірно складна версія монстра:

import StdEnv,Data.List,Data.Maybe
$l=and[?i(mapMaybe((!?)l)j)j\\i<-l&j<-map((!?)l)l|i>=0]with?a(Just(Just c))(Just b)=a==c&&b<>c;?_ _ _=False

Спробуйте в Інтернеті!

Пояснили:

$ l                           // function $ of `l` is
 = and [                      // true when all elements are true
  ?                           // apply ? to
   i                          // the element `i` of `l`
   (mapMaybe                  // and the result of attempting to
    ((!?)l)                   // try gettting an element from `l`
    j)                        // at the potentially invalid index `j`
   j                          // and `j` itself, which may not exist
  \\ i <- l                   // for every element `i` in `l`
  & j <- map                  // and every potential `j` in
    ((!?)l)                   // `l` trying to be indexed by
    l                         // every element in `l`
  | i >= 0                    // where `i` is greater than zero
 ]
with
 ? a (Just (Just c)) (Just b) // function ? when all the arguments exist
  = a==c && b<>c              // `a` equals `c` and not `b`
  ;
 ? _ _ _ = False              // for all other arguments, ? is false


1

Pyth , 17 16 байт

.A.e|>0b&nbkq@Qb

Спробуйте в Інтернеті тут або одразу підтвердіть усі тестові випадки тут .

.A.e|>0b&nbkq@QbkQ   Implicit: Q=eval(input())
                     Trailing k, Q inferred
  .e             Q   Map the input with b=element, k=index, using:
     >0b               0>b
    |                  OR (
         nbk           b != k
        &              AND
            q@Qbk      Q[b] == k)
.A                   Check if all elements are truthy

Правка: зрозумів, що кінцевий к також не потрібний





0

Математика, 42 байти

#=={}||(a=0@@#)[[#]]=!=a&&a[[#]][[#]]===a&

Чиста функція. Приймає 1-індексований список чисел як введення та повернення Trueабо Falseяк вихід. Просто слідкуйте за тунелями, переконуючись у тому, що 0карти на 01-циклі не існують, а всі цикли - це 2-цикли. (Я не зовсім впевнений, що це не вдасться в будь-яких кращих випадках, але це дає правильні результати для прикладів.)


0

Ця відповідь не працює. Тут лише для ілюстрації.

Ця відповідь передає всі (на даний момент) розміщені тестові справи. Однак він не працює (викликає помилку) на інших дійсних даних, таких як [1, 2]або[1, 0, 3, 7] .

Як воно могло пройти [1, 0, 3]і провалитися [1, 0, 3, 7]? Що ж, це проходить через список, як і ви очікували. Коли він читає елемент xсписку a, він спочатку перевіряє, чи xменший він len(a), і негайно повертається False, якщо так. Тож він правильно повертається Falseдалі [1, 0, 3], тому що 3не меншеlen(a) .

Але якщо припустити, що xпроходить цю перевірку, код потім піде робити деякі інші перевірки, і в певний момент це станеться для оцінки a[a[x]]. Ми вже гарантували, що оцінювання a[x]буде нормальним ... але ні a[a[x]], що визначається, a[7]коли xце є 3в [1, 0, 3, 7]прикладі. У цей момент Python піднімає IndexError, а не повертаєтьсяFalse .

Для повноти ось відповідь.

Python 2 , 59 байт

lambda a:all(x<len(a)>-1<a[x]!=x==a[a[x]]for x in a if-1<x)

Спробуйте в Інтернеті!

Я хотів це зробити x<len(a)and-1<a[x]..., але, звичайно len(a), завжди >-1, тому сказане рівнозначно. Ця перевірка в цілому 5 прикутих відносин ( <, >, <, !=, і ==), а також окремий чек -1<xв ifстані.

У Python (зручно) коротке замикання пов'язаних відносин, як це, наприклад, якщо x>=len(a)тоді чек повертається Falseдо того, як він потрапить a[x](що в іншому випадку підвищить IndexError).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.