मास्क के एक सेट से मेल खाते संतुलित बाइनरी स्ट्रिंग्स की गणना करें


10

एक बाइनरी स्ट्रिंग एक स्ट्रिंग है जिसमें केवल 01 से तैयार किए गए वर्ण होते हैं । एक संतुलित बाइनरी स्ट्रिंग एक बाइनरी स्ट्रिंग है जिसमें 1 एस के रूप में कई 0 एस होते हैं ।

आपको एक सकारात्मक पूर्णांक n और एक मनमानी संख्या में मास्क दिए गए हैं, जिनमें से प्रत्येक 2n वर्ण लंबा है, और इसमें केवल 012 से खींचे गए अक्षर हैं । एक बाइनरी स्ट्रिंग और एक मुखौटा मेल खाता है यदि यह समान लंबाई है और हर स्थिति में चरित्र पर सहमत होता है जहां मास्क में 2 नहीं है । जैसे मास्क 011022 बाइनरी स्ट्रिंग्स 011000 , 011001 , 011010 , 011011 से मेल खाता है ।

N और मास्क को इनपुट (newlines द्वारा अलग) के रूप में देखते हुए , आपको विभिन्न संतुलित बाइनरी स्ट्रिंग्स की संख्या को आउटपुट करना होगा जो मास्क के एक या अधिक से मेल खाते हैं।

उदाहरण

इनपुट

3
111222
000112
122020
122210
102120

विचार

  • केवल संतुलित द्विआधारी मिलान स्ट्रिंग 111,222 है 111.000
  • केवल संतुलित द्विआधारी मिलान स्ट्रिंग 000,112 है 000,111
  • संतुलित द्विआधारी मिलान तार 122,020 हैं 111,000 (पहले से ही गिना), 110010 और 101010
  • 122210 से मेल खाते हुए संतुलित बाइनरी स्ट्रिंग्स 110010 (पहले से गिने हुए), 101010 (पहले से गिने गए) और 100110 हैं
  • 102120 से मेल खाते हुए संतुलित बाइनरी स्ट्रिंग्स 101100 और 100110 (पहले से ही गिने गए) हैं।

तो आउटपुट होना चाहिए

6

इनपुट

10
22222222222222222222

विचार

  • कर रहे हैं 20 10 चुनें लंबाई 20 के संतुलित द्विआधारी तार।

उत्पादन

184756

विजेता

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

प्रतियोगिता का इनपुट

http://pastebin.com/2Dg7gbfV


2
इसके अलावा, मैं सौंदर्यशास्त्र और भविष्य के दोषों के लिए व्यक्तिगत रूप से pastebin पर gist.github.com को अत्यधिक पसंद करता हूं
orlp

3
@AlbertMasclans मुझे लगता है कि आपको इनपुट बदलने का अधिकार सुरक्षित रखना चाहिए। अन्यथा, कोई व्यक्ति आउटपुट को हार्डकोड कर सकता है।
mbomb007

1
यह उपयोगी होगा यदि आप प्रश्न में एक छोटा उदाहरण पोस्ट कर सकते हैं, अपेक्षित परिणाम और एक स्पष्टीकरण के साथ। मैं बस धीमा हो सकता हूं, लेकिन मुझे परिभाषा नहीं मिलती। इसलिए उदाहरण के लिए, n = 30 के बाद से, हम किसी भी पंक्ति में 30 0s या 30 1s (2 वाइल्डकार्ड होने के साथ) के अनुक्रम की तलाश कर रहे हैं? क्या वे क्रम ओवरलैप हो सकते हैं? उदाहरण के लिए, यदि मुझे 32 1s का अनुक्रम मिलता है, तो क्या वह 3 क्रमों के रूप में या एकल अनुक्रम के रूप में गिना जाता है? अगर मुझे 60 1s (पूरी पंक्ति) का अनुक्रम मिल जाए तो क्या होगा? क्या वह १ क्रम, २ क्रम या ३१ क्रम है?
रेटो कोराडी

3
तो आप इस मैट्रिक्स में अद्वितीय सरणियों की संख्या पूछ रहे हैं जिनकी संख्या 1s और 0s के बराबर है, है ना?
ASCIIThenANSI

