यौगिक अंग्रेजी


28

एक यौगिक शब्द एक ऐसा शब्द है जिसमें 2 या अधिक शब्द होते हैं। हम हालांकि उससे बेहतर कर सकते हैं। हमें आपको 1 (निरर्थक) शब्द बनाने की आवश्यकता है जिसमें हर शब्द हो

हालाँकि, हम चाहते हैं कि यह शब्द यथासंभव छोटा हो। इसे प्राप्त करने के लिए हम अतिव्यापी अक्षरों का उपयोग कर सकते हैं।

उदाहरण के लिए, यदि आपकी शब्द सूची थी ["cat", "atom", "a"], तो आप वापस लौटना चाहेंगे "catom"

इनपुट आउटपुट

आपके कार्यक्रम को इनपुट के रूप में शब्दों की एक सूची लेनी होगी, और एक यौगिक शब्द को आउटपुट के रूप में वापस करना होगा।

Google के अनुसार, आपके द्वारा उपयोग की जाने वाली शब्द सूची अंग्रेजी में शीर्ष 10000 शब्द है (यदि यह सूची बहुत आसान हो गई है, तो मैं इसे लंबे समय तक बदल सकता हूं)। संदर्भ के लिए, बस प्रत्येक शब्द को जोड़ने से आपको 65888 अंक मिलते हैं।

आपका अंक आपके अंतिम शब्द में अक्षरों की संख्या है, कम बेहतर है। टाई ब्रेकर पहले पोस्टर पर जाता है।



1
@Lovjo नहीं, लेकिन अगर यह समाप्त हो जाता है कि bruteforcing तेजी से चलाने के लिए पर्याप्त है, तो मैं इसे लंबे समय तक बनाने के लिए शब्द सूची को बदल दूंगा।
नाथन मेरिल

1
@PatrickRoberts यदि यह आपके उत्तर में फिट बैठता है, तो आप को सहारा देता है :) एक pastebin / gist लिंक बहुत अच्छा होगा, लेकिन इसकी आवश्यकता नहीं है।
नाथन मेरिल

1
हम्म, जो एक अच्छा असममित ट्रैवलिंग सेल्समैन को जानता है?
डेव

2
कोई लपेटन नहीं, और हां निर्धारक के लिए।
नाथन मेरिल

जवाबों:


26

सी ++, अंतिम शब्द लंबाई: 38272

(अनुकूलित संस्करण में लगभग 20 मिनट लगे)

#include <iostream>
#include <string>
#include <vector>

std::size_t calcOverlap(const std::string &a, const std::string &b, std::size_t limit, std::size_t minimal) {
    std::size_t la = a.size();
    for(std::size_t p = std::min(std::min(la, b.size()), limit + 1); -- p > minimal; ) {
        if(a.compare(la - p, p, b, 0, p) == 0) {
            return p;
        }
    }
    return 0;
}

