Adição de alinhamento de matriz

39

Introdução

Considere duas matrizes inteiras não vazias, digamos A = [0 3 2 2 8 4] e B = [7 8 7 2] . Para executar a adição de alinhamento neles, fazemos o seguinte:

  1. Repita cada matriz vezes suficientes para ter comprimento total lcm (comprimento (A), comprimento (B)) . Aqui lcm representa o menor múltiplo comum.

    A -> [0 3 2 2  8 4][0 3  2 2 8 4]
    B -> [7 8 7 2][7 8  7 2][7 8 7 2]
    
  2. Execute a adição por elementos nas matrizes repetidas e corte o resultado em todas as posições em que houver um corte em qualquer uma delas.

    A -> [0  3 2 2   8  4][0 3  2  2  8 4]
    B -> [7  8 7 2][ 7  8  7 2][7  8  7 2]
      -> [7 11 9 4][15 12][7 5][9 10 15 6]
    
  3. Essa matriz de matrizes é o seu resultado.

A tarefa

Suas entradas são duas matrizes não vazias de números inteiros e sua saída será o resultado da adição de alinhamento, conforme definido acima. As entradas e saídas podem estar em qualquer formato razoável. Você não precisa se preocupar com excesso de número inteiro ao executar a adição.

Regras e pontuação

Você pode escrever um programa completo ou uma função. A menor contagem de bytes vence.

Casos de teste

[1] [4] -> [[5]]
[1,2,-3,-4] [15] -> [[16],[17],[12],[11]]
[0,-4] [2,1,0,-3] -> [[2,-3],[0,-7]]
[0,3,2,2,8,4] [7,8,7,2] -> [[7,11,9,4],[15,12],[7,5],[9,10,15,6]]
[18,17,16] [-1,-2,-3,-4] -> [[17,15,13],[14],[16,14],[15,13],[15],[16,14,12]]
[18,17,16,15] [-1,-2,-3,-4] -> [[17,15,13,11]]
[1,1,1,1,1] [6,5,6,5,6,5,6,2,1] -> [[7,6,7,6,7],[6,7,3,2],[7],[6,7,6,7,6],[7,3,2],[7,6],[7,6,7,6,7],[3,2],[7,6,7],[6,7,6,7,3],[2],[7,6,7,6],[7,6,7,3,2]]
[1,1,1,1,1,1] [6,5,6,5,6,5,6,2,1] -> [[7,6,7,6,7,6],[7,3,2],[7,6,7],[6,7,6,7,3,2]]
[1,1,1,1,1,1,1] [6,5,6,5,6,5,6,2,1] -> [[7,6,7,6,7,6,7],[3,2],[7,6,7,6,7],[6,7,3,2],[7,6,7],[6,7,6,7,3,2],[7],[6,7,6,7,6,7,3],[2],[7,6,7,6,7,6],[7,3,2],[7,6,7,6],[7,6,7,3,2],[7,6],[7,6,7,6,7,3,2]]
Zgarb
fonte
C não tem como saber o comprimento de uma matriz - posso solicitar o comprimento da matriz como argumento ou armazená-lo no início da matriz?
gato
1
@cat Você pode considerar os comprimentos como argumentos extras, se não houver outra maneira de obtê-los.
Zgarb

Respostas:

9

JavaScript (ES6), 101 99 bytes

Aceita entrada como 2 matrizes. Retorna uma string.

f=(a,b,j=0,s='')=>a.map((v,i)=>(s+=i*j?' ':s&&'][',s+=b[j]+v,j=++j%b.length))|j?f(a,b,j,s):`[${s}]`

Como funciona

Nós iteramos na primeira matriz acom um ponteiro ienquanto atualizamos outro ponteiro jna segunda matriz b. As somas a[i] + b[j]são anexadas à sequência de saída s. Um separador é inserido toda vez i == 0ou j == 0. Repetimos esse processo até que ele jretorne exatamente no início de bno final de uma iteração.

Nota: Quando o |operador é aplicado, a.map(...)é coagido NaN(se acontém mais de um elemento) ou ao valor atual de j(se acontém exatamente um elemento). Portanto, a.map(...)|j == jem todos os casos e é seguro usar aqui.

Casos de teste

Arnauld
fonte
Eu nem tentei entender a resposta, +1 para a nota .
Copio
6

Haskell, 84 79 bytes