1
क्या हमारे पास कुछ और परीक्षण डेटा हो सकता है?
एलेक्जेंडर-ब्रेट

जवाबों:


2

सी

यदि आप लिनक्स पर नहीं हैं, या अन्यथा संकलन में परेशानी हो रही है, तो आपको शायद समय कोड ( clock_gettime) को हटा देना चाहिए ।

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

long int binomial(int n, int m) {
  if(m > n/2) {
    m = n - m;
  }
  int i;
  long int result = 1;
  for(i = 0; i < m; i++) {
    result *= n - i;
    result /= i + 1;
  }
  return result;
}

typedef struct isct {
  char *mask;
  int p_len;
  int *p;
} isct;

long int mask_intersect(char *mask1, char *mask2, char *mask_dest, int n) {

  int zero_count = 0;
  int any_count = 0;
  int i;
  for(i = 0; i < n; i++) {
    if(mask1[i] == '2') {
      mask_dest[i] = mask2[i];
    } else if (mask2[i] == '2') {
      mask_dest[i] = mask1[i];
    } else if (mask1[i] == mask2[i]) {
      mask_dest[i] = mask1[i];
    } else {
      return 0;
    }
    if(mask_dest[i] == '2') {
      any_count++;
    } else if (mask_dest[i] == '0') {
      zero_count++;
    }
  }
  if(zero_count > n/2 || any_count + zero_count < n/2) {
    return 0;
  }
  return binomial(any_count, n/2 - zero_count);
}

int main() {

  struct timespec start, end;
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);

  int n;
  scanf("%d", &n);
  int nn = 2 * n;

  int m = 0;
  int m_max = 1024;

  char **masks = malloc(m_max * sizeof(char *));

  while(1) {
    masks[m] = malloc(nn + 1);
    if (scanf("%s", masks[m]) == EOF) {
      break;
    }
    m++;
    if (m == m_max) {
      m_max *= 2;
      masks = realloc(masks, m_max * sizeof(char *));
    }
  }

  int i = 1;
  int i_max = 1024 * 128;

  isct *iscts = malloc(i_max * sizeof(isct));

  iscts[0].mask = malloc(nn);
  iscts[0].p = malloc(m * sizeof(int));

  int j;
  for(j = 0; j < nn; j++) {
    iscts[0].mask[j] = '2';
  }
  for(j = 0; j < m; j++) {
    iscts[0].p[j] = j;
  }
  iscts[0].p_len = m;

  int i_start = 0;
  int i_end = 1;
  int sign = 1;

  long int total = 0;

  int mask_bin_len = 1024 * 1024;
  char* mask_bin = malloc(mask_bin_len);
  int mask_bin_count = 0;

  int p_bin_len = 1024 * 128;
  int* p_bin = malloc(p_bin_len * sizeof(int));
  int p_bin_count = 0;


  while (i_end > i_start) {
    for (j = i_start; j < i_end; j++) {
      if (i + iscts[j].p_len > i_max) {
        i_max *= 2;
        iscts = realloc(iscts, i_max * sizeof(isct));
      }
      isct *isct_orig = iscts + j;
      int x;
      int x_len = 0;
      int i0 = i;
      for (x = 0; x < isct_orig->p_len; x++) {
        if(mask_bin_count + nn > mask_bin_len) {
          mask_bin_len *= 2;
          mask_bin = malloc(mask_bin_len);
          mask_bin_count = 0;
        }
        iscts[i].mask = mask_bin + mask_bin_count;
        mask_bin_count += nn;
        long int count =
            mask_intersect(isct_orig->mask, masks[isct_orig->p[x]], iscts[i].mask, nn);
        if (count > 0) {
          isct_orig->p[x_len] = isct_orig->p[x];
          i++;
          x_len++;
          total += sign * count;
        }
      }
      for (x = 0; x < x_len; x++) {
        int p_len = x_len - x - 1;
        iscts[i0 + x].p_len = p_len;
        if(p_bin_count + p_len > p_bin_len) {
          p_bin_len *= 2;
          p_bin = malloc(p_bin_len * sizeof(int));
          p_bin_count = 0;
        }
        iscts[i0 + x].p = p_bin + p_bin_count;
        p_bin_count += p_len;
        int y;
        for (y = 0; y < p_len; y++) {
          iscts[i0 + x].p[y] = isct_orig->p[x + y + 1];
        }
      }
    }

    sign *= -1;
    i_start = i_end;
    i_end = i;

  }

  printf("%lld\n", total);

  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);

  int seconds = end.tv_sec - start.tv_sec;
  long nanoseconds = end.tv_nsec - start.tv_nsec;
  if(nanoseconds < 0) {
    nanoseconds += 1000000000;
    seconds--;
  }

  printf("%d.%09lds\n", seconds, nanoseconds);
  return 0;
}

