চক্রবৃদ্ধি ইংরেজি


28

যৌগিক শব্দটি এমন একটি শব্দ যা এর মধ্যে 2 বা ততোধিক শব্দ থাকে। যদিও আমরা এর থেকে আরও ভাল করতে পারি। আমাদের আপনার 1 টি (অযৌক্তিক) শব্দ তৈরি করতে হবে যাতে প্রতিটি শব্দ থাকে

তবে আমরা চাই এই শব্দটি যতটা সম্ভব সংক্ষিপ্ত হোক be আমরা এটি অর্জন করতে ওভারল্যাপিং অক্ষর ব্যবহার করতে পারি।

উদাহরণস্বরূপ, যদি আপনার শব্দ তালিকা ছিল ["cat", "atom", "a"], আপনি আসতে চায় "catom"

ইনপুট আউটপুট

আপনার প্রোগ্রামটি ইনপুট হিসাবে শব্দের একটি তালিকা নিতে হবে এবং আউটপুট হিসাবে একটি যৌগিক শব্দ ফিরে আসতে হবে।

গুগলের মতে আপনি যে শব্দটি তালিকাটি ব্যবহার করবেন তা হ'ল ইংরেজের শীর্ষ 10000 শব্দ words (যদি এই তালিকাটি খুব সহজ হয়ে যায় তবে আমি এটি আরও দীর্ঘতে পরিবর্তন করতে পারি)। রেফারেন্সের জন্য, কেবলমাত্র প্রতিটি শব্দ যুক্ত করা আপনাকে 65888 এর স্কোর দেয়।

আপনার স্কোরটি আপনার চূড়ান্ত শব্দের অক্ষরের সংখ্যা, কম ভাল। টাই ব্রেকার প্রথম পোস্টারে যায়।



1
@ লভজো না, তবে যদি এটি শেষ হয়ে যায় যে ব্রুটফোর্সিং চালানোর পক্ষে যথেষ্ট দ্রুত, তবে আমি আরও দীর্ঘ করতে শব্দ তালিকাটি পরিবর্তন করব।
নাথান মেরিল

1
@ পেট্রিকরোবার্টস যদি এটি আপনার উত্তরে ফিট করে তবে আপনাকে প্রপস করুন :) একটি পেস্টবিন / গিস্ট লিঙ্কটি দুর্দান্ত হবে, তবে এটির প্রয়োজন নেই।
নাথান মেরিল

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
@ ভ্যালিউইঙ্ক হ্যাঁ ক্যাশিং একটি দুর্দান্ত পারফরম্যান্সের উত্সাহ হবে। পূর্ববর্তী সংস্করণটিতে এটি ছিল, তবে এটি অনেক জটিলতা যুক্ত করে, তাই যখন আমি কিছু যুক্তিটি গ্রহণ করি তখন আমাকে আবার অনেকগুলি লিখতে হয়েছিল। পরিবর্তে আমি ক্যাচিং ড্রপ করতে বেছে নিয়েছি। এছাড়াও না, এটি সম্পূর্ণ অনুকূল নয়। এটি একটি লোভী অ্যালগরিদম তাই এটি ট্রেড-অফগুলির বিচার করতে পারে না এবং এটি "সমানভাবে ভাল" বিকল্পগুলির মধ্যে নির্বাচন করতে অক্ষম। (এনপি-হার্ড) অনুকূল সমাধানের জন্য আমার টিএসপি মন্তব্য দেখুন।
ডেভ

1
@ থ্রিচোপ্লেক্স হ্যাঁ, এটিই করছে। চলমান সময় হ'ল ও (এন is 3), যা এই নমুনা আকারের পক্ষে খুব খারাপ নয়। ক্যাচিংয়ের সাহায্যে এটি O (n ^ 2) এ হ্রাস করা যেতে পারে। অভ্যন্তরীণ চেকটিও খুব সমান্তরাল-কার্যকর, তাই এমনকি বৃহত্তর নমুনাগুলির জন্যও এটি থ্রেডিং / বিতরণকৃত গণনার সাথে যুক্তিসঙ্গত সময়ে চলতে পারে। এছাড়াও এটি প্রতিটি পদক্ষেপের জন্য সম্ভাব্য ওভারল্যাপ প্রস্থের পরিধিটি জেনে এক বড় গতি বাড়িয়ে তোলে, যা রানটাইমকে 10 এর একটি ফ্যাক্টর দ্বারা কেটে দেয়
ডেভ

