इसके सब्सट्रेट से एक स्ट्रिंग को पहचानें


20

परिचय

मैंने पहले दो चुनौतियों का निर्माण किया है जहां विचार संभव के रूप में कुछ क्वेरी-प्रकार के संचालन का उपयोग करके किसी ऑब्जेक्ट को फिर से बनाना है; यह तीसरा होगा।

काम

आपके इनपुट Sवर्णमाला abcऔर उसकी लंबाई पर एक गैर-रिक्त स्ट्रिंग होंगे, और आपका आउटपुट होगा S। कोई प्रतिबंध नहीं होने के साथ, यह निश्चित रूप से एक तुच्छ कार्य होगा; पकड़ यह है कि आपको Sसीधे पहुंचने की अनुमति नहीं है । केवल एक चीज जो आपको करने की अनुमति है , Sवह फ़ंक्शन को कॉल करने के लिए है num_occur(T, S), जहां Tकुछ अन्य स्ट्रिंग है, और num_occurइसमें होने वाली संख्या की गणना करता Tहै S। ओवरलैपिंग की घटनाओं को विशिष्ट के रूप में गिना जाता है, इसलिए num_occur(T, S)वास्तव में iऐसे सूचकांकों की संख्या वापस आ जाती है

S[i, i+1, …, i+length(T)-1] == T

उदाहरण के लिए, num_occur("aba", "cababaababb")वापस आ जाएगी 3। ध्यान दें कि num_occur(S, S)वापस आ जाएगा 1। का परिणाम num_occur("", S)अपरिभाषित है, और आपको खाली स्ट्रिंग पर फ़ंक्शन को कॉल नहीं करना चाहिए।

संक्षेप में, आपको एक फ़ंक्शन या प्रोग्राम लिखना चाहिए जो इनपुट के रूप में Sऔर कुछ छोटे तार और कुछ समय पर length(S)कॉल करता है, उस जानकारी से पुनर्निर्माण करता है और इसे वापस करता है।num_occurSS

नियम और स्कोरिंग

आपका लक्ष्य एक ऐसा प्रोग्राम लिखना है जो यथासंभव कम कॉल num_occurकरता है। में इस भंडार , आपको फ़ाइल कहा जाता है मिलेगा abc_strings.txt। फ़ाइल में 100 स्ट्रिंग्स हैं, प्रत्येक की अपनी लाइन पर, लंबाई 50 और 99 के बीच। आपका स्कोर इन इनपुट्स पर कॉलnum_occur की कुल संख्या है , कम स्कोर बेहतर है। आपका समाधान अधिमानतः इस संख्या पर नज़र रखेगा क्योंकि यह चलता है, और इसे परिष्करण पर प्रिंट करें। तार समान रूप से यादृच्छिक अक्षरों को चुनने से उत्पन्न होते हैं abc; आप तार पैदा करने की इस विधि के लिए अनुकूलन करने की अनुमति है, लेकिन नहीं तार खुद को।

कोई समय सीमा नहीं है, सिवाय इसके कि आप इसे जमा करने से पहले परीक्षण मामलों पर अपना समाधान चलाएं। आपको समाधान किसी भी मान्य इनपुट के लिए काम करना चाहिए S, न कि केवल परीक्षण के मामलों में।

num_occurयदि आप किसी और का उपयोग नहीं कर रहे हैं, तो आपको अपने कार्यान्वयन को भी साझा करने के लिए प्रोत्साहित किया जाता है । गेंद को लुढ़कने के लिए, यहाँ पायथन में एक कार्यान्वयन है:

def num_occur(needle, haystack):
    num = 0
    for i in range(len(haystack) - len(needle) + 1):
        if haystack[i : i + len(needle)] == needle:
            num += 1
    return num

क्या हमारे एल्गोरिदम को सभी संभावित तारों के लिए काम करना है S, या सिर्फ परीक्षण के मामलों के लिए?
लवजो

@ ललोवो अच्छा सवाल। उन्हें सभी गैर-रिक्त तारों के लिए सैद्धांतिक रूप से काम करना चाहिए। मैं चुनौती संपादित करूंगा।
जरगब

all non-empty stringsजो भी लंबाई हो?
edc65

@ edc65 सैद्धांतिक रूप से हाँ। आप बंधे हुए स्मृति पतों और अन्य व्यावहारिक सीमाओं को अनदेखा कर सकते हैं।
जर्बर्ग

मूल्यांकन परीक्षण को सफलता के साथ पास करने के लिए एक VW एल्गोरिथ्म जोड़ना संभव है: abc_strings.txt के ज्ञात तारों की घटना के लिए पहले जाँच करें
Emmanuel

जवाबों:


6

जावास्क्रिप्ट, 14325 14311 कॉल

हम एक रिक्त स्ट्रिंग से शुरू करते हैं और अंत में या वर्तमान स्ट्रिंग की शुरुआत में एक नया अक्षर जोड़कर अपने तरीके से पुनरावर्ती जाते हैं जबकि हमारे पास अभी भी कम से कम एक मैच है।

