¿Es este número un factorial?


38

La tarea

Dado un número natural como entrada, su tarea es generar un valor verdadero o falso en función de si la entrada es un factorial de cualquier número natural. Puede suponer que el número de entrada siempre estará en el rango de números admitidos por su idioma, pero no debe abusar de los tipos de números nativos para trivializar el problema .

Se aplican lagunas estándar .


Entrada

Se le dará un número natural (de tipo Integero similar).

Puede tomar la entrada de la forma que desee, excepto suponiendo que esté en una variable predefinida. promptSe permite leer archivos, consolas, cuadros de diálogo ( ), cuadros de entrada, etc. ¡La entrada como argumento de función también está permitida!


Salida

Su programa debe generar un valor verdadero o falso basado en si el número de entrada es un factorial de cualquier número natural.

Asegúrese de que sus valores de verdad / falsey sean consistentes para todas las entradas, es decir, si está utilizando un par de 1 y 0 para denotar valores de verdad y falsey respectivamente, entonces su programa debe generar 1 para todas las entradas que deberían tener valores de verdad y 0 para todas las entradas que deberían tener valores falsey.

Puede tomar la salida de la forma que desee, excepto escribirla en una variable. Se permite escribir en archivos, consolas, pantallas, etc. ¡La función también returnestá permitida!

¡Su programa no debe producir errores para ninguna entrada!


Casos de prueba

Input     Output

1         Truthy (0! or 1!)
2         Truthy (2!)
3         Falsey
4         Falsey
5         Falsey
6         Truthy (3!)
7         Falsey
8         Falsey
24        Truthy (4!)
120       Truthy (5!)

Criterio ganador

Este es el , por lo que gana el código más corto en bytes.


2
Si el idioma solo admite números en el rango {0,1}, ¿puedo esperar que la entrada sea siempre 1?
eush77

11
@ eush77 El abuso de los tipos de números nativos para trivializar un problema está prohibido de forma predeterminada.
Dennis

1
es 4! una verdad?
tuskiomi

Pregunta: ¿Por qué no utiliza los valores predeterminados de E / S?
CalculatorFeline

Respuestas:


37

Brachylog , 1 byte

Pruébalo en línea!

Explicación

es un incorporado que afirma la siguiente relación: su salida es el factorial de su entrada. Simplemente le damos una salida establecida y vemos si tiene éxito o no con una entrada variable.


66
@BetaDecay Eso es porque es la forma en que está impreso en Prolog (esto tiene que ver con el hecho de que true.es una declaración y trueno lo es)
Fatalize

66
Es una solución trivial, pero es inteligente debido a la forma en que funciona el prólogo.
Esolanging Fruit


17
Primero lenguajes personalizados, luego codificaciones personalizadas ... el código golf está muerto. Hemos subvertido por completo el punto de estos divertidos problemas en primer lugar
Alexander - Restablece a Monica

13
@Alexander Las codificaciones personalizadas son irrelevantes para cualquier problema del que estés hablando. En su lugar, podría usar cualquier codificación "existente" y aún sería 1 byte. Sería mucho menos legible.
Fatalize


19

Jalea , 4 bytes

Œ?IE

No es la respuesta más breve de Jelly, pero es bastante eficiente.

Pruébalo en línea!

Cómo funciona

Œ?IE  Main link. Argument: n

Œ?    Yield the n-th permutation of the positive integers, without the sorted tail.
      For 120, this yields [5, 4, 3, 2, 1], the tail being [6, 7, 8, ...].
  I   Increments; compute all forward differences.
      For 120, this yields [-1, -1, -1, -1].
   E  Check if all differences are equal.

2
Porque nosotros los golfistas de código nos preocupamos por la eficiencia.
Okx

12
Es una mejora dramática de la complejidad a costa de un byte y es un uso inteligente de un incorporado si puedo decirlo yo mismo. ¯ \ _ (ツ) _ / ¯
Dennis

Curiosamente, esto devuelve verdadero para 0, mientras que la respuesta de 3 bytes de @ LeakyNun, aunque mucho más lenta en general, devuelve correctamente falso para 0. ¿Se necesitan bytes adicionales para devolver falso para 0 en una respuesta de tiempo de ejecución eficiente?
Código muerto el

@Deadcode La comprobación de 0 requeriría dos bytes adicionales. Si no está seguro de si la definición del OP de "números naturales" incluye 0 o no. Los casos de prueba no ...
Dennis

17

ECMAScript Regex, 733+ 690+ 158 119 118 (117🐌) bytes

Mi interés en la expresión regular se ha despertado con un vigor renovado después de más de 4 años y medio de inactividad. Como tal, fui en busca de conjuntos de números y funciones más naturales para que coincidan con expresiones regulares ECMAScript unarias, continué mejorando mi motor de expresiones regulares y comencé a repasar PCRE también.

