Determinar se um número é friável para 2017 sem primos no seu código-fonte


41

Em todos os anos em que faço esse desafio, 2017 é o primeiro ano em que é um número primo. Portanto, a questão será sobre números primos e suas propriedades.

Sua tarefa é produzir um programa ou função que receba um número inteiro positivo arbitrariamente grande como entrada e produza ou retorne com ou sem número friável de 2.017 - ou seja, se o maior fator primordial nesse número é 2.017 ou menos.


Alguns exemplos de entradas e suas saídas:

1 (has no prime factors)
true

2 (= 2)
true

80 (= 2 x 2 x 2 x 2 x 5)
true

2017 (= 2017)
true

2019 (= 3 x 673)
true

2027 (= 2027)
false

11111 (= 41 x 271)
true

45183 (= 3 x 15061)
false

102349 (= 13 x 7873)
false

999999 (= 3 x 3 x 3 x 7 x 11 x 13 x 37)
true

1234567 (= 127 x 9721)
false

4068289 (= 2017 x 2017)
true

Seu programa não precisa literalmente produzir truee false- quaisquer valores verdadeiros ou falsos e, de fato, quaisquer duas saídas diferentes que são consistentes entre casos verdadeiros e falsos são boas.


No entanto, você não pode usar números primos no seu código-fonte. Primes vêm em dois tipos:

  • Caracteres ou sequências de caracteres que representam literais de números primos.

    • Os personagens 2, 3, 5, e 7são ilegais em línguas onde os números são tokens válidos.

    • O número 141é ilegal porque contém 41, embora 1e 4são de outra maneira válida.

    • Os caracteres Be D(ou be d) são ilegais nos idiomas em que geralmente são usados ​​como 11 e 13, como CJam ou Befunge.

  • Caracteres que possuem valores Unicode com valor inicial ou contêm bytes com valor inicial em sua codificação.

    • Os caracteres %)+/5;=CGIOSYaegkmqsão ilegais no ASCII, assim como o caractere de retorno de carro.

    • O caractere óé ilegal no UTF-8 porque sua codificação está 0xb3nele. No entanto, na ISO-8859-1, sua codificação é simples 0xf3, composta e, portanto, correta.

O código mais curto para fazer o acima em qualquer idioma vence.


Nota lateral: "friável" é uma melhoria adotada em relação ao "suave" antigo e não descritivo neste contexto.
Greg Martin

11
Os valores de verdade e falsidade precisam ser consistentes? Ou elas podem variar desde que sejam verdadeiras ou falsas?
Luis Mendo

10
A falta de =regras a maioria das linguagens de padrão ...
Neil

4
-1 para um X sem desafio Y. É realmente muito trivial escondido atrás de um conjunto bastante desnecessário de restrições de caracteres
Downgoat

11
Não gosto da parte deles ser arbitrariamente grande. Seria melhor se eles chegassem a 2 ^ 31-1.
Bijan

Respostas:


37

Gelatina , 8 bytes

44‘²!*ḍ@

Experimente online! Observe que os casos de teste 11111 e acima são um pouco demais para o TIO.

Verificação

$ source="34,34,fc,82,21,2a,d5,40"
$ xxd -ps -r > 2017.jelly <<< $source
$ xxd -g 1 2017.jelly
0000000: 34 34 fc 82 21 2a d5 40                          44..!*.@
$ eval printf '"%d "' 0x{$source}; echo # Code points in decimal
52 52 252 130 33 42 213 64
$ test_cases="1 2 80 2017 2019 2027 11111 45183 102349 999999 1234567 4068289"
$ for n in $test_cases; do printf "%11d: %d\n" $n $(jelly f 2017.jelly $n); done
      1: 1
      2: 1
     80: 1
   2017: 1
   2019: 1
   2027: 0
  11111: 1
  45183: 0
 102349: 0

O caso de teste 999999 está em execução há 13 horas. Sou pessimista em relação à computação 2025! 4068289 ...

Como funciona

44‘²!*ḍ@  Main link. Argument: n

44        Yield 44.
  ‘       Increment to yield 45.
   ²      Square to yield 2025.
          Note that no integers in [2018, ..., 2025] are prime numbers.
    !     Take the factorial of 2025.
     *    Raise it to the n-th power.
          This repeats all prime factors in 2025! at least n times, so the result
          will be divisible by n if (and only if) all of its prime factors fall
          in the range [1, ..., 2025].
      ḍ@  Test the result for divisibility by n.

