Escolha uma lista plana


20

Considere o processo de "escolher" uma lista aninhada. A escolha é definida da seguinte forma:

  • Se o argumento for uma lista, pegue um elemento da lista aleatoriamente (uniformemente) e escolha uma opção.
  • Se o argumento não for uma lista, basta devolvê-lo.

Um exemplo de implementação em Python:

import random
def pick(obj):
    if isinstance(obj, list):
        return pick(random.choice(obj))
    else:
        return obj

Para simplificar, assumimos que as listas aninhadas contêm apenas números inteiros ou outras listas aninhadas.

Dada qualquer lista, é possível criar uma versão achatada que é indistinguível por pick, ou seja, escolher nela produz os mesmos resultados, com a mesma probabilidade.

Por exemplo, "achatar" a lista

[1, 2, [3, 4, 5]]

produz a lista

[1, 1, 1, 2, 2, 2, 3, 4, 5]

. O motivo pelo qual o achatamento é inválido é porque os elementos das sub-listas têm uma probabilidade menor de serem escolhidos; por exemplo, na lista, [1, [2, 3]]o 1 tem uma chance de 2/4 = 1/2 de ser escolhido, enquanto 3 e 4 têm 1/4 chance cada.

Observe também que escolher em uma lista de singleton é equivalente a escolher em seu elemento e que escolher em uma lista vazia não tem significado.

O desafio

Dada uma lista aninhada de números inteiros não negativos, retorne uma lista achatada de números inteiros não negativos, a partir da qual a seleção produz os mesmos resultados com a mesma probabilidade.

Isso é , então a resposta mais curta e válida (medida em bytes) vence.

Especificações

  • As entradas [2, 3, 4], [2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4]e [2, [3, 3], [[4]]]são equivalentes (ou seja, eles deveriam dar resultados equivalentes).
  • As saídas [2, 2, 2, 2, 3, 3, 3, 3]e [2, 3]são equivalentes (ou seja, qualquer uma pode ser saída).
  • Você pode presumir que apenas números no intervalo inclusivo de 1 a 100 estarão presentes nas listas.
  • Você pode assumir que a entrada de nível superior será uma lista, ou 2seja, não é uma entrada válida.
  • Você pode usar qualquer representação razoável de listas aninhadas, por exemplo:
    [1, [2, 3]], 1 {2 3}, "[ 1 [ 2 3 ] ]", etc.
  • Em vez de uma lista, você pode produzir um multiset ou um mapeamento ou, uma vez que apenas números no intervalo de 1 a 100 são permitidos, uma lista de 100 números inteiros representando quantidades.

Casos de teste

Observe que as saídas listadas são apenas uma possibilidade válida; consulte as especificações sobre o que constitui uma entrada ou saída válida.

format:
input -> output
[3]                          -> [3]
[1, [1, 1]]                  -> [1]
[1, [2, 3]]                  -> [1, 1, 2, 3]
[2, 3, [4, [5, 5, 6], 6, 7]] -> [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7]
[[1, 1, 2], [2, 3, 3]]       -> [1, 2, 3]
[[1, 1, 2], [2, 3, 3, 3]]    -> [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3]

Dada a opção de codificação de comprimento e a faixa delimitada, podemos alternativamente gerar uma lista de 100 elementos que representam as ocorrências de cada número inteiro? (o que resultará com muitos zeros para os exemplos dados)
Uriel

@Uriel Sure; Eu vou reformular isso.
Esolanging Fruit 07/11/19

Respostas:


8

Wolfram Language (Mathematica) , 41 20 bytes

Flatten@*Tuples//@#&

Experimente online! Ignore os muitos avisos, tudo funciona no final.

Como funciona

Para uma lista de profundidade 2, tais como {{1,2},{3},{4,5,6}}, Tuplesirá gerar a lista {{1,3,4},{1,3,5},{1,3,6},{2,3,4},{2,3,5},{2,3,6}}correspondente de todas as maneiras para escolher um elemento de {1,2} e escolher um elemento de {3} e escolher um elemento de {4,5,6}.

Se Flattenisso, então temos todos os elementos com as frequências corretas, porque escolher um elemento de um dos {1,2}, {3}ou {4,5,6}é equivalente a escolher um elemento de todos eles, em seguida, escolher um deles para manter.

Usamos //@para aplicar isso em todos os níveis da entrada. No processo, Mathematica reclama muito, porque ele está girando átomos, como 17no Tuples[17], o que realmente não é suposto ser uma coisa. Mas isso simplifica para o resultado certo mais tarde ( Tuplesé um prazer tratá-lo Tuples[17]como uma lista de comprimento 1, mesmo que tenha uma cabeça diferente List), portanto a reclamação é irrelevante.



4

Geléia , 9 8 bytes

߀Œp$¬¡F

Experimente online!

Como funciona

߀Œp$¬¡F  Main link. Argument: x (array or positive integer)

     ¬    Compute elementwise logical NOT of x: a non-empty array for a non-empty array, 0 for a positive integer.
      ¡   Apply the link to the left once if ¬ returned a non-empty
          array, zero timed if it returned 0.
    $     Monadic chain:
߀            Map the main link over x.
  Œp          Take the Cartesian product.
       F  Flatten the result.



1

C (GCC) , 234 223 bytes

h[9][101];o[101];n[9];l;L;e;main(x){for(;(x=scanf("%d",&e))>=0;x?++h[l][e],++n[l]:(e=getchar())-'['?e-']'?0:--l:++l>L&&++L);for(e=1,l=L+1;l--;){for(x=101;--x;o[x]+=e*h[l][x]);e*=n[l];}while(o[x]--?printf("%d ",x):++x<101);}

Experimente online!

Explicação:

h[9][101];  // <- number occurences per nesting level
o[101];     // <- number occurences in "flattened" array
n[9];       // <- number of entries per nesting level
l;          // <- current nesting level
L;          // <- max nesting level
e;          // <- multi-purpose temporary
main(x){    // x: multi-purpose temporary
    for(;
            // while not EOF try reading number
            (x=scanf("%d",&e))>=0;

            // number was read?
            x

                // then increment occurence and # entries in level
                ?++h[l][e],++n[l]

                // else read any character ... if not [
                :(e=getchar())-'['

                    // if not ]
                    ?e-']'

                        // do nothing
                        ?0

                        // else decrement nesting level
                        :--l

                    // else increment nesting level and adjust max level
                    :++l>L&&++L);

    // init factor in e to 1, iterate over nesting level from innermost
    for(e=1,l=L+1;l--;){

        // iterate over all numbers
        for(x=101;
                --x;

                // add factor times occurence on current level to output
                o[x]+=e*h[l][x]);

        // multiply factor by number of entries on current level
        e*=n[l];
    }

    // iterate over all numbers and output count times
    while(o[x]--?printf("%d ",x):++x<101);
}



0

JavaScript (ES6), 132 131 bytes

f=A=>(_=(a,m)=>[].concat(...a.map(m)),n=1,A=A.map(a=>a.map?f(a):[a]),_(A,a=>n*=a.length),_(A,a=>_(a.map(x=>Array(n/a.length).fill(x)))))

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.