Essas listas são iguais?

19

Como você deve saber, python possui listas. Como você talvez não saiba, essas listas podem se conter.

a = []
a.append(a)

Python 2

Python 3

Isso é legal e há muitas coisas interessantes que você pode fazer com elas, mas não pode compará-las.

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

Python 2

Python 3

Tarefa

Seu trabalho é escrever uma função no Python (ou qualquer linguagem que possa manipular objetos python diretamente) que pegue duas listas que possam se conter e as compare.

Duas listas são iguais se tiverem o mesmo comprimento e não existir uma sequência de números, de modo que a indexação de ambas as listas por essa sequência resulte em dois objetos que não sejam iguais nessa definição de igual. Todos os objetos que não constam de uma lista serão inteiros python por simplicidade e devem ser comparados com a igualdade interna de python para números inteiros.

Seu programa não deve contar com a profundidade de recursão do python para determinar se uma lista é infinitamente profunda. Isso é:

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

Não é uma maneira válida de determinar se duas listas são auto-referenciais.

Casos de teste

Supõe que você define uma função 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
Assistente de Trigo
fonte
17
Como uma nota lateral para eleitores em potencial: Observe que geralmente os desafios específicos ao idioma são desaprovados, exceto em determinadas circunstâncias (como tarefas que são interessantes apenas em determinados idiomas). IMO, este é um exemplo maravilhoso de um desafio específico do idioma.
DJMcMayhem
@WheatWizard Isso não é exatamente o suficiente - as listas aninhadas também precisam ter os mesmos comprimentos.
Xnor
@ WheatWizard Você realmente pode compará-los. No Python, você recebe apenas uma "recursão limitada excedida" se elas não forem iguais. tio.run/nexus/…
mbomb007
@ mbomb007 Isso porque o python, por padrão, compara as referências. Se você tiver dois objetos idênticos com referências diferentes, isso falhará, daí o desafio.
Assistente de trigo
2
Você pode estender esse desafio para todos os idiomas em que as listas podem se conter?
CalculatorFeline

Respostas:

9

Python 2 , 94 bytes

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)

Experimente online!

Uma melhoria na solução muito inteligente de isaacg de armazenar os idpares de listas que estão sendo processados ​​e declará-los iguais se a mesma comparação ocorrer em um nível inferior.

A etapa recursiva all(map(...,a,b))diz que ae bé igual se todos os pares correspondentes de elementos forem iguais. Isso funciona bem para rejeitar o comprimento desigual, porque mappreenche a lista mais curta None, ao contrário do zipque trunca. Como nenhuma das listas reais contém None, essas listas preenchidas sempre serão rejeitadas.

xnor
fonte
Qual é o propósito do ,depois do c?
Assistente de trigo
Torna uma tupla.
mbomb007
a=[];a+=[a,1];b=[];b+=[b,2];f(a,b)transborda a pilha e a=[1];b=[2];f(a,b);f(a,b)parece um problema de reutilização.
Anders Kaseorg
@ AndersKaseorg eu vejo, mudar a lista estava pedindo problemas. Eu acho que isso corrige.
xnor
11
@ AndersKaseorg E vejo que você escreveu basicamente a mesma solução de função em função. Há uma solução de 95-byte sem que: 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. Talvez haja uma maneira melhor de lidar com o problema map.
Xnor
5

Python, 233 218 197 217 bytes

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,{})

A função anônima na última linha executa a função desejada.

Ainda está em processo de golfe, eu só queria mostrar que isso é possível.

Basicamente, colocamos uma entrada em w se estivermos trabalhando em uma determinada verificação. Duas coisas são iguais se são o mesmo objeto, se não são listas e são iguais, ou se todos os seus elementos são iguais ou estão sendo trabalhados.

isaacg
fonte
Você não pode usar em a>[]vez de i(a,list)?
mbomb007
@ mbomb007 Foi escrito antes da adição da regra "Tudo é listas ou ints". Atualizará.
Isaacg
Você pode usar a>[]<belen(a)-len(b)
mbomb007
@ETHproductions Ah, a contagem de bytes dele está errada. É por isso que
mbomb007
Pode d(a)==d(b)ser a is b? Isso reduziria dois usos de d.
Xnor