N-movers: Quanto da placa infinita posso alcançar?

48

Movimentos únicos

O tabuleiro é uma grade quadrada bidimensional infinita, como um tabuleiro de xadrez ilimitado. Uma peça com o valor N (um motor N ) pode mover-se para qualquer quadrado que esteja a uma distância exata da raiz quadrada de N do seu quadrado atual (distância euclidiana medida centro a centro).

Por exemplo:

  • Um motor único pode se mover para qualquer quadrado horizontal ou vertical adjacente
  • Um motor de dois pode mover-se para qualquer quadrado diagonalmente adjacente
  • Um 5-move se move como um cavaleiro de xadrez

Observe que nem todos os N-movers podem se mover. Um motor de três nunca pode deixar seu quadrado atual porque nenhum dos quadrados no quadro está a uma distância exata da raiz 3 do quadrado atual.

Movimentos múltiplos

Se for permitido mover-se repetidamente, algumas peças podem atingir qualquer quadrado no tabuleiro. Por exemplo, um motor e um motor podem fazer isso. Um motor de dois movimentos só pode se mover na diagonal e atingir apenas metade dos quadrados. Uma peça que não pode se mover, como um motor de três, não pode alcançar nenhum quadrado (o quadrado inicial não é contado como "alcançado" se nenhum movimento ocorrer) .

1-motor 2 motores 3 motores 4 motores 5 motores 8 motores 9 motores 10 motores 20 motores 25 motores 40 motores 64 motores 65 motores 68 motores

As imagens mostram quais quadrados podem ser alcançados. Mais detalhes ao passar o mouse. Clique para ampliar a imagem.

  • Os quadrados alcançáveis ​​em 1 ou mais movimentos estão marcados em preto
  • Os quadrados alcançáveis ​​em exatamente 1 movimento são mostrados por peças vermelhas
    (além dos 3 motores, que não podem se mover)

Que proporção do quadro um determinado N-motor pode alcançar?

Entrada

  • Um número inteiro positivo N

Resultado

  • A proporção da placa que um N-motor pode alcançar
  • Este é um número de 0 a 1 (inclusive)
  • Para esse desafio, a saída como uma fração em termos mais baixos, como 1/4, é permitida

Portanto, para entrada 10, ambas 1/2e 0.5saídas aceitáveis. A saída como numerador e denominador separados também é aceitável, incluindo idiomas que não suportam flutuações nem frações. Por exemplo, 1 2ou [1, 2].

Para as saídas inteiras (0 e 1), qualquer um dos seguintes são formatos aceitáveis:

  • Para 0: 0, 0.0, 0/1, 0 1,[0, 1]
  • para 1: 1, 1.0, 1/1, 1 1,[1, 1]

Pontuação

Isso é código de golfe. A pontuação é o comprimento do código em bytes. Para cada idioma, o código mais curto vence.

Casos de teste

No formato input : output as fraction : output as decimal

  1 : 1     : 1
  2 : 1/2   : 0.5
  3 : 0     : 0
  4 : 1/4   : 0.25
  5 : 1     : 1
  6 : 0     : 0
  7 : 0     : 0
  8 : 1/8   : 0.125
  9 : 1/9   : 0.1111111111111111111111111111
 10 : 1/2   : 0.5
 13 : 1     : 1
 16 : 1/16  : 0.0625
 18 : 1/18  : 0.05555555555555555555555555556
 20 : 1/4   : 0.25
 25 : 1     : 1
 26 : 1/2   : 0.5
 64 : 1/64  : 0.015625
 65 : 1     : 1
 72 : 1/72  : 0.01388888888888888888888888889
 73 : 1     : 1
 74 : 1/2   : 0.5
 80 : 1/16  : 0.0625
 81 : 1/81  : 0.01234567901234567901234567901
 82 : 1/2   : 0.5
