Triângulo de Seidel


14

O triângulo de Seidel é uma construção matemática semelhante ao triângulo de Pascal e é conhecido por sua conexão com os números de Bernoulli.

As primeiras linhas são:

      1
      1  1
   2  2  1
   2  4  5  5
16 16 14 10 5
16 32 46 56 61 61

Cada linha é gerada da seguinte maneira:

Se o número da linha for par (indexado 1):

  • Reduza o primeiro item da linha anterior

  • Cada próximo item é a soma do item anterior e o item acima dele

  • Duplicar o último item

Se o número da linha for ímpar:

  • Reduza o último item da linha anterior

  • Indo para trás , cada item é a soma do item anterior e o item acima dele

  • Duplique o que agora é o primeiro item.

Basicamente, construímos o triângulo em um padrão em zig-zag:

    1
    v
    1 > 1
        v
2 < 2 < 1
v
2 > 4 > 5 > 5

Para mais informações, consulte a página da Wikipedia sobre números de Bernoulli.

O desafio:

Dado n, como argumento de função ou a partir de STDIN, imprima ou retorne a nquinta linha do triângulo Seidel ou as primeiras nlinhas. Você pode usar a indexação 0 ou 1.

Você não precisa manipular entradas negativas ou não inteiras (nem 0, se indexadas em 1). Você não precisa lidar com saídas maiores que2147483647 = 2^31 - 1

Como isso é código-golfe, faça isso no menor número de bytes possível.

Exemplos:

Nestes exemplos, o valor de retorno é a nlinha th, indexada em 0.

Input   ->  Output

0           1
1           1 1
2           2 2 1
6           272 272 256 224 178 122 61
13          22368256 44736512 66750976 88057856 108311296 127181312 144361456 159575936 172585936 183194912 191252686 196658216 199360981 199360981

"Você não tem que lidar com saídas maiores do tipo int padrão do seu idioma" torna esta trivial para idiomas com apenas ints de 1 bit
ASCII-only

As linhas podem ser produzidas sempre classificadas de pequenas a grandes?
Angs

Somente ASCII foi alterado para corresponder ao valor máximo de int do C ++
Bolce Bussiere 17/04/19

@Angs Não, as linhas devem ser ordenados como mostrado
Bolce Bussiere

@ ASCII-only Isso é uma brecha padrão (embora IMO é um pouco mal formulada, pois depende do que as pessoas consideram "razoável")
user202729

Respostas:


7

Flacidez cerebral , 66 bytes

<>(())<>{({}[()]<(()[{}]<<>{(({}<>{}))<>}>)>)}{}{{}<>{({}<>)<>}}<>

Experimente online!

A linha é indexada em 0.

# Push 1 (the contents of row 0) on other stack; use implicit zero as parity of current row
<>(())<>

# Do a number of times equal to input:
{({}[()]<

  # Subtract the row parity from 1
  (()[{}]<

    # For each entry in old row:
    <>{

      # Add to previous entry in new row and push twice
      (({}<>{}))<>

    }

  >)

>)}{}

# If row parity is odd:
{{}

  # Reverse stack for output
  <>{({}<>)<>}

# Switch stacks for output
}<>

4

JavaScript (SpiderMonkey) , 67 bytes

Esse código abusa do sort()método e não funciona em todos os mecanismos.

As linhas são indexadas em 0.

f=(n,a=[1],r)=>n--?f(n,[...a.map(n=>k+=n,k=0),k].sort(_=>n|r),!r):a

Experimente online!

Quão?

Revertemos condicionalmente uma matriz usando o sort()método com uma função de retorno de chamada que ignora seus parâmetros e retorna 0 ou um número inteiro positivo. Não tente isto em casa! Isso funciona apenas de forma confiável no SpiderMonkey.

let A = [1,2,3,4,5] and B = [1,2,3,4,5,6,7,8,9,10,11]

             | SpiderMonkey (Firefox)  | V8 (Chrome)             | Chakra (Edge)