22
Você é cruel com os números. :)
Greg Martin

3
@GregMartin bah. Eu vi uma resposta (em um idioma diferente) em que uma entrada do tamanho 6 monopolizava a memória por várias horas e depois travava. Vou apenas dizer: (2^n)!. Isso também exige entradas de seis tamanhos, mas pelo menos as entradas estão em um alfabeto decimal e não em um binário.
John Dvorak

Isso não é 13 bytes? Dennis, você tem tanta reputação que tenho certeza de que sou eu quem está cometendo um erro aqui, hahah
Albert

7
@AlbertRenshaw Seria de fato 13 bytes em UTF-8, mas o Jelly usa uma página de código personalizada que codifica todos os caracteres que entende como um único byte cada.
Dennis

3
@Dennis sabia que haveria uma explicação; muito legal para aprender, obrigado!
Albert Renshaw

11

Gelatina , 8 caracteres, 14 bytes de UTF-8

Æf½ṀḤ<90

Experimente online!

O Jelly normalmente usa sua própria página de códigos para programas. No entanto, a maioria de seus buildins relacionados ao prime começa com Æ, que é o codepoint 13; não é muito útil. Felizmente, o intérprete também suporta UTF-8, que possui uma codificação mais amigável.

Verificação

Este programa, em UTF-8, hexdumps como este:

00000000: c386 66c2 bde1 b980 e1b8 a43c 3930  ..f........<90

Verificação de que todos os bytes são compostos:

$ for x in c3 86 66 c2 bd e1 b9 80 e1 b8 a4 3c 39 30; do factor $((0x$x)); done
195: 3 5 13
134: 2 67
102: 2 3 17
194: 2 97
189: 3 3 3 7
225: 3 3 5 5
185: 5 37
128: 2 2 2 2 2 2 2
225: 3 3 5 5
184: 2 2 2 23
164: 2 2 41
60: 2 2 3 5
57: 3 19
48: 2 2 2 2 3

Verificação de que todos os pontos de código Unicode são compostos:

$ perl -Mutf8 -E '$a = ord, print `factor $a` for split //, "Æf½ṀḤ<90"'
198: 2 3 3 11
102: 2 3 17
189: 3 3 3 7
7744: 2 2 2 2 2 2 11 11
7716: 2 2 3 643
60: 2 2 3 5
57: 3 19
48: 2 2 2 2 3

O único token analisado como um número é 90. Nenhum de 9, 0e 90são primos.

Explicação

A principal visão matemática aqui é que 45² é 2025, que cai ordenadamente entre 2017 (o ano atual) e 2027 (o próximo primo). Assim, podemos obter a raiz quadrada de todos os fatores primos do número e ver se algum excede 45. Infelizmente, não podemos escrever 45devido ao literal 5; portanto, precisamos dobrá-lo e comparar com 90.

Æf½ṀḤ<90
Æf        In the list of prime factors,
  ½       taking the square root of each element
   Ṁ      then taking the largest element
    Ḥ     and doubling it
     <90  produces a result less than 90.

2
O Jelly não exige uma bandeira (1 byte) para usar UTF-8?
Luis Mendo

@LuisMendo: O intérprete da linha de comando sim, mas o intérprete do Try It Online! está configurado de forma diferente e não exige isso. Portanto, este é apenas um caso de escolher o intérprete que interpreta seu programa da maneira que você deseja. (Em qualquer caso, a bandeira em questão, ué composto, por isso seria apenas uma questão de mudar a pontuação em vez de algo que invalida.)

10

Mathematica, 62 58 55 bytes

Os últimos três bytes salvos são totalmente devidos a Martin Ender!

#4<4||#<44*46&&#6[#^-1#4]&[Divisors[#][[6-4]],,,#,,#0]&

Função sem nome, usando um argumento inteiro positivo e retornando Trueou False.

Algoritmo recursivo, por #4<4ser o caso base verdadeiro (precisamos apenas retornar Truena imput 1, mas os casos base extras estão corretos). Caso contrário, calculamos o segundo menor divisor (que é necessariamente primo) da entrada com Divisors[#][[6-4]]; se for maior que 2024 ( 44*46), sairemos com False, caso contrário, chamaremos a função recursivamente (usando #6set para #0) na entrada dividida por esse pequeno fator primo #(que devemos expressar como #^-1vezes a entrada #4, pois /não é permitida).