144 : 1/144 : 0.006944444444444444444444444444
145 : 1     : 1
146 : 1/2   : 0.5
148 : 1/4   : 0.25
153 : 1/9   : 0.1111111111111111111111111111
160 : 1/32  : 0.03125
161 : 0     : 0
162 : 1/162 : 0.006172839506172839506172839506
163 : 0     : 0
164 : 1/4   : 0.25
241 : 1     : 1
242 : 1/242 : 0.004132231404958677685950413223
244 : 1/4   : 0.25
245 : 1/49  : 0.02040816326530612244897959184
260 : 1/4   : 0.25
261 : 1/9   : 0.1111111111111111111111111111
288 : 1/288 : 0.003472222222222222222222222222
290 : 1/2   : 0.5
292 : 1/4   : 0.25
293 : 1     : 1
324 : 1/324 : 0.003086419753086419753086419753
325 : 1     : 1
326 : 0     : 0
360 : 1/72  : 0.01388888888888888888888888889
361 : 1/361 : 0.002770083102493074792243767313
362 : 1/2   : 0.5
369 : 1/9   : 0.1111111111111111111111111111
370 : 1/2   : 0.5
449 : 1     : 1
450 : 1/18  : 0.05555555555555555555555555556
488 : 1/8   : 0.125
489 : 0     : 0
490 : 1/98  : 0.01020408163265306122448979592
520 : 1/8   : 0.125
521 : 1     : 1
522 : 1/18  : 0.05555555555555555555555555556
544 : 1/32  : 0.03125
548 : 1/4   : 0.25
549 : 1/9   : 0.1111111111111111111111111111
584 : 1/8   : 0.125
585 : 1/9   : 0.1111111111111111111111111111
586 : 1/2   : 0.5
592 : 1/16  : 0.0625
593 : 1     : 1
596 : 1/4   : 0.25
605 : 1/121 : 0.008264462809917355371900826446
610 : 1/2   : 0.5
611 : 0     : 0
612 : 1/36  : 0.02777777777777777777777777778
613 : 1     : 1
624 : 0     : 0
625 : 1     : 1
Trichoplax
fonte
10
Eu postei esta pergunta no Math.SE: math.stackexchange.com/questions/3108324/…
infmagic2047
Conjectura interessante!
trichoplax
1
"Uma peça que não pode se mover, como um motor de três, não pode alcançar nenhum dos quadrados". Curiosamente, mesmo se você contar o quadrado inicial, já que o tabuleiro é infinito, ele ainda converge para 0 como proporção.
Beefster
@Beefster bom ponto. Eu segui esse caminho para tornar o limite mais fácil de encontrar, sem ter que ir até o infinito ...
trichoplax
2
A pergunta math.se de @ infmagic2047 sobre a abordagem de fatoração principal agora tem uma resposta com uma prova completa .
Ørjan Johansen

Respostas:

19

JavaScript (Node.js) , 144 138 125 74 73 70 bytes

f=(x,n=2,c=0)=>x%n?x-!c?f(x,n+1)/(n%4>2?n/=~c&1:n%4)**c:1:f(x/n,n,c+1)

Experimente online!

-4 byte obrigado @Arnauld!

Abordagem original, 125 bytes

a=>(F=(x,n=2)=>n*n>x?[x,0]:x%n?F(x,n+1):[n,...F(x/n,n)])(a).map(y=>r-y?(z*=[,1,.5,p%2?0:1/r][r%4]**p,r=y,p=1):p++,z=r=p=1)&&z

Experimente online!

Inspirado no vídeo Pi escondido em regularidades privilegiadas pela 3Blue1Brown.

Para cada fator primo na fatoração do número, calcule :pnf(pn)

  • Se for ímpar - . Porque não há para onde ir.np3 (mod 4)f(pn)=0
  • Se for par e - .np3 (mod 4)f(pn)=1pn
  • Se - .p=2f(2n)=12n
  • Se - .p1 (mod 4)f(pn)=1

Multiplique todos esses valores de função, aqui estamos.

Atualizar

Graças ao esforço dos colaboradores do Math.SE, o algoritmo agora é apoiado por uma prova