उदाहरण के मामले:

robert@unity:~/c/se-mask$ gcc -O3 se-mask.c -lrt -o se-mask
robert@unity:~/c/se-mask$ head testcase-long
30
210211202222222211222112102111220022202222210122222212220210
010222222120210221012002220212102220002222221122222220022212
111022212212022222222220111120022120122121022212211202022010
022121221020201212200211120100202222212222122222102220020212
112200102110212002122122011102201021222222120200211222002220
121102222220221210220212202012110201021201200010222200221002
022220200201222002020110122212211202112011102220212120221111
012220222200211200020022121202212222022012201201210222200212
210211221022122020011220202222010222011101220121102101200122
robert@unity:~/c/se-mask$ ./se-mask < testcase-long
298208861472
0.001615834s
robert@unity:~/c/se-mask$ head testcase-hard
8
0222222222222222
1222222222222222
2022222222222222
2122222222222222
2202222222222222
2212222222222222
2220222222222222
2221222222222222
2222022222222222
robert@unity:~/c/se-mask$ ./se-mask < testcase-hard
12870
3.041261458s
robert@unity:~/c/se-mask$ 

(टाइम्स 4.1 गीगाहर्ट्ज पर एक i7-4770K सीपीयू के लिए हैं।) सावधान रहें, testcase-hardलगभग 3-4 जीबी मेमोरी का उपयोग करता है।

यह समावेशन-अपवर्जन विधि ब्लूटोरेंज के कार्यान्वयन के साथ बहुत अधिक है, लेकिन ऐसा इसलिए किया गया है ताकि यह किसी भी गहराई के चौराहों को संभाल सके। जैसा कि लिखा गया कोड मेमोरी आवंटन पर बहुत समय बिता रहा है, और मैं मेमोरी प्रबंधन का अनुकूलन करने के बाद भी तेज हो जाएगा।

मैंने लगभग 25% का मुंडन किया testcase-hard, लेकिन मूल ( testcase-long) पर प्रदर्शन बहुत अपरिवर्तित है, क्योंकि बहुत मेमोरी आवंटन वहां से नहीं हो रहा है। मैं इसे कॉल करने से पहले थोड़ा और ट्यून करने जा रहा हूं: मुझे लगता है कि मैं 25% -50% testcase-longभी सुधार पाने में सक्षम हो सकता हूं ।

मेथेमेटिका

एक बार जब मैंने देखा कि यह एक # समस्या थी, तो मुझे एहसास हुआ कि मैं मैथमैटिक के बिल्ट-इन का उपयोग कर सकता हूं SatisfiabilityCount:

AbsoluteTiming[
 (* download test case *)
 input = Map[FromDigits, 
   Characters[
    Rest[StringSplit[
      Import["http://pastebin.com/raw.php?i=2Dg7gbfV", 
       "Text"]]]], {2}]; n = Length[First[input]];
 (* create boolean function *)
 bool = BooleanCountingFunction[{n/2}, n] @@ Array[x, n] && 
   Or @@ Table[
     And @@ MapIndexed[# == 2 || Xor[# == 1, x[First[#2]]] &, i], {i, 
      input}];
 (* count instances *)
 SatisfiabilityCount[bool, Array[x, n]]
]

आउटपुट:

{1.296944, 298208861472}

यह है कि 298,208,861,472 मास्क 1.3 सेकंड (i7-3517U @ 1.9 गीगाहर्ट्ज) में हैं, जिसमें पास्टबिन से परीक्षण के मामले को डाउनलोड करने का समय भी शामिल है।


