Отрицательные графы пространства

13

задача

Вам будет дано положительное целое число, и вы должны вывести « самодополняющий граф » с таким количеством узлов. Если вы не знаете, что такое самодополняющий граф, статья Википедии не сильно вам поможет, поэтому ниже приведены два объяснения: техническое и нетехническое.

Нетехническое

График - это набор узлов, соединенных линиями. Каждая пара точек может быть соединена одной линией или ни одной. «Дополнение» графа является результатом взятия графа и соединения всех узлов, которые не связаны, и отсоединения всех узлов, которые есть.

Самодополняющий граф - это граф, дополнение которого может быть преобразовано в форму оригинала. Ниже приведен пример самодополняющего графа и демонстрация того, как.

Вот график с 5 узлами:

5-узловая диаграмма

Мы выделим все места, где соединения могут идти с красными пунктирными линиями:

Выделенный график

Теперь мы найдем дополнение графа, поменяв местами красный и черный края:

комплемент

Это не похоже на исходный график, но если мы переместим узлы вокруг так (каждый шаг заменяет два узла):

изоморфизм

Мы получаем оригинальный график! График и его дополнение - это тот же граф

технический

Самодополняющий граф - это граф, изоморфный своему дополнению.

Характеристики

Вы получите положительное целое число любым удобным для вас способом. И вы будете выходные график в какой бы метод вы считаете целесообразным, это включает в себя , но не ограничивается матрицей смежности формы , смежности списка Форма , и, конечно , фотографии! Выводимый граф должен быть его собственным дополнением и иметь столько же узлов, сколько и целочисленный ввод. Если такого графа не существует, вы должны вывести ложное значение.

Это и вы должны стремиться минимизировать количество байт.

Тестовые случаи

Ниже приведены изображения возможных выходов для нескольких н

4

5

9