Estruturalmente, a primeira metade #4<4||#<44*46&&#6[#^-1#4]&é uma função anônima de seis argumentos, sendo chamado com argumentos Divisors[#][[6-4]], Null, Null, #, Null, e #0; este é para contornar a proibição dos personagens 2, 3e 5.

Versão anterior, que salvou quatro bytes substituindo 8018-6000por 44*46, inspirada na resposta Jelly do ais523 (Martin Ender também parecia inspirado no comentário do ais523):

#<4||Divisors[#][[6-4]]<44*46&&#0[Divisors[#][[6-4]]^-1#]&

Isso foi bastante desagradável: ainda não sei como definir uma variável no Mathematica sob essas restrições! Ambos =e o ein Setsão proibidos. Evitar +e )também foi um problema, mas não muito difícil de contornar à custa de mais bytes.


Talvez você possa definir um parâmetro lambda em vez de uma variável. (Dito isto, #2também seria anulado, por isso você tem que ter cuidado com a forma como seus lambdas aninhados, ea falta de parênteses pode fazer essa difícil.)

A implementação da sugestão de @ ais523 salva três bytes: #4<4||#<44*46&&#6[#^-1#4]&[Divisors[#][[6-4]],,,#,,#0]&lança vários avisos, porque agora tenta Divisors[#][[2]]antes garantir que a entrada seja maior que 1 (ou 3), mas o resultado ainda está correto.
Martin Ender

Oh cara, isso é astúcia.
Greg Martin

7

Haskell, 48 47 bytes

\n->[snd$[product[1..44*46]^n]!!0`divMod`n]<[1]

Basicamente, uma tradução da resposta de Dennis 'Jelly . O xnor salvou um byte.

Usa […]!!0como parênteses porque )é banido e snd+ divModporque o min mode remé banido.


Bom truque com o divMod! Eu acho que você pode substituir o !!0<1com <[1]. Mas parece que está em curto para usar divcomo [\p n->p^n`div`n*n>p^n-1]!!0$product[1..44*46].
xnor

Há também os \n->[0|p<-[product[1..44*46]^n],0<-[p,p-n..0]]que usam essas saídas apenas para serem consistentes.
precisa

@xnor Sinta-se livre para postar as como resposta em separado (s), eu acho que eles são suficientemente diferente da minha ^^
Lynn

6

Pyke, 10 8 7 9 bytes

P_Z|hwMX<

Experimente aqui!

Economizou 1 byte usando a maneira de Dennis gerar 2025

P         -     factors(input)
 _        -    reversed(^)
  Z|      -   ^ or 0
    h     -  ^[0] or 1
        < - ^ < V
     wM   -  ⁴45 (ord("M")-32)
       X  -  ^**2

5

Braquilog , 9 10 bytes

*$ph$r*<90

Experimente online!

Basicamente, usando o mesmo algoritmo da minha outra resposta. $phencontra o primeiro ( h) fator primo ( $p); esse é o maior fator primordial, pois as listas de fatores primários de Brachylog vão do maior para o menor. Então pego a raiz quadrada ( $r), o dobro ( *) e testo para ver se é menor que 90 ( <90).

Eu tive que dobrar a entrada primeiro porque 1 não possui fatores primos (e, portanto, nenhum primeiro fator primo). Isso adiciona um fator primo extra de 2, que não pode afetar se um número é friável para 2017, mas evita uma falha ao manipular 1.


5

Na verdade , 9 bytes

τyM:44u²≥

Obrigado ao Dennis por muitos bytes!

Experimente online!

Explicação:

τyM:44u²≥
τyM        largest prime factor of 2*input (doubled to deal with edge case of n = 1)
   :44u²   2025 (2027 is the next prime after 2017, so any number in [2017, 2026] can be used here - 2025 is very convenient)
        ≥  is 2025 greater than or equal to largest prime factor?

5

Mathematica, 66 74 bytes

Agradecemos a Dennis por apontar que U+F4A1é proibido.