तो मैं सी में यह फिर से लिखा है ... दुर्भाग्य से यह मेरे लिए इस पर gperftools का उपयोग करने के लिए बहुत तेज है! मैं कल पोस्ट करने से पहले कुछ कठिन परीक्षण मामलों को खोजूंगा।
२०१२कम्पियन

testcase-hardयदि आपका कोड संयुक्त किए जा सकने वाले मास्क की तलाश करता है तो बहुत जल्दी पूरा किया जा सकता है। यदि आपका कोड ऐसा करता है, तो हर दूसरी पंक्ति को हटा दें (ताकि बस /^2*02*$/मामले बने रहें)। मुझे नहीं लगता कि इस मामले को अनुकूलित किया जा सकता है।
२०१२कम्पियन

4

माणिक, बहुत तेज, लेकिन यह इनपुट पर निर्भर करता है

अब स्ट्रिंग्स से पूर्णांक पर स्विच करके 2 ~ 2.5 के कारक द्वारा स्पीड-अप करें।

उपयोग:

cat <input> | ruby this.script.rb

उदाहरण के लिए।

mad_gaksha@madlab ~/tmp $ ruby c50138.rb < c50138.inp2
number of matches: 298208861472
took 0.05726237 s

एक एकल मास्क के लिए मैचों की संख्या द्विपद गुणांक द्वारा आसानी से गणना की जाती है। इसलिए उदाहरण के लिए 1220203 2एस भरे, 1 0और 2 चाहिए 1। इस प्रकार nCr(3,2)=nCr(3,1)=3!/(2!*1!)=3इस मास्क से मेल खाते हुए अलग - अलग बाइनरी स्ट्रिंग्स हैं।

N मास्क m_1, m_2, ... m_n के बीच एक प्रतिच्छेदन एक मास्क q है, जैसे कि एक बाइनरी स्ट्रिंग s केवल q से मेल खाता है यदि यह सभी मास्क m_i से मेल खाता है।

यदि हम दो मास्क m_1 और m_2 लेते हैं, तो इसका प्रतिच्छेदन आसानी से गणना की जाती है। बस m_1 [i] = m_2 [i] यदि m_1 [i] == २ सेट करें। बीच चौराहे 122020और 111222है 111020:

122020 (matched by 3 strings, 111000 110010 101010)
111222 (matched by 1 string, 111000)
111020 (matched by 1 string, 111000)

दो अलग-अलग मास्क 3 + 1 = 4 स्ट्रिंग्स से मेल खाते हैं, इंटरसेक्शन मास्क एक स्ट्रिंग से मेल खाता है, इस प्रकार 3 या 1-1 = 3 अद्वितीय स्ट्रिंग्स हैं जो एक या दोनों मास्क से मेल खाते हैं।

मैं N (m_1, m_2, ...) को कॉल करूंगा, जिसमें स्ट्रिंग की संख्या सभी m_i से मेल खाती है। उपरोक्त के रूप में एक ही तर्क को लागू करते हुए, हम कम से कम एक मुखौटा द्वारा मिलान किए गए अनूठे तारों की संख्या की गणना कर सकते हैं, समावेशन अपवर्जन सिद्धांत द्वारा दिया गया है और नीचे भी देखें, जैसे:

N(m_1) + N(m_2) + ... + N(m_n) - N(m_1,m_2) - ... - N(m_n-1,m_n) + N(m_1,m_2,m_3) + N(m_1,m_2,m_4) + ... N(m_n-2,m_n-1,m_n) - N(m_1,m_2,m_3,m_4) -+ ...

कई, कई, लेने के कई संयोजन हैं, 200 में से 30 मास्क कहते हैं।

तो यह समाधान धारणा बनाता है कि इनपुट मास्क के कई उच्च-क्रम वाले चौराहे मौजूद नहीं हैं, अर्थात। n> 2 मास्क के अधिकांश n-tuples का कोई आम मिलान नहीं होगा।

यहां कोड का उपयोग करें, ideone पर कोड आउट-डेटेड हो सकता है।

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

