По краям гиперкуба

12

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

Пример 1

1-мерный гиперкуб представляет собой прямую и содержит две вершины, которые мы будем называть aи b.

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

Поэтому на выходе будет:

[[a, b]]

Пример 2

4-мерный гиперкуб (или тессеракт) состоит из 32 ребер, и его график выглядит следующим образом

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

и результат может выглядеть следующим образом

[[a, b], [a, c], [a, e], [a, i], [b, d], [b, f], [b, j], [c, d], [c, g], [c, k], [d, h], [d, l], [e, f], [e, g], [e, m], [f, h], [f, n], [g, h], [g, o], [h, p], [i, j], [i, k], [i, m], [j, l], [j, n], [k, l], [k, o], [l, p], [m, n], [m, o], [n, p], [o, p]]

правила

  • Вы можете называть вершины любым удобным вам способом, если имя уникально.
  • Ребра являются ненаправленными, то есть [a, b]и [b, a]считаются одним ребром.
  • Ваш вывод не должен содержать дубликаты ребер.
  • Вывод может быть в любом разумном формате.
  • Стандартные лазейки запрещены.

счет

Самый короткий код выигрывает.

Murphy
источник
Итак, [1,2], [2,3] и т. Д. В порядке?
Rɪᴋᴇʀ
@EasterlyIrk Да.
Мерфи
Края могут быть выведены в любом порядке, верно?
Луис Мендо
@DonMuesli Правильно.
Мерфи

Ответы:

4

Желе, 13 байт

ạ/S’
2ṗœc2ÇÐḟ

Попробуй это здесь. Для ввода 3вывод:

[[[1, 1, 1], [1, 1, 2]],
 [[1, 1, 1], [1, 2, 1]],
 [[1, 1, 1], [2, 1, 1]],
 [[1, 1, 2], [1, 2, 2]],
 [[1, 1, 2], [2, 1, 2]],
 [[1, 2, 1], [1, 2, 2]],
 [[1, 2, 1], [2, 2, 1]],
 [[1, 2, 2], [2, 2, 2]],
 [[2, 1, 1], [2, 1, 2]],
 [[2, 1, 1], [2, 2, 1]],
 [[2, 1, 2], [2, 2, 2]],
 [[2, 2, 1], [2, 2, 2]]]

Я надеюсь, что [1, 1, 1]и т. Д. Это хорошее имя.

объяснение

Первая строка представляет собой «предикат» на паре ребер: [A, B] ạ/S’она равна sum(abs(A - B)) - 1нулю (false-y) тогда Aи только тогда, когда Bотличается только одной координатой.

Вторая строка - основная программа:

  • Генерируем все ребра с помощью 2ṗ(декартовой степени [1, 2]).
  • Получить все возможные пары, используя œc2(комбинации размера два без замены).
  • Оставьте только элементы, удовлетворяющие предикату, определенному ранее ( ÐḟÇ).
Линн
источник
1
ạ/S’и 2ṗœc2ÇÐḟсохранить пару байтов.
Деннис
c/P=2, 2ṗṗ2ÇÐfТоже работает.
Деннис
Умная схема «именования»! Конечно, в рамках правил.
Мерфи
9

Python 2, 54 56 62 байта

lambda n:{tuple({k/n,k/n^1<<k%n})for k in range(n<<n)}

Дублирующие ребра удаляются путем создания набора наборов, за исключением того, что Python требует, чтобы элементы набора были хэшируемыми, поэтому они преобразуются в кортежи. Обратите внимание, что множества {a,b}и {b,a}равны и конвертируются в один и тот же кортеж. xsot сохранил 2 байта с n<<n.

Это может быть сокращено до 49 байт, если строки наборов имеют формат вывода OK

lambda n:{`{k/n,k/n^1<<k%n}`for k in range(n<<n)}

который дает вывод как

set(['set([1, 3])', 'set([2, 3])', 'set([0, 2])', 'set([0, 1])'])

lambda n:[(k/n,k/n^1<<k%n)for k in range(n*2**n)if k/n&1<<k%n]

Сначала давайте посмотрим на старую версию решения.

