जीवन के कॉनवे के खेल को लागू करने के कार्यात्मक-प्रोग्रामिंग तरीके क्या हैं [बंद]


12

मैंने हाल ही में जावास्क्रिप्ट में कॉनवे के गेम ऑफ लाइफ को लागू किया (वास्तव में कॉफ़ीस्क्रिप्ट लेकिन यही बात)। चूंकि जावास्क्रिप्ट का उपयोग एक कार्यात्मक भाषा के रूप में किया जा सकता है जो मैं स्पेक्ट्रम के उस छोर पर रहने की कोशिश कर रहा था। मैं अपने परिणामों से खुश नहीं था। मैं एक काफी अच्छा OO प्रोग्रामर हूं और मेरा समाधान पुराने-पुराने समान-समान है। इतना लंबा प्रश्न छोटा: इसे करने की कार्यात्मक शैली (छद्मकोश) क्या है?

यहाँ मेरे प्रयास के लिए स्यूडोकोड है:

class Node
  update: (board) ->
    get number_of_alive_neighbors from board
    get this_is_alive from board
    if this_is_alive and number_of_alive_neighbors < 2 then die
    if this_is_alive and number_of_alive_neighbors > 3 then die
    if not this_is_alive and number_of_alive_neighbors == 3 then alive

class NodeLocations
  at: (x, y) -> return node value at x,y
  of: (node) -> return x,y of node

class Board
  getNeighbors: (node) -> 
   use node_locations to check 8 neighbors 
   around node and return count

nodes = for 1..100 new Node
state = new NodeState(nodes)
locations = new NodeLocations(nodes)
board = new Board(locations, state)

executeRound:
  state = clone state
  accumulated_changes = for n in nodes n.update(board)
  apply accumulated_changes to state
  board = new Board(locations, state)


@Oded कि मेरे सिर पर निराशाजनक है। मैं मूल अवधारणाओं को पहचानता हूं लेकिन केवल मुश्किल से
जॉर्ज मौअर

मेरे सिर पर भी रास्ता ... मैंने इसे सिर्फ एक उदाहरण के रूप में पोस्ट किया है कि एक विशेष भाषा का एक मास्टर क्या कर सकता है। इसे हम सभी के लिए एक प्रेरणा
कहें

@GeorgeMauer "वास्तव में कॉफ़ीस्क्रिप्ट लेकिन एक ही बात है" यह दुखद दिन है
रेयनोस

जवाबों:


11

खैर, विचारों की एक जोड़ी। मैं एफपी में विशेषज्ञ नहीं हूं, लेकिन ...

यह बिल्कुल स्पष्ट है कि हमारे पास एक प्रकार होना चाहिए Boardजो एक खेल राज्य का प्रतिनिधित्व करता है। कार्यान्वयन का आधार evolveप्रकार का एक कार्य होना चाहिए evolve :: Board -> Board; यह Boardखेल के नियमों को लागू करने से एक पैदा करता है Board

हमें कैसे लागू करना चाहिए evolve? A Boardको शायद s का एक nxm मैट्रिक्स होना चाहिए Cell। हम एक cellEvolveप्रकार के फ़ंक्शन को लागू कर सकते हैं, cellEvolve :: Cell -> [Cell] -> Cellजो एक दिया गया है Cellऔर उसके पड़ोसी राज्य अगले पुनरावृत्ति में राज्य की Cellगणना करता है Cell

हमें एक getCellNeighborsफ़ंक्शन को भी लागू करना चाहिए जो कि एक Cellपड़ोसी को एक से निकालता है Board। मैं इस पद्धति के हस्ताक्षर के बारे में पूरी तरह सुनिश्चित नहीं हूं; उदाहरण के लिए , आप कैसे लागू करते हैं Cellऔर Boardआपके पास हो सकता है getCellNeighbors :: Board -> CoordElem -> CoordElem -> [Cell], जो एक बोर्ड और दो निर्देशांक देता है ( CoordElemएक में अनुक्रमणिका पदों के लिए इस्तेमाल किया जाने वाला प्रकार होगा Board), आपको पड़ोसियों की एक चर लंबाई सूची देता है (बोर्ड की सभी कोशिकाओं में नहीं है) पड़ोसियों की एक ही संख्या- कोनों में 3 पड़ोसी, सीमा 5 और बाकी सभी, 8) हैं।

evolveइस प्रकार के संयोजन के द्वारा लागू किया जा सकता cellEvolveहै और getCellNeighborsबोर्ड में सभी कक्षों के लिए, फिर से सही कार्यान्वयन आप कैसे लागू पर निर्भर करेगा Boardऔर Cell, लेकिन ऐसा लगता है "वर्तमान बोर्ड में सभी कक्षों के लिए, अपने पड़ोसियों हो और गणना करने के लिए उन्हें इस्तेमाल कुछ किया जाना चाहिए नए बोर्ड के संबंधित सेल '। यह "बोर्ड के सेल फ़ंक्शन पर नक्शा" का उपयोग करके पूरे बोर्ड पर उन कार्यों के एक सामान्य अनुप्रयोग के साथ करना संभव है।

