गणना सरणियाँ जो वास्तव में अद्वितीय हैं


9

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

Aलंबाई की एक सरणी पर विचार करें n। सरणी में केवल धनात्मक पूर्णांक होते हैं। उदाहरण के लिए A = (1,1,2,2)। आइए हम f(A)सभी गैर-रिक्त सन्निधियों के योगों के समूह के रूप में परिभाषित करते हैं A। इस मामले में f(A) = {1,2,3,4,5,6}। उत्पादन के चरण f(A) इस प्रकार हैं:

की अधीनताएँ Aहैं (1), (1), (2), (2), (1,1), (1,2), (2,2), (1,1,2), (1,2,2), (1,1,2,2)। उनके संबंधित योग हैं 1,1,2,2,2,3,4,4,5,6। इस सूची से आपको जो सेट मिलता है, वह है {1,2,3,4,5,6}

किसी सरणी को हम A यूनिक कहते हैं, यदि Bसमान लंबाई का कोई दूसरा एरे न हो f(A) = f(B), तो एरे को Aउल्टा करने के अलावा। एक उदाहरण के रूप में, f((1,2,3)) = f((3,2,1)) = {1,2,3,5,6}लेकिन लंबाई का कोई अन्य सरणी नहीं है 3जो समान सेट का उत्पादन करता है।

कार्य

कार्य, दिए गए nऔर sउस लंबाई के अद्वितीय सरणियों की संख्या की गणना करना है। आप मान सकते हैं कि sबीच में है 1और 9। आपको केवल एरे की गणना करने की आवश्यकता है जहां तत्व या तो दिए गए पूर्णांक हैं sया s+1। उदाहरण के लिए, यदि s=1आप जो गिनती कर रहे हैं, उसमें केवल शामिल हैं 1और 2। हालांकि, विशिष्टता की परिभाषा समान लंबाई के किसी भी अन्य सरणी के संबंध में है। एक ठोस उदाहरण के रूप में [1, 2, 2, 2]है नहीं के रूप में यह रूप में रकम का एक ही सेट देता है अद्वितीय [1, 1, 2, 3]

आपको एक सरणी के साथ-साथ सरणी को भी उल्टा गिनना चाहिए (जब तक कि सरणी निश्चित रूप से एक palindrome नहीं है)।

उदाहरण

s = 1n = 2,3,4,5,6,7,8,9 के उत्तर हैं:

4, 3, 3, 4, 4, 5, 5, 6

के लिए s = 1, लंबाई 4 की अनूठी सरणियाँ हैं

(1, 1, 1, 1)
(2, 1, 1, 2)
(2, 2, 2, 2)

s = 2n = 2,3,4,5,6,7,8,9 के उत्तर हैं:

4, 8, 16, 32, 46, 69, 121, 177

सरणी का एक उदाहरण जो अद्वितीय नहीं है, s = 2वह है:

(3, 2, 2, 3, 3, 3). 

यह दोनों के रूप में रकम का एक ही सेट है: (3, 2, 2, 2, 4, 3)और (3, 2, 2, 4, 2, 3)

s = 8n = 2,3,4,5,6,7,8,9 के उत्तर हैं:

4, 8, 16, 32, 64, 120, 244, 472

स्कोर

किसी दिए गए के लिए n, अपने कोड के सभी मानों के लिए उत्पादन में उत्तर देना चाहिए sसे 1करने के लिए 9। आपका स्कोर उच्चतम मूल्य है nजिसके लिए यह एक मिनट में पूरा होता है।

परिक्षण

मुझे अपने कोड को मेरे ubuntu मशीन पर चलाने की आवश्यकता होगी ताकि कृपया अपने कोड को संकलित करने और चलाने के लिए यथासंभव विस्तृत निर्देश शामिल करें।

लीडरबोर्ड

  • n = 13 हास्केल में क्रिश्चियन सिवर्स द्वारा (42 सेकंड)

हमें कितनी मेमोरी का उपभोग करने की अनुमति है?
काला उल्लू काई

@BlackOwlKai मेरी मशीन में 8GB है इसलिए मुझे लगता है कि 6GB सुरक्षित है?
अनुष्का

मुझे लगता है कि उदाहरणों में अंतिम संख्या 427 के बजाय 472 होनी चाहिए।
क्रिश्चियन सेवर्स

@ChristianSievers धन्यवाद। अभी तय किया है।
अनुष्का

क्या है s? यह क्या दिखाता है?
गीगाफ्लॉप

जवाबों:


5

हास्केल

import Control.Monad (replicateM)
import Data.List (tails)
import qualified Data.IntSet as S
import qualified Data.Map.Strict as M
import qualified Data.Vector.Unboxed as V
import Data.Vector.Unboxed.Mutable (write)
import System.Environment (getArgs)
import Control.Parallel.Strategies

orig:: Int -> Int -> M.Map S.IntSet (Maybe Int)
orig n s = M.fromListWith (\ _ _ -> Nothing) 
               [(sums l, Just $! head l) | 
                   l <- replicateM n [s, s+1],
                   l <= reverse l ]

sums :: [Int] -> S.IntSet
sums l = S.fromList [ hi-lo | (lo:r) <- tails $ scanl (+) 0 l, hi <- r ]

construct :: Int -> Int -> S.IntSet -> [Int]
construct n start set =
   setmax `seq` setmin `seq` setv `seq`
   [ weight r | r <- map (start:) $ constr (del start setlist)
                                           (V.singleton start)
                                           (n-1)
                                           (setmax - start),
                r <= reverse r ]
  where
    setlist = S.toList set
    setmin = S.findMin set
    setmax = S.findMax set
    setv = V.modify (\v -> mapM_ (\p -> write v p True) setlist)
                    (V.replicate (1+setmax) False)

    constr :: [Int] -> V.Vector Int -> Int -> Int -> [[Int]]
    constr m _ 0 _ | null m    = [[]]
                   | otherwise = []
    constr m a i x =
         [ v:r | v <- takeWhile (x-(i-1)*setmin >=) setlist,
                 V.all (V.unsafeIndex setv . (v+)) a,
                 let new = V.cons v $ V.map (v+) a,
                 r <- (constr (m \\\ new) $! new) (i-1) $! (x-v) ]