Me fascina la extrañeza de construir funciones matemáticas en expresiones regulares ECMAScript. Los problemas deben abordarse desde una perspectiva completamente diferente, y hasta la llegada de una idea clave, se desconoce si tienen solución alguna. Obliga a echar una red mucho más amplia para encontrar qué propiedades matemáticas podrían utilizarse para resolver un problema particular.

La coincidencia de números factoriales fue un problema que ni siquiera consideré abordar en 2014, o si lo hice, solo momentáneamente, descartándolo como demasiado improbable. Pero el mes pasado, me di cuenta de que podía hacerse.

Al igual que con mis otras publicaciones de expresiones regulares de ECMA, daré una advertencia: recomiendo aprender a resolver problemas matemáticos unarios en expresiones regulares de ECMAScript. Ha sido un viaje fascinante para mí, y no quiero estropearlo para cualquiera que quiera probarlo ellos mismos, especialmente aquellos interesados ​​en la teoría de números. Consulte esta publicación anterior para obtener una lista de problemas recomendados etiquetados consecutivamente con spoilers para resolver uno por uno.

Así que no sigas leyendo si no quieres que se te estropee un poco de magia regex unaria avanzada . Si desea intentar descubrir esta magia usted mismo, le recomiendo comenzar resolviendo algunos problemas en la expresión regular de ECMAScript como se describe en la publicación vinculada anteriormente.

Esta fue mi idea:

El problema con la coincidencia de este conjunto de números, como con la mayoría de los demás, es que en ECMA generalmente no es posible realizar un seguimiento de dos números cambiantes en un bucle. A veces se pueden multiplexar (por ejemplo, los poderes de la misma base se pueden sumar sin ambigüedad), pero depende de sus propiedades. Por lo tanto, no podría comenzar con el número de entrada y dividirlo por un dividendo incrementalmente creciente hasta llegar a 1 (o eso pensé, al menos).

Luego investigué un poco sobre la multiplicidad de factores primos en números factoriales, y aprendí que hay una fórmula para esto , ¡y es una que probablemente podría implementar en una expresión regular de ECMA!

Después de estofarlo durante un tiempo y, mientras tanto, construir otras expresiones regulares, tomé la tarea de escribir la expresión regular factorial. Tomó varias horas, pero terminó funcionando bien. Como una ventaja adicional, el algoritmo podría devolver el factorial inverso como una coincidencia. No había forma de evitarlo, incluso; Por la naturaleza misma de cómo debe implementarse en ECMA, es necesario adivinar cuál es el factorial inverso antes de hacer cualquier otra cosa.

La desventaja es que este algoritmo generó una expresión regular muy larga ... pero me complació que terminara requiriendo una técnica utilizada en mi expresión regular de multiplicación de 651 bytes (la que terminó siendo obsoleta, porque un método diferente hizo un 50 byte regex). Esperaba que surgiera un problema que requiriera este truco: operar con dos números, que son ambas potencias de la misma base, en un bucle, al sumarlos sin ambigüedad y separarlos en cada iteración.

Pero debido a la dificultad y la longitud de este algoritmo, utilicé lookaheads moleculares (de la forma (?*...)) para implementarlo. Esa es una característica que no está en ECMAScript ni en ningún otro motor de expresiones regulares convencional, sino una que había implementado en mi motor . Sin ninguna captura dentro de una búsqueda molecular por adelantado, es funcionalmente equivalente a una búsqueda atómica, pero con las capturas puede ser muy potente. El motor retrocederá hacia adelante, y esto puede usarse para conjeturar un valor que recorre todas las posibilidades (para pruebas posteriores) sin consumir caracteres de la entrada. Usarlos puede hacer una implementación mucho más limpia. (La mirada retrospectiva de longitud variable es al menos igual en potencia a la búsqueda molecular adelantada, pero esta última tiende a hacer implementaciones más directas y elegantes).

Por lo tanto, las longitudes de 733 y 690 bytes no representan en realidad encarnaciones de la solución compatibles con ECMAScript, de ahí el "+" después de ellas; seguramente es posible portar ese algoritmo a ECMAScript puro (lo que aumentaría un poco su longitud), pero no lo logré ... ¡porque pensé en un algoritmo mucho más simple y compacto! Uno que podría implementarse fácilmente sin miradas moleculares. También es significativamente más rápido.

Este nuevo, como el anterior, debe adivinar el factorial inverso, recorrer todas las posibilidades y probarlas para un partido. Divide N entre 2 para dejar espacio para el trabajo que necesita hacer, y luego siembra un ciclo en el que dividirá repetidamente la entrada por un divisor que comienza en 3 e incrementa cada vez. (Como tal, 1! Y 2! No pueden coincidir con el algoritmo principal, y deben tratarse por separado). El divisor se mantiene al agregarlo al cociente corriente; estos dos números se pueden separar inequívocamente porque, suponiendo M! == N, el cociente corriente continuará siendo divisible por M hasta que sea igual a M.