int main() {
    std::vector<std::string> words;

    // Load all words from input
    while(true) {
        std::string word;
        std::getline(std::cin, word);
        if(word.empty()) {
            break;
        }
        words.push_back(word);
    }

    std::cerr
        << "Input word count: " << words.size() << std::endl;

    // Remove all fully subsumed words

    for(auto p = words.begin(); p != words.end(); ) {
        bool subsumed = false;
        for(auto i = words.begin(); i != words.end(); ++ i) {
            if(i == p) {
                continue;
            }
            if(i->find(*p) != std::string::npos) {
                subsumed = true;
                break;
            }
        }
        if(subsumed) {
            p = words.erase(p);
        } else {
            ++ p;
        }
    }

    std::cerr
        << "After subsuming checks: " << words.size()
        << std::endl;

    // Sort words longest-to-shortest (not necessary but doesn't hurt. Makes finding maxlen a tiny bit easier)
    std::sort(words.begin(), words.end(), [](const std::string &a, const std::string &b) {
        return a.size() > b.size();
    });

    std::size_t maxlen = words.front().size();

    // Repeatedly combine most-compatible words until there is only one left
    std::size_t bestPossible = maxlen - 1;
    while(words.size() > 1) {
        auto bestA = words.begin();
        auto bestB = -- words.end();
        std::size_t bestOverlap = 0;
        for(auto p = ++ words.begin(), e = words.end(); p != e; ++ p) {
            if(p->size() - 1 <= bestOverlap) {
                continue;
            }
            for(auto q = words.begin(); q != p; ++ q) {
                std::size_t overlap = calcOverlap(*p, *q, bestPossible, bestOverlap);
                if(overlap > bestOverlap) {
                    bestA = p;
                    bestB = q;
                    bestOverlap = overlap;
                }
                overlap = calcOverlap(*q, *p, bestPossible, bestOverlap);
                if(overlap > bestOverlap) {
                    bestA = q;
                    bestB = p;
                    bestOverlap = overlap;
                }
            }
            if(bestOverlap == bestPossible) {
                break;
            }
        }
        std::string newStr = std::move(*bestA);
        newStr.append(*bestB, bestOverlap, std::string::npos);

        if(bestA == -- words.end()) {
            words.pop_back();
            *bestB = std::move(words.back());
            words.pop_back();
        } else {
            *bestB = std::move(words.back());
            words.pop_back();
            *bestA = std::move(words.back());
            words.pop_back();
        }

        // Remove any words which are now in the result
        for(auto p = words.begin(); p != words.end(); ) {
            if(newStr.find(*p) != std::string::npos) {
                std::cerr << "Now subsumes: " << *p << std::endl;
                p = words.erase(p);
            } else {
                ++ p;
            }
        }

        std::cerr
            << "Words remaining: " << (words.size() + 1)
            << " Latest combination: (" << bestOverlap << ") " << newStr
            << std::endl;

        words.push_back(std::move(newStr));
        bestPossible = bestOverlap; // Merging existing words will never make longer merges possible
    }

    std::string result = words.front();

    std::cout
        << result
        << std::endl;
    std::cerr
        << "Word size: " << result.size()
        << std::endl;
    return 0;
}

सत्यापन बैश वन-लाइनर:

cat commonwords.txt | while read p; do grep "$p" merged.txt >/dev/null || echo "Not found: $p"; done

इसने कुछ बहुत ही अच्छे इन-प्रोग्रेस शब्दों का भी उत्पादन किया। यहां मेरे कुछ पसंदीदा हैं:

  • पॉलीडेय (सिंथेटिक नॉस्टैल्जिया)
  • अफ़गानिस्तानबुल (कुछ [राजनेता डालें जिसे आप नापसंद करते हैं] कहेंगे)
  • साथ-साथ (अनुकूल इंटरनेट)
  • हाथी (एक बड़ा भूत)
  • थंडरग्राउंड वाटरप्रूफ (जैसा कि "मुझे नहीं पता कि उन्हें इसे थंडरग्राउंड वाटरप्रूफ बनाने की आवश्यकता क्यों महसूस हुई, लेकिन यह आपको परेशान कर रहा है")

तथा:

  • वर्णन करना (शायद इस साइट पर एक आगामी चुनौती?)

अंतिम आउटपुट यहाँ पास्टबिन पर है: http://pastebin.com/j3qYb65b


2
एक अवलोकन जो अन्य लोगों के लिए उपयोगी हो सकता है जो इष्टतम समाधान प्राप्त करना चाहते हैं: समस्या को एक गैर-यूक्लिडियन, असममित यात्रा सेल्समैन समस्या में कम किया जा सकता है: एक मैट्रिक्स को परिभाषित करें जहां तत्व i, j = max_word_length - overlap(word[i], word[j])(जहां overlapदाईं ओर से ओवरलैप की जांच करता है) पहले तर्क दूसरे के बाईं ओर)। इस (अच्छी किस्मत!) को हल करने के बाद परिणामी लूप को उच्चतम लागत (सबसे कम ओवरलैप) में काटकर, उन शब्दों की एक आदेशित सूची दी जाएगी जिन्हें एक इष्टतम समाधान देने के लिए विलय किया जा सकता है।
डेव