पिछले सभी परिणाम ऑब्जेक्ट numOccur()में सहेजे गए हैं symऔर हम इस डेटा का उपयोग किसी भी नए स्ट्रिंग को अस्वीकार करने के लिए करते हैं जो संभवतः एक उम्मीदवार नहीं हो सकता है।

EDIT : क्योंकि हम हमेशा से शुरू करते हैं 'a', हम हमेशा aस्ट्रिंग में सटीक संख्या जानते हैं । हम इस जानकारी का उपयोग प्रक्रिया को समाप्त करने से पहले करते हैं जब हम पता लगाते हैं कि केवल एक क्रम aगायब है। नियमित अभिव्यक्ति भी तय की जो Chrome और IE में अमान्य थी।

var test = [
  'ccccbcbbbbacbaaababbccaacbccaaaaccbccaaaaaabcbbbab',
  // etc.
];
var call = 0;

function guess(S, len) {
  var sym = {};
  recurse(S, len, "", sym);
  return sym.result;
}

function recurse(S, len, s, sym) {
  var dictionary = [];

  if(s == '' || (isCandidate(s, sym) && (sym[s] = numOccur(S, s)))) {
    if(s.length == len) {
      sym.result = s;
    }
    else if(sym['a'] && count(s, 'a') == sym['a'] - (len - s.length)) {
      dictionary = [ Array(len - s.length + 1).join('a') ];
    }
    else {
      dictionary = [ "a", "b", "c" ];
    }
    dictionary.some(function(e) {
      return recurse(S, len, s + e, sym) || recurse(S, len, e + s, sym);
    });
    return true;
  }
  return false;
}

function isCandidate(s, sym) {
  return sym[s] === undefined && Object.keys(sym).every(function(k) {
    return count(s, k) <= sym[k];
  });
}

function count(s0, s1) {
  return (s0.match(new RegExp(s1, 'g')) || []).length;
}

function numOccur(S, s) {
  call++;
  return count(S, s);
}

test.forEach(function(S) {
  if(guess(S, S.length) != S) {
    console.log("Failed for: '" + S + "'");
  }
});
console.log(call + " calls");

नीचे पूर्ण निष्पादन योग्य स्निपेट।


"संक्षेप में, आपको एक फ़ंक्शन या प्रोग्राम लिखना चाहिए जो [...], उस जानकारी से एस को फिर से संगठित करता है और इसे वापस करता है ।"
कार्लकास्टर

@ कर्लकास्टर - उफ़। आप सही हे। यह तय है। धन्यवाद!
अरनौलड

4

पायथन, 15205 कॉल

def findS(S, len_s, alphabeth = "abc"):
    if len_s == 0:
        return ""
    current = ""
    add_at_start = True
    while len(current) < len_s:
        worked = False 
        for letter in alphabeth:
            if add_at_start:
                current_new = current + letter
            else:
                current_new = letter + current
            if num_occur(current_new, S) > 0:
                current = current_new
                worked = True
                break
        if not worked:
            add_at_start = False
    return current 

यह सबमिशन सबसे अधिक संभावना है, क्योंकि यह केवल यह num_occurजांचने के लिए उपयोग करता है कि क्या स्ट्रिंग स्ट्रिंग का विकल्प है S, और यह इसका उपयोग वास्तव में सबस्ट्रिंग की मात्रा को गिनने के लिए नहीं करता है।

एल्गोरिथ्म एक स्ट्रिंग को संग्रहीत करके काम करता है currentजो Sअंत में बराबर होने के लिए बनाया गया है । यहाँ एल्गोरिथ्म में सभी चरण दिए गए हैं:

  1. हमने currentबराबर सेट किया''

  2. वर्णमाला के प्रत्येक अक्षर के माध्यम से जाओ, और निम्नलिखित करें:

    2.1। एक नया स्ट्रिंग बनाएं current_new, और इसे सेट करें currentजो अक्षर द्वारा अनुसरण किया जाता है।

    2.2। जांचें कि current_newक्या उस पर Sचलने से num_occurशामिल है और देखें कि क्या परिणाम एक से अधिक है।

    2.3। अगर current_newमें शामिल है S, सेट currentकरने के लिए current_newऔर कदम 2. वरना के लिए वापस जाओ, हम अगले पत्र में जाते हैं।

  3. यदि की लंबाई के currentबराबर है तो Sहम कह सकते हैं कि हम कर रहे हैं। और, हम चरण 2 पर वापस जाते हैं, लेकिन बदले current_newमें पत्र के बराबर बनाने के लिए चरण 2.1 को संशोधित currentकरते हैं। जब हम इस कदम पर दोबारा पहुंचते हैं, तो हम किए जाते हैं।


1
पाइथन के लूप के लिए एक और क्लॉज है। यह इसके लिए एक सही उपयोग का मामला होगा।
जक्यूब

4

अजगर 2, 14952 14754 कॉल

