Encontrar perímetros de triángulos rectos con patas de longitud entera, hasta un límite -- python campo con combinatorics camp codereview Relacionados El problema

Finding perimeters of right triangles with integer-length legs, up to a limit


5
vote

problema

Español

Tengo un 99887766655544330 -loop que llena una lista con elementos:

  a = [] for i in range(1, limit+1):     for j in range(1, limit+1):         p = i + j + (i**2 + j**2)**0.5         if p <= limit:             a.append(p)   

Podría refactarlo en la lista de la lista:

  a = [i + j + (i**2 + j**2)**0.5      for i in range(1, limit+1)      for j in range(1, limit+1)      if i + j + (i**2 + j**2)**0.5 <= limit]   

Pero ahora la misma expresión compleja está en ambas partes, lo que es inaceptable. ¿Hay alguna forma de crear una lista de una manera funcional, pero más elegante?

Supongo que en Lisp Idría la recursión con let . ¿Cómo se hace en idiomas más funcionales como Clojure, Scala, Haskell?

En la raqueta, es posible vincular expresiones dentro de un for/list comprensión. He encontrado una solución a mi problema:

  [k  for i in range(1, limit+1)  for j in range(1, limit+1)  for k in [i + j + (i**2 + j**2)**0.5]  k <= limit]   

No estoy seguro de cómo es Pythonic.

Original en ingles

I have a nested for-loop that populates a list with elements:

a = [] for i in range(1, limit+1):     for j in range(1, limit+1):         p = i + j + (i**2 + j**2)**0.5         if p <= limit:             a.append(p) 

I could refactor it into list comprehension:

a = [i + j + (i**2 + j**2)**0.5      for i in range(1, limit+1)      for j in range(1, limit+1)      if i + j + (i**2 + j**2)**0.5 <= limit] 

But now the same complex expression is in both parts of it, which is unacceptable. Is there any way to create a list in a functional way, but more elegantly?

I guess in Lisp I would use recursion with let. How it is done in more functional languages like Clojure, Scala, Haskell?

In Racket it's possible to bind expressions inside a for/list comprehension. I've found one solution to my problem:

[k  for i in range(1, limit+1)  for j in range(1, limit+1)  for k in [i + j + (i**2 + j**2)**0.5]  k <= limit] 

I'm not sure how pythonic it is.

     
 
 

Lista de respuestas

3
 
vote
vote
La mejor respuesta
 

En el caso general, la respuesta de Jeff es el camino a seguir: generar luego filtrar.

Para su ejemplo particular, ya que la expresión está aumentando WRT ambas variables, debe detenerse tan pronto como alcance el límite.

  assertThrows()7  

Ahora, proporcionar este assertThrows()8 es un error propenso y bastante ad-hoc. Queremos mantener la condición de parada según el valor calculado. En su solución imperativa, agregue assertThrows()9 cuando else0 haría el trabajo. Encontremos un equivalente funcional:

  else1  
 

In the general case, Jeff's answer is the way to go : generate then filter.

For your particular example, since the expression is increasing wrt both variables, you should stop as soon as you reach the limit.

def max_value(limit, i) :    """return max positive value one variable can take, knowing the other"""    if i >= limit :       return 0    return int(limit*(limit-2*i)/(2*(limit-i)))  def collect_within_limit(limit) :    return [ i + j + (i**2 + j**2)**0.5               for i in range(1,max_value(limit,1)+1)               for j in range(1,max_value(limit,i)+1) ] 

Now, providing this max_value is error prone and quite ad-hoc. We would want to keep the stopping condition based on the computed value. In your imperative solution, adding break when p>limit would do the job. Let's find a functional equivalent :

import itertools  def collect_one_slice(limit,i) :    return itertools.takewhile(lambda x: x <= limit,             (i + j + (i**2 + j**2)**0.5 for j in range(1,limit)))  def collect_all(limit) :    return list(itertools.chain(*(collect_one_slice(limit, i)                                         for i in range(1,limit)))) 
 
 
3
 
vote

Puede reescribirlo con dos comprensiones separadas. Uno para generar los valores y uno para filtrarlos. Puede usarla else2 para obtener El producto cartesiano.

  else3  
 

You can rewrite it with two separate comprehensions. One to generate the values and one to filter them out. You can use itertools.product to get the cartesian product.

a = [x for x in (i + j + (i**2 + j**2)**0.5                  for i, j in itertools.product(range(1, limit+1), repeat=2))      if x <= limit] 
 
 

Relacionados problema

15  Cracker de contraseña de fuerza bruta  ( Brute force password cracker ) 
Escribí este script para una prueba de concepto JavaScript Password Cracker: var charset = " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_...

10  Función recursiva que genera las permutaciones de una cadena  ( Recursive function that generates the permutations of a string ) 
Estoy buscando una revisión de mi función recursiva que genere las permutaciones de una cadena. ¿Hay mejores formas de hacer esto? var permutations = []; ...

1  Encuentra triángulos de la línea  ( Find triangles from line ) 
Tengo algunas líneas que forman triángulos. Me gustaría desafiar la forma más rápida de encontrar todos los triángulos. En particular, el código debe tom...

1  Imprima todos los tamaños posibles de subsecuencias de cadena en C  ( Print out all possible sizes of subsequences of string in c ) 
Por ejemplo, dada una cadena "abcdefghijk", quiero que mi función se imprima: a, b, c, d, e, f, g, h, i, j, k. ab, bc, cd, de, ef, fg, gh, hi, ij, jk ab...

1  Encuentra la frecuencia de combinaciones en un gran conjunto de datos  ( Find frequency of combinations in large data set ) 
Mi preocupación es el rendimiento del Código. Se tarda mucho más de lo que me gustaría. Estaría dispuesto a renunciar a un poco de memoria para un mayor rendi...

7  Generar un diccionario de contraseñas  ( Generate a dictionary of passwords ) 
Tengo un script de Python que genera un diccionario de todas las combinaciones de contraseña posibles de 3 dígitos. Esencialmente funciona solo en la anidació...

3  Encuentra todas las combinaciones distintas de letras en una cadena  ( Find all distinct combinations of letters in a string ) 
Me he estado preparando para las entrevistas y recogiendo moderno C ++. Una pregunta reciente que hice fue encontrar todas las combinaciones (o subconjuntos d...

4  Permodificar codility  ( Permcheck codility ) 
El siguiente código obtiene un 100% en el Permdeck tarea en la CODILIDAD . Debe ser O (n). La pregunta es: Se da una matriz no vacía que consta de n ent...

1  Reto de primos consecutivos en Codeeeval.com  ( Consecutive primes challenge at codeeval com ) 
Estoy trabajando a través de un nuevo desafío en Codeeeval.com y creo que estoy obteniendo un resultado correcto, pero no puedo pasar por su alumnador. No est...

3  Mi implementación de permutación lexicográfica en F # es 3x más lenta que C #  ( My implementation of lexicographic permutation in f is 3x slower than c ) 
¿Puede alguien ayudarme con la siguiente micro optimización para el código F # para la permutación lexicográfica? Tengo código en C # que se ejecuta para 0,...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos