fundo
Os átomos aritméticos da geléia se vetorizam automaticamente. De fato, x + y é bem definido sempre que x e y são números ou matrizes irregulares de números. O código fonte do Jelly implementa esse comportamento usando um vetorizador genérico, mas para esse desafio, consideraremos apenas a adição de números inteiros e matrizes inteiras aninhadas.
Definições
Defina a profundidade de x como 0 se x for um número inteiro, como 1 se for uma matriz plana (possivelmente vazia) de números inteiros e como n + 1 se contiver pelo menos um elemento de profundidade n e nenhum elemento de profundidade k> n .
Dessa forma, 1 tem profundidade 0 , [] e [1] e [1, 1] têm profundidade 1 , [[], []] e [[1], [1]] e [[1]] e [1 , []] possui profundidade 2 , [1, [1, [1]]] possui profundidade 3 , etc.
A operação x + y é definida da seguinte forma.
Se x e y tem profundidade 0 , volte sua soma.
Se x e y têm profundidades iguais, mas positivas, de forma recursiva aplicam + a todos os itens de x e os itens correspondentes do y .
Se x e y têm diferentes comprimentos, acrescentar a cauda da matriz de mais tempo para a série de somas.
Retorne o resultado.
Se a profundidade de x for estritamente menor que a profundidade de y , aplique recursivamente + a x e todos os itens de y e retorne o resultado.
Faça o oposto se a profundidade de y for estritamente menor que x .
Por exemplo, considere a operação [1, [2, 3], [4]] + [[[10, 20], [30], 40, 50], 60] .
A profundidade do argumento da esquerda é 2 , enquanto a profundidade do argumento da direita é 3 , portanto calculamos [1, [2, 3], [4]] + [[10, 20], [30], 40, 50 ] e [1, [2, 3], [4]] + 60 .
[1, [2, 3], [4]] e [[10, 20], [30], 40, 50] têm profundidade 2 , então calculamos 1 + [10, 20] , [2, 3] + [30] e [4] + 40 .
1 + [10, 20] = [1 + 10, 1 + 20] = [11, 21]
[2, 3] + [30] = [2 + 30, 3] = [32, 3]
Observe que 3 permanece intocado, pois não possui um elemento correspondente.
[4] + 40 = [4 + 40] = [44]
50 não tem um elemento correspondente, de modo que o resultado é [[[11, 21], 44 [32, 3], [], 50]] .[1, [2, 3], [4]] + 60 = [1 + 60, [2, 3] + 60, [4] + 60] = [61, [2 + 60, 3 + 60], [ 4 + 60]] , resultando em [61, [62, 63], [64]] .
O resultado final é [[[11, 21], [32, 3], [44], 50], [61, [62, 63], [64]]] .
Tarefa
Escreva um programa ou uma função que use dois números inteiros, duas matrizes aninhadas de números inteiros ou uma combinação dos mesmos como entrada e retorne sua soma, conforme definido acima.
Se o seu idioma tiver vários tipos de array (listas, tuplas, vetores, etc.), você poderá escolher qualquer um deles para sua resposta. O tipo de retorno deve corresponder ao tipo de argumento.
Para evitar soluções chatas e imbatíveis, se um idioma tiver essa operação exata como um built-in, você não poderá usá-lo.
Todos os built-ins de todos os outros idiomas são permitidos. Se o seu idioma de escolha permitir, você poderá sobrecarregar e / ou redefinir a adição interna.
Isso é código-golfe , então o código mais curto em bytes vence.
Casos de teste
0 + 0 = 0
[-1, 0, -1] + [1] = [0, 0, -1]
[] + [0] = [0]
[] + 0 = []
[] + [] = []
[[], 0] + [] = [[], []]
[1, 2, 3] + 10 = [11, 12, 13]
[1, 2, 3] + [10] = [11, 2, 3]
[1, 2, 3] + [10, [20]] = [[11, 12, 13], [21, 2, 3]]
[1, 2, 3, []] + [10, [20]] = [11, [22], 3, []]
[1, [2, [3, [4]]]] + [10, [20]] = [[11, [21]], [[12, [22]], [13, [24]]]]
Para gerar mais casos de teste, você pode usar este programa Jelly .
Respostas:
Pitão, 42 bytes
Suíte de teste
Os últimos 4 bytes simplesmente executam a função na entrada.
fonte
APL, 44 bytes
O APL também
+
distribui por matrizes, mas de uma maneira diferente o suficiente para que isso realmente não possa ser usado. No entanto, há uma função interna de profundidade (≡
).Explicação:
1=≡⍺⍵:⍺+⍵
: se as profundidades de⍺
⍵
são zero (e, portanto, a profundidade⍺ ⍵
é 1), adicione-as.∆←|≡¨⍺⍵
: Tomar o absoluto da profundidade de ambos⍺
e⍵
e armazená-los em∆
. (≡
fornece um valor negativo se nem todos os elementos tiverem a mesma profundidade.)=/∆
: se eles tiverem a mesma profundidade:↓↑⍺⍵
: preencha a matriz mais curta com zeros para corresponder à matriz mais longa⊃∇¨/
: distribuir a função pelas duas matrizes</∆
: se a profundidade de⍺
for menor que a de⍵
:⍺∘∇¨⍵
: ligar⍺
e depois mapear sobre⍵
⍵∇⍺
: se nada mais (por isso⍵
é mais profundo que⍺
), troque os argumentos e tente novamente.fonte
Mathematica, 122 bytes
Define uma função recursiva
f
que calcula a soma. Utilizando a correspondência de padrões do Mathematica, essa função é composta de quatro definições separadas:Se a profundidade de
x
for maior que a dey
, troque os argumentos para que apenas tenhamos de lidar com a distribuição em uma direção (o que podemos fazer, pois a adição é comutativa).Se a profundidade
x
é menor thann a dey
, substituir cada valor#
noy
comf[x,#]
, que cuida da distribuição para os argumentos de profundidade desigual.Caso contrário, se um argumento for uma lista (o que implica que o outro também seja uma lista, já que sabemos que eles têm a mesma profundidade), colocaremos os dois argumentos em uma lista, preenchê-los com o mesmo comprimento
PadRight[..., Automatic]
(que simplesmente preenche um matriz irregular com zeros para torná-lo retangular) e, em seguida, useMapThread
para aplicarf
aos pares correspondentes das duas listas.E, finalmente, o caso base:
Se nenhum dos outros padrões corresponder, devemos estar tentando adicionar dois números, então fazemos isso.
fonte
Haskell, 150 bytes
Explicação
A primeira linha define um tipo de dados algébrico
L
, que é umS
calar (contendo umInt
) ou umV
ector (contendo uma lista deL
s, acessados usando um gravador de registrosv
, que é uma função parcialL → [L]
).A segunda linha define a função de profundidade : a profundidade de um
V
etor é uma mais a sua profundidade máxima. Eu prefiroS 0
os valores no vetor, de modo quedepth [] == 1 + maximum [depth (S 0)] == 1
. A profundidade de "qualquer outra coisa" (um escalar) é0
.A terceira linha define o caso base para
!
(a função de adição): a soma dos escalares é simplesmente um escalar.A quinta linha define uma variante
zipWith (!)
que apenas seleciona elementos da lista mais longa quando um deles está vazio.A quarta linha é dividida em três casos:
Se a profundidade de
x
for estritamente menor que a profundidade dey
, mapeie(x!)
os elementos dey
. (O uso dev
é garantido como válido, comod(y) ≥ 1
.)Se a profundidade de
x
for estritamente maior, inverta os argumentos e reinicie.Se a profundidade for igual, junte os argumentos
(!)
. (O uso dev
é garantido como válido, pois o casod(x) = d(y) = 0
foi tratado como um caso base.)Casos de teste
Então
show (lArg ! rArg) == "[[11,[21]],[[12,[22]],[13,[24]]]]"
.fonte
import
Isso ocorre porque o Ideone tem um antigo compilador Haskell. Versões modernas do GHC colocou<$>
emPrelude
, assim você não precisa importarControl.Applicative
para usá-lo nos dias de hoje.Java,
802794754746 bytesDecidi aceitar @ Dennis ♦ para o desafio de operar com cordas "como último recurso" porque provavelmente era "muito complicado". Além disso, no pior idioma para jogar golfe.
As matrizes na entrada são separadas por vírgula, entre colchetes e sem espaço em branco.
Programa completo com funções agrupadas em uma classe e com casos de teste
Eu poderia porta isso para C ++ mais tarde, uma vez que é a outra língua que eu sei que não suporta matrizes irregulares, desde que eu sou
certezaquase certo que vai ser mais curto do que esta resposta. Isso era principalmente uma prova de conceito, mas qualquer dica de golfe ainda seria apreciada!-31 bytes de @ user902383, sugerindo o uso de um foreach sobre uma matriz de caracteres convertida e, em seguida, salvei um pouco mais de reorganizar os blocos if na parte final.
fonte
Object[]
, que contém aninhadoObject[]
ouInteger
. Ou apenas lista não genérica.Python 2.7,
261209202198191185197181 bytesSolução trivial FGITW
EDIT: Claro que @Dennis vence
Agradecemos ao @LeakyNun por salvar 57 bytes com dicas sobre expressões lambda e 2 bytes entre colchetes desnecessários.
Obrigado a @Adnan por 4 bytes devido à sugestão de usar em
type
vez deisinstance
Graças a @Lynn por 7 bytes com
-~
emap
Obrigado a @FryAmTheEggman em
z>=[]
vez detype
+12 bytes para converter lambda em if else e corrigir um erro grave
-16 bytes graças a @Kevin Lau - não Kenny
Experimente online
fonte
z==[]or`z`>']'and ...
max(d(a)+1for a in z)
por-~max(d(a)for a in z)
salva um byte (porque você pode remover o espaço antesmax
). O que é então apenas-~max(map(d,z))
.[p(a,b)for a,b in zip(x,y)]
emmap(p,x,y)
. Você ainda pode fazer isso em 3, mas precisa adicionar uma chamada paralist
. Eu acho que você também pode melhorar a sugestão de Lynnz>=[]
. Não relacionado, você também deve poder trocar atype
ordem de comparação para economizar espaço.or`z`>'['
, é claro, mas não posso mais mudar meu comentário. Mas, de fato,z>[]
é ainda mais curto (o==
caso já está resolvido)!Python 2,
145136 bytesTeste em Ideone .
Como funciona
No Python 2, todos os números inteiros são menores que todos os dicionários, mas todas as listas são maiores. d calcula recursivamente a profundidade de t retornando 0 para números inteiros ou o máximo incrementado das profundidades de seus elementos e 0 .
t+[0]
evita que a lista vazia seja colocada em maiúsculas e minúsculas.s calcula recursivamente a soma da geléia de x e y .
Se a profundidade de y excede x ,
s(y,x)
chama s com argumentos trocados, certificando-se de que d (x) ≤ d (y) .Se y tiver profundidade positiva,
map(s,(x,[x]*len(y))[d(x)<d(y)],y)
faça o seguinte.Se as profundidades de x e y coincidirem, ele será executado
map(s,x,y)
, mapeando s sobre todos os elementos de x e os elementos correspondentes de y .No caso de listas de tamanhos diferentes, o mapa passará None como argumento esquerdo ou direito para elementos ausentes na lista mais curta.
Se a profundidade de x for menor que a de y , ela será executada
map(s,[x]*len(y),y)
, mapeando s (x, ·) sobre y .Se y (e, portanto, x ) tiver profundidade 0 ,
(x or 0)+(y or 0)
substitui argumentos falsos ( Nenhum ou 0 ) por zeros e retorna a soma dos números inteiros resultantes.fonte
JavaScript (ES6), 152 bytes
fonte
Ruby 2.3,
143145148149 bytesRuby tem todas essas pequenas peculiaridades de como
zip
funciona com matrizes de comprimento diferente emap
com funções com vários argumentos, tornando isso muito divertido jogar golfe.fonte
map
com dois argumentos da maneira como o configurei no final. Aqui está uma versão editada para 2.1 que funciona que ajusta amap
chamada no final do trabalho. ideone.com/q1jqTAJulia, 113 bytes
Experimente online!
Como funciona
cria um alias de 1 byte para endof , que retorna o comprimento de uma matriz.
define uma função de profundidade. A profundidade de t é zero se e somente se 0t == 0 . Caso contrário, t é uma matriz e sua profundidade é calculada como o máximo incrementado das profundidades de seus elementos e 0 .
[t;0]
anexa um 0 à matriz t , evitando assim a necessidade de criar um caso especial para a matriz vazia.A soma interna de Julia + já se comporta como a soma de Jelly se um (ou ambos) de seus argumentos for um número inteiro. No entanto, a soma de duas matrizes ( + ) requer matrizes da mesma forma e até a soma vetorizada ( . + ) Requer matrizes que podem ser transmitidas para uma forma comum.
Redefinimos + para um par de matrizes via
Isso não afeta a definição de + para argumentos inteiro / inteiro, matriz / número inteiro ou número inteiro / matriz.
(!x,~x)>(!y,~y)
lexicograficamente compara os pares de profundidades e comprimentos de ambos x e y . Se a profundidade de x exceder y , ou se a profundidade corresponder e o comprimento de x exceder y ,y+x
recursivamente chamará + com argumentos trocados.Caso contrário,
!x<!y
testa se a profundidade de x é menor que a de y . Se for,map(t->x+t,y)
mapeia x + · sobre y .Se as profundidades coincidirem,
~x<~y
testa se x é menor que y . Se estiver,[x;0]+y
chama recursivamente + após anexar um 0 ao argumento esquerdo.Finalmente, se as profundidades e os comprimentos forem idênticos,
x.+y
mapeia + todos os elementos de x e os elementos correspondentes de y .fonte