Чи рівні ці списки?


19

Як ви дуже добре знаєте, у python є списки. Як ви можете не знати, ці списки можуть містити себе.

a = []
a.append(a)

Пітон 2

Пітон 3

Це круто і є багато цікавого, що ви можете зробити з ними, однак ви не можете їх порівняти.

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

Пітон 2

Пітон 3

Завдання

Ваше завдання - написати функцію в Python (або будь-яку мову, яка може обробляти об'єкти python безпосередньо), яка візьме два списки, які можуть містити себе та порівняти їх.

Два списки рівні, якщо вони однакової довжини і не існує послідовності чисел, така що індексація обох списків за цією послідовністю призводить до двох об'єктів, які не є рівними за цим визначенням рівними. Усі об'єкти, що не містять списку, містяться в списку, будуть цілими числами python для простоти і повинні порівнюватися з вбудованою python в рівності для цілих чисел.

Ваша програма не повинна покладатися на глибину рекурсії пітона, щоб визначити, чи список нескінченно глибокий. Тобто:

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

Не є правильним способом визначення, чи є два списки самореференційними.

Тестові шафи

Передбачає, що ви визначаєте функцію 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?
Пшеничний майстер

Це робить його кортеж.
mbomb007

a=[];a+=[a,1];b=[];b+=[b,2];f(a,b)переповнює стек і a=[1];b=[2];f(a,b);f(a,b)виглядає як проблема повторного використання.
Anders Kaseorg

@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

Пітон, 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 Це було написано до того, як було додано правило "Все є списками чи вставками". Буде оновлено.
isaacg

Ви можете використовувати 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.