कोड:

# factorial table
FAC = [1]
def gen_fac(n)
  n.times do |i|
    FAC << FAC[i]*(i+1)
  end
end

# generates a mask such that it is matched by each string that matches m and n
def diff_mask(m,n)
  (0..m.size-1).map do |i|
    c1 = m[i]
    c2 = n[i]
    c1^c2==1 ? break : c1&c2
  end
end

# counts the number of possible balanced strings matching the mask
def count_mask(m)
  n = m.size/2
  c0 = n-m.count(0)
  c1 = n-m.count(1)
  if c0<0 || c1<0
    0
  else
    FAC[c0+c1]/(FAC[c0]*FAC[c1])
  end
end

# removes masks contained in another
def remove_duplicates(m)
  m.each do |x|
    s = x.join
    m.delete_if do |y|
      r = /\A#{s.gsub(?3,?.)}\Z/
      (!x.equal?(y) && y =~ r) ? true : false
    end
  end
end

#intersection masks of cn masks from m.size masks
def mask_diff_combinations(m,n=1,s=m.size,diff1=[3]*m[0].size,j=-1,&b)
  (j+1..s-1).each do |i|
    diff2 = diff_mask(diff1,m[i])
    if diff2
      mask_diff_combinations(m,n+1,s,diff2,i,&b) if n<s
      yield diff2,n
    end
  end
end

# counts the number of balanced strings matched by at least one mask
def count_n_masks(m)
  sum = 0
  mask_diff_combinations(m) do |mask,i|
    sum += i%2==1 ? count_mask(mask) : -count_mask(mask)
  end
  sum
end

time = Time.now

# parse input
d = STDIN.each_line.map do |line|
  line.chomp.strip.gsub('2','3')
end
d.delete_if(&:empty?)
d.shift
d.map!{|x|x.chars.map(&:to_i)}

# generate factorial table
gen_fac([d.size,d[0].size].max+1)

# count masks
puts "number of matches: #{count_n_masks(d)}"
puts "took #{Time.now-time} s"

इसे समावेशन अपवर्जन सिद्धांत कहा जाता है, लेकिन इससे पहले कि कोई मुझे इसे इंगित करता है मेरे पास अपना प्रमाण था, इसलिए यहां यह जाता है। हालांकि कुछ करना अपने आप में बहुत अच्छा लगता है।

आइए 2 मास्क के मामले पर विचार करें, फिर कॉल करें 0और 1, पहले। हम प्रत्येक संतुलित बाइनरी स्ट्रिंग लेते हैं और इसे किस मास्क (नों) के अनुसार वर्गीकृत करते हैं, यह मेल खाता है। c0उन है कि केवल मेल खाते हैं मुखौटा की संख्या है 0, c1जो केवल मेल खाते की nunber 1, c01उन है कि मैच मुखौटा 0और 1

आज्ञा दें s0कि प्रत्येक मास्‍क के लिए माचिस की संख्‍या का योग (वे ओवरलैप हो सकते हैं)। आज्ञा दें s1कि प्रत्येक जोड़ी (2-संयोजन) के मास्क की संख्या का योग है। आज्ञा देना s_iप्रत्येक के लिए मैचों की संख्या का योग हो (i + 1) मास्क का संयोजन। एन-मास्क के मैचों की संख्या बाइनरी स्ट्रिंग्स की संख्या है जो सभी मास्क से मेल खाती है।

यदि n मास्क हैं, तो वांछित आउटपुट सभी का योग है c, अर्थात। c = c0+...+cn+c01+c02+...+c(n-2)(n-1)+c012+...+c(n-3)(n-2)(n-1)+...+c0123...(n-2)(n-1)। कार्यक्रम की गणना सभी की वैकल्पिक राशि है s, अर्थात। s = s_0-s_1+s_2-+...+-s_(n-1)। हम इसका प्रमाण देना चाहते हैं s==c

n = 1 स्पष्ट है। N = 2 पर विचार करें। मास्क के सभी मैचों की गिनती, 0देता है c0+c01(केवल मिलान करने वाले तार की संख्या 0 + जो दोनों से मेल खाते हैं ) 0और देता है 1, सभी मैचों की गिनती 1करता है c1+c02। हम इसका वर्णन इस प्रकार कर सकते हैं:

0: c0 c01
1: c1 c10

परिभाषा के अनुसार, s0 = c0 + c1 + c12। यानी s1के प्रत्येक 2-संयोजन के मैचों की संख्या है [0,1]। सभी uniqye c_ijएस। ध्यान रखें कि c01=c10

s0 = c0 + c1 + 2 c01
s1 = c01
s = s0 - s1 = c0 + c1 + c01 = c

इस प्रकार s=cn = 2 के लिए।

अब n = 3 पर विचार करें।

0  : c0 + c01 + c02 + c012
1  : c1 + c01 + c12 + c012
2  : c2 + c12 + c02 + c012
01 : c01 + c012
02 : c02 + c012
12 : c12 + c012
012: c012

s0 = c0 + c1 + c2 + 2 (c01+c02+c03) + 3 c012
s1 = c01 + c02 + c12 + 3 c012
s2 = c012

s0 = c__0 + 2 c__1 + 3 c__2
s1 =          c__1 + 3 c__2
s2 =                   c__2

s = s0 - s1 + s2 = ... = c0 + c1 + c2 + c01 + c02 + c03 + c012 = c__0 + c__1 + c__2 = c

इस प्रकार s=cn = 3 के लिए। c__iसभी के cसाथ (i + 1) सूचकांकों का प्रतिनिधित्व करता है , उदाहरण के c__1 = c01लिए n = 2 और c__1 = c01 + c02 + c12n == 3 के लिए।

N = 4 के लिए, एक पैटर्न उभरने लगता है:

0:   c0 + c01 + c02 + c03 + c012 + c013 + c023 + c0123
1:   c1 + c01 + c12 + c13 + c102 + c103 + c123 + c0123
2:   c2 + c02 + c12 + c23 + c201 + c203 + c213 + c0123
3:   c3 + c03 + c13 + c23 + c301 + c302 + c312 + c0123

01:  c01 + c012 + c013 + c0123
02:  c02 + c012 + c023 + c0123
03:  c03 + c013 + c023 + c0123
12:  c11 + c012 + c123 + c0123
13:  c13 + c013 + c123 + c0123
23:  c23 + c023 + c123 + c0123

012:  c012 + c0123
013:  c013 + c0123
023:  c023 + c0123
123:  c123 + c0123

0123: c0123

s0 = c__0 + 2 c__1 + 3 c__2 + 4 c__3
s1 =          c__1 + 3 c__2 + 6 c__3
s2 =                   c__2 + 4 c__3
s3 =                            c__3

s = s0 - s1 + s2 - s3 = c__0 + c__1 + c__2 + c__3 = c

इस प्रकार s==cn = 4 के लिए।

सामान्य तौर पर, हमें इस तरह के द्विपद गुणांक मिलते हैं (i i, → j है):

   0  1  2  3  4  5  6  .  .  .

0  1  2  3  4  5  6  7  .  .  .
1     1  3  6  10 15 21 .  .  .
2        1  4  10 20 35 .  .  .
3           1  5  15 35 .  .  .
4              1  6  21 .  .  .
5                 1  7  .  .  .
6                    1  .  .  . 
.                       .
.                          .
.                             .

इसे देखने के लिए, इस बात पर विचार करें कि कुछ iऔर jहैं:

  • x = ncr (n, i + 1): n के बाहर (i + 1) मास्क के प्रतिच्छेदन के लिए संयोजन C
  • y = ncr (ni-1, ji): ऊपर दिए गए प्रत्येक संयोजन C के लिए, (J + 2) मास्क के चौराहे के लिए y अलग संयोजन होते हैं, जिनमें से C होते हैं।
  • z = ncr (n, j + 1): n के चौराहे (j + 1) मास्क के लिए अलग-अलग संयोजन

जैसा कि भ्रामक लग सकता है, यहाँ एक उदाहरण पर लागू किया गया विक्षेप है। I = 1, j = 2, n = 4 के लिए, यह ऐसा दिखता है (ऊपर cf.):

