2012-11-14 31 views
5

मेरे दोस्त ने एक कार्यक्रम लिखा है जो सबसे समान रूप से वितरित चेहरे वाले व्यक्ति को खोजने के लिए मरने वाले चेहरों की यादृच्छिक व्यवस्था की तुलना करता है - खासकर जब चेहरे केवल अनुक्रम नहीं होते हैं।हास्केल युक्तियाँ/इस पैमाने पर रैखिक रूप से क्यों नहीं है?

मैंने अपने कार्यक्रम को हैकेल में अनुवादित किया क्योंकि मैं किसी के कान से बात करने का कोई कारण ढूंढ रहा हूं कि कितना ठंडा हैकेल है। हालांकि, मैं हैकेल के साथ बहुत कुशल नहीं हूं (यह मुझे हमेशा लिखने के लिए ले गया है और इसमें दो विशाल रिफैक्टरिंग हैं) और इसलिए मुझे दो समस्याएं हैं।

  1. वह अपने संस्करणों को अनुकूलित करने में बड़ा रहा है, और यह बहुत तेज़ नहीं है, और यह रैखिक रूप से स्केल नहीं करता है। क्या मैंने कुछ पूंछ रिकर्सन गड़बड़ कर दी है या क्या यह किसी तरह की बड़ी समस्या है?
  2. इस कोड से निकलने वाला कोड वास्तव में उतना ही सुरुचिपूर्ण नहीं है जैसा मैंने भविष्यवाणी की थी। मैं जानता हूँ कि यह एक चर्चा बोर्ड नहीं है, लेकिन यह कैसे सरल करने के लिए अगर आप पर कोई विचार है मैं कर रहा हूँ सब कान

यह सबसे अधिक प्रासंगिक कोड है:

-- _CENTERS :: [{ x :: Float, y :: Float, z :: Float}] 
-- _VALUES :: [Num] 

-- Basically just (repeat $ map rand [0.._SIDES]), but never using a seed twice 
randstates from = (take _SIDES (infrand from)) : randstates newseed 
    where infrand seed = seed : infrand (shuffle seed) 
      newseed  = (infrand from) !! (_SIDES + 1) 

-- yates shuffle 
yates _ (last:[]) = [last] 
yates (rand:pass) (swap:order) = choice:yates pass rorder 
     where choice = order !! index 
       index = (randfrom rand) `mod` (length order) 
       rorder = take (index) order ++ swap : drop (index + 1) order 

arrangements seed = map arrange $ randstates seed 
     where arrange rands = yates rands [0.._SIDES - 2] 

-- fns comparing arrangements -- 
arcLength i j = 1/(1 + _WEIGHT * acos(dot3D/_VEC_LEN_SQUARED)) 
     where dot3D = apply x + apply y + apply z 
       apply fn = (fn i) * (fn j) 

matrix arr = map crosscmp arr 
     where crosscmp s1 = [ value s1 * (distance s1 s2) | s2 <- arr ] 
       distance a b = arcLength (_CENTERS !! a) (_CENTERS !! b) 
       value s  = fromInteger $ _VALUES !! s 

variance arr = sum $ map perside (matrix arr) 
     where perside s = (sum s - mean)^2 
       mean  = (sum (concat $ matrix arr))/(sides + 1) 
       sides  = fromInteger $ toInteger _SIDES 

maxDistr = maximumBy (\a b -> variance a `compare` variance b) 

मुख्य मूल रूप से सिर्फ

है
print $ maxDistr $ take _TRIALS $ arrangements seed 
+3

शायद http://codereview.stackexchange.com आज़माएं? –

+6

स्पष्ट बात यह है कि सूची अनुक्रमण 'ओ (सूचकांक) 'है। जब तक आपकी सूचियां वास्तव में कम नहीं होतीं, तब तक यह चोट पहुंचाने वाला है। –

+0

धन्यवाद, मैंने वहां एक पोस्ट रखा जहां यह अधिक प्रासंगिक है। तो क्या आप पक्षों को परिभाषित करने की सिफारिश करेंगे 0 = _, पक्ष 1 = _, आदि, या क्या मुझे किसी अन्य डेटा संरचना का उपयोग सरणी की तरह करना चाहिए? –

उत्तर

1

टिप्पणियों के नोट के रूप में, यह सूची में अनुक्रमण के रूप में रैखिक रूप से स्केल नहीं कर सकता है O(index) है। सुधार देखने के लिए आपको एक सरणी संरचना में स्थानांतरित करने की आवश्यकता होगी।