Shieru Asakoto
fonte
O vídeo contém uma prova? Estou tentando provar esse resultado há algumas horas, mas não consegui descobrir.
infmagic2047 11/02
1
@ infmagic2047 Não é verdade, mas fornece um método para contar o número de pontos em um círculo . Isso é útil quando se trata de como o n-mover pode funcionar. n
Shieru Asakoto
3
@ infmagic2047 Acho que é trivial provar os casos de mas os casos para os restantes são difíceis de provar formalmente ...q=pPp{2,3} (mod 4)pep
Shieru Asakoto
1
A pergunta math.se de @ infmagic2047 sobre essa abordagem agora tem uma resposta com uma prova completa .
Ørjan Johansen
11

Mathematica, 80 bytes

d[n_]:=If[#=={},0,1/Det@LatticeReduce@#]&@Select[Tuples[Range[-n,n],2],#.#==n&];

Esse código depende principalmente de um teorema matemático. A idéia básica é que o código solicite a densidade de uma rede dada um conjunto de geradores.

Mais precisamente, nos é dada uma coleção de vetores - ou seja, aqueles cujo comprimento ao quadrado é N - e solicitados a calcular a densidade do conjunto de possíveis somas desses vetores, em comparação com todos os vetores inteiros. A matemática em jogo é que sempre podemos encontrar dois vetores (e seu oposto) que "geram" (ou seja, cujas somas são) o mesmo conjunto da coleção original. LatticeReduce faz exatamente isso.

Se você tiver apenas dois vetores, poderá imaginar um paralelogramo idêntico centralizado em cada ponto acessível, mas cujos comprimentos das arestas são os vetores fornecidos, de modo que o plano seja completamente revestido por esses paralelogramos. (Imagine, por exemplo, uma treliça de formas de "diamante" para n = 2). A área de cada paralelogramo é o determinante dos dois vetores geradores. A proporção desejada do plano é a recíproca dessa área, uma vez que cada paralelogramo possui apenas um ponto acessível.

O código é uma implementação bastante direta: gere os vetores, use LatticeReduce, tome o determinante e depois o inverso. (Provavelmente, pode ser melhor jogar golfe)

Milo Brandt
fonte
76 bytes:d@n_:=Boole[#!={}]/Det@LatticeReduce@#&@Select[Range[-n,n]~Tuples~2,#.#==n&]
u54112
11

Limpo , 189 185 172 171 bytes

import StdEnv
$n#r=[~n..n]
#p=[[x,y]\\x<-r,y<-r|x^2+y^2==n]
=sum[1.0\\_<-iter n(\q=removeDup[k\\[a,b]<-[[0,0]:p],[u,v]<-q,k<-[[a+u,b+v]]|all(\e=n>=e&&e>0)k])p]/toReal(n^2)

Experimente online!

Localiza todas as posições alcançáveis ​​no nquadrado ao lado do canto, na origem no primeiro quadrante, e depois divide n^2para obter a parte de todas as células alcançáveis.

Isso funciona porque:

  • Todo o plano alcançável pode ser considerado como cópias sobrepostas desse nquadrado ao lado, cada uma encurralada em um ponto acessível a partir da origem como se fosse a origem.
  • Todos os movimentos vêm em grupos de quatro com sinais ++ +- -+ --, permitindo que o mosaico sobreposto seja estendido pelos outros três quadrantes através de espelhamento e rotação.
Furioso
fonte
Minhas desculpas - eu estava analisando os casos de teste que variam de N = 10 a N = 13, enquanto seus casos de teste incluem N = 11 e N = 12 também. Você está realmente correto para N = 13. +1 de mim :)
trichoplax 11/02
1
@trichoplax Alterei os testes para corresponder à pergunta para evitar a mesma confusão novamente
Οurous
Já testei até N = 145 e todos estão corretos. Não pude testar 146 no TIO devido ao tempo limite de 60 segundos. Estou esperando alguns tempos de execução muito longos nas respostas aqui ...
trichoplax
1
Desde que demorei um pouco para perceber isso: A razão pela qual os cantos quadrados são alcançáveis ​​se houver pelo menos um movimento (a, b), é a equação complexa (a + bi) (a-bi) = a ^ 2 + b ^ 2, que na forma de vetor se torna (N, 0) = a (a, b) + b (b, -a).
Ørjan Johansen
5

Retina 0.8.2 , 126 82 bytes

.+
$*
+`^(1(1111)+)(?<!^\3+(11+))(\1)*$
1$#4$*
^(?!((^1|11\2)+)\1?$)1+
0
11+
1/$.&

Experimente online! O link inclui casos de teste. Explicação:

.+
$*

Converta para unário.

+`^(1(1111)+)(?<!^\3+(11+))(\1)*$
1$#4$*

Divida repetidamente por fatores primos do formulário 4k+1.

^(?!((^1|11\2)+)\1?$)1+
0

Se o resultado não for quadrado nem duas vezes quadrado, o resultado será zero.

11+
1/$.&

Calcule o recíproco como uma fração decimal.

Neil
fonte
5

Regex (ECMAScript, saída recíproca), 256 163 157 157 94 83 82 bytes

-93 bytes graças a Neil
-6 bytes graças novamente a Neil
-63 bytes executando a divisão sem capturar o divisor
-11 bytes graças à divisão opcional simultânea de Grimy por divisão constante por raiz constante e raiz quadrada de
-1 bytes movendo a condição de finalização e devolver a captura de valor ao loop como uma segunda alternativa, graças ao Grimy

Isso usa a mesma matemática que a resposta JavaScript de Shieru Asakoto .

A entrada está em unário. Como um regex puro só pode retornar como saída uma substring da entrada (ou seja, um número natural menor ou igual à entrada) ou "sem correspondência", esse regex retorna o inverso da proporção da placa que um N-motor pode alcançar. Como o recíproco de 0 é infinito, ele retorna "sem correspondência" nesse caso.

AVISO DE SPOILER : Para a raiz quadrada, esse regex usa uma variante do algoritmo de multiplicação generalizada, o que não é óbvio e pode ser um quebra-cabeça gratificante para você resolver sozinho. Para obter mais informações, consulte uma explicação para esta forma do algoritmo em Localizar um número Rocco .

Esse regex primeiro entra em loop identificando todos os fatores primos tais que e divide o número de entrada por cada um quantas vezes for possível. Seja o resultado final disso. Em seguida, ele testa indiretamente para ver se a fatoração primária de (e, portanto, também o número de entrada) inclui primos elevados a uma potência ímpar, testando para ver se ou é um quadrado perfeito. Se não, então incluiu um número primo elevado a uma potência ímpar e o regex retorna "sem correspondência"; caso contrário, ele retornará .pp1 (mod 4)mm3 (mod 4)mm/2mm

(Agora é um pouco mais complicado do que isso. Devido à otimização do golfe na versão de saída recíproca, ele testa não apenas e por ser um quadrado, mas também o resultado intermediário antes da divisão de cada , se o o primeiro teste falha. Isso não altera o resultado final, porque se o primeiro teste do quadrado perfeito falhar, pelo menos uma potência ímpar de um número primo ainda estará presente no número a cada passo, e não pode ser um quadrado.)mm/2p3 (mod 4)

^(?=((?=(x+)(?!(\2+)(\2\3)+$)((\2{4})+$))\5|((xx?)(\8*))(?=(\7*)\9+$)\7*$\10)+$)\1

Experimente online!
Experimente online! (apenas os casos de teste)

^
(?=
    (                          # Capture return value, which will just be the value
                               # matched by the last iteration of this loop.
    # Divide tail by every one of its prime factors that's ≡1 mod 4, as many times as
    # possible.
        (?=
            (x+)               # \2 = quotient
            (?!(\2+)(\2\3)+$)  # Assert divisor is prime
            ((\2{4})+$)        # Assert divisor ≡1 mod 4; \5 = tool to make tail = \2
        )\5                    # tail = \2
    |
    # When the above alternative has been done as many times as possible:
    # Test if tail or tail/2 is a perfect square. If this test fails, the regex engine
    # will backtrack into the division loop above, and run the same perfect square
    # test on every previous number (effectively "multiplying" it by each previous P
    # in reverse, one at a time). This will not cause a failure of the test to change
    # into a success, however, because the odd power of a prime ≡3 mod 4 will see be
    # present in the number at every step. Allowing this backtracking to happen is a
    # golf optimization, and it does make the regex slower.
    # Failure of this perfect square test results in returning "no match" and indicates
    # a return value of zero.
        (                      # \7 = \8 * sqrt(tail / \8)
            (xx?)              # \8 = control whether to take sqrt(tail)
                               #                         or 2*sqrt(tail/2)
            (\8*)              # \9 = \7 - \8
        )
        (?=
            (\7*)\9+$          # Iff \8 * (\7 / \8)^2 == our number, then the first match
                               # here must result in \10==0
        )
        \7*$\10                # Test for divisibility by \7 and for \10==0
                               # simultaneously
    )+
    $                          # Require that the last iteration of the above loop was
                               # the perfect square test. Since the first alternative,
                               # the division, always leaves >=1 in tail, this guarantees
                               # that the last step is a successful perfect square test,
                               # or else the result will be "no match".
)
\1                             # Return value (which is a reciprocal)

Regex (ECMAScript + (? *), Saída recíproca), 207 138 132 bytes

Obsoleto ao fazer a divisão sem capturar o divisor (ou seja, agora é idêntico ao acima).

Regex (ECMAScript 2018, saída recíproca), 212 140 134 bytes

Obsoleto ao fazer a divisão sem capturar o divisor (ou seja, agora é idêntico ao acima).

Regex (ECMAScript, saída de fração), 80 bytes

Nesta versão, o numerador é retornado em \10(zero se não definido / NPCG) e o denominador em \7.

Ao contrário da versão de saída recíproca:

  • Uma entrada de zero não é tratada corretamente (ela retorna "sem correspondência", exatamente como aquela versão, mas, ao contrário dela, que não corresponde a um valor de saída igual a zero).
  • Se o teste do quadrado perfeito falhar, ele não retornará ao loop de divisão; portanto, esta versão será mais eficiente no tempo de execução.

A grande desvantagem de uma especificação de saída como essa é que ela não está contida no próprio programa.

((?=(x+)(?!(\2+)(\2\3)+$)((\2{4})+$))\5)*((((x)x?)(\9*))(?=(\8*)\11+$)\8*$\12|x)

Experimente online!
Experimente online! (apenas os casos de teste)

# No need to anchor, since we return a match for all inputs in the domain.
# Divide tail by every one of its prime factors that's ≡1 mod 4
(
    (?=
        (x+)               # \2 = quotient
        (?!(\2+)(\2\3)+$)  # Assert divisor is prime
        ((\2{4})+$)        # Assert divisor ≡1 mod 4; \5 = tool to make tail = \2
    )\5                    # tail = \2
)*
# Test if tail or tail/2 is a perfect square. If this test succeeds, return tail as
# the denominator and 1 as the numerator.
(                          # \7 = denominator output
    (                      # \8 = \9 * sqrt(tail / \9)
        ((x)x?)            # \9 = control whether to take sqrt(tail) or 2*sqrt(tail/2);
                           # \10 = numerator output (NPCG to represent zero)
        (\9*)              # \11 = \8 - \9
    )
    (?=
        (\8*)\11+$         # Iff \9 * (\8 / \9)^2 == our number, then the first match
                           # here must result in \12==0
    )
    \8*$\12                # Test for divisibility by \8 and for \12==0
                           # simultaneously
|
# Failure of the perfect square test results in returning 0/1 as the answer, so here
# we return a denominator of 1.
    x
)
Deadcode
fonte
1
Desculpe, obviamente eu não tentei em casos de teste suficientes.
Neil
1
@trichoplax Você poderia considerar a resposta como sendo a proporção de comprimentos de dois grupos de captura específicos? (Isso na verdade tornaria a resposta mais curta, pois é necessário o esforço para fazer com que toda a correspondência seja o resultado.)
Neil
1
Seguindo o comentário de @ Neil, editei para permitir a saída como numerador e denominador separados, pois essa parece a menor alteração que permite regex puro. Deixe-me saber se isso ainda é um problema
trichoplax 25/02
1
-11 bytes usando (((xx?)(\9*))(?=(\8*)\10+$)\8*$\11)para verificar se N ou N / 2 é um quadrado.
Grimmy 26/02
1
Os ponteiros @Deadcode para as refexs não devem receber um custo de byte, pois são permitidos por padrão .
Grimmy 26/02
4

Geléia ,  25  24 bytes

ÆFµ%4,2CḄ:3+2Ịị,*/ʋ÷*/)P