a#b=a%b where(c:d)%(e:f)|(x:y)<-d%f=(c+e:x):y;[]%[]=[[]];c%[]=[]:c%b;_%d=[]:a%d

Minha primeira versão foi a mesma em um layout mais legível:

a#b=a%b where
 (c:d)%(e:f)|(x:y)<-d%f=(c+e:x):y
 []%[]=[[]]
 c%[]=[]:c%b
 _%d=[]:a%d

Usando uma definição local para evitar a necessidade de fornecer (%)argumentos extras para ae b. Surpreendentemente, essa é quase a mesma solução fornecida quase ao mesmo tempo que a @ nimi, de quem tomei a ideia de usar apenas uma linha para a definição local.

Uso:

*Main> [0,3,2,2,8,4] # [7,8,7,2]
[[7,11,9,4],[15,12],[7,5],[9,10,15,6]]
Peneiradores cristãos
fonte
Ah, é uma boa maneira de acrescentar a soma ao primeiro elemento da lista. Muito mais baixo que o meu pesado !.
nimi
4

PHP, 126 120 bytes

function($a,$b){do{$c[$j][]=$a[$i%$x=count($a)]+$b[$i%$y=count($b)];++$i%$x&&$i%$y?:$j++;}while($i%$x|$i%$y);return$c;};

Experimente aqui!

Função anônima que retorna a matriz resultante de matrizes.

Essencialmente, percorremos o conteúdo de ambas as matrizes, modificando nosso iterador pelo comprimento da matriz para simular 'copiá-las'. Tomando cada um dos valores das matrizes, nós somá-los e adicioná-los para uma matriz em $c. Se chegarmos ao final de uma de nossas matrizes de entrada (uma divisão, em termos do desafio), começaremos a atribuir uma nova matriz em $c.

A razão para o do whileloop é porque nossa condição é baseada $i, que começa em 0. Se usarmos um loop em que a condição é verificada no início, o loop não será executado

Somente finalizamos a soma quando atingimos o final de ambas as matrizes ao mesmo tempo, o que implicaria o LCM.

Xanderhall
fonte
Não deveria ser $b[$i%$y]? Você pode salvar 3 bytes passando $x=count($a)para o primeiro uso de $x; mesmo para $y=count($b)e um byte com bit a bit ou na whilecondição
Titus
Mas acho que funções anônimas são consideradas trechos e, portanto, não há respostas válidas.
Titus
As funções anônimas do @Titus são permitidas por padrão, conforme consenso no Meta .
Zgarb
Obrigado pelas sugestões @Titus, eu meio que juntei tudo isso porque queria vencer as outras respostas do PHP: P
Xanderhall 16/12/16
4

Haskell, 87 84 bytes

a#b=a%b where[]%[]=[[]];(e:f)%(g:h)=f%h!(e+g);e%[]=[]:e%b;_%g=[]:a%g
(m:n)!l=(l:m):n

Exemplo de uso: [0,3,2,2,8,4] # [7,8,7,2]-> [[7,11,9,4],[15,12],[7,5],[9,10,15,6]].

Recursão simples. Caso base: as duas listas estão vazias. Se apenas um deles estiver vazio, reinicie com uma versão completa e inicie um novo cluster na saída. Se nenhum estiver vazio, acrescente a soma ao elemento from.

Veja também a resposta de @Christian Sievers , que é quase idêntica e foi publicada alguns segundos antes.

nimi
fonte
Você tem certeza? Existe uma maneira de obter os horários exatos?
Christian Sievers
@ ChristianSievers: Eu não sei se você pode ver os horários diretamente. Quando os horários de nossas edições foram mostrados em minutos, lembro que o seu foi contado alguns segundos (cerca de 20) antes do meu.
nimi
Você está certo: encontrei carimbos de data e hora no código-fonte html desta página
Christian Sievers
Passe o mouse sobre o tempo em "respondeu há 2 dias" para ver a hora exata. (Dica: essa é uma interface de usuário padrão na Internet; portanto, (a) se você deseja um horário exato, tente passar o tempo relativo; e (b) se alguma vez implementar algo que mostre tempo relativo, mostre o horário exato ao passar o mouse !)
wchargin
2

Oitava, 113 bytes

@(a,b)mat2cell(sum([repmat(a,1,(L=lcm(A=numel(a),B=numel(b)))/A);repmat(b,1,L/B)]),1,diff(unique([0:A:L,0:B:L])))