01:  c01 + c012 + c013 + c0123
02:  c02 + c012 + c023 + c0123
03:  c03 + c013 + c023 + c0123
12:  c11 + c012 + c123 + c0123
13:  c13 + c013 + c123 + c0123
23:  c23 + c023 + c123 + c0123

तो यहाँ x = 6 (01, 02, 03, 12, 13, 23), y = 2 (प्रत्येक संयोजन के लिए दो सी तीन सूचकांकों के साथ), z = 4 (c012, c013, c023, c123)।

कुल में, (j + 1) सूचकांकों के साथ x*yगुणांक होते हैं c, और zअलग - अलग होते हैं, इसलिए प्रत्येक x*y/zबार होता है, जिसे हम गुणांक कहते हैं k_ij। साधारण बीजगणित के द्वारा, हम प्राप्त करते हैंk_ij = ncr(n,i+1) ncr(n-i-1,j-i) / ncr(n,j+1) = ncr(j+1,i+1)

इसलिए इंडेक्स k_ij = nCr(j+1,i+1)यदि आप सभी डिफेक्ट को याद करते हैं, तो हमें यह बताना होगा कि हमें प्रत्येक कॉलम का वैकल्पिक योग 1 देता है।

वैकल्पिक राशि s0 - s1 + s2 - s3 +- ... +- s(n-1)इस प्रकार व्यक्त की जा सकती है:

s_j = c__j * ∑[(-1)^(i+j) k_ij] for i=0..n-1
     = c__j * ∑[(-1)^(i+j) nCr(j+1,i+1)] for i=0..n-1
     = c__j * ∑[(-1)^(i+j) nCr(j+1,i)]{i=0..n} - (-1)^0 nCr(j+1,0)
     = (-1)^j c__j

s   = ∑[(-1)^j  s_j] for j = 0..n-1
    = ∑[(-1)^j (-1)^j c__j)] for j=0..n-1
    = ∑[c__j] for j=0..n-1
    = c

इस प्रकार s=cसभी n = 1,2,3 के लिए, ...


1
मुझे यकीन नहीं है कि आप जानते हैं, लेकिन आप जिस विधि को लागू कर रहे हैं वह en.wikipedia.org/wiki/Inclusion%E2%80%93exclusion_principle है , इसलिए आपको यह साबित करने की ज़रूरत नहीं है, अगर यह वही है जो आप करने की कोशिश कर रहे हैं करना। इसके अलावा परीक्षण के मामलों की जरूरत नहीं है जब आप समूह मास्क से पूरी तरह से समाप्त हो सकते हैं जो समूह में दूसरे मास्क में पूरी तरह से शामिल हैं। टीसी 5 में उदाहरण के लिए: 0011 < 2211, 0022 < 0222। मुझे लगता है कि यह समूहों को इससे बड़ा नहीं बनाता है 2*n, हालांकि सबसे खराब स्थिति में यह अभी भी बहुत बड़ा है।
नटकी

@ कुटकी मुझे इसकी जानकारी नहीं थी, इसलिए लिंक के लिए धन्यवाद। कभी-कभी, अपने आप के लिए कुछ के बारे में साबित करना और सोचना अभी भी एक अच्छा व्यायाम है, हालांकि :)। आपके सुझाव के अनुसार, हां, इसने मुझे ऐसा करने के लिए प्रेरित किया था, लेकिन मुझे नहीं लगता कि मैं इसे लागू करने जा रहा हूं जब तक कि एक परीक्षण मामला नहीं जोड़ा जाता है जिसके लिए उचित समय में परिणाम प्राप्त करने की आवश्यकता होती है।
ब्लुटोरेंज

@blutorange क्या आपने निर्णय वृक्ष का उपयोग करना उचित समझा?
अब्राहम

मुझे लगता है कि आपका मतलब चौराहे से है (दोनों मास्क से मेल खाता है), न कि संघ (एक या दूसरे मास्क से मेल खाता है)।
२०१२ आर्कम्पियन