lambda n:[(i,i^2**j)for i in range(2**n)for j in range(n)if i&2**j]

Каждое число в интервале [0,2^n)соответствует вершине с координатами, заданными ее n-битными двоичными строками. К вершинам примыкают, если они отличаются одним битом, т. Е. Если один получен из другого путем xor степени 2.

Эта анонимная функция генерирует все возможные ребра, переворачивая каждую вершину и каждую битовую позицию. Чтобы избежать дублирования ребра в обоих направлениях, только 1 переворачиваются на 0.

В более удобном решении kиспользуется для кодирования как iи jчерез k=n*i+j, из которого (i,j)можно извлечь как (k/n,k%n). Это сохраняет цикл в понимании. Полномочия 2сделаны так, 1<<чтобы иметь правильный приоритет оператора.

Альтернативный подход к генерации каждой пары вершин и проверке, немного ли они разошлись, кажется длиннее (70 байт):

lambda n:[(i,x)for i in range(2**n)for x in range(i)if(i^x)&(i^x)-1<1] 
XNOR
источник
1
n*2**nпростоn<<n
xsot
Переход на Python 3.5, lambda n:{(*{k//n,k//n^1<<k%n},)for k in range(n<<n)}сохраняет байт. (Звездное выражение сохраняет три, но синтаксис деления теряет два.) Однако я вполне уверен, что 49-байтовое решение, которое у вас есть, подходит.
Линн
4

Mathematica, 48 24 байта

EdgeList@*HypercubeGraph

Просто анонимная функция, которая использует встроенные модули.

LegionMammal978
источник
Ах, встроенный! Поскольку вам не нужно называть вершины в алфавитном порядке, вы можете опустить FromLetterNumber. Я даже думаю, что EdgeList@*HypercubeGraphэто правильный ответ.
Мерфи
3

JavaScript (SpiderMonkey 30+), 69 64 байта

n=>[for(i of Array(n<<n).keys())if(i/n&(j=1<<i%n))[i/n^j,i/n^0]]

Это началось как порт решения @ xnor Python 2, но я смог сэкономить 9 байт, переписав код для использования одного цикла. Изменить: Сохранение еще 5 байтов путем разделения iна части в соответствии с обновленным решением @ xnor, которое теперь также использует один цикл.

Нил
источник
2

MATL , 20 байтов

2i^:qt!Z~Zltk=XR2#fh

Это работает с текущей версией (14.0.0) языка / компилятора.

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

объяснение

Это использует более или менее ту же идею, что и ответ @ xnor .

2i^    % take input n and compute 2^n
:q     % range [0,1,...,2^n-1] (row vector)
t!     % duplicate, transpose into a column vector
Z~     % bitwise XOR with broadcast
Zl     % binary logarithm
tk     % duplicate and round down
=      % true if equal, i.e. for powers of 2
XR     % upper triangular part, above diagonal
2#f    % row and index columns of nonzero values
h      % concatenate vertically
Луис Мендо
источник
2

Pyth, 13 байт

fq1.aT.c^U2Q2

Выход на вход 3 :

[[[0, 0, 0], [0, 0, 1]], [[0, 0, 0], [0, 1, 0]], [[0, 0, 0], [1, 0, 0]], [[0, 0, 1], [0, 1, 1]], [[0, 0, 1], [1, 0, 1]], [[0, 1, 0], [0, 1, 1]], [[0, 1, 0], [1, 1, 0]], [[0, 1, 1], [1, 1, 1]], [[1, 0, 0], [1, 0, 1]], [[1, 0, 0], [1, 1, 0]], [[1, 0, 1], [1, 1, 1]], [[1, 1, 0], [1, 1, 1]]]

Объяснение:

fq1.aT.c^U2Q2
                  Implicit: input = Q
        ^U2Q      All Q entry lists made from [0, 1].
      .c    2     All 2 element combinations of them.
f                 Filter them on
   .aT            The length of the vector
 q1               Equaling 1.
isaacg
источник
1

Python 2: 59 байт

lambda n:[(a,a|1<<l)for a in range(2**n)for l in range(n)if~a&1<<l]
DolphinDream
источник