Um link monádico usando a rota de fator principal.

Experimente online!

Quão?

ÆFµ%4,2CḄ:3+2Ịị,*/ʋ÷*/)P - Link: integer, n               e.g. 11250
ÆF                       - prime factor, exponent pairs        [[2,1], [3,2], [5,4]]
  µ                   )  - for each pair [F,E]:
    4,2                  -   literal list [4,2]
   %                     -   modulo (vectorises)                [2,1]  [3,0]  [1,0]
       C                 -   complement (1-x)                  [-1,0] [-2,1]  [0,1]
        Ḅ                -   from base 2                         -2     -3      1      
         :3              -   integer divide by three             -1     -1      0
           +2            -   add two (call this v)                1      1      3
                  ʋ      -   last four links as a dyad, f(v, [F,E])
             Ị           -     insignificant? (abs(x)<=1 ? 1 : 0)   1      1      0
                */       -     reduce by exponentiation (i.e. F^E)  2      9     625
               ,         -     pair v with that                   [1,2]  [1,9]  [3,625]
              ị          -     left (Ị) index into right (that)     1      1     625
                    */   -   reduce by exponentiation (i.e. F^E)    2      9     625
                   ÷     -   divide                                1/2    1/9  625/625
                       P - product                                 1/18 = 0.05555555555555555