प्रभावशाली। क्या यह वर्तमान सूची के प्रत्येक शब्द को हर बार, हर बार, एक-दूसरे के खिलाफ जाँच रहा है? मैं इस पर विचार कर रहा था, लेकिन मान लिया कि मुझे एक उचित समय में इसे चलाने के लिए एक यादृच्छिक नमूने की जांच करनी होगी।
ट्राइकोप्लाक्स

1
@ValueInk हाँ कैशिंग एक बड़ा प्रदर्शन को बढ़ावा मिलेगा। पहले के संस्करण में ऐसा था, लेकिन इसमें बहुत अधिक जटिलता शामिल है, इसलिए जब मैंने कुछ तर्क को अनुकूलित किया तो मुझे फिर से लिखना पड़ा। इसके बजाय मैंने कैशिंग छोड़ना चुना। इसके अलावा नहीं, यह पूरी तरह से इष्टतम नहीं है। यह एक लालची एल्गोरिथ्म है, इसलिए यह ट्रेड-ऑफ्स का न्याय नहीं कर सकता है, और यह "समान रूप से अच्छे" विकल्पों में से चुनने में असमर्थ है। (NP- हार्ड) इष्टतम समाधान के लिए मेरी TSP टिप्पणी देखें।
डेव

1
@trichoplax हाँ, यह क्या कर रहा है। रनिंग टाइम O (n ^ 3) है, जो इस नमूने के आकार के लिए इतना बुरा नहीं है। कैशिंग के साथ इसे O (n ^ 2) तक कम किया जा सकता है। आंतरिक जांच भी बहुत समानांतर है, इसलिए बड़े नमूनों के लिए भी यह थ्रेडिंग / वितरित संगणना के साथ उचित समय में चल सकता है। इसके अलावा इस हर कदम, जिनमें से 10 एक पहलू से क्रम में कटौती के लिए संभव ओवरलैप चौड़ाई की सीमा जानने से एक बड़ा गति को बढ़ावा देने हो जाता है
डेव