@ 2012 चापलूसी unifying two masksशब्द के रूप में unionमेरे लिए समझ में आता है और मैं उस तरह से परिभाषित करता हूं, लेकिन आप सही हैं, मैं आपसी समझ के हित में, जो मैंने पीछा किया है। @ Agawa001 क्या आप अधिक विशिष्ट हो सकते हैं? इसके अलावा, अगर आपको इसे तेज करने के लिए कुछ अच्छा विचार मिल गया है, तो अपने कार्यक्रम / उत्तर के लिए इस उत्तर से किसी भी विचार का उपयोग करने के लिए स्वतंत्र महसूस करें। अभी के लिए, यह बड़े परीक्षण के मामले के लिए पर्याप्त तेज़ है, और यदि इसे बहु-थ्रेडेड बनाया जाए तो इसे <0.1 s लेना चाहिए, जो कि किसी भी सार्थक माप / तुलना से नीचे है, इसलिए कठिन परीक्षण के मामलों की आवश्यकता है।
ब्लुटोरांगे

1

सी

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gsl/gsl_combination.h>

int main (int argc, char *argv[]) {

    printf ("reading\n");
    char buffer[100];
    gets(buffer);
    char n = atoi(buffer);

    char *masks[1000];
    masks[0] = malloc(2 * n * sizeof(char));
    char c,nrows,j,biggestzerorun,biggestonerun,currentzerorun,currentonerun = 0;

    while ((c = getchar()) && c != EOF) {
        if (c == '\n') {
            nrows++;
            if (currentonerun > biggestonerun) {
                biggestonerun = currentonerun;
            }
            if (currentzerorun > biggestzerorun) {
                biggestzerorun = currentzerorun;
            }
            j=currentonerun=currentzerorun=0;
            masks[nrows] = malloc(2 * n * sizeof(char));
        } else if (c == '0') {
            masks[nrows][j++] = 1;
            currentzerorun++;
            if (currentonerun > biggestonerun) {
                biggestonerun = currentonerun;
            }
            currentonerun=0;
        } else if (c == '1') {
            masks[nrows][j++] = 2;
            currentonerun++;
            if (currentzerorun > biggestzerorun) {
                biggestzerorun = currentzerorun;
            }
            currentonerun=0;
        } else if (c == '2') {
            masks[nrows][j++] = 3;
            currentonerun++;
            currentzerorun++;
        }
    }
    if (currentonerun > biggestonerun) {
        biggestonerun = currentonerun;
    }
    if (currentzerorun > biggestzerorun) {
        biggestzerorun = currentzerorun;
    }

    printf("preparing combinations\n");

    int nmatches=0;

    gsl_combination *combination = gsl_combination_calloc(2*n, n);

    printf("entering loop:\n");

    do {
        char vector[2*n];
        char currentindex, previousindex;
        currentonerun = 0;
        memset(vector, 1, 2*n);


        // gsl_combination_fprintf (stdout, combination, "%u ");
        // printf(": ");

        for (char k=0; k<n; k++) {
            previousindex = currentindex;
            currentindex = gsl_combination_get(combination, k);
            if (k>0) {
                if (currentindex - previousindex == 1) {
                    currentonerun++;
                    if (currentonerun > biggestonerun) {
                        goto NEXT;
                    }
                } else {
                    currentonerun=0;
                    if (currentindex - previousindex > biggestzerorun) {
                        goto NEXT;
                    }
                }
            }
            vector[currentindex] = 2;
        }

        for (char k=0; k<=nrows; k++) {
            char ismatch = 1;
            for (char l=0; l<2*n; l++) {
                if (!(vector[l] & masks[k][l])) {
                    ismatch = 0;
                    break;
                }
            }
            if (ismatch) {
                nmatches++;
                break;
            }
        }

        NEXT: 1;

    } while (
        gsl_combination_next(combination) == GSL_SUCCESS
    );

    printf ("RESULT: %i\n", nmatches);

    gsl_combination_free(combination);
    for (; nrows>=0; nrows--) {
        free(masks[nrows]);
    }
}

सौभाग्य इस पर चलने के लिए बड़ा इनपुट मिल रहा है - यह लगभग पूरी रात लगभग ले जाएगा। 60 ^ 30 क्रमपरिवर्तन! शायद एक मध्यवर्ती आकार का डेटासेट एक अच्छा विचार हो सकता है?

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