Os 25 anteriores foram:

ŒRp`²S⁼ɗƇ⁸+€`Ẏ;Ɗ%³QƊÐLL÷²

Programa completo forcer bruto ; código possivelmente mais longo que a rota de fator principal (eu poderia tentar isso mais tarde).

Experimente online!

Começa por criação de movimentos individuais como coordenadas, em seguida, move-se repetidamente a partir de todos os locais que acumulam alcançados os resultados, tendo modulo nde cada coordenada (para restringir a um npor nquadrante) e manter aqueles que são distintas, até um ponto fixo é atingido; finalmente divide a contagem porn^2

Jonathan Allan
fonte
4

05AB1E , 27 26 25 bytes

ÓεNØ©<iozë®4%D≠iyÈ®ymz*]P

Porto da resposta JavaScript de @ShieruAsakoto , por isso, certifique-se de que ele também vota !

Experimente online ou verifique todos os casos de teste .

Explicação:

Ó                   # Get all prime exponent's of the (implicit) input's prime factorization
                    #  i.e. 6 → [1,1]      (6 → 2**1 * 3**1)
                    #  i.e. 18 → [1,2]     (18 → 2**1 * 3**2)
                    #  i.e. 20 → [2,0,1]   (20 → 2**2 * 3**0 * 5**1)
                    #  i.e. 25 → [0,0,2]   (25 → 2**0 * 3**0 * 5**2)
 ε                  # Map each value `n` to:
  NØ                #  Get the prime `p` at the map-index
                    #   i.e. map-index=0,1,2,3,4,5 → 2,3,5,7,11,13
    ©               #  Store it in the register (without popping)
     <i             #  If `p` is exactly 2:
       oz           #   Calculate 1/(2**`n`)
                    #    i.e. `n`=0,1,2 → 1,0.5,0.25
      ë             #  Else:
       ®4%          #   Calculate `p` modulo-4
                    #    i.e. `p`=3,5,7,11,13 → 3,1,3,3,1
          D         #   Duplicate the result (the 1 if the following check is falsey)
           i       #   If `p` modulo-4 is NOT 1 (in which case it is 3):
             yÈ     #    Check if `n` is even (1 if truthy; 0 if falsey)
                    #     i.e. `n`=0,1,2,3,4 → 1,0,1,0,1
             ®ymz   #    Calculate 1/(`p`**`n`)
                    #     i.e. `p`=3 & `n`=2 → 0.1111111111111111 (1/9)
                    #     i.e. `p`=7 & `n`=1 → 0.14285714285714285 (1/7)
              *     #    Multiply both with each other
                    #     i.e. 1 * 0.1111111111111111 → 0.1111111111111111
                    #     i.e. 0 * 0.14285714285714285 → 0
 ]                  # Close both if-statements and the map
                    #  i.e. [1,1] → [0.5,0.0]
                    #  i.e. [1,2] → [0.5,0.1111111111111111]
                    #  i.e. [2,0,1] → [0.25,1.0,1]
                    #  i.e. [0,0,2] → [1.0,1.0,1]
  P                 # Take the product of all mapped values
                    #  i.e. [0.5,0.0] → 0.0
                    #  i.e. [0.5,0.1111111111111111] → 0.05555555555555555
                    #  i.e. [0.25,1.0,1] → 0.25
                    #  i.e. [1.0,1.0,1] → 1.0
                    # (and output implicitly as result)
