O qvolume de um número inteiro

31

É do conhecimento antigo que todo número inteiro não negativo pode ser reescrito como a soma de quatro números inteiros ao quadrado. Por exemplo, o número 1 pode ser expresso como 02+02+02+12 . Ou, em geral, para qualquer número inteiro não negativo n , existem números inteiros a,b,c,d tais que

n=a2+b2+c2+d2

Joseph-Louis Lagrange provou isso na década de 1700 e, portanto, costuma ser chamado de Teorema de Lagrange .

Isso às vezes é discutido em relação aos quaternions - um tipo de número descoberto por William Hamilton nos anos 1800, representado como

w+xi+yj+zk
onde w,x,y,z são números reais e i,j e k são unidades imaginárias distintas que não se multiplicam comutativamente. Especificamente, é discutido em relação ao quadrado de cada componente do quaternário
w2+x2+y2+z2
Essa quantidade às vezes é chamada denorma ou norma ao quadradoou tambémquadrante. Algumasprovas modernasdo teorema de Lagrange usam quaternions.

Rudolf Lipschitz estudou quaternions com apenas componentes inteiros, chamados quaternions Lipschitz. Usando quadrance, podemos imaginar que todo quaternário de Lipschitz pode ser considerado um amigo nos números inteiros. Por exemplo Quatérnion 0+0i+0j+1k pode ser pensada como estando associadas com o número inteiro 1=02+02+02+12 . Além disso, se recuarmos, todo número inteiro pode ser considerado como tendo um amigo nos quaternions de Lipschitz.

Mas há um detalhe interessante do teorema de Lagrange - a soma não é única. Cada número inteiro pode ter vários conjuntos diferentes de quatro quadrados que podem ser somados para criá-lo. Por exemplo, o número 1 pode ser expresso de quatro maneiras, usando números inteiros não negativos (consideremos não negativos para este desafio):

1=02+02+02+12
1=02+02+12+02
1=02+12+02+02
1=12+02+02+02

Os summands são sempre quadrados de 0 ou 1, mas podem estar em posições diferentes na expressão.

Para esse desafio, vamos também "classificar" nossas somas mais baixa para mais alta, para eliminar duplicatas, para que possamos considerar, para este exercício, que 1 só tem uma maneira de ser representada como a soma de quatro quadrados:

1=02+02+02+12

Outro exemplo é o número 42, que pode ser expresso de quatro maneiras (novamente, considerando apenas as negativas a, b, c, d e eliminando arranjos de componentes duplicados)

42=02+12+42+52
42=12+12+22+62
42=12+32+42+42
42=22+22+32+52

E se imaginarmos cada uma dessas maneiras diferentes de expressar um número inteiro como associadas a um quaternion específico? Então poderíamos dizer que o número 42 está associado a esses quatro quaternions:

0+1i+4j+5k
1+1i+2j+6k
1+3i+4j+4k
2+2i+3j+5k

Se imaginarmos a interpretação padrão de computação gráfica de um quaternion, onde i , j e k são vetores no espaço euclidiano tridimensional e, portanto, os componentes x , y e z do quaternion são coordenadas cartesianas tridimensionais , então podemos imaginar que cada inteiro, através desse processo de pensamento, pode ser associado a um conjunto de coordenadas tridimensionais no espaço. Por exemplo, o número 42 está associado às quatro coordenadas (x,y,z) a seguir :

(1,4,5),(1,2,6),(3,4,4),(2,3,5)

Isso pode ser pensado como uma nuvem de pontos ou um conjunto de pontos no espaço. Agora, uma coisa interessante sobre um conjunto de pontos finitos no espaço é que você sempre pode desenhar uma caixa delimitadora em torno deles - uma caixa grande o suficiente para caber em todos os pontos, mas não maior. Se você imaginar a caixa como uma caixa comum alinhada com os eixos x,y,z , ela será chamada de caixa delimitadora alinhada ao eixo . A caixa delimitadora também possui um volume calculável determinando sua largura, comprimento e altura e multiplicando-os.

