2012-03-07 10 views
5

Lo siguiente tendrá más sentido si alguna vez has jugado Minecraft. Como muchos de ustedes no lo han hecho, intentaré explicarlo de la mejor manera posiblePython Recursive Data Reading

Estoy tratando de escribir una función recursiva que pueda encontrar los pasos para elaborar cualquier elemento de Minecraft a partir de un archivo plano de recetas de Minecraft. Este me tiene realmente perplejo.

El archivo plano es un poco largo, así que lo incluí en this gist.

def getRecipeChain(item, quantity=1): 
    #magic recursive stuffs go here 

Así que básicamente tienen que buscar la primera receta a continuación, buscar las recetas para todos los componentes de esa primera receta y así sucesivamente hasta llegar a los elementos sin recetas. Cada vez que necesito para anexar la receta a una lista de lo que obtener una especie de juego de instrucciones de lo que el fin de artículos de artesanía en.

Así que aquí es la función que tengo ahora (la que el no funciona)

def getRecipeChain(name, quantity=1): 
    chain = [] 

    def getRecipe(name1, quantity1=1): 
     if name1 in recipes: 
      for item in recipes[name1]["ingredients"]["input"]: 
       if item in recipes: 
        getRecipe(item, quantity1) 
       else: 
        chain.append(item) 

    getRecipe(name, quantity) 
    return chain 

Aquí está la salida ideal que estoy buscando. Es un diccionario con el nombre del elemento y la cantidad almacenada en él.

>>> getRecipeChain("solar_panel", 1): 
{"insulated_copper_cable":13, "electronic_circuit":2, "re_battery":1, "furnace":1, "machine":1, "generator":1, "solar_panel":1} 

Entonces la pregunta es, ¿cómo lo hago?

Sé que pedirle a la gente que trabaje para usted está mal visto aquí, así que si siente que esto está demasiado cerca de usted solo para hacer la codificación, dígalo.

+2

Simplemente decir, pero creo que su salida de la muestra no está bien ... – PearsonArtPhoto

+0

En qué sentido es incorrecto? – giodamelio

+2

Bueno, insulated_copper_cable no es un elemento base, ¿verdad? Ni es electronic_circuit. Parece que quieres obtener los ingredientes básicos, no los complejos. – PearsonArtPhoto

Respuesta

3

Esto se puede resolver con elegancia utilizando collections.Counter, que apoya además:

from collections import Counter 

def getRecipe(name, quantity=1): 
    if not name in recipes: return Counter({name: quantity}) 

    subitems = recipes[name]["ingredients"]["input"] 
    return sum((getRecipe(item, quantity) for item in subitems), 
      Counter()) 

print repr(dict(getRecipe("solar_panel"))) 
# => {'copper': 39, 'refined_iron': 10, 'glass': 3, 
#  'rubber': 78, 'cobblestone': 8, 'tin': 4, 
#  'coal_dust': 3, 'nothing': 10, 'redstone': 6} 
1

Creo que el problema es 2 veces. En primer lugar, debe agregar los elementos a la cadena en la llamada recursiva a getRecipe(). En segundo lugar, creo que las dos funciones complican innecesariamente las cosas. Creo que solo el interno debería hacer. Algo como esto es lo que estás buscando. No lo he probado, pero debe estar lo suficientemente cerca como para comenzar por el camino correcto.

def getRecipe(name, quantity=1): 
    chain=[]; 
    if name in recipes: 
     for item in recipes[name]["ingredients"]["input"]: 
      if item in recipes: 
       chain.append(getRecipe(item, quantity)) 
      else: 
       chain.append(item) 
    return chain 

EDIT: Los comentarios están llenando mi falta de conocimiento de Python, así que aquí hay una mejor solución.

from collections import Counter 
def getRecipe(name, quantity=1, count=Counter()): 
    if name in recipes: 
     for item in recipes[name]["ingredients"]["input"]: 
      if item in recipes: 
       getRecipe(item, quantity,counter) 
      else: 
       counter[item]+=quantity 
    return counter 
+0

Su salida deseada es un dict, así que en lugar de chain.append, debe hacer * chain.setdefault (item, 0) + = quantity * –

+0

@campos: Esto no funcionará como se esperaba, el valor no se incrementará. Un 'defaultdict (int)' sería la estructura de datos ideal aquí. –

+0

oops, eso es cierto. –