Kevin Cruijssen
fonte
4

APL (Dyalog Extended) , 21 bytes

Este programa usa a rota de fator principal. Sou grato a Adám, dzaima, H.PWiz, J.Sallé e ngn. O APL Orchard é um ótimo lugar para aprender APL e eles estão sempre dispostos a ajudar

(×/÷,34|*∘≢⌸)⍭*14|⍭

Experimente online!

Ungolfing

A parte 2 deste código é a mesma da versão Dyalog Unicode abaixo e, portanto, nesta explicação, vou me concentrar em ⍭*1≠4|⍭

⍭*14|⍭

        Gives us a list of the prime factors of our input.
           Example for 45: 3 3 5
  14|   Checks if each prime is of the form 4k+1.
⍭*       Takes each prime to the power of 1 or 0,
           turning all the 4k+1 primes into 1s.
           Example for 45: 3 3 1

APL (Dyalog Unicode) , 41 40 36 35 bytes SBCS

Este programa usa a rota de fator principal. Aprendi alguns truques ao escrever isso e sou profundamente grato a Adám, dzaima, H.PWiz, J.Sallé e ngn. O APL Orchard é um ótimo lugar para aprender APL e eles estão sempre dispostos a ajudar (ou esse post nunca teria saído do papel :)

Edit: -1 byte de ngn. -2 bytes de Adám e -2 mais de ngn. -1 byte de ngn.