Esta expresión regular se divide por una variable en la parte más interna del bucle. El algoritmo de división es el mismo que en mis otras expresiones regulares (y similar al algoritmo de multiplicación): para A≤B, A * B = C si existe solo si C% A = 0 y B es el número más grande que satisface B≤C y C% B = 0 y (CB- (A-1))% (B-1) = 0, donde C es el dividendo, A es el divisor y B es el cociente. (Se puede usar un algoritmo similar para el caso de que A≥B, y si no se sabe cómo A se compara con B, una prueba de divisibilidad adicional es todo lo que se necesita).

Así que me encanta que el problema se haya podido reducir a una complejidad aún menor que la expresión regular de Fibonacci optimizada para el golf , pero suspiro con decepción porque mi técnica de multiplexación de poderes de la misma base tendrá que esperar otro problema eso realmente lo requiere, porque este no. ¡Es la historia de que mi algoritmo de multiplicación de 651 bytes fue reemplazado por uno de 50 bytes, todo de nuevo!

Editar: pude soltar 1 byte (119 → 118) usando un truco encontrado por Grimy que puede acortar aún más la división en el caso de que el cociente sea mayor o igual que el divisor.

Sin más preámbulos, aquí está la expresión regular:

Versión verdadera / falsa (118 bytes):

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$|^xx?$

Pruébalo en línea!

Devuelve factorial inverso o no coincidencia (124 bytes):

^(?=((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\3$)\3|^xx?$

Pruébalo en línea!

Devuelve factorial inverso o no coincidencia, en ECMAScript +\K (120 bytes):

^((x*)x*)(?=\1$)(?=(xxx\2)+$)((?=\2\3*(x(?!\3)xx(x*)))\6(?=\5+$)(?=((x*)(?=\5(\8*$))x)\7*$)x\9(?=x\6\3+$))*\2\K\3$|^xx?$

Y la versión libre con comentarios:

  ^
  (?=                           # Remove this lookahead and the \3 following it, while
                                # preserving its contents unchanged, to get a 119 byte
                                # regex that only returns match / no-match.
    ((x*)x*)(?=\1$)             # Assert that tail is even; \1 = tail / 2;
                                # \2 = (conjectured N for which tail == N!)-3; tail = \1
    (?=(xxx\2)+$)               # \3 = \2+3 == N; Assert that tail is divisible by \3
    # The loop is seeded: X = \1; I = 3; tail = X + I-3
    (
      (?=\2\3*(x(?!\3)xx(x*)))  # \5 = I; \6 = I-3; Assert that \5 <= \3
      \6                        # tail = X
      (?=\5+$)                  # Assert that tail is divisible by \5
      (?=
        (                       # \7 = tail / \5
          (x*)                  # \8 = \7-1
          (?=\5(\8*$))          # \9 = tool for making tail = \5\8
          x
        )
        \7*$
      )
      x\9                       # Prepare the next iteration of the loop: X = \7; I += 1;
                                # tail = X + I-3
      (?=x\6\3+$)               # Assert that \7 is divisible by \3
    )*
    \2\3$
  )
  \3                            # Return N, the inverse factorial, as a match
|
  ^xx?$                         # Match 1 and 2, which the main algorithm can't handle

La historia completa de mis optimizaciones de golf de estas expresiones regulares está en github:

regex para hacer coincidir números factoriales: método de comparación de multiplicidad, con lookahead.txt molecular
regex para hacer coincidir números factoriales.txt (el que se muestra arriba)

((x*)x*)((x*)+)((x+)+)norte=3!\23-3=0 0

El motor .NET regex no emula este comportamiento en su modo ECMAScript y, por lo tanto, la regex de 117 bytes funciona:

Pruébalo en línea! (versión de desaceleración exponencial, con motor .NET regex + emulación ECMAScript)


14

JavaScript (ES6), 30 29 28 bytes

Espera un entero positivo. Devoluciones -1por falsedad y -2por verdad.

f=(n,k=2)=>n>1?f(n/k,k+1):~n

console.log(1,  '-->',f(1))   // Truthy (0! or 1!)
console.log(2,  '-->',f(2))   // Truthy (2!)
console.log(3,  '-->',f(3))   // Falsey
console.log(4,  '-->',f(4))   // Falsey
console.log(5,  '-->',f(5))   // Falsey
console.log(6,  '-->',f(6))   // Truthy (3!)
console.log(7,  '-->',f(7))   // Falsey
console.log(8,  '-->',f(8))   // Falsey
console.log(24, '-->',f(24))  // Truthy (4!)
console.log(120,'-->',f(120)) // Truthy (5!)

Nota : Esta función admite entradas bastante grandes (debe leer esto como: 'bastante grande para JS'). Debería funcionar de forma segura hasta 2 53 - 1 . Con seguridad comenzará en N = 121,645,100,408,831,992 , ¡esta entrada se redondeará a 19! = 121,645,100,408,832,000 debido a su codificación IEEE-754. No puede haber otros resultados positivos falsos antes 121.645.100.408.831.991 debido a errores de redondeo, pero no lo sé a ciencia cierta.


Agradable, me gusta mucho el uso ~al final.
Steve Bennett

¿Puedes editar para que yo pueda cancelar la votación? (Si desea saber por qué downvoted, es porque me había olvidado de las reglas I / O inusuales de esta pregunta.)
CalculatorFeline

@Arnauld Undownvoted.
CalculatorFeline

11

Python 3 , 39 38 bytes

f=lambda n,i=1:n>1and f(n/i,i+1)or n<1

Una función recursiva teniendo un número entero, n, devolviendo un valor booleano inversley que representa el resultado (Truthy: False, Falsey: True)

Pruébalo en línea!

Se divide repetidamente nentre i, con un valor inicial de 1, hasta que el resto sea menor o igual que 1luego, compruebe si ese resto es menor 1, solo los factoriales terminarán con un resto igual a 1, y <es un byte más corto que ==.


@ovs nos hemos restringido a dos salidas consistentes. Desafortunadamente, eso devuelve 1todos los factoriales, excepto los 1que devuelve True.
Jonathan Allan

11

Java 8, 46 bytes

i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;}

Esto se basa en la entrada de Roman Gräf de la que pude eliminar una docena de bytes. ¡Lo habría sugerido allí, pero todavía no tengo suficiente reputación para comentar! Mi código de corredor de prueba modificado:

import java.util.function.Function;
import java.util.stream.IntStream;

public class IsFactorial {
    public static Function<Integer, Boolean> isFactorial = i->{int j=1,c=0;for(;j<i;j*=++c);return j==i;};
    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};
    public static void main(String[] args){
        System.out.println(
            IntStream.of(truthyCases).allMatch(i->isFactorial.apply(i)) &&
            IntStream.of(falsyCases).allMatch(i->!isFactorial.apply(i)));
    }
}

