Bileşik ingilizce


28

Bir bileşik kelime, içinde 2 veya daha fazla kelime içeren bir kelimedir. Bundan daha iyisini yapabiliriz. Her kelimeyi içeren 1 (saçma) kelimeyi yaratmanız gerekiyor .

Ancak, bu kelimenin mümkün olduğunca kısa olmasını istiyoruz. Bunu başarmak için üst üste gelen harfleri kullanabiliriz.

Örneğin, kelime listeniz ["cat", "atom", "a"]olsaydı, geri dönmek isterdiniz "catom".

Giriş çıkış

Programınızın giriş olarak kelimelerin bir listesini alması ve bileşik bir kelimeyi çıktı olarak döndürmesi gerekecektir.

Kullanacağınız kelime listesi , Google’a göre İngilizce’deki en iyi 10000 kelimedir . Başvuru için, sadece her bir kelimeyi eklemek size 65888 puan verir.

Puanınız, son kelimenizdeki harf sayısı, düşük puan daha iyidir. Kravat kırıcı ilk postere gider.



1
@Loovjo hayır, ancak sonuçta bruteforcing'in çalışacak kadar hızlı olması durumunda, o zaman daha uzun yapmak için kelime listesini değiştiririm.
Nathan Merrill

1
@PatrickRoberts Cevabınıza uyuyorsa, size aittir :) Bir pastebin / gist bağlantısı harika olurdu, ama gerekli değil.
Nathan Merrill,

1
Hmm, kim iyi bir asimetrik seyahat satıcısı sezgisel bilir?
Dave

2
Kaydırma yok ve deterministik için evet.
Nathan Merrill

Yanıtlar:


26

C ++, son kelime uzunluğu: 38272

(optimize edilmiş sürüm yaklaşık 20 dakika sürdü)

#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;
}

Doğrulama bash bir-liner:

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

Aynı zamanda bazı güzel devam eden kelimeler üretti. İşte benim favorilerimden bazıları:

  • polyesterday (sentetik nostalji)
  • afghanistanbul (bir şey [sevmediğiniz bir politikacı ekleyin] derdi)
  • togethernet (arkadaş canlısı internet)
  • elephantom (büyük bir hayalet)
  • thundergroundwaterproof ("Neden thundergroundwaterproof yapılması gerektiğini hissettiklerini bilmiyorum, ama bu beni tedirgin ediyor")

Ve:

  • codescribingo (bu sitede belki yaklaşmakta olan bir mücadele?)

Son çıktı burada pastebin üzerinde: http://pastebin.com/j3qYb65b


2
Sorun, bir Öklid olmayan, asimetrik seyyar satıcı sorununa azaltılabilir: Diğer uygun çözüm elde etmek için ideal bir yararlı olabilir bir gözlem bir matris tanımlar burada eleman, j = max_word_length - overlap(word[i], word[j])( overlapkontrol üst üste binme sağdan ikincisinin solundaki ilk argüman). Bunun çözülmesi (iyi şanslar!) Ve ardından elde edilen döngünün en düşük maliyetle kesilmesi (en düşük örtüşme), optimum bir çözüm elde etmek için birleştirilebilecek sıralı bir sözcük listesi verecektir.
Dave

Etkileyici. Bu, mevcut listedeki her kelimeyi, her seferinde birbirine karşı mı kontrol ediyor? Bunu düşünüyordum ama makul bir sürede çalışması için rastgele bir örneği kontrol etmem gerektiğini düşündüm.
trichoplax

1
@ValueInk evet önbellekleme büyük bir performans artışı olur. Daha eski bir versiyonda buna sahipti, ancak çok fazla karmaşıklık ekliyor, bu yüzden bazı mantıkları uyarladığımda tekrar yazmam gerekiyordu. Bunun yerine önbelleklemeyi bırakmayı seçtim. Ayrıca hayır, bu tamamen optimal değil. Açgözlü bir algoritma olduğundan takasları yargılayamaz ve “eşit derecede iyi” seçenekler arasında seçim yapamaz. (NP-Hard) optimal çözüm için TSP yorumuma bakın.
Dave

1
@trichoplax yup, öyle yapıyor. Çalışma süresi O (n ^ 3), bu örneklem büyüklüğü için fena değil. Önbelleğe alma ile O (n ^ 2) 'ye düşürülebilir. İç kontrol de çok paraleldir, bu nedenle daha büyük numuneler için bile diş açma / dağıtma işlemiyle makul sürede çalışabilir. Ayrıca bu, çalışma süresini
Dave