{(×/÷,34|*∘≢⌸)p*14|p←¯2÷/∪∧\⍵∨⍳⍵}

Experimente online!

Ungolfing

Este é um programa em duas partes:

p*14|p←¯2÷/∪∧\⍵∨⍳⍵  Part 1

      p             We can define variables mid-dfn (a function in {} brackets).
               ⍵∨⍳⍵  We take the GCD of our input 
                       with every member of range(1, input).
            ∪∧\      This returns all the unique LCMs of every prefix
                       of our list of GCDs.
                       Example for 31500: 1 2 6 12 60 420 1260 6300 31500
        ¯2÷/         We divide pairwise (and in reverse)
                       by using a filter window of negative two 2).
                       Example for 31500: 2 3 2 5 7 3 5 5
  14|p              Check if the primes are 1 modulo 4 or not
p*                   And take each prime to the power of the result (1 or 0),
                       turning the 4k+3 primes into 1s
                       and leaving any 2s and 4k+3 primes.
                       Example for 31500: 2 3 2 1 7 3 1 1

(×/÷,34|*∘≢⌸)  Part 2

(            )  We apply all this to the filtered array of primes.
         *∘≢⌸   This takes all of our primes to their exponents
                  (the number of times those primes appear in the factorization).
                  Example for 31500: 4 9 1 7
     34|       Then we take each prime modulo 4 and check if not equal to 3.
                  We will only get a falsey if any 4k+3 primes, as an even number of
                  4k+3 primes multiplied together will result in some 4m+1.
                  Example for 31500: 1 1 1 0
   ÷,           We append the results of the above condition check
                  to the reciprocals of the primes in p.
                  Example for 31500: (1/2) (1/3) (1/2) 1 (1/7) (1/3) 1 1 1 1 1 0
 ×/             We multiply it all together, resulting in a positive fraction or 0
                  depending on our condition check.
                  Example for 31500: 0
                We return the results of all our checks implicitly.
Sherlock9
fonte