esta função pode ser chamada diretamente para colocá-la entre parênteses e chamar como (@ (a, b) ...) ([1 2 3 4], [6 4 5])

rahnema1
fonte
1
Agora, o TIO-Nexus suporta o Octave. Aqui está um link para testar o código
Luis Mendo
@LuisMendo Obrigado, serviço interessante
rahnema1
2

CJam , 30 bytes

{Sf*Laf+_s,f*:.+La/0=S2*a-Sa/}

Experimente online!

Recebe a entrada como um par de listas.

Explicação

A idéia é inserir alguns marcadores nas matrizes de entrada (na forma de cadeias curtas) que indicam onde termina a matriz alinhada e onde precisamos inserir as quebras nas matrizes. Dessa forma, podemos evitar ter que calcular o LCM.

Sf*    e# Riffle each list with spaces. These are just place holders, so that having
       e# an array-end marker between two elements doesn't misalign subsequent elements.
Laf+   e# Append an empty string to each list. This is the array-end marker.
_s,    e# Convert the pair of lists to a string and get its length. This is always
       e# greater than the number of elements in either input.
f*     e# Repeat either array that many times. This is definitely more than necessary
       e# to reach the LCM (since multiplying by the length of the other list always
       e# gives a common multiple).
:.+    e# Pairwise addition of the list elements. There are four cases:
       e# - Both elements are numbers, add them. This is the actual addition
       e#   we need for the problem.
       e# - Both elements are spaces. This is just a regular position between
       e#   list elements.
       e# - One is a space, one is empty: the result is a single space, and
       e#   this marks a position where one of the arrays ended, which means
       e#   we need to split here.
       e# - Both elements are empty. This happens at the LCM of both list lengths
       e#   and indicates where we need to stop the output.
La/0=  e# Split the input around empty strings and discard everything except
       e# the first chunk.
S2*a-  e# Remove the double-space strings, we no longer need them.
Sa/    e# Split the list around single spaces.
Martin Ender
fonte
2

Geléia , 21 20 18 bytes

ṁ€L€æl/$S
J€ỊÇœṗÇḊ

Experimente online!

Como funciona

ṁ€L€æl/$S  Helper link. Argument [X, Y] (arrays of integers).

       $   Combine the two links to the left into a monadic chain.
  L€       Length each; yield the lengths of X and Y.
    æl/    Reduce by least common multiple.
ṁ€         Mold each; cyclically repeat the elements of X and Y to extend them
           to length lcm(length(X), length(Y)).
        S  Compute the sum of the extended X and Y arrays.

J€ỊÇœṗÇḊ   Main link. Argument [A, B] (arrays of integers).

J€         Indices each; replace A and B by the arrays of there 1-based indices.
  Ị        Insignificant; map 1 to itself, all other indices to 0.
   Ç       Apply the helper link to the result.
           This yield a Boolean array with a 1 (or 2) at all indices where a new
           repetition of A or B (or both) begins.
      Ç    Apply the helper link to [A, B].
    œṗ     Partition; break the result to the right at truthy elements (1 or 2) in
           the result to the right.
       Ḋ   Dequeue; remove the first element of the partition (empty array).
Dennis
fonte
2

Python 3.5 - ( 146 137 134 130 + 12) = 142 bytes