पहले उत्तर के समान है, लेकिन अगले वर्णों की कोशिश नहीं करता है जिसके परिणामस्वरूप असंभव पदार्थ होते हैं:

  • हम जानते हैं num_occurकि वे लक्ष्य में नहीं होते हैं (पिछली कॉल से)

  • हम पहले से ही सब-स्ट्रिंग का उपयोग पहले से ही करते हैं, जिसके अनुसार यह होता है num_occur

(एक मिनट में सबस्ट्रिंग गिनती जोड़ देगा) किया

def get_that_string(h,l,alpha = "abc"):
    dic = {}
    s = ""
    ##costs 1 additional call per example, but its worth it
    char_list = [num_occur(j,h) for j in alpha[:-1]]
    char_list.append(l - sum(char_list))
    for y, z in zip(char_list,alpha):
        dic[z] = y
    end_reached = False
    while len(s) < l:
        for t in alpha:
            if not end_reached:
                neu_s = s + t
                substrings = [neu_s[i:]   for i in range(len(neu_s))]
            else:
                neu_s = t + s
                substrings = [neu_s[:i+1] for i in range(len(neu_s))]
            ## Test if we know that that can't be the next char
            all_in_d = [suff for suff in substrings if suff in dic.keys()]
            poss=all(map(dic.get,all_in_d))
            if poss:
                if not neu_s in dic.keys():
                    dic[neu_s] = num_occur(neu_s,h)
                if dic[neu_s] > 0:
                    s=neu_s
                    for suff in all_in_d:
                        dic[suff] -= 1
                    break
        else:
            end_reached = True
    ##print s
    return s


## test suite start
import urllib

def num_occur(needle, haystack):
    global calls
    calls += 1
    num = 0
    for i in range(len(haystack) - len(needle) + 1):
        if haystack[i : i + len(needle)] == needle:
            num += 1
    return num

calls = 0
url = "https://raw.githubusercontent.com/iatorm/random-data/master/abc_strings.txt"
inputs = urllib.urlopen(url).read().split("\n")
print "Check: ", inputs == map(lambda h: get_that_string(h, len(h)), inputs)
print "Calls: ", calls

4

पायथन 12705 12632 कॉल

  1. 2 वर्णों की घटनाओं की एक सूची बनाएं
  2. सूची को क्रमबद्ध करें
  3. सबसे संभावित चरित्र की कोशिश करने वाले स्ट्रिंग को पहले बनाएं, केवल एक संभावना होने पर परीक्षण न करें
  4. सूची अपडेट करें
  5. यदि सूची खाली है तो चरण 2 समाप्त हो गया है

मैंने लोजोवो फंक्शन कंकाल का इस्तेमाल किया। मैं पायथन में कभी भी कोड नहीं करता था मुझे एक बूटस्ट्रैप की आवश्यकता थी

संपादित करें: पहले से मिलान किए गए पैटर्न को अस्वीकार करने
के लिए एक वर्ण लंबाई के तार के लिए
जोड़ा गया कोड

def finds(S):

    if len(S) == 0:
            return ""
    if len(S) == 1 
            if num_occur("a",S) == 1 :
                         return "a"
            if num_occur("b",S) == 1 :
                         return "b"
            return "c"
    tuples=[]
    alphabet=[ "aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb"]
    for s in alphabet : tuples.append( (num_occur(s,S), s) )

    sum=0
    for (i,s) in tuples :   sum+=i
    tuples.append( (len(S)-sum-1, "cc") )
    tuples.sort(key=lambda x:(-x[0],x[1]))

    (i, current) = tuples[0]
    tuples[0] = (i-1, current)

    add_at_start = True
    nomatch=[]
    while len(tuples) > 0:
            worked = False
            tuples.sort(key=lambda x:(-x[0],x[1]))
            count=0
            if not add_at_start :
                    for (n, s) in tuples :
                            if s[0]==current[-1:] :         count+=1
            for i in range(len(tuples)):
                    (n, s)=tuples[i]
                    if add_at_start:
                            if current[0] == s[1] :
                                    current_new = s[0] + current
                                    possible=True
                                    for nm in nomatch :
                                            lng=len(nm)
                                            if current_new[0:lng] == nm :
                                                    possible=False
                                                    break
                                    if possible and num_occur(current_new, S) > 0:
                                            current = current_new
                                            worked = True
                                    else :
                                            nomatch.append(current_new)
                    else:
                            if current[-1:] == s[0] :
                                    current_new =  current + s[1]
                                    possible=True
                                    for nm in nomatch :
                                            lng=len(nm)
                                            if current_new[-lng:] == nm :
                                                    possible=False
                                                    break
                                    if count == 1 or (possible and num_occur(current_new, S) > 0) :
                                            current = current_new
                                            worked = True
                                    else :
                                            nomatch.append(current_new)
                    if worked :
                            if n == 1:
                                    del tuples[i]
                            else    :
                                    tuples[i] = (n-1, s)
                            break
            if not worked:
                    add_at_start = False
    return current

आपके वर्णमाला में कोई 'cc' नहीं है?
Sparr

@Sparr "cc" की गणना की जाती है, जो 100 कॉल बचाता है: `tuples.append ((len (S) -sum-1," cc "))`
Emmanuel
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.