Podemos então imaginar o volume de uma caixa delimitadora para os pontos formados por nossos quaternions. Para o número inteiro 1, temos, usando os critérios deste exercício, um quaternion cuja quadrância é 1, 0+0i+0j+1k . Esta é uma nuvem de pontos muito simples, possui apenas um ponto, portanto, a caixa delimitadora tem o volume 0. Para o número inteiro 42, no entanto, temos quatro quaternions e, portanto, quatro pontos, em torno dos quais podemos desenhar uma caixa delimitadora. O ponto mínimo da caixa é (1,2,4) e o máximo é (3,4,6) resultando em uma largura, comprimento e altura de 2, 2 e 2, resultando em um volume de 8.

Digamos que, para um número inteiro n , o qvolume seja o volume da caixa delimitadora alinhada ao eixo de todos os pontos 3D formados por quaternions que possuem uma quadrante igual a n , onde os componentes do quaternion w+xi+yj+zk são não negativos e w<=x<=y<=z .

Crie um programa ou função que, dado um número inteiro não negativo n , produza o volume q de n .

Exemplos:

input -> output
0 -> 0
1 -> 0
31 -> 4
32 -> 0
42 -> 8
137 -> 96
1729 -> 10032

Este é o código-golfe, o menor número de bytes ganha.

não brilhante
fonte
o que preciso adicionar? eu pretendia indicar que o menor número de bytes venceria
don bright
3
Você esqueceu a tag code-golf, eu ajudei a adicioná-la
Modalidade de Ignorância
1
Este é um bom desafio, mas seria ainda melhor o IMHO se fosse um pouco menos detalhado. Além disso, cuidado com os links irrelevantes (não estou dizendo que todos os seus links são irrelevantes, mas apenas alguns deles realmente trazem informações significativas para o desafio, enquanto os outros são apenas uma distração).
Arnauld
1
Sim, mas por que usar apenas i, j, k como espaço 3D, mas não como espaço 4D?
tsh
1
@tsh porque os Quaternions não representam necessariamente um espaço euclidiano de 4 dimensões. Hamilton os descobriu enquanto procurava uma maneira de trabalhar com espaço tridimensional. Seria possível fazer uma versão 4d, mas eu estava pensando em seu uso no espaço 3D quando fiz a pergunta
don bright

Respostas:

13

Wolfram Language (Mathematica) , 67 58 bytes