import math
def s(a,b):
 l,k,*r=map(len,[a,b])
 for i in range(l*k//math.gcd(l,k)):
  r+=a[i%l]+b[i%k],
  if i%k==k-1or i%l==l-1:print(r);r=[]

Não consigo descobrir como colocar o loop for inteiro em uma linha.

Edições:

  • Obrigado zgarb por salvar 9 bytes!
  • Obrigado vaultah por salvar 3 bytes!
  • Obrigado mathmandan economizando 5 bytes!
Gurupad Mamadapur
fonte
Isso dá um erro para mim . A gcdfunção está dentro fractions, não math.
Zgarb
@Zgarb o módulo gcd in frations está obsoleto , você pode verificar a alteração aqui . Eu acho que o Rexter está usando a versão antiga 3.4.3.
Gurupad Mamadapur
Legal, eu não sabia sobre essa mudança. Você deve marcar o idioma como "Python 3.5", pois ele não funciona no 3.4 ou anterior. Além disso, você pode soltar os parênteses l*ke colocar print(r);r=[]na última linha.
Zgarb
Tem certeza de que sua contagem de bytes está correta? Eu acho que existem apenas 145 bytes.
vaultah
1
Estou recebendo 142 bytes. Você está usando o Windows? O Windows normalmente conta novas linhas com 2 bytes cada, mas aqui cada nova linha é contada como um único byte.
mathmandan
2

Python 2, 119 bytes

a=input()
i,v,l=0,list(a),len
while 1:q=l(v[0])>l(v[1]);print map(sum,zip(*v)[i:]);i=l(v[q]);v[q]+=a[q];1/(i-l(v[q^1]))

Recebe a entrada do stdin como duas tuplas separadas por vírgula, gera as listas resultantes para o stdout. Encerra levantando a ZeroDivisionErrorexceção, pois isso parece ser permitido .

Por exemplo, se a entrada for (0, 3, 2, 2, 8, 4), (7, 8, 7, 2), o programa imprimirá

[7, 11, 9, 4]
[15, 12]
[7, 5]
[9, 10, 15, 6]

para stdout e a exceção traceback para stderr.

vaultah
fonte
Você pode sair do programa lançando um erro . Então você pode conseguir o loop em uma única linha.
Zgarb
2

J , 34 32 bytes

[:(<;.1~*)/[:+/*.&#$&>,:&(;2>#\)

Experimente online!

Explicação

[:(<;.1~*)/[:+/*.&#$&>,:&(;2>#\)  Input: array A (LHS), array B (RHS)
                             #\   Length of each prefix of A and B
                           2>     Less than 2
                          ;       Link each with A and B
                      ,:&         Pair them
                  #               Length of A and B
               *.&                LCM of the lengths
                    &>            For each box
                   $              Reshape it to the LCM of the lengths
           [:+/                   Reduce by addition
[:        /                       Reduce by
        *                           Sign of RHS
   <;.1~                            Box each partition of LHS
milhas
fonte
1

Haskell, 166 bytes

Essa provavelmente não é a abordagem mais elegante: basicamente, a função ?cria uma lista do comprimento necessário com essas somas e %está cortando essa soma novamente. !é a função final que mescla esses dois.

l=length
a?b=take(lcm(l a)$l b)$zipWith(+)(cycle a)$cycle b
l%(i:ind)|l==[]=[]|1>0=take i l:(drop i l)%(map(+(-i))ind)
a!b=(a?b)%[k|k<-[1..],k`mod`l a<1||k`mod`l b<1]
flawr
fonte
Você pode substituir indpor kou algo assim, e existem alguns parênteses desnecessários ao redor drop i le map(+(-i))ind. Considere também ter dois casos para %, com a correspondência de padrões ativada l.
Zgarb
1

[PHP], 183 152 135 135 bytes

function O($A,$B){while($f<2){$O[$k][]=$A[+$i]+$B[+$j];$f=0;isset($A[++$i])?:$i=!++$k|!++$f;isset($B[++$j])?:$j=!++$k|!++$f;}return$O;}

Nice version:

function O($A,$B)
{
    while($f<2) {
        $O[$k][]=$A[+$i]+$B[+$j];
        $f=0;
        isset($A[++$i])?:$i=!++$k|!++$f;
        isset($B[++$j])?:$j=!++$k|!++$f;
    }

    return$O;
}

Saída:

array (size=4)
  0 => 
    array (size=4)
      0 => int 7
      1 => int 11
      2 => int 9
      3 => int 4
  1 => 
    array (size=2)
      0 => int 15
      1 => int 12
  2 => 
    array (size=2)
      0 => int 7
      1 => int 5
  3 => 
    array (size=4)
      0 => int 9
      1 => int 10
      2 => int 15
      3 => int 6
Dexa
fonte
Desenhe mesmo comigo usando esses ajustes: $i=$j=$k=0;é desnecessário se você usar +$ietc. para os índices da matriz na atribuição anexa (-8 bytes). $i++;if(!isset($A[$i])){$i=0;$k++;}-> isset($A[++$i])?:$i=!++$k;(-9, duas vezes). $i==0&&$j==0&&!isset()-> !$i&!$j&!isset()(-6). return$O;não precisa de espaço (-1).
Titus
O @Titus não pode remover $i=$j=0;peças, pois os primeiros valores das matrizes não estarão corretos. Eu modifiquei a lógica um pouco para não ter certeza de como implementar operadores ternários neste caso. Obrigado por ++$iconselhos.
Dexa
Tente unset($i);$A[+$i]. O +será convertido nullpara inteiro 0.
Titus
if(!isset($A[++$i])){$i=0;++$k;++$f;}-> isset($A[++$i])?:$i=!++$k|!++$f;ainda salva 5 bytes cada. Salve mais um com em $f<2vez de $f!=2. e outro com duas while($f=$f<3){...}em vez de while($f<2){$f=0;...}(inicializa e repõe $fa 1, a menos que IT'S incrementado duas vezes)
Titus
@ Titus Muito obrigado, agora é mais curto.
Dexa
1

PowerShell , 147 145 bytes

param($a,$b)$o=@{};do{$o[+$j]+=,($a[+$i%($x=$a.count)]+$b[$i++%($y=$b.count)]);if(!($i%$x-and$i%$y)){$j++}}until(($x,$y|?{!($i%$_)}).count-eq2)$o

Experimente online!

( Sugestões de golfe são bem-vindas. Acho que provavelmente existem outros 10 a 15 bytes que podem ser extraídos disso. )

Recebe entrada como duas matrizes explícitas (com a @(...)sintaxe) como argumentos da linha de comando. Retorna uma hashtable das matrizes resultantes, porque matrizes multidimensionais no PowerShell podem ficar estranhas e isso é mais consistente. Define algumas variáveis ​​iniciais e, em seguida, insere um loop do/ untilnovamente, com o estado condicional até que $io lcm da matriz conte .

Cada iteração de loop, adicionamos os valores correspondentes $ae $bos tratamos como um array ,(...)antes de adicioná-los à hashtable $ono local apropriado $j. O encapsulamento da matriz é necessário para evitar a adição aritmética - isso força a +=sobrecarga à concatenação da matriz. Em seguida, um condicional em $xe $y(as contagens) para determinar se estamos em uma borda da matriz - nesse caso, incrementamos $j.

Finalmente, deixamos $oo pipeline e a produção está implícita.
(NB: devido ao modo como o PowerShell enumera tabelas de hash com o padrão Write-Output, isso tende a ser gerado "para trás"; como em, a "0a" matriz resultante fica na "parte inferior" da saída. O próprio hash é bom e seria usado muito bem se você, por exemplo, encapsular esse código em uma variável de retorno ... parece estranho quando é impresso.)

Economizou 2 bytes movendo $ xe $ y para a indexação da matriz em vez de separar (salvou dois pontos e vírgulas).

AdmBorkBork
fonte
1

Python 2, 113 bytes

a,b=input()
i=m=n=0;r=[]
while(not i)+m+n:r+=[[]]*(not m*n);r[-1]+=[a[m]+b[n]];i+=1;m=i%len(a);n=i%len(b)
print r
orlp
fonte
Em vez disso, poderiam notser os <1s?
Zgarb
1

Python 3.5, 210 176 173 169 158 Bytes

def f(a,b):
 x=[];e=f=0              
 while 1:
  if e==len(a):         
   print(x);x=[];e=0;
   if f==len(b):break
  if f==len(b):print(x);x=[];f=0
 x+=a[e]+b[f],;e+=1;f+=1

Pega duas listas como entrada e imprime todas as listas.

É a minha primeira resposta e ainda não sei jogar golfe. A idéia básica que usei é ter dois contadores para cada lista, que indicam uma divisão e uma lista atual em que os valores adicionados são anexados; assim que uma divisão é encontrada, imprimimos a lista atual e fazemos uma nova lista vazia.

  • 34 bytes salvos : Graças a Dennis e TimmyD
  • Economizou 3 bytes : estava usando c e d para len (a) e len (b), mas acontece que eles não foram úteis
  • 4 bytes salvos : graças ao orlp , removeu a parênteses indesejada
  • Economizou 11 bytes : reorganizou alguns blocos e os triturou
officialaimm
fonte
1
Olá, e seja bem-vindo à programação de quebra-cabeças e código de golfe! Não competir significa algo mais aqui; você deve remover isso. Você pode salvar alguns bytes eliminando espaços em branco. Por exemplo, as linhas 2 a 5 podem se tornar x=[];c=len(a);d=len(b);e=f=0. Além disso, truepode se tornar 1e x.append(a[e]+b[f])pode se tornar x+=a[e]+b[f],.
Dennis
1
Bem-vindo ao PPCG! Além dos ajustes específicos de Dennis, consulte Dicas para jogar golfe em Python para obter dicas e truques mais gerais.
AdmBorkBork
1
ife whiledeclarações não precisam de parênteses.
orlp
1

Raquete 373 bytes

(let*((lg length)(fl flatten)(ml make-list)(t rest)(r reverse)(m modulo)(o cons)(ln(lg l))(jn(lg j))(c(lcm ln jn))(l2(fl(ml(/ c ln)l)))
(j2(fl(ml(/ c jn)j)))(ll(for/list((a l2)(b j2))(+ a b))))(let p((ll ll)(ol '())(tl '())(n 0))(cond[(empty? ll)(t(r(o(r tl)ol)))]
[(or(= 0(m n ln))(= 0(m n jn)))(p(t ll)(o(r tl)ol)(take ll 1)(+ 1 n))][(p(t ll)ol(o(first ll)tl)(+ 1 n))])))

Ungolfed:

(define(f l j)
  (let* ((ln (length l))
         (jn (length j))
         (c (lcm ln jn))
         (l2 (flatten (make-list (/ c ln) l)))
         (j2 (flatten (make-list (/ c jn) j)))
         (ll (for/list ((a l2)(b j2))
               (+ a b))))

    ; TO CUT LIST INTO PARTS: 
    (let loop ((ll ll)
               (ol '())
               (templ '())
               (n 0))
      (cond
        [(empty? ll) 
         (rest (reverse (cons (reverse templ) ol)))]
        [(or (= 0 (modulo n ln))
             (= 0 (modulo n jn)))
         (loop (rest ll)
               (cons (reverse templ) ol)
               (list (first ll))
               (add1 n))]
        [(loop (rest ll)
               ol
               (cons (first ll) templ)
               (add1 n))]))))

Teste:

(f '[1]  '[4])
(f '[1 2 -3 -4] '[15])
(f '[0 3 2 2 8 4]  '[7 8 7 2])

Saída:

'((5))
'((16) (17) (12) (11))
'((7 11 9 4) (15 12) (7 5) (9 10 15 6))
rnso
fonte
1

Clojure, 280 206 bytes

(fn[a b](let[A(count a)B(count b)Q quot](map #(map last %)(partition-by first(take-while #((% 0)2)(map-indexed(fn[i s][[(Q i A)(Q i B)(or(= i 0)(>(mod i A)0)(>(mod i B)0))]s])(map +(cycle a)(cycle b))))))))

Bem, isso faz muito mais sentido. Gerando a soma elemento a elemento, adicionando metadados posicionais, demorando enquanto ainda não repetimos e colocando o valor da soma em cada partição.

(def f (fn[a b]
         (let[A(count a)B(count b)Q quot]
           (->> (map +(cycle a)(cycle b))
                (map-indexed (fn [i s][[(Q i A)(Q i B)(or(= i 0)(>(mod i A)0)(>(mod i B)0))]s]))
                (take-while #((% 0)2))
                (partition-by first)
                (map #(map last %))))))

Original: Espero melhorar isso, mas este é o mais gentil que tenho por enquanto.

(fn[a b](let [C cycle o count c(take-while #(or(=(% 0)0)(>(% 1)0)(>(% 2)0))(map-indexed(fn[i[A B]][i(mod i(o a))(mod i(o b))(+ A B)])(map(fn[& v]v)(C a)(C b))))](map #(map last %)(partition-by first(map(fn[p c][p(last c)])(reductions + (map #(if(or(=(% 1)0)(=(% 2)0))1 0)c))c)))))

Ungolfed e verbose:

(def f (fn[a b]
         (let [c(->> (map (fn[& v]v) (cycle a) (cycle b))
                     (map-indexed (fn[i[A B]][i (mod i(count a)) (mod i(count b)) (+ A B)]))
                     (take-while #(or(=(% 0)0)(>(% 1)0)(>(% 2)0))))]
           (->> (map (fn[p c][p(last c)]) (reductions +(map #(if(or(=(% 1)0)(=(% 2)0))1 0)c)) c)
                (partition-by first)
                (map #(map last %))))))

Começa "mesclando" um ciclo infinito de coleções a e b, adiciona metadados ao índice de cada elemento dentro da coleção, leva até que as duas seqüências iniciem novamente no índice 0.

Essa coleção cé então mesclada com os dados da partição (uma soma acumulada de uns e zeros), particionada e o último elemento (sendo soma de itens) é selecionado.

Penso que para melhorias significativas é necessária uma abordagem totalmente diferente.

NikoNyrh
fonte
1

PHP, 150 121 119 bytes

function($a,$b){while($i<2|$x|$y)$r[$k+=!($x=$i%count($a))|!$y=$i++%count($b)][]=$a[$x]+$b[$y];array_pop($r);return$r;}

função anônima recebe entrada como matrizes.

demolir

while($i<2|$x|$y)   // loop while either $a or $b has NO cut
    $r[
                // if either $a or $b has a cut, increment $k; post-increment $i
        $k+=!($x=$i%count($a))|!$y=$i++%count($b)
                // append current $a + current $b to $r[$k]
    ][]=$a[$x]+$b[$y];
array_pop($r);  // $r has one element too much; remove it
return$r;
Titus
fonte
0

C ++ 14, 206 bytes

Como lambda sem nome genérico, que necessitam de recipientes de entrada P, Qe a saída do recipiente Rpara ser assim vector<vector<int>>.

[](auto P,auto Q,auto&R){R.clear();auto a=P.begin(),b=Q.begin(),x=P.end(),y=Q.end();auto A=a,B=b;do{R.emplace_back();while(a!=x&&b!=y)R.back().push_back(*a+++*b++);a=a==x?A:a;b=b==y?B:b;}while(a!=A||b!=B);}

Ungolfed e uso:

#include<vector>
#include<iostream>

using namespace std;

auto f=
[](auto P,auto Q,auto&R){
 R.clear();               //just clear the output to be sure
 //a and b are the iterators, x and y is the end
 auto a=P.begin(),b=Q.begin(),x=P.end(),y=Q.end();
 //just some abbreviations for .begin()
 auto A=a,B=b;
 do{
  R.emplace_back();      //add new vector
  while(a!=x&&b!=y)      //while not at the end of one vector
   R.back().push_back(*a+++*b++);  //add the pointed elements and advance
  a=a==x?A:a;            //reset if at the end   
  b=b==y?B:b;
 }while(a!=A||b!=B);     //if both were resetted, then finish
}
;


int main(){
 vector<int> A = {0, 3, 2, 2, 8, 4};
 vector<int> B = {7, 8, 7, 2};
 vector<vector<int>> R;
 f(A,B,R);
 for (auto c:R){
  for (int x:c)
   cout << x << ", ";
  cout << endl;
 }
 cout << endl;
}
Karl Napf
fonte
0

Mathematica 112 Bytes

Provavelmente isso poderia ser melhorado. A idéia é criar uma matriz 2D com o segundo elemento usado para rastrear o locador do contador e modificar o comprimento de cada matriz de entrada.

Split[Table[{#[[1,(m=Mod[i,d=Length/@#,1])[[1]]]]+#[[2,m[[2]]]],Min@m},{i,LCM@@d}],#2[[2]]>#1[[2]]&][[;;,;;,1]]&

Uso

%@{{0,3,2,2,8,4},{7,8,7,2}}
Kelly Lowder
fonte
0

JavaScript (ES6), 131 bytes

(a,b,g=(r,[n,...d]=a,[m,...e]=b,s=[])=>1/n?1/m?g(r,d,e,[...s,n+m]):g([...r,s],[n,...d]):1/m?g([...r,s],a,[m,...e]):[...r,s])=>g([])

Ligeiramente não destruído:

(a,b,r=[],[n,...d]=a,[m,...e]=b,s=[])
=>1/n?1/m?f(a,b,r,d,e,[...s,n+m])
         :f(a,b,[...r,s],[n,...d],b,[])
     :1/m?f(a,b,[...r,s],a,[m,...e],[])
         :[...r,s]
  • Se ambas as matrizes d e econtiverem números, a soma do primeiro número será anexada se os elementos restantes serão processados ​​recursivamente
  • Se uma das matrizes contiver números, a matriz de somas s será anexada ao resultado re a outra matriz será redefinida para sua matriz inicial
  • Se ambas as matrizes estiverem vazias, basta retornar o resultado com as últimas somas anexadas.

Infelizmente, esta solução não tem a eficiência implacável da @ Arnauld's, mas pelo menos eu acho que é uma solução bonita.

Neil
fonte