Эти списки равны?


19

Как вы, наверное, очень хорошо знаете, у python есть списки. Как вы, возможно, не знаете, эти списки могут содержать сами.

a = []
a.append(a)

Python 2

Python 3

Это круто, и есть много интересных вещей, которые вы можете сделать с ними, однако вы не можете их сравнить.

a = []
a.append(a)
b = []
b.append(b)
a == b

Python 2

Python 3

задача

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

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

Ваша программа не должна полагаться на глубину рекурсии python, чтобы определить, является ли список бесконечно глубоким. То есть:

def isInfinite(a,b):
 try:
  a==b
  return False
 except RunTimeError:
  return True

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

Testcases

Предполагается, что вы определяете функцию equal

a = []
a.append(a)
b = []
b.append(b)
print(equal(a,b))

True

a = []
b = []
a.append(b)
b.append(a)
print(equal(a,b))

True

a = []
b = []
a.append(1)
a.append(b)
b.append(1)
b.append(a)
print(equal(a,b))

True

a = []
a.append(a)
b = [a]
print(equal(a,b))

True

a = []
b = []
c = []
a.append(b)
b.append(c)
c.append(a)
equal(a,b)

True

a=[1,[2]]
b=[1,[2,[1]]]
a[1].append(a)
b[1][1].append(b[1])

True

a = []
a.append(a)
b = [1]
b.append(a)
c = [1]
c.append([c])
print(equal(b,c))

False

a = []
b = []
a.append(1)
a.append(b)
b.append(a)
b.append(1)
print(equal(a,b))

False

a = []
b = []
a.append(a)
b.append(b)
b.append(b)
print f(a,b)

False

17
В качестве дополнительного примечания к потенциальным избирателям: обратите внимание, что в целом языковые проблемы не одобряются, за исключением определенных обстоятельств (например, задач, которые интересны только на определенных языках). ИМО, это замечательный пример языковой проблемы.
DJMcMayhem

@WheatWizard Этого не достаточно - вложенные списки также должны быть одинаковой длины.
xnor

@WheatWizard Вы действительно можете сравнить их. В Python «рекурсия ограничена превышением», только если они не равны. tio.run/nexus/…
mbomb007

@ mbomb007 Это потому, что python по умолчанию сравнивает ссылки. Если у вас есть два одинаковых объекта, которые имеют разные ссылки, это не удастся, следовательно, проблема.
Пшеничный волшебник

2
Можете ли вы распространить эту проблему на все языки, где списки могут содержать себя?
CalculatorFeline

Ответы:


9

Python 2 , 94 байта

g=lambda c,*p:lambda a,b:c in p or all(map(g((id(a),id(b)),c,*p),a,b))if a>[]<b else a==b
g(0)

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

Усовершенствование очень умного решения isaacg - сохранение idпар списков, которые обрабатываются, и объявление их равными, если такое же сравнение подходит к более низкому уровню.

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


Какова цель ,после c?
Wheat Wizard

Это делает его кортежем.
mbomb007

a=[];a+=[a,1];b=[];b+=[b,2];f(a,b)переполняет стек и a=[1];b=[2];f(a,b);f(a,b)выглядит как проблема повторного использования.
Андерс Касеорг

@AndersKaseorg Понятно, что мутировавший список требовал неприятностей. Я думаю, что это исправляет.
xnor

1
@AndersKaseorg И я вижу, вы написали одно и то же решение «функция в функции». Там в 95-байтовое решение без этого: f=lambda a,b,p=[0]:p[0]in p[1:]or all(map(f,a,b,[[(id(a),id(b))]+p]*len(a)))if a>[]<b else a==b. Может быть, есть лучший способ справиться с map.
xnor

5

Python, 233 218 197 217 байт

d=id
def q(a,b,w):
 w[(d(a),d(b))]=0
 if d(a)==d(b):return 1
 if(a>[]and[]<b)-1:return a==b
 if len(a)!=len(b):return 0
 for x,y in zip(a,b):
  if((d(x),d(y))in w or q(x,y,w))-1:return 0
 return 1
lambda a,b:q(a,b,{})

Анонимная функция в последней строке выполняет желаемую функцию.

Это все еще в процессе игры в гольф, я просто хотел показать, что это возможно.

По сути, мы помещаем запись в w, если мы работаем над данной проверкой. Две вещи равны, если это один и тот же объект, если они не списки и они равны, или если все их элементы равны или работают над ними.


Вы не можете использовать a>[]вместо i(a,list)?
mbomb007

@ mbomb007 Это было написано до того, как было добавлено правило «Все - списки или целые». Буду обновлять.
Исаак

Вы можете использовать a>[]<bиlen(a)-len(b)
mbomb007

@ETHproductions О, его количество байтов неверно. Вот почему
mbomb007

Может d(a)==d(b)быть a is b? Это сократило бы два использования d.
xnor
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.