9

Retina , 50 38 bytes

12 bytes guardados gracias a @Neil al combinar acortar el ciclo y deshacerse del ;

.+
1¶$&$*
+`^(1+)¶(\1)+$
1$1¶$#2$*
¶.$

Pruébalo en línea!

Salidas 1para verdadero y 0para falso.

.+ coincide con el número entero

1¶$&$*reemplazándolo por 1seguido de una nueva línea y el partido convertido a unario

El programa restante divide el número unario en la línea inferior al aumentar sucesivamente los enteros positivos, se mantiene un seguimiento en la línea superior, mientras que es posible hacerlo.

+` bucle hasta que la cadena permanezca igual

  • ^(1+)¶(\1)+$haga coincidir la línea superior con muchos 1sy un múltiplo de muchas 1s en la línea inferior y reemplácela con

  • 1$1¶$#2$*la línea superior muchos 1s con otra 1, es decir, aumentar el número representado por la línea superior en 1, seguido de la nueva línea y el número de coincidencias de la línea superior en la línea inferior (es decir, conteo de coincidencias del segundo grupo de captura ) muchos 1s, es decir, dividiendo el número inferior por el número superior

Una vez que ya no sea posible hacerlo,

¶.$dar el número de coincidencias de esta expresión regular, es decir. ¿existe un solitario 1en la línea de fondo, que solo sucede si el número es un factorial


Si se permite no-crash / crash en lugar de valores de verdad / falsedad, entonces puedo obtener 36 34 bytes.