2
Bu, genel TSP kadar zor olmayabilir, çünkü hepimiz için üst üste (a, b) ≥ min {üst üste (a, d), üst üste (c, d), üst üste (c, b)} komik kısıtlama getirilmiştir. , b, c, d.
Anders Kaseorg

21

C ++ 11, 38272 harf, en uygunluğu kanıtlandı

Bu algoritmanın çözüme daha düşük bir sınır getireceği garanti edilir. Bu durumda, alt sınır elde etmek ve optimal bir 38272 harf çözümü elde etmek mümkün. (Bu Dave'in açgözlü algoritması tarafından bulunan çözüme uyuyor. Şaşırdım ve optimal olduğunu keşfetmek için biraz hayal kırıklığına uğradım.)

Aşağıdaki gibi inşa edilen ağdaki minimum maliyet akış problemini çözerek çalışır .

  • İlk olarak, başka bir deyişle içerdiği herhangi bir kelime gereksizdir; onları atın.
  • Her w kelimesi için , w _0 ve w _1 olan iki düğümü çiziniz; burada w _0, 1 kapasiteli bir kaynak ve w _1, 1 kapasiteli bir lavabodur.
  • Her (katı) önek veya sonek için bir herhangi bir kelimenin, bir düğüm çizmek a .
  • Her eki için a ait ağırlık , bir yay çizmek ağırlık için _0 bir kapasite 1 ve 0 maliyet.
  • Her önek için a ait ağırlık , bir yay çizmek bir üzere ağırlık kapasitesi 1 ve maliyet uzunluğu ile (_1 ağırlık uzunluk (-) bir ).

Her sözcüğü içeren herhangi bir uzunluk n uzunluğu bu ağdaki bir akışa dönüştürülebilir ve maliyeti en fazla n'dir . Bu nedenle, bu ağdaki minimum maliyet akışı, bu tür en kısa dize uzunluklarında daha düşük bir sınırdır.

Biz iseniz şanslı-ve bu durumda biz-o zaman akış gelen yönlendirmek sonra w arasında _1 arka dışarı w _0' dan , sadece bir bağlı bileşene sahip olan ve boş için düğümden geçen en uygun akışı bulacağız. dize. Eğer öyleyse, orada başlayan ve biten bir Eulerian devre içerecektir. Böyle bir Eulerian devre en uygun uzunlukta bir dizi olarak okunabilir.

Şanslı olmasaydık, bir Eulerian devrenin var olduğundan emin olmak için boş dize ile diğer bağlı bileşenlerde bulunan en kısa dizeler arasına biraz fazla yay ekleyin. Dize artık bu durumda mutlaka uygun olmaz.

I kullanma LiMON onun dakika ekonomik akış ve Euler devre algoritmalar için kütüphane. (Bu kütüphaneyi ilk kez kullanıyordum ve çok etkilendim - Gelecekteki grafik algoritması ihtiyaçları için kesinlikle tekrar kullanacağım.) LEMON, dört farklı minimum maliyetli akış algoritmasıyla geliyor; Onları buraya deneyebilirsiniz ile --net, --cost, --cap, ve--cycle (varsayılan).

Program , bu çıkış dizesini üreterek 0,5 saniyede çalışır .

#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;
}

Min akışının nasıl çalıştığını anladığımı iddia edemesem de, bu gerçekten uygunsa, aferin!
Nathan Merrill,

1
Hayal kırıklığına uğrattığım için üzgünüm: PI bir akış ağı düşünmemişti; bu oldukça zarif. Sonunda farkına varmadan önce ağınızdaki kelimeleri nasıl bağladığınızı anlamam biraz zaman aldı "Herhangi bir kelimenin her (katı) ön eki veya soneki için," a "düğümlerinin" arasında paylaşılabileceği anlamına gelen bir düğüm çizin. Birden çok kelime.
Dave,

1
Ayrıca çözümün benimkinden yaklaşık 2.000 kat daha hızlı!
Dave,

1
Belki bu adama ( cs.cmu.edu/~tom7/portmantout ) benzer bir şeye teşebbüsünde yardım eder ?
Oliver Daugherty-Long