अन्य विचार:

  • आपको वास्तव में cellEvolveइसे लागू करना चाहिए ताकि यह एक पैरामीटर के रूप में हो GameRulesजो एक प्रकार का खेल है जो खेल के नियमों को कूटबद्ध करता है- ट्यूल की सूची कहें (State,[(State,NumberOfNeighbors)],State)जो किसी दिए गए राज्य के लिए कहता है और प्रत्येक राज्य में पड़ोसियों की संख्या, जो अगले पुनरावृत्ति में राज्य होना चाहिए । cellEvolveतब हस्ताक्षर हो सकते हैंcellEvolve :: GameRules -> Cell -> [Cell] -> Cell

  • यह तार्किक रूप से आपको evolve :: Board -> Boardमोड़ बनाने में ले जाएगा evolve :: GameRules -> Board -> Board, ताकि आप evolveविभिन्न के साथ अपरिवर्तित उपयोग कर सकें GameRules, लेकिन आप एक कदम आगे बढ़ सकते हैं और cellEvolveइसके बजाय प्लग करने योग्य बना सकते हैं GameRules

  • getCellNeighborsआपके साथ खेलना भी 'की टोपोलॉजी के evolveसंबंध में सामान्य Boardहो सकता है- आप getCellNeighborsबोर्ड के किनारों, 3 डी बोर्ड आदि के चारों ओर लपेट सकते हैं ।


9

यदि आप जीवन का एक कार्यात्मक प्रोग्रामिंग संस्करण लिख रहे हैं, तो आप इसे Gosper के एल्गोरिथ्म के बारे में जानने के लिए खुद पर निर्भर हैं। यह एक पक्ष पर खरबों के बोर्ड खरबों पर प्रति सेकंड पीढ़ियों के खरबों को प्राप्त करने के लिए कार्यात्मक प्रोग्रामिंग के विचारों का उपयोग करता है । यह असंभव लगता है मुझे पता है, लेकिन यह पूरी तरह से संभव है; मेरे पास C # में एक अच्छा सा कार्यान्वयन है जो आसानी से एक तरफ वर्ग बोर्डों 2 ^ 64 वर्गों को संभालता है।

चाल समय और स्थान दोनों पर जीवन बोर्डों की भारी आत्म-समानता का लाभ उठाने के लिए है। बोर्ड के बड़े वर्गों के भविष्य की स्थिति को याद करके आप एक ही बार में बहुत बड़े वर्गों को तेजी से आगे बढ़ा सकते हैं।

मुझे लगता है कि अब कई वर्षों के लिए गोस्पर के एल्गोरिथ्म के लिए एक शुरुआती परिचय ब्लॉग के लिए किया गया है, लेकिन मेरे पास कभी समय नहीं था। अगर मैं ऐसा कर रहा हूं, तो मैं यहां एक लिंक पोस्ट करूंगा।

ध्यान दें कि आप जीवन संगणना के लिए गोस्पर के एल्गोरिथ्म को देखना चाहते हैं , न कि हाइपरोमेट्रिक रकम की गणना के लिए गोस्पर का एल्गोरिथम।


दिलचस्प लग रहा है - अभी भी उस लिंक की प्रतीक्षा कर रहा है ...;)
jk।

3

अच्छा संयोग है, हमने आज अपने हास्केल व्याख्यान में इस सटीक समस्या को कवर किया। पहली बार मैंने इसे देखा है, लेकिन यहाँ स्रोत कोड का लिंक दिया गया है:

http://pastebin.com/K3DCyKj3


क्या आप इस बारे में और अधिक व्याख्या करने का मन बना रहे हैं कि यह पूछे गए प्रश्न का उत्तर देने के लिए क्या करता है और इसकी अनुशंसा क्यों करता है? "केवल-लिंक का जवाब देता" काफी स्टैक एक्सचेंज पर स्वागत करते हैं नहीं कर रहे हैं
कुटकी

3

आप प्रेरणा के लिए RosettaCode पर कार्यान्वयन को देखना चाह सकते हैं ।

उदाहरण के लिए, कार्यात्मक हास्केल और ओकेएमएल संस्करण हैं जो पिछले एक फ़ंक्शन को लागू करके एक नया बोर्ड बनाते हैं, जबकि ग्राफिकल ओकेमेल संस्करण दो सरणियों का उपयोग करता है और उन्हें गति के लिए वैकल्पिक रूप से अपडेट करता है।

कुछ कार्यान्वयन पड़ोस को गिनने , जीवन के नियम को लागू करने और बोर्ड पर पुनरावृत्ति करने के लिए बोर्ड अपडेट फ़ंक्शन को विघटित करते हैं। वे एक कार्यात्मक डिजाइन को आधार बनाने के लिए उपयोगी घटकों की तरह लगते हैं। केवल बोर्ड को संशोधित करने का प्रयास करें, बाकी सभी को शुद्ध कार्यों के रूप में रखें।


1

यहाँ क्लोजर में एक छोटा विशुद्ध रूप से कार्यात्मक संस्करण है। सारा श्रेय क्रिस्टोफ ग्रैंड को जाता है जिन्होंने इसे अपने ब्लॉग पोस्ट: कॉनवे के गेम ऑफ लाइफ में प्रकाशित किया

(defn neighbours [[x y]]
  (for [dx [-1 0 1] 
        dy (if (zero? dx) [-1 1] [-1 0 1])]
    [(+ dx x) (+ dy y)]))

(defn step [cells]
  (set (for [[loc n] (frequencies (mapcat neighbours cells))
             :when (or (= n 3) (and (= n 2) (cells loc)))]
         loc)))

फिर खेल को "चरण" फ़ंक्शन को कोशिकाओं के एक सेट पर बार-बार लागू करके खेला जा सकता है, जैसे:

(step #{[1 0] [1 1] [1 2]})
=> #{[2 1] [1 1] [0 1]}

चतुराई (मैपकैट पड़ोसी कोशिकाएं) हिस्सा है - यह जो करता है वह सक्रिय कोशिकाओं में से प्रत्येक के लिए आठ पड़ोसियों की सूची बनाता है और उन सभी को एक साथ मिलाता है। फिर इस सूची में दिखाई देने वाली प्रत्येक सेल की संख्या (आवृत्तियों ....) के साथ गिना जा सकता है और अंत में जिन लोगों की सही आवृत्ति होती है, वे इसे अगली पीढ़ी के माध्यम से बनाते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.