^
1¶
{`.+$
$*
^(1+)¶(\1)+$
1$1¶$#2

Esto sigue el mismo enfoque, pero combina las $*líneas tercera y cuarta. La tercera línea en adelante es parte del mismo bucle, {es la abreviatura de +(donde (agrupa las líneas restantes en el bucle. Los factoriales terminan en el programa saliendo del bucle, mientras que los no factoriales se atascan en el bucle para siempre hasta que Retina lanza una excepción de desbordamiento causada por la última falla de reemplazo, por lo que la parte inferior está en unario en lugar de en decimal, y el primer reemplazo del bucle convierte la línea inferior de decimal a unario, por lo que explota rápidamente.


Guarde un byte quitando el 1como está implícito cuando $*está al final del reemplazo.
Neil

Mejor aún, combine el $*con las otras dos líneas.
Neil


3
Estoy impresionado de que hayas encontrado una manera de bloquear a Retina condicionalmente. :)
Martin Ender

2
¿Puedes agregar una explicación?
CalculatorFeline

8

05AB1E , 4 bytes

L!QO

Pruébalo en línea!

Explicación

L      # range [1 ... input]
 !     # calculate factorial of each
  Q    # compare with input for equality
   O   # sum

1
¿No necesitarías duplicar la entrada primero porque Laparece su entrada? Además, Å!le brinda una lista de factorial menor o igual que la entrada.
Neil A.

@NeilA. Afortunadamente, la entrada vuelve a aparecer si no hay suficientes argumentos en la pila para una operación, por lo que no necesito Daquí. Buena captura sobre Å!. Siempre me olvido de los comandos de lista. No guardará ningún byte, pero es más eficiente con seguridad.
Emigna

No sabía que la entrada volvía a aparecer ... eso seguro podría ahorrar muchos bytes.
Neil A.

@NeilA. Es una característica bastante nueva. Fue agregado hace menos de un mes, creo.
Emigna

8

C ++, 102 100 92 Bytes

#include<cmath>
int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}

Loops a través de todos los valores de 0a ny calcula los controles factoriales y luego, si es igual a n.

Gracias Christoph! (guardado 8 bytes)


¡Hola! Bienvenido a PPCG! Buena primera respuesta! ¡Buena suerte en el futuro!
Arjun

Buena primera respuesta! Usted puede ahorrar unos pocos bytes de la siguiente manera: int a(int n){int i=n,j=0;for(;i;)j|=lround(exp(lgamma(i--+1)))==n;return j;}. lroundy lgammaya son C ++ 11, así que simplemente podría #include<cmath>. Tal vez puedas mejorar aún más mis sugerencias :)
Christoph

7

Haskell , 43 26 bytes

f n=elem n$scanl1(*)[1..n]

Pruébalo en línea!

  • Guardado 17 bytes, gracias a Laikoni

2
f n=elem n$scanl1(*)[1..n]Es ridículo ineficiente pero más corto.
Laikoni

¿No hay alguna regla sobre la eficiencia del código?
sudee

1
Ninguno que yo sepa. code-golf pide una solución en la menor cantidad de bytes posible sin ninguna declaración de eficiencia. También en mi máquina la función funciona 40430sin demora notable.
Laikoni

Me refería a algo como "la solución debería terminar dentro de un plazo razonable", pero supongo que se ajusta a los requisitos de cualquier manera. ¡Gracias!
sudee

1
Agradable y simple Pensé que podía hacerlo mejor con la división, digamos, divModpor [1..]sucesivamente hasta llegar a un resto de cero con un cociente de 1 (factorial) o un resto distinto de cero (no factoriales), pero no parece ser el enfoque correcto. Lo que encontrar esta solución linda 46 caracteres, sin embargo: f|let x%n=mod n x==0&&(x+1)%div n x||n==1=(1%).
Jon Purdy

6

Haskell , 38 bytes

m#n=n<2||mod n m<1&&(m+1)#div n m
(2#)

Pruébalo en línea! Ejemplo de uso: (2#) 24. Devoluciones Trueo False.

Esto es lo más corto que pude obtener sin dejar de ser muy eficiente. Incluso para números tan grandes como

145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000

El resultado se da de inmediato. La solución funciona dividiendo la entrada npor m = 2,3,4,5,...hasta que el resultado sea uno o nno sea divisible entre m.

Para la solución más corta pero increíblemente ineficiente de 26 bytes que calcula las n!entradas que no son factoriales, mire aquí .



5

Fourier , 40 39 bytes

I~Q1~N(i^~i*N~N{Q}{1~Xo}N>Q{1}{1~X0o}X)

Pruébalo en FourIDE!

Básicamente multiplica el número N por una cantidad creciente hasta que N sea igual a (salida 1) o mayor que (salida 0) la entrada.

Explicación Pseudocódigo:

Q = Input
N = 1
While X != 1
    i += 1
    N = N*i
    If N = Q Then
        Print 1
        X = 1
    End If
    If N > Q Then
        Print 0
        X = 1
    End If
End While

5

Japt , 8 6 bytes

ol x¥U

Pruébalo en línea!

Esto genera 0 para falso y 1 para verdadero.

Explicación

 ol x¥ U
Uol x==U
Uo       # Create the range [0 ... input]
  l      # Replace each element by its factorial
     ==U # Compare each element to the input (yielding 1 if equal and 0 otherwise)
    x    # And sum the result

1
Realmente debería agregar un "contiene" incorporado: P
ETHproductions

1
Oh, bueno, usted podría cambiar aU ¦Ja x¥U(mapear cada Xa X==Uy suma), a pesar de que no funcionará en TIO.
ETHproductions

Las fallas por 2causa osolo te darán [0,1]. Aquí hay una solución con un ahorro de 1 byte.
Shaggy

4

Perl 5, 31 bytes

$a=<>;$a/=++$i while$a>1;exit$a

La entrada se toma a través de STDIN, la salida se da a través del código de salida (1 para factorial, 0 para no factorial).

La entrada se divide por enteros sucesivos hasta que sea 1 o una fracción menor que uno, que se trunca en el resultado.


-5 bytes TIO
Nahuel Fouilleul

4

Perl 6 , 29 bytes

{($_,{$_/++$}...2>*).tail==1}

Pruébalo

Expandido:

{   # bare block lambda with implicit parameter 「$_」

  (              # generate a sequence

    $_,          # starting with the input

    {
      $_ / ++$   # divide previous element by an ever increasing number
                 # 1,2,3,4,5,6,7,8 ... *
    }

    ...          # keep generating until

    2 > *        # 2 is greater than what was generated
                 # ( 1 or a fractional number )

  ).tail == 1    # check if it ended at 1
}

17 bytes: {$_∈[\*] 1..$_}. Otro enfoque interesante es 2>*.polymod(1..*).sum.
nwellnhof el

4

setlX , 32 bytes

f:=n|=>exists(x in{0..n}|n==x!);

Crea una función llamada fdonde usa su factorial potencial como parámetro.

Funciona con un tamaño entero arbitrario, pero es bastante ineficiente.

(por cierto: esta es mi primera participación en un rompecabezas de programación)




4

C # (.NET Core) , 68 bytes

bool f(System.Numerics.BigInteger n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

Pruébalo en línea!

No es la solución más corta, pero funciona con números realmente grandes. El enlace TIO incluye un ejemplo con 10000!.

Aquí hay una versión más corta que usa intque tiene un valor máximo de 2147483647 .

C # (.NET Core) , 45 bytes

bool f(int n,int k=2)=>n<2||n%k<1&f(n/k,k+1);

Pruébalo en línea!

¡Crédito a @KevinCruijssen por jugar 3 bytes en total en ambas respuestas!


2
Se &&puede jugar al golf &, y el seguimiento ;no tiene que contarse para las funciones lambda. Además, ¿no puede ulong k=2estar uint k=2en su respuesta de 50 bytes?
Kevin Cruijssen

1
Buena captura en la &frente &&. Pensé que estaba teniendo un desbordamiento de pila, pero parece funcionar después de todo. ulonges de 64 bits mientras que uintes de 32. Parece que otros lo están usando, intasí que tal vez lo usaré para la versión corta. Con respecto al seguimiento ;, estas son funciones completas, no lambdas, ¿así que creo que necesito incluirlas?
dana

Es realmente extraño cómo .NET puede resolver /y %entre ulongy uint, pero no ulongy int. No sabía eso :)
dana

1
@Oliver - Con doubleusted comienza a ver redondeo en algún momento, por ejemplo, ¡24! y 120! fallar. Si bien System.Numerics.BigIntegertiene la mayor precisión, intes la respuesta más corta :)
dana

1
@Deadcode: tienes razón acerca de 0 :) Según los ejemplos del desafío, interpreté que "números naturales" significan 1,2, ... Estoy de acuerdo en que en el mundo real, es mejor usar el &&operador de cortocircuito . Pero este es el código de golf;) Me alegra que te guste el 10000!ejemplo.
dana

4

C ++ (clang), 51 bytes

La recursión gana en lo que respecta al golf.

51 bytes, cero es verdadero:

int f(int n,int i=2){return n<2?!n:n%i|f(n/i,i+1);}

Esto sacrifica bastante velocidad por 1 byte de ahorro. Reemplace |con ||para hacerlo más rápido, debido a la evaluación de cortocircuito del OR lógico.

Pruébalo en línea! (Versión lenta de 51 bytes) ¡
Pruébelo en línea! (Versión rápida de 52 bytes)

Versión lenta sin golf:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    // Because any nonzero value represents "false", using "|" here is equivalent
    // to "||", provided that the chain of recursion always eventually ends. And
    // it does always end, because whether or not "n" is factorial, the "n / i"
    // repeated division will eventually give the value of zero or one, satisfying
    // the above condition of termination.
    return (n % i) | isFactorial(n / i, i+1);
}

Versión rápida sin golf:

int isFactorial(int n, int i=2)
// returns 0 for true, and nonzero for false
{
    if (n < 2) // same as "if (n==0 || n==1)" in our natural number input domain
    {
        if (n==0)
            return 1; // not factorial
        else // n==1
            return 0; // is factorial (could be either 0! or 1!)
    }

    if (n % i != 0)
        return 1; // not factorial
    else
        return isFactorial(n / i, i+1);
}

Hay muchas formas de reorganizar esto.

52 bytes, distinto de cero es cierto:

int f(int n,int i=2){return n<2?n:n%i?0:f(n/i,i+1);}

Pruébalo en línea!

52 bytes, cero es verdadero:

int f(int n,int i=2){return!n?1:n%i?n-1:f(n/i,i+1);}

Pruébalo en línea!

Antes de recurrir a la recursión, intenté hacer algunas versiones iterativas, y se acercaron.

54 bytes, distinto de cero es cierto:

int f(int n){for(int i=2;n>1;)n=n%i?0:n/i++;return n;}

Pruébalo en línea!

54 bytes, cero es verdadero (basado en el envío de Java 8 de Roman Gräf ):

int f(int n){int a=1,i=0;for(;a<n;a*=++i);return a-n;}

Pruébalo en línea!

Ahora, para el fondo del barril, versiones recursivas sin n==0 manejo (considero que estos no son válidos, porque 0 es un número natural, y cualquier definición en la que no esté es para "números naturales" de uso muy limitado). En las versiones a continuación, la recursión infinita de f(0)cualquiera desencadena un defecto por desbordamiento de la pila, o con compiladores que lo optimizan para la iteración, bucles sin fin:

48 bytes, cero es verdadero:

int f(int n,int i=2){return n%i?n-1:f(n/i,i+1);}

Pruébalo en línea!

48 bytes, cero es verdadero (basado en el envío de 33 bytes C (gcc) de Hagen von Eitzen ):

int f(int n,int e=0){return n%++e?n-1:f(n/e,e);}

Pruébalo en línea!


50 EDIT: 49 , sin recursividad.
Grimmy

Volver a la recursividad para 48 . Y probablemente no le gustará esto, pero 44 al usar una var global.
Grimmy

3

Mathematica, 20 bytes

!FreeQ[Range[#]!,#]&

otra versión para probar números grandes (ver comentarios)

Range[10^3]!~MemberQ~#&

prueba hasta 1000!


2
Según tengo entendido la pregunta, ¡si Mathematica es capaz de tomar 1001! como entrada, entonces esto no cumple con las especificaciones.
Peter Taylor

2
Incluso podría guardar tres bytes mientras lo hace válido para todas las entradas. Simplemente reemplace 10 ^ 3 con #; podría guardar otro byte con el uso de Range @ #
Julien Kluge

@Julien Klugethen buscar 1243234 llevaría una eternidad ...
J42161217

1
Creo que puede guardar otro byte reemplazándolo Range[#]con Range@#:)
numbermaniac

3
Parece que se puede salvar a otro byte con la sintaxis infija: !Range@#!~FreeQ~#&.
numbermaniac

3

Cubix , 24 bytes

U0O@1I1>-?1u>*w;W;@Orq)p

Pruébalo en línea

Cubified

    U 0
    O @
1 I 1 > - ? 1 u
> * w ; W ; @ O
    r q
    ) p

Comenzamos empujando 1, Input, 1en la pila. Estos serán nuestro índice, nuestro objetivo y nuestro acumulador, respectivamente.

Luego hacemos un bucle. En cada iteración, restamos el acumulador de la entrada. Si el resultado es 0, hemos terminado, así que empujamos 1, Outilizamos y salimos. Si es negativo, hemos ido demasiado lejos, así que empujamos 0, Ohablamos y salimos. De lo contrario, vemos

;p)*rq;
;         Pop the difference off the stack.
 p)       Move the index to the top of the stack and increment it.
   *      Multiply the accumulator by the index to get the next factorial.
    rq;   Put the stack back in the right order.

3

Neim , 8 bytes

𝐈Γ𝐈𝐩₁𝔼)𝐠

Explicación:

Example input: 6
𝐈         Inclusive range [1 .. input]
          [1, 2, 3, 4, 5, 6]
 Γ        For each...
  𝐈         Inclusive range [1 .. element]
            [[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6]]
   𝐩        Product
            [1, 2, 6, 24, 120, 720]
     𝔼      Check for equality with
    ₁       the first line of input
            [[0, 0, 1, 0, 0, 0]]
      )   End for each
       𝐠  Select largest element
          [1]

¡Intentalo!

Neim , 3 bytes (no competitivos)

No competitivos ya que el token contiene y el token factorial se agregaron después de que se realizó el desafío.

𝐈𝐓𝕚

Explicación:

Example input: 6
𝐈     Inclusive range [1 .. input]
      [[1, 2, 3, 4, 5, 6]
 𝐓    Factorial each
      [[1, 2, 6, 24, 120, 720]]
  𝕚   Check that the [cycled] input is in the list
      [1]

¡Intentalo!


3

> <> , 24 22 bytes

-2 bytes gracias a @Aaron

Estoy probando un nuevo idioma (ya que mi licencia de Mathematica expiró ...)

01\{=n;
?!\$1+:@*:{:}(

Pruébelo en línea o en el área de juegos para peces

Asume que el número de entrada ya está en la pila y devuelve 0 o 1. Funciona multiplicando juntos los primeros n números hasta que deje de ser menor que la entrada, y luego imprima 1 si es igual a la entrada y 0 si no lo hace. t.


Podrías transformarte v>\n<^en \\n/; ver aquí
Aaron

@ Aaron, eso es genial, ¡gracias!
No es un árbol

3

APL (Dyalog Unicode) , 5 6 7 bytes

Golfé un byte cambiando ×/a !gracias a Erik the Outgolfer

⊢∊!∘⍳

Pruébalo en línea!

Explicación

                          Range of numbers from 1 to argument, 1 2 3 4 .. n
   !                       Factorial; 1! 2! 3! 4! .. n!
⊢∊                         Is the right argument a member of this list?

Suma acumulativa?
Leaky Nun

@LeakyNun solucionado
Kritixi Lithos

Un byte extra en GNU APL 1.2 N∊×\⍳N←⎕¿Cómo toma esto un argumento? No veo por nningún lado. ¿Es esto algo específico de Dyalog?
Arc676

2
@ Arc676 Mi solución es un tren y lo llamas así: (⊢∊(×/⍳)) right_argumentcomo puedes ver en el enlace TIO. Y el se refiere al argumento correcto.
Kritixi Lithos

Notas: AGL le ahorrará un byte; ⊢∊×\ä⍳. La solución "correcta" (pero más larga) sería 0=1|!⍣¯1; "¿Es el factorial inverso un entero?"
Adám

2

JavaScript (ES6), 71 bytes

Esto toma la entrada como argumento de función y alerts la salida. Salidas 0para falsey y 1para la verdad.

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}alert(r)}

Explicación

El programa consta de dos funciones, fy g. fes una función recursiva de computación factorial y ges la función principal del programa. g se supone que tiene un solo argumento n. Define un argumento predeterminado rcon un valor de 0 y otro argumento predeterminado con un valor de 0. Luego, itera sobre todos los números enteros de 0 a ny, en cada iteración, verifica si la función faplicada sobre i(el índice actual) es igual n, es decir, si nes un factorial de i. Si ese es el caso, rel valor se establece en 1. Al final de la función, rse alertedita.

Fragmento de prueba

( Nota: el fragmento sale console.log()como nadie le gusta a muchos de esos molestosalert() ) .

f=n=>n?n*f(n-1):1;g=(n,r=0,i=0)=>{while(i<=n){r=f(i)==n|r;i++}console.log(r)}

g(1)
g(2)
g(3)
g(4)
g(5)
g(6)
g(7)
g(8)
g(24)
g(120)


Eval puede ser más corto que usar un bloque de código.
Downgoat

@Downgoat ¿Cómo debo hacer eso? Lo siento si es demasiado obvio! : P
Arjun

2

QBIC , 21 19 bytes

[:|q=q*a~q=b|_x1}?0

Explicación

[:|     Start a FOR loop from 1 to n
q=q*a   q starts as 1 and is multiplied by the FOR loop counter
        consecutively: q=1*1, *2, *3, *4 ... *n
~q=b|   If that product equals n
_x1     Then quit, printing a 1
}       Close the IF and the FOR
?0      If we're here, we didn't quit early and didn't find a factorial, print 0

Previamente

[:|q=q*a┘c=c+(q=b)}?c

Explicación:

[:|         Start a FOR loop from 1 to n
q=q*a       q starts as 1 and is multiplied by the FOR loop counter
            consecutively: q=1*1, *2, *3, *4 ... *n
┘           Syntactic line break
c=c+        c starts out at 0 and then keeps track of 
    (q=b)       how often our running total == n
}           Closes the FOR-loop
?c          Print c, which is 0 fir non-factorials and -1 otherwise.

2

Java 8, 59 bytes

i->{for(int j=1,c=0;j<=i;j*=++c)if(j==i)return 1;return 0;}

Código de prueba

import java.util.function.IntFunction;
import java.util.stream.IntStream;

public class IsFactorial
{
    public static IntFunction<Integer> isFactorial = i->
    {
        for(int j=1,c=0;j<=i;j*=++c)
            if(j==i)return 1;return 0;
    };

    public static int[] truthyCases = {1,2,6,24,120};
    public static int[] falsyCases = {3,4,5,7,8};

    public static void main(String[] args)
    {
        System.out.println
        (
            IntStream.of(truthyCases)
                .allMatch(i->isFactorial.apply(i)==1)
            && IntStream.of(falsyCases)
                .allMatch(i->isFactorial.apply(i)==0)
        );
    }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.