2
यह सामान्य टीएसपी जितना कठिन नहीं हो सकता है, क्योंकि हमारे पास मज़ेदार बाधा है जो ओवरलैप (ए, बी) (मिनट {ओवरलैप (ए, डी), ओवरलैप (सी, डी), ओवरलैप (सी, बी)} सभी के लिए है , बी, सी, डी।
एंडर्स कासोर्ग

21

सी ++ 11, 38272 अक्षर, सिद्ध इष्टतम

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

यह निम्न प्रकार से निर्मित नेटवर्क पर न्यूनतम-लागत प्रवाह समस्या को हल करके काम करता है ।

  • पहला, अन्य शब्दों में निहित कोई भी शब्द निरर्थक है; उन्हें त्याग दो।
  • प्रत्येक शब्द w के लिए , दो नोड्स w _0 और w _1 खींचें , जहां w _0 क्षमता 1 के साथ एक स्रोत है और w _1 क्षमता 1 के साथ एक सिंक है।
  • हर (सख्त) उपसर्ग या प्रत्यय के लिए एक किसी भी शब्द का, एक नोड आकर्षित एक
  • हर प्रत्यय के लिए एक की डब्ल्यू , से एक चाप बनाएं डब्ल्यू करने के लिए _0 एक क्षमता 1 के साथ और लागत 0।
  • हर उपसर्ग के लिए एक की डब्ल्यू , से एक चाप बनाएं एक करने के लिए डब्ल्यू क्षमता 1 और लागत लंबाई (साथ _1 डब्ल्यू लंबाई (-) एक )।

प्रत्येक शब्द में लंबाई n के किसी भी तार को इस नेटवर्क पर प्रवाह में परिवर्तित किया जा सकता है जिसमें अधिकांश n लागत होती है । इसलिए, इस नेटवर्क पर न्यूनतम लागत प्रवाह कम से कम इस तरह की स्ट्रिंग की लंबाई पर बाध्य है।

अगर हम भाग्यशाली-और इस मामले हम कर रहे हैं-तो हम प्रवाह में आने के बाद पुन: निर्देशित में डब्ल्यू की _1 वापस बाहर w _0, हम एक इष्टतम प्रवाह सिर्फ एक जुड़ा घटक है कि और खाली के लिए नोड के माध्यम से है कि गुजरता मिलेगा स्ट्रिंग। यदि हां, तो इसमें एक यूलरियन सर्किट शुरू और समाप्त होगा। इस तरह के एक यूलरियन सर्किट को इष्टतम लंबाई की एक स्ट्रिंग के रूप में वापस पढ़ा जा सकता है।

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

मैं अपने न्यूनतम लागत प्रवाह और Eulerian सर्किट एल्गोरिदम के लिए LEMON पुस्तकालय का उपयोग करता हूं । (इस पुस्तकालय का उपयोग करते हुए यह मेरा पहला अवसर था, और मैं प्रभावित हुआ था- भविष्य के ग्राफ एल्गोरिथ्म की आवश्यकता के लिए मैं इसे फिर से उपयोग करूँगा।) लेमोन चार अलग-अलग न्यूनतम-लागत प्रवाह एल्गोरिदम के साथ आता है; आप उन लोगों के साथ यहाँ की कोशिश कर सकते --net, --cost, --cap, और --cycle(डिफ़ॉल्ट)।

कार्यक्रम 0.5 सेकंड में चलता है , इस आउटपुट स्ट्रिंग का निर्माण करता है

#include <iostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <lemon/core.h>
#include <lemon/connectivity.h>
#include <lemon/euler.h>
#include <lemon/maps.h>
#include <lemon/list_graph.h>
#include <lemon/network_simplex.h>
#include <lemon/cost_scaling.h>
#include <lemon/capacity_scaling.h>
#include <lemon/cycle_canceling.h>

using namespace std;

typedef lemon::ListDigraph G;

struct Word {
    G::Node suffix, prefix;
    G::Node tour_node;
};

struct Edge {
    unordered_map<string, Word>::iterator w;
    G::Arc arc;
};

struct Affix {
    vector<Edge> suffix, prefix;
    G::Node node;
    G::Node tour_node;
};

template<class MCF>
bool solve(const G &net, const G::ArcMap<int> &lowerMap, const G::ArcMap<int> &upperMap, const G::ArcMap<int> &costMap, const G::NodeMap<int> &supplyMap, int &totalCost, G::ArcMap<int> &flowMap)
{
    MCF mcf(net);
    if (mcf.lowerMap(lowerMap).upperMap(upperMap).costMap(costMap).supplyMap(supplyMap).run() != mcf.OPTIMAL)
        return false;
    totalCost = mcf.totalCost();
    mcf.flowMap(flowMap);
    return true;
}

int main(int argc, char **argv)
{
    clog << "Reading dictionary from stdin" << endl;
    unordered_map<string, Affix> affixes;
    unordered_map<string, Word> words;
    unordered_set<string> subwords;
    G net, tour;
    G::ArcMap<int> lowerMap(net), upperMap(net), costMap(net);
    G::NodeMap<int> supplyMap(net);
    string new_word;
    while (getline(cin, new_word)) {
        if (subwords.find(new_word) != subwords.end())
            continue;
        for (auto i = new_word.begin(); i != new_word.end(); ++i) {
            for (auto j = new_word.end(); j != i; --j) {
                string s(i, j);
                words.erase(s);
                subwords.insert(s);
            }
        }
        words.emplace(new_word, Word());
    }
    for (auto w = words.begin(); w != words.end(); ++w) {
        w->second.suffix = net.addNode();
        supplyMap.set(w->second.suffix, 1);
        w->second.prefix = net.addNode();
        supplyMap.set(w->second.prefix, -1);
        for (auto i = w->first.begin(); ; ++i) {
            affixes.emplace(string(w->first.begin(), i), Affix()).first->second.prefix.push_back(Edge {w});
            affixes.emplace(string(i, w->first.end()), Affix()).first->second.suffix.push_back(Edge {w});
            if (i == w->first.end())
                break;
        }
        w->second.tour_node = tour.addNode();
    }
    for (auto a = affixes.begin(); a != affixes.end();) {
        if (a->second.suffix.empty() || a->second.prefix.empty() ||
            (a->second.suffix.size() == 1 && a->second.prefix.size() == 1 &&
             a->second.suffix.begin()->w == a->second.prefix.begin()->w)) {
            affixes.erase(a++);
        } else {
            a->second.node = net.addNode();
            supplyMap.set(a->second.node, 0);
            for (auto &e : a->second.suffix) {
                e.arc = net.addArc(e.w->second.suffix, a->second.node);
                lowerMap.set(e.arc, 0);
                upperMap.set(e.arc, 1);
                costMap.set(e.arc, 0);
            }
            for (auto &e : a->second.prefix) {
                e.arc = net.addArc(a->second.node, e.w->second.prefix);
                lowerMap.set(e.arc, 0);
                upperMap.set(e.arc, 1);
                costMap.set(e.arc, e.w->first.length() - a->first.length());
            }
            a->second.tour_node = lemon::INVALID;
            ++a;
        }
    }

    clog << "Read " << words.size() << " words and found " << affixes.size() << " affixes; ";
    clog << "created network with " << countNodes(net) << " nodes and " << countArcs(net) << " arcs" << endl;

    int totalCost;
    G::ArcMap<int> flowMap(net);
    bool solved;
    if (argc > 1 && string(argv[1]) == "--net") {
        clog << "Using network simplex algorithm" << endl;
        solved = solve<lemon::NetworkSimplex<G>>(net, lowerMap, upperMap, costMap, supplyMap, totalCost, flowMap);
    } else if (argc > 1 && string(argv[1]) == "--cost") {
        clog << "Using cost scaling algorithm" << endl;
        solved = solve<lemon::CostScaling<G>>(net, lowerMap, upperMap, costMap, supplyMap, totalCost, flowMap);
    } else if (argc > 1 && string(argv[1]) == "--cap") {
        clog << "Using capacity scaling algorithm" << endl;
        solved = solve<lemon::CapacityScaling<G>>(net, lowerMap, upperMap, costMap, supplyMap, totalCost, flowMap);
    } else if ((argc > 1 && string(argv[1]) == "--cycle") || true) {
        clog << "Using cycle canceling algorithm" << endl;
        solved = solve<lemon::CycleCanceling<G>>(net, lowerMap, upperMap, costMap, supplyMap, totalCost, flowMap);
    }

    if (!solved) {
        clog << "error: no solution found" << endl;
        return 1;
    }
    clog << "Lower bound: " << totalCost << endl;

    G::ArcMap<string> arcLabel(tour);
    G::Node empty = tour.addNode();
    affixes.find("")->second.tour_node = empty;
    for (auto &a : affixes) {
        for (auto &e : a.second.suffix) {
            if (flowMap[e.arc]) {
                if (a.second.tour_node == lemon::INVALID)
                    a.second.tour_node = tour.addNode();
                arcLabel.set(tour.addArc(e.w->second.tour_node, a.second.tour_node), "");
            }
        }
        for (auto &e : a.second.prefix) {
            if (flowMap[e.arc]) {
                if (a.second.tour_node == lemon::INVALID)
                    a.second.tour_node = tour.addNode();
                arcLabel.set(tour.addArc(a.second.tour_node, e.w->second.tour_node), e.w->first.substr(a.first.length()));
            }
        }
    }

    clog << "Created tour graph with " << countNodes(tour) << " nodes and " << countArcs(tour) << " arcs" << endl;

    G::NodeMap<int> compMap(tour);
    int components = lemon::stronglyConnectedComponents(tour, compMap);
    if (components != 1) {
        vector<unordered_map<string, Affix>::iterator> breaks(components, affixes.end());
        for (auto a = affixes.begin(); a != affixes.end(); ++a) {
            if (a->second.tour_node == lemon::INVALID)
                continue;
            int c = compMap[a->second.tour_node];
            if (c == compMap[empty])
                continue;
            auto &b = breaks[compMap[a->second.tour_node]];
            if (b == affixes.end() || b->first.length() > a->first.length())
                b = a;
        }
        int offset = 0;
        for (auto &b : breaks) {
            if (b != affixes.end()) {
                arcLabel.set(tour.addArc(empty, b->second.tour_node), b->first);
                arcLabel.set(tour.addArc(b->second.tour_node, empty), "");
                offset += b->first.length();
            }
        }
        clog << "warning: Found " << components << " components; solution may be suboptimal by up to " << offset << " letters" << endl;
    }

    if (!lemon::eulerian(tour)) {
        clog << "error: failed to make tour graph Eulerian" << endl;
        return 1;
    }

    for (lemon::DiEulerIt<G> e(tour, empty); e != lemon::INVALID; ++e)
        cout << arcLabel[e];
    cout << endl;

    return 0;
}

हालांकि मैं यह समझने का दावा नहीं कर सकता कि मिन प्रवाह कैसे काम करता है, अगर यह वास्तव में इष्टतम है, अच्छी तरह से किया गया है!
नाथन मेरिल

1
निराशा के लिए खेद: PI ने एक प्रवाह नेटवर्क के बारे में नहीं सोचा था; यह बहुत सुंदर है। मुझे समझने में थोड़ा समय लगा कि आप अपने नेटवर्क में शब्दों को एक साथ कैसे जोड़ रहे हैं, इससे पहले कि मैं अंत में महसूस करूं "हर (सख्त) उपसर्ग या किसी भी शब्द के प्रत्यय के लिए, एक नोड खींचें जिसका अर्थ है कि नोड्स" ए "के बीच साझा किया जा सकता है कई शब्द।
डेव

1
इसके अलावा आपका समाधान मेरा से लगभग 2,000 गुना तेज है!
डेव

1
शायद इस आदमी ( cs.cmu.edu/~tom7/portmantout ) को एक समान काम में उसके प्रयास से मदद करें ?
ओलिवर डौगर्टी-लॉन्ग

2
@ ओलिवरडॉगर्टी-लॉन्ग डन ! (वास्तविक समय के लिए।) सबसे पहले ज्ञात सीमाएं 520732 ≤ इष्टतम लंबाई 37 537136 थीं, और मेरा मानना ​​है कि मैंने दोनों सीमाएं 536186 में सुधार की हैं।
एंडर्स केसेर्ग

13

जावा 8, ~ 5 मिनट, लंबाई 39,279

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

public class Words {

    public static void main(String[] args) throws Throwable {
        File file = new File("words.txt");
        List<String> wordsList = new ArrayList<>();
        BufferedReader reader = new BufferedReader(new FileReader(file));
        String line;
        while ((line = reader.readLine()) != null) {
            wordsList.add(line);
        }
        reader.close();

        Set<String> words = new HashSet<>();

        System.out.println("Finished I/O");

        for (int i = 0; i < wordsList.size(); i++) { //Step 1: remove any words that occur in other words
            boolean in = false;
            for (int j = 0; j < wordsList.size(); j++) {
                if (i != j && wordsList.get(j).contains(wordsList.get(i))) {
                    in = true;
                    break;
                }
            }
            if (!in) {
                words.add(wordsList.get(i));
            }
        }

        System.out.println("Removed direct containers");

        List<String> working = words.stream().sorted((c, b) -> Integer.compare(c.length(), b.length())).collect(Collectors.toList()); //Sort by length, shortest first
        StringBuilder result = new StringBuilder();
        result.append(working.get(0));
        while (!working.isEmpty()) {
            Optional<String> target = working.stream().sorted((c, b) -> Integer.compare(firstLastCommonality(result.toString(), b), firstLastCommonality(result.toString(), c))).findFirst(); //Find the string that has the greatest in common with the end of 'result'
            if(target.isPresent()) { //It really should be present, but just in case
                String s = target.get();
                working.remove(s);
                int commonality = firstLastCommonality(result.toString(), s);
                s = s.substring(commonality);
                result.append(s);
            }
        }

        System.out.println("Finished algorithm");

        String r = result.toString();
        System.out.println("The string: \n" + r);
        System.out.println("Length: \n" + r.length());
        System.out.println("Verified: \n" + !wordsList.stream().filter(s -> !r.contains(s)).findFirst().isPresent());
    }

    private static int firstLastCommonality(String a, String b) {
        int count = 0;
        int len = b.length();
        while (!a.endsWith(b) && !b.equals("")) {
            b = cutLastChar(b);
            count++;
        }
        return len - count;
    }

    private static String cutLastChar(String string) {
        if (string.length() - 1 < 0) {
            return string;
        } else {
            return string.substring(0, string.length() - 1);
        }
    }

}

इनपुट:

  • एक फाइल जिसे वर्क वर्ड्स में 'words.txt' कहा जाता है, मुख्य पोस्ट में फाइल की तरह ही सटीक स्वरूप में है

आउटपुट:

Finished I/O
Removed direct containers
Finished algorithm
The string: 
[Moved to pastebin](http://pastebin.com/iygyR3zL)
Length: 
39279
Verified: 
true

2
FGITW, और जावा में कोई कम नहीं। आप सर मेरा वोट है
पैट्रिक रॉबर्ट्स

2
अच्छा! आपने 26,609वर्णों से छुटकारा पा लिया ।
आर। काप

@ आर.कैप जाओ आंकड़ा! मैंने यह गणना करने के लिए भी नहीं सोचा था कि ... एक चालाक एल्गोरिथ्म होना चाहिए, हालांकि, यह सिर्फ पहली चीज है जो दिमाग में आई ...
सुकराती फीनिक्स

7

पायथन 2, 39254 वर्ण

मेरी मशीन पर चलने के लिए 1-2 मिनट लगते हैं, सबसे लंबे समय तक शब्द लेने से काम करता है और फिर हमेशा शब्द को परिणाम स्ट्रिंग में जोड़ देता है जिसमें सबसे अधिक तार होते हैं। (इससे पहले वे सभी शब्द जो दूसरे शब्दों के सबस्ट्रिंग हैं, स्ट्रिंग में अनावश्यक जोड़ को रोकने के लिए हटा दिए जाते हैं।)

अद्यतन: दोनों दिशाओं में देखने की कोशिश की, लेकिन यह किसी भी बेहतर नहीं है। (शायद यह उन शब्दों का उपयोग कर रहा है जो बाद में बेहतर उपयोग किए जा सकते हैं?)

पास्टबिन पर शब्द का लिंक।

पहले 100 वर्ण:

telecommunicationsawayneillegallynnbabyenbcjrxltdxmlbsrcwvtxxxboxespnycdsriconsentencessexyrsslipodc

कोड:

import re
import urllib

def suffix_dist(w1,w2):
    for i in range(min(map(len,[w1,w2])))[::-1]:
        if w1[-i:]==w2[:i]:
            return i
    return 0

url="https://raw.githubusercontent.com/first20hours/google-10000-english/master/google-10000-english.txt"
s=urllib.urlopen(url).read()
words=s.split()
words.sort(key=len,reverse=True)

## remove words that are substrings of other words anyway
for i in range(len(words))[::-1]:
    if any(words[i] in w for w in words[:i]):
        words.pop(i)

print len(words)

words.sort(key=len)
w1=words.pop(-1)
result=w1
while words:
    ## get the word with longest shared suffix/prefix
    w2=max(words,key=lambda x:suffix_dist(w1,x))
    print w2
    words.pop(words.index(w2))
    if w2 in result:
        break
    result+=w2[suffix_dist(w1,w2):]
    w1=w2


print result[:100]
print len(result)
print "Test:", all(w in result for w in s.split())

2
वेल्ड, मुझे 25 पात्रों द्वारा पीटा गया है ... इसके लिए +1
सुकराती फीनिक्स

अच्छा काम! मेरे पास एक समान विचार था लेकिन आपके पास पहले से ही एक उत्तर था। मेरा संस्करण एक बड़े शब्द के बजाय एक छोटे शब्द से शुरू होता है, साथ ही कुछ अन्य छंटाई जो इसे समय के कारक पर बहुत कम करने का कारण बनता है, को चलाने के लिए समय की मात्रा को 3x तक ले जाता है।
वैल्यू इंक

5

रूबी, 39222 वर्ण

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

मेरी मशीन पर 4 मिनट से अधिक में चलता है, शब्दों की सूची को पुनः प्राप्त करने के लिए वेब अनुरोध की गिनती नहीं, लेकिन काफी 4:20 नहीं।

पास्टबिन पर शब्द।

require 'net/http'

puts "Obtaining word list..."
data = Net::HTTP.get(URI'https://raw.githubusercontent.com/first20hours/google-10000-english/master/google-10000-english.txt')
puts "Word list obtained!"

puts "Starting calculation..."
time = Time.now

words = data.split.sort_by(&:size)
words.reject!{|w| words.find{|x| w!=x && x.include?(w)}}

string = words.shift

def merge_dist(prefix, suffix)
    [prefix.size,suffix.size].min.downto(0).find{|i| prefix.end_with?(suffix[0,i])}
end

while words.length > 0
    suffix = words.max_by{|w| merge_dist string, w}
    string += suffix[merge_dist(string, suffix)..-1]
    words.reject!{|w| string.include? w}
end

delta = Time.now - time

puts "Calculation completed in #{delta} seconds!"
puts "Word is #{string.size} chars long."

open("word.txt", 'w') << string

puts "Word saved to word.txt"

3

PowerShell v2 +, 46152 वर्ण

param([System.Collections.ArrayList]$n)$n=$n|sort length -des;while($n){$x=$n.Count;$o+=$n[0];0..$x|%{if($o.IndexOf($n[$_])-ge0){$n.RemoveAt($_)}}}$o

एक सूची के रूप में इनपुट लेता है, इसे एक ArrayList में सम्मिलित करता है (इसलिए हम इसे हेरफेर कर सकते हैं)। हम sortइसे क्रम lengthमें -desरखते हैं। फिर, whileहमारे पास अभी भी हमारे इनपुट ऐरे में शब्द हैं, एक लूप करते हैं। प्रत्येक पुनरावृत्ति, सेट करने के लिए सहायक $xके बराबर है कि हमने कितने को छोड़ दिया है, हमारे आउटपुट में सूची में अगले आइटम पर $oव्यवहार करें, और फिर हमारी सूची में अभी भी सब कुछ के माध्यम से ट्रैवेल करें। यदि यह (यानी, शब्द कहीं पाया गया था ) के .IndexOfबराबर नहीं है , तो हम उस शब्द को अपनी शेष शब्दों की सूची से हटा देते हैं। अंत में, आउटपुट ।-1$o$o

मेरे पास एक पास्टबीन या इसी तरह की पहुंच नहीं है, इसलिए यहां अस्थायी के लिए शब्द की शुरुआत और अंत है - telecommunicationscharacterizationresponsibilitiessublimedirectory...fcmxvtwvfxwujmjsuhjjrxjdbkdxqc। जो मुझे लगता है कि इनपुट से लगभग 20,000 वर्णों को काट दिया गया है, इसलिए यह बुरा नहीं है, मुझे लगता है।

मैं शोधन पर काम कर रहा हूँ।


0

PHP 46612 अक्षर

यह तो केवल एक शुरुआत है। मुझे इसमें सुधार की उम्मीद है। अब तक मैंने जो भी किया है वह किसी भी शब्द को हटा दें जो दूसरे शब्द का उप-स्ट्रिंग है। मैं सरणी की 3 प्रतियों पर काम कर रहा हूं, लेकिन स्मृति एक मुद्दा नहीं लगती है।

<?php
set_time_limit(3000);

$words=file('https://raw.githubusercontent.com/first20hours/google-10000-english/master/google-10000-english.txt');
$words = array_map('trim', $words);

usort($words, function ($a, $b)
{
    if (strlen($a) == strlen($b) ){
        return 0;
    }
    return ( strlen($a) < strlen($b) )? -1 : 1;
});

$final_array=$words;
$comparison_array=$words;


  foreach($words as $key => $word){
    echo $word."<br>\n";
      foreach($comparison_array as $nestedKey => $nestedWord){
          if (strlen($nestedWord) <= strlen($word)) {
            unset($comparison_array[$nestedKey]);
            continue;
          }
          if( strpos($nestedWord,$word) !== FALSE ){
              unset($final_array[$key]);
              $restart=true;
              break;
          } 
      }    
  }


sort($final_array);
$compound='';
$compound = implode($final_array);
echo $compound;
echo "  <br><br>\n\n". strlen($compound);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.