Cómo refactorizar esto en J?
-
21-09-2019 - |
Pregunta
Mi solución novato para Proyecto Euler # 1
+/((0=3|1+i.1000-1) +. (0=5|1+i.1000-1)) * (1+i.1000-1)
Sé que esto puede ser reprogramado, y se transforma en una función, que no sé cómo hacerlo, y que tendría que leer todos los laboratorios para aprenderlo.
Solución
No es necesario "manejar cero" debido a la adición de cero no va a cambiar la respuesta por lo que sólo puede utilizar i.
para generar la lista de números inferiores a 1000, por ejemplo:
i. 10
0 1 2 3 4 5 6 7 8 9
J funciona mejor con matrices de lo que debería ser capaz de pedir el residuo (|
) de 3 y 5, al mismo tiempo, puede utilizar rango ("
) para controlar cómo los argumentos son alimentados a los residuos:
3 5 |"0 1 i. 10
0 1 2 0 1 2 0 1 2 0
0 1 2 3 4 0 1 2 3 4
El |"0 1
dice para alimentar el argumento de la izquierda a una |
-elemento-en-un-tiempo, mientras que la alimentación de los argumentos adecuados una línea-en-un-tiempo. Debido a que el argumento de la derecha sólo se compone de una línea, que se alimenta varias veces para cada uno de los artículos argumento izquierdo.
Ahora podemos hacer el 0=
a todo el conjunto:
0 = 3 5 |"0 1 i. 10
1 0 0 1 0 0 1 0 0 1
1 0 0 0 0 1 0 0 0 0
Insertar una condición OR entre los dos elementos (líneas) de la matriz:
+./ 0 = 3 5 |"0 1 i. 10
1 0 0 1 0 1 1 0 0 1
Obtener el índice de cada 1 en la lista / vector:
I. +./ 0 = 3 5 |"0 1 i. 10
0 3 5 6 9
Y suma:
+/ I. +./ 0 = 3 5 |"0 1 i. 10
23
Puede hacer esto una función explícita / verbo con bastante facilidad:
euler1=: verb define
+/ I. +./ 0 = 3 5 |"0 1 i. y
)
O, una vez que el cuelgue de J tácita se podría definir:
euler1=: +/@I.@(+./)@(0 = 3 5 |"0 1 i.)
Otros consejos
-
0=
Refactor (voluntad aumenta el tamaño del programa)
+/((3|1+i.1000-1)+.&(0=])5|1+i.1000-1)*1+i.1000-1
- Refactor
1+i.1000-1
+/(((3|])+.&(0=[)5|])1+i.1000-1)*1+i.1000-1
- Refactor
1+i.1000-1
nuevo
+/(*(3|])+.&(0=[)5|])1+i.1000-1
La única cosa que no podía refactor hasta ahora es el operador |