2
এটি সাধারণ টিএসপির মতো কঠিন হতে পারে না, কারণ আমাদের কাছে মজার সীমাবদ্ধতা রয়েছে যে ওভারল্যাপ (ক, খ) ≥ মিনিট {ওভারল্যাপ (ক, ডি), ওভারল্যাপ (সি, ডি), ওভারল্যাপ (সি, বি) a , বি, সি, ডি।
অ্যান্ডারস ক্যাসরগ

21

সি ++ 11, 38272 অক্ষর, প্রমাণিত সর্বোত্তম

এই অ্যালগরিদমটি সমাধানটির উপর একটি নিম্ন সীমা সরবরাহ করার গ্যারান্টিযুক্ত। এই ক্ষেত্রে, এটি নিম্ন সীমাবদ্ধ এবং একটি সর্বোত্তম 38272 অক্ষর সমাধান আউটপুট অর্জন করতে সক্ষম। (এটি ডেভের লোভী অ্যালগরিদমের সন্ধানের সমাধানের সাথে মেলে। আমি অবাক হয়ে গিয়েছিলাম এবং আবিষ্কার করে যে এটি সর্বোত্তম, তবে আমরা সেখানে রয়েছি।)

এটি নীচে নির্মিত নেটওয়ার্কে সর্বনিম্ন ব্যয় প্রবাহের সমস্যা সমাধানের মাধ্যমে কাজ করে।

  • প্রথমত, অন্য শব্দের মধ্যে থাকা কোনও শব্দই বাজে; এগুলি বাতিল করুন।
  • প্রত্যেক শব্দ জন্য W , দুই নোড আঁকা W _0 এবং W _1, যেখানে W _0 ধারণক্ষমতা 1 এবং একটি উৎস W _1 ধারণক্ষমতা 1 একটি বেসিনে হয়।
  • প্রত্যেক (প্রখর) উপসর্গ বা প্রত্যয় জন্য একটি কোনো শব্দের, একটি নোড আঁকা একটি
  • প্রত্যেক প্রত্যয় জন্য একটি এর W থেকে একটি চাপ আঁকা W করার _0 একটি ধারণক্ষমতা 1 এবং খরচ 0।
  • প্রত্যেক উপসর্গ জন্য একটি এর W থেকে একটি চাপ আঁকা একটি থেকে W ধারণক্ষমতা 1 এবং খরচ দৈর্ঘ্য (সঙ্গে _1 W দৈর্ঘ্য (-) একটি )।

দৈর্ঘ্য n এর যে কোনও স্ট্রিংয়ে প্রতিটি শব্দ রয়েছে এটি বেশিরভাগ এন ব্যয়ে এই নেটওয়ার্কের প্রবাহে রূপান্তরিত হতে পারে । সুতরাং, এই নেটওয়ার্কটিতে সর্বনিম্ন ব্যয়ের প্রবাহ হ'ল সংক্ষিপ্ততর স্ট্রিংয়ের দৈর্ঘ্যের উপর কম আবদ্ধ।

আমরা যদি করছি ভাগ্যবান-এবং এই ক্ষেত্রে আমরা-তারপর আমরা প্রবাহ উদ্ভেদ পুনর্নির্দেশ পরে W এর _1 ফিরে আউট W _0, আমরা একটি অনুকূল প্রবাহ মাত্র এক সংযুক্ত উপাদান আছে যা খালি জন্য নোড মাধ্যমে পাস পাবেন স্ট্রিং। যদি তা হয় তবে এটিতে একটি ইউুলেরিয়ান সার্কিট থাকবে এবং এটি এখানে শেষ হবে। এই জাতীয় একটি ইউরোলিয়ান সার্কিট অনুকূল দৈর্ঘ্যের স্ট্রিং হিসাবে আবার পড়তে পারে।

যদি আমরা ভাগ্যবান না হয়ে থাকি তবে ইউলেরিয়ান সার্কিটের অস্তিত্ব রয়েছে তা নিশ্চিত করার জন্য অন্যান্য সংযুক্ত উপাদানগুলির মধ্যে খালি স্ট্রিং এবং সংক্ষিপ্ততম স্ট্রিংগুলির মধ্যে কিছু অতিরিক্ত আরাকস যুক্ত করুন। সেই ক্ষেত্রে স্ট্রিংটি আর সর্বোত্তমভাবে হবে না।

আমি লেমন লাইব্রেরিটি এর ন্যূনতম ব্যয়ের প্রবাহ এবং ইউলেরিয়ান সার্কিট অ্যালগরিদমের জন্য ব্যবহার করি। (এই গ্রন্থাগারটি ব্যবহার করার এটি আমার প্রথমবার ছিল, এবং আমি মুগ্ধ হয়েছিলাম future ভবিষ্যতের গ্রাফ অ্যালগরিদম প্রয়োজনের জন্য আমি অবশ্যই এটি আবার ব্যবহার করব)) লেমন চারটি ন্যূনতম ব্যয়ের প্রবাহ অ্যালগরিদম নিয়ে আসে; আপনি তাদের সঙ্গে এখানে চেষ্টা করে দেখতে পারেন --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
হতাশার জন্য দুঃখিত: পিআই কোনও ফ্লো নেটওয়ার্কের কথা ভাবেনি; এটা বেশ মার্জিত। "কীভাবে আপনি আপনার নেটওয়ার্কে শব্দগুলিকে একসাথে সংযুক্ত করছেন তা বুঝতে আমাকে কিছুটা সময় নিয়েছিল অবশেষে" প্রতিটি (কড়া) উপসর্গ বা কোনও শব্দের প্রত্যয়ের জন্য, একটি নোড আঁক "এর অর্থ নোডগুলি" এ "এর মধ্যে ভাগ করা যায় একাধিক শব্দ
ডেভ