del x [] = []
del x yl@(y:ys) = if x==y then ys else if y<x then y : del x ys else yl

(\\\) = V.foldl (flip del)

weight l = if l==reverse l then 1 else 2

count n s = sum ( map value [ x | x@(_, Just _) <- M.toList $ orig n s]
                      `using` parBuffer 128 rseq )
  where 
    value (sms, Just st) = uniqueval $ construct n st sms
    uniqueval [w] = w
    uniqueval _   = 0


main = do
  [ n ] <- getArgs
  mapM_ print ( map (count (read n)) [1..9]
                    `using` parBuffer 2 r0 )

origसमारोह लंबाई की सभी सूचियों बनाता nप्रविष्टियों के साथ sया s+1, उन्हें रहता है अगर वे आते हैं उनके रिवर्स से पहले, उनके sublist गणना करता है sumsऔर कहते हैं एक नक्शा जो भी सूची के पहले तत्व याद है में उन। जब रकम का एक ही सेट एक से अधिक बार मिल जाता है, तो पहले तत्व को बदल दिया जाता है Nothing, इसलिए हम जानते हैं कि हमें इन रकमों को प्राप्त करने के अन्य तरीकों की तलाश नहीं करनी होगी।

constructदिया लंबाई की सूची के लिए समारोह खोजों और दी शुरू करने से मूल्यवान हैं, sublist रकम का एक सेट। इसकी पुनरावर्ती हिस्सा constrअनिवार्य रूप से के रूप में ही तर्क इस प्रकार यह है, लेकिन राशि शेष सूची प्रविष्टियों की आवश्यकता देने के लिए एक अतिरिक्त तर्क है। इस राशि को प्राप्त करने की अनुमति देता है जब इस योग को प्राप्त करने के लिए सबसे छोटे संभव मान बहुत बड़े होते हैं, जिसने एक बड़े प्रदर्शन में सुधार किया। इस परीक्षण को पहले वाले स्थान (संस्करण 2) पर ले जाकर और वर्तमान रकमों की सूची को एक Vector(संस्करण 3 (टूटा हुआ) और 4 (अतिरिक्त सख्ती के साथ ) द्वारा बदलकर बड़े सुधार किए गए । नवीनतम संस्करण लुकअप टेबल के साथ सेट सदस्यता परीक्षण करता है और कुछ और सख्ती और समानांतरकरण जोड़ता है।

जब constructएक सूची मिली है जो सबलिस्ट सूची देती है और अपने रिवर्स से छोटी है, तो वह इसे वापस कर सकती है, लेकिन हम वास्तव में इसमें रुचि नहीं रखते हैं। यह लगभग केवल ()अपने अस्तित्व को इंगित करने के लिए वापस जाने के लिए पर्याप्त होगा , लेकिन हमें यह जानना होगा कि क्या हमें इसे दो बार गिनना है (क्योंकि यह एक palindrome नहीं है और हम इसके रिवर्स को कभी नहीं संभालेंगे)। इसलिए हमने weightपरिणामों की सूची में इसके 1 या 2 को रखा है ।

फ़ंक्शन countइन भागों को एक साथ रखता है। सबलिस्ट सम्स के प्रत्येक सेट के लिए (से आने वाला orig) जो केवल sऔर s+1, युक्त सूचियों के बीच अद्वितीय था , यह कहता हैvalue , जो कॉल , जो कॉल करता है constructऔर, के माध्यम से uniqueval, जाँच करता है कि क्या केवल एक परिणाम है। यदि हां, तो यह वह वजन है जिसे हमें गिनना है, अन्यथा रकम का सेट अद्वितीय नहीं था और शून्य वापस आ गया है। ध्यान दें कि आलस्य के कारण, constructदो परिणाम मिल जाने पर रुक जाएंगे।

mainसमारोह हैंडल आईओ और के पाश s1 से 9 तक।

संकलन और चल रहा है

डेबियन पर पैकेज की जरूरत है ghc, libghc-vector-devऔर libghc-parallel-dev। प्रोग्राम को एक फ़ाइल में सहेजें prog.hsऔर इसके साथ संकलित करें ghc -threaded -feager-blackholing -O2 -o prog prog.hs। साथ चलाने के लिए ./prog <n> +RTS -Nजहां <n>सरणी लंबाई जिसके लिए हम अद्वितीय सरणियों की गणना करना चाहते है।


यह कोड बहुत अद्भुत है (और संक्षिप्त!)। यदि आप कुछ स्पष्टीकरण जोड़ सकते हैं तो मुझे यकीन है कि लोग यह समझने के लिए प्यार करेंगे कि आपने क्या किया है।
अनुश्

आपका नया संस्करण मेरे लिए संकलन नहीं है। मुझे bpaste.net/show/c96c4cbdc02e
Anush

क्षमा करें, बड़ा कोड हटाना और चिपकाना इतना असहज है कि मैं कभी-कभी बस कुछ लाइनों को हाथ से बदल देता हूं। निश्चित रूप से मैंने एक गलती की ... अब निश्चित (मुझे उम्मीद है), और एक और सुधार जोड़ा, इस बार केवल कुछ प्रतिशत के लिए। अन्य परिवर्तन अधिक महत्वपूर्ण थे।
क्रिश्चियन सिवर्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.