-------------+-------------------------+-------------------------+------------------------
A.sort(_=>0) | 1,2,3,4,5               | 1,2,3,4,5               | 1,2,3,4,5
A.sort(_=>1) | 5,4,3,2,1               | 5,4,3,2,1               | 1,2,3,4,5
B.sort(_=>0) | 1,2,3,4,5,6,7,8,9,10,11 | 6,1,3,4,5,2,7,8,9,10,11 | 1,2,3,4,5,6,7,8,9,10,11
B.sort(_=>1) | 11,10,9,8,7,6,5,4,3,2,1 | 6,11,1,10,9,8,7,2,5,4,3 | 1,2,3,4,5,6,7,8,9,10,11

Observe que a V8 provavelmente está usando algoritmos de classificação diferentes, dependendo do comprimento da matriz (menos ou mais de 10 elementos).

Comentado

f = (                     // f = recursive function taking:
  n,                      //   n   = row counter
  a = [1],                //   a[] = current row, initialized to [1]
  r                       //   r   = 'reverse' flag, initially undefined
) =>                      //
  n-- ?                   // decrement n; if it was not equal to zero:
    f(                    //   do a recursive call with:
      n,                  //     - the updated value of n
      [ ...a.map(n =>     //     - a new array:
          k += n, k = 0   //       - made of the cumulative sum of a[]
        ), k              //         with the last value appended twice
      ].sort(_ => n | r), //       - reversed if n is not equal to 0 or r is set
      !r                  //     - the updated flag r
    )                     //   end of recursive call
  :                       // else:
    a                     //   stop recursion and return a[]

Que característica específica do macaco-aranha isso usa?
Downgoat

@Downgoat Ele está aproveitando a implementação específica sort()deste mecanismo. Eu adicionei uma explicação.
Arnauld


3

Haskell , 89 87 82 bytes

(cycle[r,id]!!)<*>s
r=reverse
s 0=[1]
s n=let a=zipWith(+)(0:a)$(r.s$n-1)++[0]in a

Apenas simprime as linhas na ordem em zigue-zague, a função anônima na primeira linha inverte metade das linhas.

Obrigado a @nimi por economizar 5 bytes!

Experimente online!



2

Python 3 , 98 91 bytes

from itertools import*
f=lambda n:n and[*accumulate(f(n-1)[::n&1or-1]+[0])][::n&1or-1]or[1]

Experimente online!

Mudar para a numeração de linhas com base em 0 economizou 7 bytes.


2

Julia 0.6 , 85 bytes

r(l,n=cumsum(l))=[n...,n[end]]
w=reverse
f(n)=n<2?[1]:n%2<1?r(f(n-1)):w(r(w(f(n-1))))

Experimente online!

Esta é uma solução recursiva em Julia. Observe que ele possui indexação baseada em 1. Daí os testes.

Versão não destruída, para entender a lógica:

function new_row(last_row)
    new_row = cumsum(last_row)
    push!(new_row, new_row[end])
    return new_row
end


function triangle(n)
    if n == 1
        return [1]
    elseif mod(n,2) == 0
        return new_row(triangle(n-1))
    else
        return reverse(new_row(reverse(triangle(n-1))))
    end
end

Como bônus, aqui está uma versão não recursiva, mas é mais longa:

w=reverse;c=cumsum
r(l,i)=i%2<1?c([l...,0]):w(c(w([0,l...])))
f(n,l=[1])=(for i=2:n l=r(l,i)end;l)

1

Python 2 , 103 97 bytes

f=lambda n,r=[1],k=2:n and f(n-1,[sum(r[-2::-1][:i],r[-1])for i in range(k)],k+1)or r[::-(-1)**k]

Experimente online!

Versão não recursiva (mais fácil de ler):

Python 2 , 106 bytes

def f(n,r=[1],j=1):
 while n:
	a=r[-2::-1];r=r[-1:];n-=1;j=-j
	for x in a+[0]:r+=[r[-1]+x]
 return r[::-j]

Experimente online!

Certamente, melhor é possível!


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.