1
এছাড়াও আপনার সমাধানটি আমার চেয়ে প্রায় ২ হাজার গুণ বেশি দ্রুত!
ডেভ

1
সম্ভবত এই লোকটিকে ( cs.cmu.edu/~tom7/portmantout ) অনুরূপ কিছুতে চেষ্টা করার সাথে সাহায্য করতে পারেন ?
অলিভার ডাওগার্টি-লং

2
অলিভারডৌগার্টি-লং ডোন ! (এই সময়ের জন্য বাস্তবের জন্য।) এর আগে সর্বাধিক পরিচিত সীমাগুলি ছিল 520732 ti অনুকূল দৈর্ঘ্য and 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);
        }
    }

}

ইনপুট:

  • ওয়ার্কিং ডিরেক্টরিতে ওয়ার্ডস.টেক্সট নামে একটি ফাইল, মূল পোস্টের ফাইলের মতো ঠিক একই ফর্ম্যাটে

আউটপুট:

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 টি অক্ষর

তার পাইথন উত্তরে @ কার্লকাস্টোরের অনুরূপ পন্থা ব্যবহার করে, তবে প্রথম স্ট্রিংটি বৃহত্তমটির পরিবর্তে ক্ষুদ্রতম শব্দের মধ্যে একটি। আরেকটি অপ্টিমাইজেশন (আমি জানি না এটি কতটা সাহায্য করে) হ'ল প্রতিটি সংযোজনের মধ্যে এটি ওভারল্যাপিং শব্দের কারণে ইতিমধ্যে স্ট্রিংয়ের অন্তর্ভুক্ত থাকা কোনও শব্দকে ছাঁটাই করে দেয়।

আমার মেশিনে 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

পাওয়ারশেল ভি 2 +, 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

ইনপুটটিকে একটি তালিকা হিসাবে নিয়ে যায়, এটি অ্যারেলিস্টে কাস্ট করে (যাতে আমরা এটি পরিচালনা করতে পারি)। আমরা sortতা lengthমধ্যে -desঅর্ডার cending। তারপরে, whileআমাদের ইনপুট অ্যারেতে এখনও শব্দ রয়েছে, একটি লুপ করুন। প্রতিটি পুনরাবৃত্তি, সহায়কটিকে $xআমরা কয়টি রেখেছি সমান হতে সেট করে আমাদের আউটপুটে তালিকার পরবর্তী আইটেমটি টেক করুন $oএবং তারপরে এখনও আমাদের তালিকায় থাকা সমস্ত কিছুতে ট্রল করুন। যদি এর .IndexOfসমান না হয় -1(অর্থাত্ শব্দটি কোথাও কোথাও পাওয়া গিয়েছিল $o), আমরা সেই শব্দটি আমাদের বাকী শব্দের তালিকা থেকে সরিয়ে দেব। শেষ পর্যন্ত, আউটপুট $o

আমার কাছে কোনও পাস্তবিন বা অনুরূপ অ্যাক্সেস নেই, তাই এখানে অস্থায়ী জন্য শব্দের শুরু এবং শেষ - telecommunicationscharacterizationresponsibilitiessublimedirectory...fcmxvtwvfxwujmjsuhjjrxjdbkdxqc। আমার ধারণা, যা ইনপুট থেকে প্রায় 20,000 অক্ষর মুণ্ডন করেছে, তাই মনে হয় খারাপ নয়।

আমি সংশোধন কাজ করছি।


0

পিএইচপি 46612 অক্ষর

এটি শুধুমাত্র শুরু। আমি এটি উন্নতি আশা করি। আমি এখন পর্যন্ত যা কিছু করেছি তা হ'ল যে কোনও শব্দ অন্য শব্দের একটি সাব-স্ট্রিং remove আমি অ্যারে 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);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.