Пост Рок Гарф Хантер
источник
Самодополняющий граф может существовать только тогда, когда полный граф имеет четное число ребер. Нам это гарантировано?
xnor
@xnor Я забыл включить это. Исправлено сейчас.
Пост Рок Гарф Хантер
Должны ли мы обрабатывать отрицательные входные данные?
xnor
@xnor Нет. Я исправлю вопрос, чтобы он был конгруэнтным
Post Rock
3
Прежде чем кто-либо получит идею обоснования ответа GraphData@{"SelfComplementary",{#,1}}&, я полагаю, что он просто загружает некоторые примеры для низкого уровня nиз базы данных Wolfram, поэтому это не сработает для произвольно больших входных данных.
Мартин Эндер

Ответы:

9

Haskell , 77 байт

f n=[(a,b)|b<-[1..n],a<-[1..b-1],mod n 4<2,mod(a+(last$b:[a|odd n,n==b]))4<2]

Попробуйте онлайн!

При этом используется простой для вычисления явный критерий, чтобы решить, (a,b)принадлежит ли ребро графу. Реализует этот алгоритм с циклической перестановкой значений по модулю 4

4*m -> 4*m+1 -> 4*m+2 -> 4*m+3 -> 4*m

Мы включаем ребра, две вершины конечных точек которых добавляются к 0 или 1 по модулю 4. Обратите внимание, что циклические вершины согласно этой перестановке добавляют 2 по модулю 4 к сумме вершин каждого из них, и, таким образом, меняются ребра и не ребра. Это дает перестановку вершин, которая дополняет ребра.

Если у графа есть дополнительный узел, кратный 4, он помещается в один цикл. К ним добавляются ребра, когда другая вершина четна. Перестановка вершин переворачивает четность, и поэтому граф остается самодополняющим.

Если число вершин не равно 0 или 1 по модулю 4, самодополняющий граф невозможен, поскольку в полном графе имеется нечетное число ребер

В целом, вот условия:

  • Если вход n не равен 0 или 1 по модулю 4, выведите пустой список
  • В противном случае, если n четное, включите все ребра (a,b)с помощью a<bиa+b равным 0 или 1 по модулю 4.
  • В противном случае, если n нечетно, сделайте то же самое, но вместо этого добавьте ребра формы, (a,n)когда a чётно.

Код объединяет второй и третий случаи, заменяя условие mod(a+b)4<2на mod(a+a)4<2когда odd nи b==n.

XNOR
источник
5

Brachylog 2 , 24 байта

{⟦₁⊇Ċ}ᶠpḍ.(\\ᵐcdl?∨?<2)∧

Попробуйте онлайн!

Эта функция возвращает пару, состоящую из двух списков смежности: один для графа, другой для графа дополнения. (В интерпретаторе Brachylog на TIO вы можете попросить его оценить функцию, а не полную программу, передавая Zв качестве аргумента командной строки.) Например, выходные данные для ввода 5:

[[[1,2],[1,3],[1,5],[3,5],[4,5]],[[2,5],[2,3],[2,4],[3,4],[1,4]]]

Вот как это выглядит как изображение (показывает два графика):

график и его идентичное дополнение на 5 элементов

Как обычно в языках на основе Пролога, функция поддерживает более одного шаблона вызова. В частности, если вы попытаетесь использовать его как генератор, он выведет все возможные самодополняющие графы с заданным количеством вершин (хотя я не приложил никаких усилий, чтобы сделать этот случай пригодным для использования, и, в частности, он выведет каждый из графики много раз каждый).

объяснение

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

{⟦₁⊇Ċ}ᶠpḍ.(\\ᵐcdl?∨?<2)∧
 ⟦₁                       The range [1, 2, …, ?], where ? is the input
   ⊇                      A subset of that range…
    Ċ                     …which has exactly two elements
{    }ᶠ                   A list of everything that fits the above description
{⟦₁⊇Ċ}ᶠ                   All edges that could exist in a ?-element graph
       p                  Find a permutation of these…
        ḍ                 …so that splitting it into two equal parts…
          (       ∨   )   …either:
               dl?          produces ? distinct elements
           \                after transposing it
            \ᵐ              and transposing its elements
              c             and flattening one level;
                          or:
                   ?<2      ? was less than 2
         .             ∧  Once you've found it, . specifies what to output

Между прочим, мне пришлось потратить целых 6 байт (¼ программы, символы (∨?<2) ) на особые случаи 0 и 1. Разочарование, но это характер особых случаев.

Этот \\ᵐcdl?раздел немного сложен для понимания, так что вот рабочий пример. Его цель - проверить, является ли что-то графом и его дополнением, причем соответствующие ребра в графе и дополнении находятся в одном и том же порядке в списках. Пара граф / дополнение становится возможным выходом программы. Вот пример случая:

[[[1,2],[1,3],[1,5],[3,5],[4,5]],[[2,5],[2,3],[2,4],[3,4],[1,4]]]

Транспонирование этого дает нам список пар соответствующих ребер между графом и дополнением:

[[[1,2],[2,5]],[[1,3],[2,3]],[[1,5],[2,4]],[[3,5],[3,4]],[[4,5],[1,4]]

Далее мы транспонируем элементы списка и выравниваем один уровень; это дает нам список пар соответствующих элементов между графом и дополнением:

[[1,2],[2,5],[1,2],[3,3],[1,2],[5,4],[3,3],[5,4],[4,1],[5,4]]

Ясно, что мы хотим, чтобы здесь было не более 1 пары, начиная с каждого элемента (таким образом, доказывая, что элементы графа и дополнения находятся в соответствии 1-к-1). Мы можем почти убедиться в этом, просто указав, что список содержит ровно ?разные элементы (т. Е. Количество разных элементов равно числу вершин). В этом случае тест проходит успешно; Отличительными элементами являются:

[[1,2],[2,5],[3,3],[5,4],[4,1]]

Однако это оставляет место для потенциальной проблемы; если вершина полностью отключена в исходном графе, ее соответствие не будет упомянуто, оставляя место для дубликата соответствия от какой-либо другой вершины. Если это так, дополнение график должен иметь границу между этой вершиной (без ограничения общности, допустим , что это 1), и каждая другая вершина, и поэтому список соответствий будет содержать [1,2], [1,3], ..., [1, ?]. Когда ?он большой, это приведет к большему количеству соответствий, чем было бы в противном случае, так что проблем нет. Единственная проблема возникает, когда значение ?равно 3 или ниже, и в этом случае мы добавляем только одну дополнительную корреспонденцию (удаляя ее из1не появляется на входе); однако на практике это не является проблемой, поскольку на 3-элементном графе имеется 3 возможных ребра, что является нечетным числом (аналогично, 1 возможное ребро на 2-элементном графе также является нечетным числом), и, таким образом, на \шаге тест завершится неудачей (вы не можете транспонировать рваный список, то есть те, чьи элементы имеют разную длину).


источник
Разница между zи \заключается в том, что zэто циклический почтовый индекс, что означает, что в [[1,2,3],["a"]]конечном итоге будет [[1,"a"],[2,"a"],[3,"a"]]с z, в то время как он потерпит неудачу \. \сейчас работает только на квадратных матрицах; будущая реализация заставит это работать как z, кроме не циклически.
фатализировать
Я на самом деле понял разницу, но только после того, как написал объяснение. Это конкретное решение зависит от `` работы только с прямоугольниками (хотя это займет всего 2 байта, если вы не можете воспользоваться этим шагом).
2

BBC BASIC, 161 байт

Токенизированный размер файла 140 байт

Скачать переводчик можно по адресу http://www.bbcbasic.co.uk/bbcwin/bbcwin.html.

I.m:IF2ANDm ORm<4P.0:END
r=400n=-2A.m:t=2*PI/n:F.i=1TOn*n:a=i DIVn:b=i MODn:c=b:IFa+b A.2a*=t:b*=t:L.r+r*SINa,r+r*COSa,r+r*SINb,r+r*COSb:IF 1A.m A.c DRAWr*3,0
N.

Код без правил

  INPUTm                           :REM get input
  IF2ANDm ORm<4PRINT0:END          :REM if m=4x+2 or 4x+3 or less than 4, print 0 and exit
  r=400                            :REM radius of diagram
  n=-2ANDm                         :REM n = m truncated to an even number
  t=2*PI/n                         :REM t = 1/n turns
  FORi=1TOn*n                      :REM for each combination of vertices
    a=i DIVn                       :REM extract a and b
    b=i MODn                       :REM make a copy of c
    c=b                            :REM if a+b MOD 4 = 2 or 3, convert a and b to angles and draw edge.
    IFa+b AND2 a*=t:b*=t:LINEr+r*SINa,r+r*COSa,r+r*SINb,r+r*COSb:IF 1ANDm ANDc DRAWr*3,0
  NEXT                             :REM if m is odd and c is odd, draw a line to the additional vertex for m=4x+1 input.

объяснение

Он использует тот же алгоритм, что и Xnor, но выдает схематический вывод.

Где nформа 4x+2или 4x+3нет решения, так как число ребер нечетное.

Где nэто имеет форму 4x, мы размещаем все вершины в окружности и рисуем те ребра, где (a+b) mod 42 или 3 (не 0 или 1, как в случае с Xnor, по соображениям игры в гольф. Поэтому это дополнение к решению, данному Xnor.)

Чтобы увидеть это в более наглядном смысле, мы берем каждую вторую вершину и отводим ребра к вершинам 1 и 2 мест в направлении против часовой стрелки. Это определяет nпараллельные направления, половину от общего. Затем мы добавляем все остальные ребра, параллельные этим.

Дополнение можно найти, добавив 1 к a и b в каждой спецификации ребра, или пиктограмму, повернув диаграмму на один 1/nоборот.

Где nэто имеет форму 4x + 1, мы добавляем еще одну вершину, которая связана с каждой второй вершиной графа 4x. Если бы это было помещено в центр, симметрия диаграммы была бы сохранена, но я решил поместить это вне основного круга точек для ясности.

Выход

Ниже приведены первые несколько случаев для 4x + 1. случаи 4x можно увидеть, удалив вершину внизу справа и связанные с ней ребра.

введите описание изображения здесь

Уровень реки St
источник
1

JavaScript (ES6), 191 байт

f=(n,a=[],v=n*~-n/4)=>v%1?0:eval(n>5?f(n-=4,a)&&'for(i=0;i<n;)a.push([i,n+1],[i++,n+2]);a.push([n,++n],[n,++n],[n,++n])-v':'for(l=x=0;x<n;x++)for(y=x;y<n;y++)l<v&y>>x&1?l=a.push([x,y]):a')||a

Эта функция возвращает список смежности. Он использует два алгоритма и различает пустые дополнительные графы и не выходные данные, возвращая 0вместо того, []когда ни один не существует. Первый алгоритм основан на графах Rado, построенных с использованием предиката BIT , и создает действительные дополнительные графы 0-, 1-, 4- и 5-го порядка. Другой алгоритм, найденный нашими друзьями по математике , создает действительный V + 4 вершинный дополнительный граф, применяя 4-путевое сложение к действительному V вершинному дополнительному графу.

Он начинается с проверки входных данных, чтобы подтвердить существование допустимого дополнительного графа (используя n*~-n/4%1), и, если это не удается, возвращает 0. Затем он проверяет, если n>5и возвращается к n-4случаю, чтобы построить правильное решение более низкого порядка, затем применяет 4-дополнение к возвращенному списку смежности на пути обратно вверх по цепочке рекурсии. Наконец, если n>5это не так, он выполняет итерацию от 0к n-1для xи yи проверяет,(y>>x)&1 это правдой. Если это так, то эти узлы являются парными.

Вот более читаемый формат функции, в котором троичные операторы расширены до операторов if-else и eval()встроены:

// precalculate amount of required vertices in v
f = (n, a = [], v = n*~-n / 4) => {
  // if amount is non-integer
  if (v % 1) {
    // no valid complementary graph
    return 0;
  } else {
    if (n > 5) {
      // generate valid (n-4)-order complementary graph
      f(n -= 4, a);
      // apply 4-path addition
      for (i = 0; i < n;)
        a.push([i, n+1],[i++, n+2]);
      a.push([n, ++n], [n, ++n], [n, ++n]);
    } else {
      // construct Rado graph using BIT predicate
      for(l = x = 0; x < n; x++)
        for(y = x; y < n; y++)
          // if amount of pairs is less than required and xth bit of y is high
          if (l < v && (y>>x & 1))
            // vertices x and y should be paired
            a.push([x,y]);
    }
    return a;
  }
};

демонстрация

f=(n,a=[],v=n*~-n/4)=>v%1?0:eval(n>5?f(n-=4,a)&&'for(i=0;i<n;)a.push([i,n+1],[i++,n+2]);a.push([n,++n],[n,++n],[n,++n])-v':'for(l=x=0;x<n;x++)for(y=x;y<n;y++)l<v&y>>x&1?l=a.push([x,y]):a')||a
<input type="number" onchange="o.textContent=JSON.stringify(f(this.value))"><pre id="o"></pre>

Патрик Робертс
источник