Как проверить, содержит ли список целые целые числа в Mathematica?

Я хочу проверить, содержит ли список последовательные целые числа.

 consQ[a_] := Module[
  {ret = True}, 
  Do[If[i > 1 && a[[i]] != a[[i - 1]] + 1, ret = False; Break[]], {i, 
  1, Length[a]}]; ret]

Хотя функция consQ выполняет задание, мне интересно, есть ли лучший (более короткий, быстрый) способ сделать это, предпочтительно используя стиль функционального программирования.

EDIT: Функция выше отображает списки с последовательными целыми числами в порядке убывания до False. Я хотел бы изменить это на True.

Ответ 1

Вы можете использовать

consQ[a_List ? (VectorQ[#, IntegerQ]&)] := [email protected][a] === {1}
consQ[_] = False

Вы можете удалить тест для целых чисел, если знаете, что каждый список, который вы передаете ему, будет иметь целые числа.

EDIT: Немного больше: если вы используете очень старую версию, которая не имеет Differences, или задаться вопросом, как ее реализовать,

differences[a_List] := Rest[a] - Most[a]

ИЗМЕНИТЬ 2: Запрошенное изменение:

consQ[a : {Integer___}] := MatchQ[[email protected][a], {1} | {-1} | {}]
consQ[_] = False

Это работает как с увеличением, так и с уменьшением последовательностей и дает True для списка размером 1 или 0.

В более общем смысле, вы можете проверить, равно ли распределен ли список чисел с чем-то вроде equallySpacedQ[a_List] := [email protected]@Differences[a] == 1

Ответ 2

Решение Szablics - это, наверное, то, что я сделал бы, но здесь альтернатива:

consQ[a : {___Integer}] := Most[a] + 1 === Rest[a]
consQ[_] := False

Обратите внимание, что эти подходы отличаются тем, как они обрабатывают пустой список.

Ответ 3

Мне нравятся решения двух других, но меня беспокоят очень длинные списки. Рассмотрим данные

d:dat[n_Integer?Positive]:= d = {1}~Join~Range[1, n]

который имеет свою непоследовательную точку в самом начале. Установив consQ1 для Бретта и consQ2 для Sabololcs, я получаю

AbsoluteTiming[ #[dat[ 10000 ] ]& /@ {consQ1, consQ2}
{ {0.000110, False}, {0.001091, False} }

Или, примерно в десять раз разница между ними, которая остается относительно согласной с несколькими испытаниями. Это время можно сократить примерно наполовину за счет короткого замыкания процесса, используя NestWhile:

Clear[consQ3]
consQ3[a : {__Integer}] := 
 Module[{l = Length[a], i = 1},
   NestWhile[# + 1 &, i, 
      (#2 <= l) && a[[#1]] + 1 == a[[#2]] &, 
   2] > l
 ]

который проверяет каждую пару и продолжается, только если они возвращают true. Тайминги

AbsoluteTiming[consQ3[dat[ 10000 ]]]
{0.000059, False}

с

{0.000076, False}

для consQ. Итак, ответ Бретта довольно близок, но иногда это займет вдвое больше.

Изменить. Я переместил графики данных синхронизации в ответ Community Wiki.

Ответ 4

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

a = Range[10^7];
f[a_] := Range[Sequence @@ ##, Sign[-#[[1]] + #[[2]]]] &@{a[[1]], a[[-1]]} == a;
Timing[f[a]]
b = [email protected];
Timing[f[b]]

Edit

Короткий тест для решений по быстродействию:

a = Range[2 10^7];
[email protected]@a
[email protected]@a
[email protected]@a
(*
{6.5,True}
{0.703,True}
{0.203,True}
*)

Ответ 5

Fold может использоваться в довольно сжатом выражении, которое выполняется очень быстро:

consQFold[a_] := (Fold[If[#2 == #1 + 1, #2, Return[False]] &, a[[1]]-1, a]; True)

Сравнение шаблонов может использоваться для обеспечения очень четкого выражения намерения за счет значительно более низкой производительности:

consQMatch[{___, i_, j_, ___}] /; j - i != 1 := False
consQMatch[_] = True;

Edit

consQFold, как написано, работает в Mathematica v8.0.4, но не в более ранних версиях v8 или v7. Чтобы исправить эту проблему, существует несколько альтернатив. Первый - явно указать точку Return:

consQFold[a_] :=
  (Fold[If[#2==#1+1, #2, Return[False,CompoundExpression]] &, a[[1]]-1, a]; True)

Второй, как предложил @Mr.Wizard, заключается в замене Return на Throw/Catch:

consQFold[a_] :=
  Catch[Fold[If[#2 == #1 + 1, #2, Throw[False]]&, a[[1]]-1, a]; True]

Ответ 6

Теперь я убежден, что belisarius пытается получить мою козу, написав намеренно свернутый код.:-p

Я бы написал: f = Range[##, Sign[#2 - #]]& @@ #[[{1, -1}]] == # &

Кроме того, я считаю, что WReach, вероятно, намеревался написать что-то вроде:

consQFold[a_] := 
 Catch[
  Fold[If[#2 === # + 1, #2, [email protected]] &, a[[1]] - 1, a]; 
  True
 ]

Ответ 7

Поскольку время кажется весьма важным. Я переместил сравнения между различными методами на это, Community Wiki, ответ.

Используемые данные - это просто списки последовательных целых чисел с одной непоследовательной точкой, и они генерируются через

d : dat[n_Integer?Positive] := (d = {1}~Join~Range[1, n])
d : dat[n_Integer?Positive, p_Integer?Positive] /; p <= n := 
     Range[1, p]~Join~{p}~Join~Range[p + 1, n]

где первая форма dat[n] эквивалентна dat[n, 1]. Код синхронизации прост:

Clear[consQTiming]
Options[consQTiming] = {
   NonConsecutivePoints -> {10, 25, 50, 100, 250,500, 1000}};
consQTiming[fcns__, OptionPattern[]]:=
With[{rnd = RandomInteger[{1, #}, 100]}, 
  With[{fcn = #}, 
     Timing[ fcn[dat[10000, #]] & /@ rnd ][[1]]/100
  ] & /@ {fcns}
] & /@ OptionValue[NonConsecutivePoints]

Он генерирует 100 случайных чисел от 1 до каждого из {10, 25, 50, 100, 250, 500, 1000} и dat, а затем использует каждое из этих случайных чисел в качестве непоследовательной точки в списке 10000 элементов. Каждая реализация consQ затем применяется к каждому списку, создаваемому dat, и результаты усредняются. Функция построения графика просто

Clear[PlotConsQTimings]
Options[PlotConsQTimings] = {
     NonConsecutivePoints -> {10, 25, 50, 100, 250, 500, 1000}};
PlotConsQTimings[timings : { _?VectorQ ..}, OptionPattern[]] :=
  ListLogLogPlot[
    Thread[{OptionValue[NonConsecutivePoints], #}] & /@ Transpose[timings],
    Frame -> True, Joined -> True, PlotMarkers -> Automatic
  ]

timing data for various functions

Я приурочил следующие функции consQSzabolcs1, consQSzabolcs2, consQBrett, consQRCollyer, consQBelisarius, consQWRFold, consQWRFold2, consQWRFold3, consQWRMatch и версия MrWizard consQBelisarius.

В порядке возрастания самого последнего времени: consQBelisarius, consQWizard, consQRCollyer, consQBrett, consQSzabolcs1, consQWRMatch, consQSzabolcs2, consQWRFold2, consQWRFold3 и consQWRFold.

Изменить. Повторите все функции с timeAvg (второй) вместо Timing в consQTiming. Тем не менее, я все же выполнял более 100 пробегов. По большей части произошли какие-либо изменения, за исключением самых низких двух, где есть несколько вариантов от запуска до запуска. Итак, возьмите эти две линии с зерном соли, поскольку они тайминги практически идентичны.

enter image description here