Volume@BoundingRegion[Rest/@PowersRepresentations[#,4,2]]&

Experimente online!

                         ...&   Pure function:
PowersRepresentations[#,4,2]    Get the sorted reprs. of # as sums of 4 2nd powers
Rest/@                         Drop the first coordinate of each
BoundingRegion[...]            Find the bounding region, a Cuboid[] or Point[].
                               By default Mathematica finds an axis-aligned cuboid.
Volume                         Find volume; volume of a Point[] is 0.
lirtosiast
fonte
4
uau, eu não tinha ideia de que algo como PowersRepresentations seria incorporado em um idioma. Na verdade, pensei em fazer um desafio para mostrar as diferentes maneiras de somar um número inteiro como quatro quadrados, mas fico feliz por não ter feito.
don bright
4
Lol, o Mathematica ainda tem um built-in para determinar cabras em uma imagem , portanto, ter um built-in para isso realmente não me surpreende. xD
Kevin Cruijssen
8

Geléia , 17 bytes

Żœċ4²S⁼ɗƇ⁸ZḊṢ€I§P

Experimente online! (muito lento - torná-lo rápido o suficiente para todos os casos de teste com um líder½ )

Quão?

Żœċ4²S⁼ɗƇ⁸ZḊṢ€I§P - Link: non-negative integer, n    e.g. 27
Ż                 - zero-range                            [0,1,2,...,27]
   4              - literal four                          4
 œċ               - combinations with replacement         [[0,0,0,0],[0,0,0,1],...,[0,0,0,27],[0,0,1,1],[0,0,1,2],...,[27,27,27,27]]
        Ƈ         - filter keep those for which:          e.g.: [0,1,1,5]
       ɗ          -   last three links as a dyad:
    ²             -     square (vectorises)                     [0,1,1,25]
     S            -     sum                                     27
      ⁼  ⁸        -     equal to? chain's left argument, n      1
                  -                                       -> [[0,1,1,5],[0,3,3,3],[1,1,3,4]]
          Z       - transpose                             [[0,0,1],[1,3,1],[1,3,3],[5,3,4]]
           Ḋ      - dequeue                               [[1,3,1],[1,3,3],[5,3,4]]
            Ṣ€    - sort each                             [[1,1,3],[1,3,3],[3,4,5]]
              I   - incremental differences (vectorises)  [[ 0,2 ],[ 2,0 ],[ 1,1 ]]
               §  - sum each                              [2,2,2]
                P - product                               8
Jonathan Allan
fonte
6

Haskell , 132 123 bytes

z=zipWith
(!)=foldr1.z
h n=[0..n]
f n|p<-[[c,b,a]|a<-h n,b<-h a,c<-h b,d<-h c,a^2+b^2+c^2+d^2==n]=product$z(-)(max!p)$min!p

Experimente online!

Solução bastante simples. Força bruta de todas as soluções possíveis, iterando sobre todos os valores de 0 a n (excedente de maneira, mas menor por conta). Eu mostro o ponto como uma lista para que possamos usar o (!)operador mágico de @ Lynn . Esse operador reduz cada dimensão com a função no lado esquerdo, max!pretornando uma lista do tamanho 3, que consiste nos máximos ao longo de cada dimensão e min!pfaz o mesmo no mínimo. Em seguida, encontramos o tamanho mínimo em cada dimensão (subtraindo o valor mínimo do máximo por z(-)) e multiplicando-o.

Muito obrigado a @Lynn por tirar 9 bytes com alguma mágica dobrável de zip!

user1472751
fonte
1
Raspei alguns bytes renunciando à transposição em favor de alguma zipWithlógica. 123 bytes
Lynn
5

Marreta 0,2, 12 bytes

⡌⢎⣟⡊⢘⣚⡏⡨⠍⠁⡇⠨

Use com o Mathematica 11.2 e esta versão do Sledgehammer, que antecede o desafio. Consulte o histórico de edições para obter uma versão que funciona na versão 0.3, que possui uma GUI e gera uma expressão do Mathematica.

Isso empurra a entrada para a pilha e chama a sequência de comandos

{intLiteral[4], intLiteral[2], call["PowersRepresentations", 3], call["Thread", 1], call["Rest", 1], call["Thread", 1], call["BoundingRegion", 1], call["Volume", 1]}

que é equivalente a avaliar o seguinte código Wolfram derivado da minha resposta no idioma Wolfram :

Volume[BoundingRegion[Thread@Rest@Thread@PowersRepresentations[#, 4, 2]]]&

Experimente online!

lirtosiast
fonte
isso requer que o mathematica o teste?
don bright
@don bright Sim, o repositório tem instruções. É um trabalho em andamento, portanto não é muito fácil de usar ainda. Após executar o setup.wls, você pode testar com wolframscript ou interactive_app.wls.
lirtosiast
2
@Downgoat Sim. Pretendo implementar uma biblioteca de golfe, mas atualmente ela é descompactada para facilitar o Mathematica.
lirtosiast
2
@pipe A versão mais antiga deve funcionar (agora que penso nisso, o código é exatamente o mesmo em uma versão mais antiga), mas eu teria que fazer o download e executar a instalação novamente. (As mudanças desde então têm escrito principalmente a GUI e o código de refatoração sem grandes alterações na funcionalidade.) Como essa resposta é mais curta, parece importante provar a elegibilidade, portanto farei isso amanhã de manhã.
lirtosiast
1
mais alguém pode executar isso? Eu meio que gostaria de verificar se funciona antes de dar a marca de seleção.
don bright
4

Python 2 , 138 bytes

q=lambda n,x=0,*t:[t]*(n==0)if t[3:]else q(n-x*x,x,x,*t)+q(n,x+1,*t+(0,)*(x>n))
p=1
for l in zip(*q(input()))[:3]:p*=max(l)-min(l)
print p

Experimente online!

Gera recursivamente os quaterniões classificados de forma inversa com a norma especificada e, em seguida, leva o produto entre o máximo e o mínimo de todos os valores possíveis nos três primeiros índices.

itertools poderia ter tido uma chance se não usasse nomes ridiculamente longos como itertools.combinations_with_replacement

Python 2 , 161 bytes

from itertools import*
n=input();p=1
for l in zip(*[t[1:]for t in combinations_with_replacement(range(n+1),4)if sum(x*x for x in t)==n]):p*=max(l)-min(l)
print p

Experimente online!

É por isso que itertoolsnunca é a resposta .

xnor
fonte
3

JavaScript (ES6),  148  143 bytes

n=>(r=[[],[],[]]).map(a=>p*=a.length+~a.indexOf(1),(g=(s,k=0,a=[])=>a[3]?s||r.map(r=>r[a.pop()]=p=1):g(s-k*k,k,[...a,++k],k>s||g(s,k,a)))(n))|p

Experimente online!

Comentado

Inicializamos uma matriz r com 3 matrizes vazias.

r = [ [], [], [] ]

Para cada valor válido de x, definiremos como 1 o valor em x+1na primeira matriz. O mesmo vale paray e z com a segunda e a terceira matrizes, respectivamente.

As dimensões da caixa delimitadora serão deduzidas da distância entre a primeira e a última entrada definida como 1 nessas matrizes.

Passo 1

Preencher r, usamos a função recursiva g.

g = (              // g is a recursive function taking:
  s,               // s   = current sum, initially set to the input n
  k = 0,           // k   = next value to be squared
  a = []           // a[] = list of selected values
) =>               //
  a[3] ?           // if we have 4 values in a[]:
    s ||           //   if s is equal to zero (we've found a valid sum of 4 squares):
      r.map(r =>   //     for each array r[] in r[]:
        r[a.pop()] //       pop the last value from a[]
        = p = 1    //       and set the corresponding value in r[] to 1
                   //       (also initialize p to 1 for later use in step 2)
      )            //     end of map()
  :                // else:
    g(             //   do a recursive call:
      s - k * k,   //     subtract k² from s
      k,           //     pass k unchanged
      [...a, ++k], //     increment k and append it to a[]
      k > s ||     //     if k is less than or equal to s:
        g(s, k, a) //       do another recursive call with s and a[] unchanged
    )              //   end of outer recursive call

Passo 2

Agora podemos calcular o produto p das dimensões.

r.map(a =>         // for each array a[] in r[]:
  p *=             //   multiply p by:
    a.length +     //     the length of a[]
    ~a.indexOf(1)  //     minus 1, minus the index of the first 1 in a[]
) | p              // end of map(); return p
Arnauld
fonte
2

C # (compilador interativo do Visual C #) , 229 bytes

a=>{uint b=0,c=~0U,d,e,f=0,g=0,h=0,i=c,j=c,k=c;for(;b*b<=a;b++)for(c=b;c*c<=a;c++)for(d=c;d*d<=a;d++)for(e=d;e*e<=a;e++)if(b*b+c*c+d*d+e*e==a){f=c>f?c:f;g=d>g?d:g;h=e>h?e:h;i=c<i?c:i;j=d<j?d:j;k=e<k?e:k;}return(f-i)*(g-j)*(h-k);}

Experimente online!

Modalidade de ignorância
fonte
1

Haskell , 108 bytes

n%i=sum[maximum[t!!i*b|t<-mapM([0..n]<$f)[0..3],sum(map(^2)t)==n,scanr1 max t==t]|b<-[-1,1]]
f n=n%0*n%1*n%2

Experimente online! (atinge o tempo limite nos casos de teste maiores)

Há algumas otimizações estranhas aqui. Para calcular maximum l-minimum la lista lde elementos em uma determinada posição, fica mais curto no contexto convertê-los ao máximo negando o segundo termo: maximum l+maximum(map((-1)*))lou equivalente sum[maximum$map(b*)l||b<-[-1,1]].

Para multiplicar as três dimensões, é mais curto escrever o produto f n=n%0*n%1*n%2do que usar qualquer tipo de loop. Aqui n%iestá a diferença entre o mínimo e o máximo dos ivalores da quinta coordenada, que são extraídos com a indexação !!i.

Para gerar as quatro tuplas válidas, tomamos listas de quatro números [0..n]cujos quadrados somam ne estão em ordem decrescente. Verificamos a ordem inversa de tcom scanr1 max t==t, que verifica se o máximo de execução reversa é ele próprio, pois Haskell não possui uma classificação interna sem uma importação dispendiosa. Tentei várias maneiras de gerar recursivamente as quatro tuplas, como nas minhas respostas em Python, mas elas eram todas mais longas que essa maneira de gerar e filtrar de força bruta.

xnor
fonte