Fold[Function[{x,d},And[x,Tr[Divisors@d^0]>6-4||d<44*46]],0<1,Divisors@#]&

Explicação:

Divisors@#: Lista de divisores inteiros do primeiro argumento #.

0<1: Golf for True(também evita o uso da letra e).

Divisors@d^0: Lista do formulário {1, 1, ..., 1}com comprimento igual ao número de divisores de d.

Tr: Para uma lista simples, Trretorna a soma dessa lista. Assim, Tr[Divisors@d^0]retorna o número de divisores de d.

Function[{x,d},And[x,Tr[Divisors@d^0]>6-4||d<44*46]]: Função anônima com dois argumentos xe d. A idéia é que dé um divisor de #e testamos para ver se é composto ou menor que ou igual a 2017(inclusive). 2017-friabilidade é equivalente a todos os divisores que satisfazem essa condição. Como o ais523 descobriu, ser um número primo menor ou igual a 2017é equivalente a ser um número primo menor que 2025. Como apontou Greg Martin , basta testar se é menor que 2024=44*46. O argumento xatua como um acumulador para saber se todos os divisores encontrados até o momento satisfazem essa propriedade. Em seguida, deixamos Foldessa função através de todos os divisores de #com valor inicialTrue, já que temos acesso a nem Mapnem /@.


11
Maneira de lutar através das restrições!
Greg Martin

2

05AB1E , 10 bytes

fθ46n99-›È

Retorna 1 se verdadeiro, 0 caso contrário.

Experimente online!

Explicação

f          # Push the list of prime factors (ordered)
 θ         # Get the last element
  46n99-   # Push 2017 (46² - 99)
        >  # Push 1 if the last prime factor is greater than 2017, 0 otherwise
         È # Is the resulting number even ? Transforms 1 to 0 and 0 to 1.
           # Implicit display

Bem-vindo ao PPCG!
Martin Ender

1

MATL , 15 bytes

t:\~ftZp*44QU<A

Saídas 0para não-2017-friable ou 1para 2017-friable.

Experimente online! Ou verifique todos os casos de teste .

Este programa verifica se todos os bytes são compostos.

Explicação

t       % Implicit input n. Duplicate
:       % Range [1 2 ... n]
\       % Modulo. Gives 0 for divisors of n
~f      % Indices of zero values
t       % Duplicate
Zp      % Is-prime. Gives 1 for primes, 0 for composites
*       % Multiply
44QU    % 44, add 1, square: 2025
<       % Less than, element-wise
A       % True (1) if all entries are nonzero

1

Bash, 144 bytes

Codificação ASCII:

{
printf '[ '
`tr D-Z _-z <<<KFH`tor $1|tr -d :|`tr B-Z _-z <<<JUH`p -o '[0-9]*$'
printf ' -lt $[24*86-46] ]'
}|tr \\n \ |`tr B-Z _-z <<<EDVK`

Como de costume no shell, o código de saída indica sucesso (0) ou falha (não-0).

Esta é efetivamente uma grafia diferente de

[ factor $1|tr -d :|grep -o '[0-9]*$' -lt 2018 ]

Temos o maior fator com factor $1|grep -o '[0-9]*$'; o tr -d :é um caso especial para input = 1.

A expressão é $[6*6*69-466]avaliada para 2018.

Era complicado usar tros nomes de comando e ainda usar a substituição de comando - como eu não conseguia usar o formulário de aninhamento $( ), acabei inserindo outro Bash para avaliar o resultado.

Resultado dos testes:

$ for i in 1 2 80 2017 2019 2027 11111 45183 102349 999999 1234567 4068289; do printf '%d %s\n' $i `./105241.sh $i  && echo true || echo false`; done
1 true
2 true
80 true
2017 true
2019 true
2027 false
11111 true
45183 false
102349 false
999999 true
1234567 false
4068289 true

Confirmação dos códigos de caracteres:

$ grep -v '^#' ./105241.sh | perl -n -Mutf8 -E '$a = ord, print `factor $a` for split //, $_' | grep -v ': .* ' | wc -l
0




0

Braingolf , 11 bytes [muito pouco competitivo]

VRp#ߢ-?0:1

Experimente online!

Ilegível devido aos ߢquais aparafusa os números, no entanto ainda funciona em um intérprete.

Eu nem percebi as restrições de caracteres quando escrevi isso, mas tudo que eu tinha a fazer era mudar o estranho caractere unicode de 2017 para 2018.

Dado que 2018 não é primo, qualquer primo <= 2018também é<= 2017

Explicação

VRp#ߢ-?0:1  Implicit input from command-line args
VR            Create stack2, return to stack1
  p           Split last item into prime factors, push each one to stack in asc order
   #ߢ         Push 2018
     -      Subtract last 2 items (highest prime factor - 2017)
      ?     If last item > 0..
       0    ..push 1
        :   Else..
         1  ..Push 1
            Implicit output of last item on stack
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.