2
@ OliverDaugherty-Uzun Yapıldı ! (Bu sefer gerçekte.) Daha önce bilinen en iyi sınırlar 520732 ≤ optimal uzunluk ≤ 537136 idi ve sanırım her iki sınırı da 536186'ya yükselttim.
Anders Kaseorg

13

Java 8, ~ 5 Dakika, 39.279 Uzunluk

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);
        }
    }

}

Giriş:

  • Ana dizindeki dosyayla aynı biçimde, çalışma dizininde 'words.txt' adında bir dosya

Çıktı:

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

2
FGITW ve Java'da daha az değil. Efendim benim oyum var.
Patrick Roberts

2
Güzel! 26,609Karakterlerden kurtuldun .
R. Kap,

@ R.Kap git figürü! Bu akla gelen sadece ilk şey ... olduğunu olsa bile daha akıllı algoritması olmalı ... o hesaplamak düşünmüyordu
Sokrates Phoenix

7

Python 2,39254 karakter

Makinemde çalışması 1-2 dakika sürüyor, en uzun kelimeyi alarak çalışıyor ve ardından her zaman ortak olarak en çok dizeye sahip olan sonuç dizisine sözcüğü ekliyor. (Bundan önce, diğer kelimelerin alt dizeleri olan tüm kelimeler, dizgiye gereksiz yere eklenmesini önlemek için silinir.

Güncelleme: Her iki yöne de bakmaya çalıştım, ancak bu daha iyi bir şey değil (belki daha sonra daha iyi kullanılabilecek kelimeler kullanıyor?)

Pastebin üzerindeki kelimeye link.

ilk 100 karakter:

telecommunicationsawayneillegallynnbabyenbcjrxltdxmlbsrcwvtxxxboxespnycdsriconsentencessexyrsslipodc

Kod:

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
Welp, 25 karakter tarafından dövüldüm ... Bunun için +1
Socratic Phoenix

İyi iş! Ben de benzer bir fikrim vardı ama zaten bir cevap aldın. Sürümüm büyük bir kelime yerine küçük bir sözcükle başlıyor, artı zamanın 3 katına kadar çıkarak zaman faktörü üzerinde ciddi bir şekilde kaybedilmesine neden olan başka bir budama.
Value Ink,

5

Ruby, 39222 karakter

Python cevabında @KarlKastor için benzer bir yaklaşım kullanır, ancak başlangıç ​​dizesi en büyük yerine en küçük kelimelerden biridir. Diğer bir optimizasyon (ne kadar yardımcı olduğunu bilmiyorum), her ekleme arasında, üst üste gelen kelimelerden dolayı dizgede bulunan tüm kelimeleri budanırır.

Makinemde 4 dakikadan biraz fazla sürüyor, sözcük listesini almak için web isteğini saymıyor, ancak saat 4:20 değil.

Pastebin'deki kelime.

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 karakter

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

Girişi liste halinde alır, ArrayList'e dönüştürür (böylece değiştirebiliriz). Biz sortbunu lengthiçinde -desdüzeni cending. Sonra, whilegiriş dizimizde hala kelimeler var, bir döngü yapın. Her bir yineleme, yardımcı $xmaddeyi kalan ne kadarımıza eşit olacak şekilde ayarladı , listedeki bir sonraki öğeyi $oçıktımıza sokun ve daha sonra hala listemizdeki her şeyi dolaştırın. Eğer .IndexOfeşit değil -1(yani kelime içinde bir yerlerde bulunmuştur $o), biz kalan kelimelerin listemizden o kelimeyi kaldırın. Sonunda, sonunda, çıktı$o .

Bir Pastebin veya benzeri bir siteye erişimim yok, bu yüzden işte geçici - için kelimenin başlangıcı ve sonu telecommunicationscharacterizationresponsibilitiessublimedirectory...fcmxvtwvfxwujmjsuhjjrxjdbkdxqc. Sanırım bu girişten yaklaşık 20.000 karakter çıktı, sanırım o kadar da kötü değil.

İyileştirmeler üzerinde çalışıyorum.


0

PHP 46612 karakter

Bu sadece bir başlangıç. Bunu iyileştirmeyi umuyorum. Şimdiye kadar yaptığım tek şey, başka bir kelimenin alt dizesi olan herhangi bir kelimeyi kaldırmak. Dizinin 3 kopyası üzerinde çalışıyorum, ancak bellek bir sorun gibi görünmüyor.

<?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);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.