Compressão de placa Boggle


18

Ao trabalhar no Boggl poliglota não palindrômico , achei bastante entediante colocar os códigos da maneira mais eficiente possível na placa do Boggle, mesmo com apenas duas seqüências de caracteres. Mas somos programadores, certo? Nós sabemos como automatizar as coisas.

Dada uma lista de strings, você deve gerar um quadro Boggle no qual cada uma dessas strings pode ser encontrada (independentemente das outras). O desafio é tornar o quadro do Boggle o menor possível. Como essa é (espero) uma tarefa bastante difícil, esse é um : não há requisito para otimizar - o desafio é fazê-lo da melhor maneira possível.

Regras

  • O quadro do Boggle será retangular e conterá apenas letras maiúsculas. Portanto, as seqüências de entrada também conterão apenas letras maiúsculas.
  • As regras usuais do Boggle se aplicam: uma string faz parte do quadro se, começando em qualquer lugar, você puder encontrá-la movendo-se repetidamente para caracteres adjacentes (horizontal, vertical ou diagonal). Para formar uma única sequência, você não pode usar nenhuma célula do quadro mais de uma vez. No entanto, os caracteres podem ser reutilizados entre cadeias diferentes.
  • Você tem 30 minutos para processar os dados de teste e seu código não deve usar mais de 4 GB de memória. Darei um pouco de margem de manobra no limite de memória, mas se o seu programa usar consistentemente mais de 4 GB ou picos significativamente acima dele, eu o desqualificarei (temporariamente).
  • Testarei todos os envios em minha própria máquina, que está executando o Windows 8. Eu tenho uma VM do Ubuntu, mas se tiver que testar, você não poderá usar tanto os 30 minutos quanto o contrário. Inclua um link para um intérprete / compilador gratuito para o idioma escolhido, além de instruções sobre como compilar / executar seu código.
  • Sua pontuação será do tamanho do quadro do Boggle para os dados de teste abaixo (sem contar as novas linhas). No caso de empate (por exemplo, porque várias pessoas conseguiram produzir uma solução ideal), o vencedor será o envio que produzirá essa solução ideal mais rapidamente.
  • Você não deve otimizar seu código especificamente para os dados de teste. Se eu suspeito que alguém o faça, reservo-me o direito de gerar novos dados de teste.

Exemplo

Dadas as cordas

FOO
BAR
BOOM

Uma vez, você poderia colocá-los trivialmente em uma placa Boggle 4x3:

FOOX
BARX
BOOM

Fazendo uso do fato de que as strings não precisam ser retas, podemos compactá-las para 5x2:

BORFO
OMABO

Mas podemos torná-lo ainda menor reutilizando caracteres entre diferentes cadeias e ajustando-as em 4x2:

FOOM
BARX

Agora o Bé usado para ambos BOOMe BAR, e o OOé usado para ambos BOOMe FOO.

Dados de teste

Seu envio será testado nas 50 seqüências a seguir. Para fins de teste, você pode simplesmente usar subconjuntos menores desses dados, que devem ser executados mais rapidamente. Eu acredito que o limite inferior absoluto para esses dados de teste é uma placa com 120 caracteres, embora isso não seja necessariamente possível.

T
WP
GVI
CIHM
EGWIV
QUTYFZ
LWJVPNG
XJMJQWSW
JLPNHFDUW
SWMHBBZWUG
XVDBMDQWDEV
TIUGAVZVUECC
IWDICFWBPSPQR
MMNWFBGMEXMSPY
YIHYXGJXKOUOIZA
BZSANEJNJWWNUJLJ
XTRMGOVPHVZYLLKKG
FLXFVVHNTWLMRRQYFQ
VZKJRAFQIYSBSXORTSH
FNQDIGCPALCHVLHDNZAV
GEAZYFSBSWCETXFKMSWLG
KWIZCEHVBDHEBGDGCJHOID
SKMQPHJAPDQKKHGTIPJCLMH
ZSFQDNYHALSUVWESQVVEUIQC
HXHBESUFCCECHNSTQGDUZPQRB
DSLXVHMOMLUXVHCNOJCBBRPVYB
DVTXKAOYYYRBVAVPSUAOYHIPPWN
PJAIYAWHMTNHTQDZDERPZYQEMLBZ
SYNSHJNOIWESMKWTBIANYUAUNRZOS
WADGUKIHUUFVRVUIBFUXQIOLAWIXAU
LGLXUFIXBEPSOFCKIAHXSHVKZPCXVPI
LIUYFHITTUYKDVQOZPNGZLWOZSRJTCTZ
IZDFTFFPNEBIYGVNTZHINICBXBXLBNBAL
BSKQNTPVUAVBXZGHVZCOUCRGCYISGFGYAS
DPGYYCIKDGCETXQOZGEQQLFQWACMVDTRYAT
RQDNIPGUHRYDRVHIPJLOWKBXMIBFAWCJGFMC
PFKOAGEQLXCMISSVEARWAPVYMRDCLSLPJOMQQ
EQPCNHQPTWABPFBVBXHQTFYELPNMNCWVKDDKGR
RAHTJMGIQJOJVWJBIHVRLJYVCSQJCKMEZRGRJMU
SZBJBPQYVYKDHAJHZMHBEWQEAQQKIEYCFACNLJBC
ANVDUCVXBPIZVRAXEBFEJOHSYKEKBIJELPIWEYXKH
DJUNPRLTISBFMGBEQNXSNUSOGDJNKESVKGAAMTIVXK
TZPUHDSHZFEURBNZTFBKXCDPYRELIAFMUWDIQTYWXGU
FJIKJROQSFSZUCGOOFJIEHBZREEUUSZWOLYFPCYHUSMR
TPMHJEAWVAJOCSDOPMQMHKRESBQSTRBXESYGCDVKLFOVS
ABJCCDJYMYDCYPZSGPGIAIKZQBYTZFDWYUZQBOESDSDGOY
IIHKTVPJNJDBCBOHCIYOPBKOVVKGNAKBDKEEKYIPRPHZOMF
IABGEPCSPNSMLVJBSGLRYNFSSYIALHWWAINTAVZAGJRVMDPW
GFMFVEFYJQJASVRIBLULUEHPMZPEXJMHIEMGJRMBLQLBDGTWT
YPWHLCVHQAVKVGHMLSOMPRERNHVYBECGCUUWTXNQBBTCMVTOVA

Verificador

Você pode usar o seguinte snippet de pilha para verificar se um quadro do Boggle contém todas as seqüências de caracteres em uma determinada lista. Eu portado o código de pesquisa Boggle da resposta do edc65 aqui . Deixe-me saber se algo parece com erros.

Respostas:


6

C ++ 11, pontuação = 992 1024

O algoritmo é realmente estúpido, mas até agora ninguém mais fez um sério, então eu o publicarei. Coloca mais ou menos aleatoriamente as palavras em um quadro quadrado e recomeça se não conseguir ajustá-las. Ele tenta maximizar a sobreposição com as palavras existentes, mas de uma maneira realmente ineficiente.

Editar: pontuação aprimorada adicionando 1 a um comprimento lateral e tentando um retângulo depois de falhar 50 vezes. Também classifique as seqüências de entrada por tamanho, em vez de aleatoriamente a ordem.

#include <iostream>
#include <cstring>
#include <string>
#include <random>
#include <algorithm>
using namespace std;

struct grid {
    char *g;
    int h,w;
    grid(int h, int w):h(h),w(w) {
        g = new char[h*w];
        memset(g,0,h*w*sizeof(*g));
    }
    grid(const grid &o) {
        h=o.h, w=o.w;
        g = new char[h*w];
        memcpy(g,o.g,h*w*sizeof(*g));
    }
    grid(grid &&o) {
        h=o.h, w=o.w;
        g = o.g;
        o.g = 0;
    }
    grid& operator=(const grid &o) {
        h=o.h, w=o.w;
        memcpy(g,o.g,h*w*sizeof(*g));
        return*this;
    }
    grid& operator=(grid &&o) {
        h=o.h, w=o.w;
        g = o.g;
        o.g = 0;
        return*this;
    }
    char& operator()(int i, int j) {
        return g[i*w+j];
    }
    ~grid() { delete []g; }
};
typedef struct { int n, i, j; grid g; } ng;


const int qmax = 140;
const bool sizesort = true;
const int maxtries = 50;

inline int sq(int x){return x*x;}
bool operator<(const ng &a, const ng& b) {return a.n < b.n;}
void search(vector<string>& s) {
    int tl = 0;
    for(auto&x: s) tl += x.size();
    int l = 0;
    while(l*l < tl) l++;
    vector<string*> v;
    for(size_t i = 0; i < s.size(); i++) v.push_back(&s[i]);
    struct{bool operator()(string*a,string*b){return a->size()>b->size();}} scmp;
    if(sizesort) sort(v.begin(), v.end(), scmp);
    mt19937 rng;
    for(;;l--) {
        int tries = 0;
        int side2 = l;
        retry:
        tries++;
        if(!sizesort) shuffle(v.begin(), v.end(), rng);

        if(tries == maxtries) cout<<"rectangle",side2++;
        grid g(l,side2);

        for(string* x: v) {
            string& z = *x;
            vector<ng> p;
            for(int i = 0; i < g.h; i++)
            for(int j = 0; j < g.w; j++) {
                if(g(i,j) && g(i,j) != z[0]) continue;
                p.push_back({!g(i,j), i,j, g});
                p.back().g(i,j) = z[0]|32;
            }
            for(size_t zi = 1; zi < z.size(); zi++) {
                vector<ng> p2;
                for(ng &gg: p) {
                    for(int i = max(gg.i-1,0); i <= min(gg.i+1,g.h-1); i++)
                    for(int j = max(gg.j-1,0); j <= min(gg.j+1,g.w-1); j++) {
                        if(!gg.g(i,j) || gg.g(i,j) == z[zi]) {
                            p2.push_back({gg.n+!g(i,j),i,j,gg.g});
                            p2.back().g(i,j) = z[zi]|32;
                        }
                    }
                }
                shuffle(p2.begin(), p2.end(), rng);
                sort(p2.begin(), p2.end());
                if(p2.size() > qmax) p2.erase(p2.begin() + qmax, p2.end());
                p = move(p2);
            }
            if(p.empty()) goto retry;
            g = p[0].g;
            for(int i = 0; i < g.h; i++)
            for(int j = 0; j < g.w; j++)
                g(i,j) &= ~32;
        }
        cout<<g.w*g.h;
        for(int i = 0; i < g.h; i++) {
            cout<<'\n';
            for(int j = 0; j < g.w; j++)
                cout<<(g(i,j)?g(i,j):'X');
        }
        cout<<endl;
    }
}

int main()
{
    vector<string> v = {"T","WP","GVI","CIHM","EGWIV","QUTYFZ","LWJVPNG","XJMJQWSW","JLPNHFDUW","SWMHBBZWUG","XVDBMDQWDEV","TIUGAVZVUECC","IWDICFWBPSPQR","MMNWFBGMEXMSPY","YIHYXGJXKOUOIZA","BZSANEJNJWWNUJLJ","XTRMGOVPHVZYLLKKG","FLXFVVHNTWLMRRQYFQ","VZKJRAFQIYSBSXORTSH","FNQDIGCPALCHVLHDNZAV","GEAZYFSBSWCETXFKMSWLG","KWIZCEHVBDHEBGDGCJHOID","SKMQPHJAPDQKKHGTIPJCLMH","ZSFQDNYHALSUVWESQVVEUIQC","HXHBESUFCCECHNSTQGDUZPQRB","DSLXVHMOMLUXVHCNOJCBBRPVYB","DVTXKAOYYYRBVAVPSUAOYHIPPWN","PJAIYAWHMTNHTQDZDERPZYQEMLBZ","SYNSHJNOIWESMKWTBIANYUAUNRZOS","WADGUKIHUUFVRVUIBFUXQIOLAWIXAU","LGLXUFIXBEPSOFCKIAHXSHVKZPCXVPI","LIUYFHITTUYKDVQOZPNGZLWOZSRJTCTZ","IZDFTFFPNEBIYGVNTZHINICBXBXLBNBAL","BSKQNTPVUAVBXZGHVZCOUCRGCYISGFGYAS","DPGYYCIKDGCETXQOZGEQQLFQWACMVDTRYAT","RQDNIPGUHRYDRVHIPJLOWKBXMIBFAWCJGFMC","PFKOAGEQLXCMISSVEARWAPVYMRDCLSLPJOMQQ","EQPCNHQPTWABPFBVBXHQTFYELPNMNCWVKDDKGR","RAHTJMGIQJOJVWJBIHVRLJYVCSQJCKMEZRGRJMU","SZBJBPQYVYKDHAJHZMHBEWQEAQQKIEYCFACNLJBC","ANVDUCVXBPIZVRAXEBFEJOHSYKEKBIJELPIWEYXKH","DJUNPRLTISBFMGBEQNXSNUSOGDJNKESVKGAAMTIVXK","TZPUHDSHZFEURBNZTFBKXCDPYRELIAFMUWDIQTYWXGU","FJIKJROQSFSZUCGOOFJIEHBZREEUUSZWOLYFPCYHUSMR","TPMHJEAWVAJOCSDOPMQMHKRESBQSTRBXESYGCDVKLFOVS","ABJCCDJYMYDCYPZSGPGIAIKZQBYTZFDWYUZQBOESDSDGOY","IIHKTVPJNJDBCBOHCIYOPBKOVVKGNAKBDKEEKYIPRPHZOMF","IABGEPCSPNSMLVJBSGLRYNFSSYIALHWWAINTAVZAGJRVMDPW","GFMFVEFYJQJASVRIBLULUEHPMZPEXJMHIEMGJRMBLQLBDGTWT","YPWHLCVHQAVKVGHMLSOMPRERNHVYBECGCUUWTXNQBBTCMVTOVA"};
    search(v);
    return 0;
}

O quadro:

TGBHXEXMPYTECWBSFYOXKXKXFSQJXKXX
UZBWMLJKSXXPIXSVYYXATVDLVOCVCXMT
WWPSJGBUFWPOUHPAKRZMXIPCHHXJYEAX
SQPBNXFQNMLAYSQVBGAESYGWQJOVXJZY
RJXWJJDWMNSGFUQXSEAWXBMIJAYWLRTR
XMXFEIWIHTIHIGMOJTKVARJNPSVFJVDG
XJHNCGCCQXTYLSJHVNOJXHTSCKERBHMR
XVCLACEDGTCCDGLPMCJXXMQMQPVGIAJC
DLZSFPURZYUGRKENTWSDPVLSHBFFHBMA
HNBUQYZPDOKNMYDDVBBOGJBQGKSMLUWQ
XXZRSEBQNCQDPVFNKSSQNCDLXERPMSLF
XKVAIHMHTGZVUXPTQUSXXGEBRXEZHOUQ
XRJUXYNLQFJLHAVQPNNXTCXYMRJPKEQH
FAPIHATDBSWXWGBHCQHPBWUVNMJGKGVP
XQVVWMLJRZZOVRZXESFQTAUFHIMLLYZV
XIWXUSOQTXTLSEABVBIPXGXSYEAEMGOX
WEYQCBIUXCNSJKGRFZXTBXXSMFLIRYPQ
XGSBIPFLPAMIBEEMVEJLXDWDUBHTYXDX
XQSUXIZQGFOCPLKSUOAREVYQDWDVXCTA
XXVEBKXLEKCIOFYYHCBJPCTKIAWKIMZE
ORVEUGVIXYEWFPCCDJCNUDANHIBODFCI
XTOFPUSHKQXAZYDYIYOBJZVZBFMXLGOU
SZNSCXHLWQQSGCTQMBPDGAXXTRACJJXO
HRUAUKIAXEUOPGUIKWRJMNKKDGUWPBGK
ZVEYNGDNBUEOJIAZQORVGBDSEEOYIYXX
VMHCCAIBHRHFAESSBXVJKQOSKYFZHVPB
ALEVJPTWLMZJHXXFJYXIZUEFLIGUSRRB
GZCBDHPKMXXBXDSBTZJDUYVXNQPPHDYC
UIPJQKEQSBNICKYPNEFHWVHFDFRUZOJX
KWTGKXGBEOIJHNVQFBTLNTNMYXLTXNMX
DIOHJCXDGWHZTSGYIFJPMRRQOMXVHCFX

4

Python 3, pontuação = 1225

Nesta solução, usamos apenas 1 linha. A partir da string vazia em cada etapa, adicionamos a palavra que garante a maior sobreposição possível. (As palavras estão marcadas nas quatro orientações possíveis.)

Isso fornece uma pontuação de 1225, que é 50 inferior à pontuação de 1275, para concatenar todas as palavras, sem sobreposição.

O resultado:

CBJLNCAFCYEIKQQAEQWEBHMZHJAHDKYVYQPBJBZSFQDNYHALSUVWESQVVEUIQCMFGJCWAFBIMXBKWOLJPIHVRDYRHUGPINDQRQPSPBWFCIDWIPVXCPZKVHSXHAIKCFOSPEBXIFUXLGLWSMKFXTECWSBSFYZAEGWIVGNPVJWLIUYFHITTUYKDVQOZPNGZLWOZSRJTCTZPUHDSHZFEURBNZTFBKXCDPYRELIAFMUWDIQTYWXGUWZBBHMWSKMQPHJAPDQKKHGTIPJCLMHICCEUVZVAGUITAYRTDVMCAWQFLQQEGZOQXTECGDKICYYGPDIOHJCGDGBEHDBVHECZIWKXVITMAAGKVSEKNJDGOSUNSXNQEBGMFBSITLRPNUJDSLXVHMOMLUXVHCNOJCBBRPVYBZSANEJNJWWNUJLJLPNHFDUWPDMVRJGAZVATNIAWWHLAIYSSFNYRLGSBJVLMSNPSCPEGBAIZDFTFFPNEBIYGVNTZHINICBXBXLBNBALQUTYFZBLMEQYZPREDZDQTHNTMHWAYIAJPFKOAGEQLXCMISSVEARWAPVYMRDCLSLPJOMQQFYQRRMLWTNHVVFXLFNQDIGCPALCHVLHDNZAVOTVMCTBBQNXTWUUCGCEBYVHNRERPMOSLMHGVKVAQHVCLHWPYPSMXEMGBFWNMMXJMJQWSWADGUKIHUUFVRVUIBFUXQIOLAWIXAUMJRGRZEMKCJQSCVYJLRVHIBJWVJOJQIGMJTHARGKDDKVWCNMNPLEYFTQHXBVBFPBAWTPQHNCPQEXVDBMDQWDEVZKJRAFQIYSBSXORTSHXHBESUFCCECHNSTQGDUZPQRBSKQNTPVUAVBXZGHVZCOUCRGCYISGFGYASYNSHJNOIWESMKWTBIANYUAUNRZOSVOFLKVDCGYSEXBRTSQBSERKHMQMPODSCOJAVWAEJHMPTWTGDBLQLBMRJGMEIHMJXEPZMPHEULULBIRVSAJQJYFEVFMFGKKLLYZVHPVOGMRTXYIHYXGJXKOUOIZANVDUCVXBPIZVRAXEBFEJOHSYKEKBIJELPIWEYXKHDVTXKAOYYYRBVAVPSUAOYHIPPWNFJIKJROQSFSZUCGOOFJIEHBZREEUUSZWOLYFPCYHUSMRABJCCDJYMYDCYPZSGPGIAIKZQBYTZFDWYUZQBOESDSDGOYIIHKTVPJNJDBCBOHCIYOPBKOVVKGNAKBDKEEKYIPRPHZOMF

O código:

import sys

def com_len(a,b):
    for i in range(min(len(a),len(b)),-1,-1):
        if (a[-i:] if i else '')==b[:i]:
            return i

def try_s(a,b,sn,mv):
    v=com_len(a,b)
    if v>mv:
        return a+b[v:],v
    return sn,mv

ws=[w.rstrip() for w in sys.stdin.readlines()]
s=''
while ws:
    mv=-1
    sn=None
    mi=None
    for i in range(len(ws)):
        mvo=mv
        for a in [s,s[::-1]]:
            for b in [ws[i],ws[i][::-1]]:
                sn,mv=try_s(a,b,sn,mv)
        if mvo<mv:
            mi=i
    s=sn
    del ws[mi]
print(s)

4

C, pontuação 1154

AVOTVMCTBBQNXTWUUCGCEBYVHNRERPMOSLMHGVKVAQHVCLHWPYGOSUNSXNQEBGMFBSITLRPNUJDXJMHIEMGJRMBLQLBDGTWTWVJOJQIGMJTHARYPDCXKBFTZNBRUEFZHSDHUPZTCUZSFSQORJKIJFYNDQFSZOWLZGNPZOQVDKYUTTIHFYUILHWWAINTAVZAGJRVMDPWPQRBEAWVAJOCSDOPMQMHKRESBQSTRBXESYGCDVKLFOVSOYNUAUYNAIBTWKMSEWIONJHSNYSKYVYQPBJBZSOHCIYOPBKOVVKGNAKBDKEEKYIPRPHZOMFGJCWAFBIMXBKWOLJPIHVRDYRHUGPINDQRQPSPBWFCIDWIVPAWRAEVSSIMCXLQEGAOKFPFFTFDZIWLMRRQYFQSXORTSHLUXVHCNOJCBBRPVYBMKSNTPVUAVBXZGHVZCOUCRGCYISGFGYASOZGEQQLFQWACMVDTRYATIAJPVUECCYFSBSWCETXFKMSWLGFUUHIKUGDAWIYXCPZKVHSXHAIKCFOSPEBXIFUXLGLJNHFDUWSWQJMJXWSMXEMGBFWNMMGOVPHVZY
NDUCVXBPIZVRAEBFEJOHSYKEKBIJLPIWEYXKKXITMAGKSEKNJDFMFVEFYJQJASVRILULUEHMZPEUMRGRZKCJQSCVYJRVHIBJUGXWYTDWUFAILERMSUHYCPYLOWZSUERBEIJFOOGQIEVVQEWVUSLAHZTCTJRIABGEPCSNSMLJBSGLRYNFSSYAXHBESUFCCECHNSTQGUZTMHJABJCCDYMYDCYZSGPGIAIKZBYZFDWYUZQBOESDSDGZRCBJLNCAFCYEIQQAQEBHMZJAHDIIHKTVJNDCBNWPPHAUSPVABRYYYOAKXTVDWQDMBDVXCRGKDDKVWCNNPLEYFTQHXBBFPBAWTPQHCPEQMOJLSLCDRMYLABNBLXBXBCNIHZTNVYIBENLXVVHNTVZKJAFISBDLVHMOMCJPITGHKKQDPAJHPQBSQKWIZCEHDHEBDGCJHIDDPYYCKDCETXQZBLMYZPREDZDQTHNMHWYUGVZIWGAZUAXIWALOIQUBIUVRVAZIOUOXJXYHPVAZNDHLCLAPCGDQNBZANJNJWWNUJLPGPVJWLGUZBBHMYPHICQUTYZXTRVIXGKKLL

Use duas linhas para que palavras recém-adicionadas possam reutilizar as letras da linha superior.

char l[2][2000];
char s[2][2000];
char w[100][200];
int d[200];
void pri() {
    puts(l[0]);
    puts(l[1]);
}
void sav() { memcpy(s,l,sizeof(l)); }
void res() { memcpy(l,s,sizeof(l)); }
int fit(char *t, int l0, int l1) {
    if (!*t) return 0;
    if (l[0][l0] == *t && (l0 <= l1 || l[1][l1])) return 1+fit(t+1,l0+1,l1+(l1<l0));
    if (l[1][l1] == *t && (l1 <= l0 || l[0][l0])) return 1+fit(t+1,l0+(l0<l1),l1+1);
    if (!l[0][l0]) {
    strcpy(l[0]+l0,t);
    return 0;
    }
    if (!l[0][l1]) {
    strcpy(l[0]+l1,t);
    return 0;
    }
    if (!l[1][l1]) {
    l[1][l1] = *t;
    return fit(t+1,l0+(l0<l1),l1+1);
    }
    return 1000;
}
int main(){
    int j,i,n,best,besti,bestk,c,tot = 0;
    for (i = 0; scanf("%s ",w[i])>0; i+=2) {
    int j = strlen(w[i]);
    for (c = 0; c < j; c++) w[i+1][c] = w[i][j-c-1];
    }
    n = i;
    pri();
    for (j = 0; j < n/2; j++) {
    int k = -1;
    best = -1;
    for (k = 0; k <= strlen(l[1]); k++) {
    for (i = 0; i<n; i++) if (!d[i/2]) {
    sav();
    c = fit(w[i],k,k);
    if (c < 1000 && c >= best) best = c, besti = i, bestk = k;
    res();
    }
    }
    fit(w[besti],bestk,bestk);
    d[besti/2] = 1; tot += best;
    }
    pri();
    printf("%d - %d\n",tot, strlen(l[0])+strlen(l[1]));
    return 0;
}

3

CJam, 1122 1089 letras

qN%{,}$__W%Wf%+:A;s[,mQ)__2#_S*:B;+2/:P;:DX1$W*W]:M;1:L;{BQCelt:B;}:T;
{A,,{B:G;P:H;D:I;L:J;A=:Z{:C;PL+D-:QB=C=
{T}{QD+:QB=C={T}{BPCelt:B;PD+:PL+B=' ={MD#)M=:D;ML#)M=:L;}&}?}?}/BS-,Z,-G:B;H:P;I:D;J:L;}$
0=:KA={:C;PL+D-:QB=C={T}{QD+:QB=C=
{T}{BPCelt:B;PD+:PL+B=' ={MD#)M=:D;ML#)M=:L;}&}?}?}/Beu:B;AKWtK~WtW-:A}g
{PL+B=' -PD-L+B=' -e&}{BP'Zt:B;PD+:P;}w
BM0=/Sf-Oa-N*

O programa constrói o retângulo a partir do centro, espiralando para fora. Esta é uma abordagem bastante simples até agora. Ainda há espaço para melhorias.

O código está uma grande bagunça no momento. Vou limpá-lo quando estiver satisfeito com minha pontuação.

Experimente on-line no intérprete CJam .

Borda

GXVDBDQDEVGPVJWLWSWQJMJMHCFNQDIGC
UIWESMKWBIANYUANRZOLGLXUFIXBEPSOP
WOPZUDGQTSHCCCUSEBHSKMQHJADKKHGFA
ZNQDKVWCMNPLEYFTQHXBVBPBATPQHNTCL
BJRDOWLZNPZQVDKYUTTIHFYILWADGCIKH
BHBKZXZGHZCOUCGCIGFGYSUGXYQIUPJAV
MSNGSBSMLVJSGLRYNSSIALHWWNTDKQCHL
WYWPRVNDSEBQZUYWFZTYBQZIAIAWIELXD
GSPAJAPSDIOHJDGHDBECZIWKSGVUHQMSN
VTHITUCGAWUUCGEBYVHNERPMZPZMUQHVZ
EIOYCVPONTFOOCUZSSQORJKOBGAFUMDKA
WGUAZTEYVXJYGDVKLFOSFMISJSJIVOPZV
IASWRNGTDNISBCBDJJPVTOJLBZRLRJGCS
IVPHDQBWUQHEOGOSUNNQKZFMPYVEVPYXF
WZVMNKATCBBXHDTROXSEHHTHQCMRULYVQ
DUATISIGVTZBCJSVZFBGIPMGYDPYISCPD
IEVNPBSDXCERINHKTYSMIRHVYMWDBLIYN
FCBHGRXLBMETYKDJQUIFKPJKDJGCFCKHA
WCRTUAVQPVUSOEURAFQBXIEVHDFXUDGYL
BQYQHTHLITUQPSNPLTISVYAQACMKQRCXS
PFYDRJMBZOZSBVKGAAMTIKWHJCFBIMEGU
SQYZYGOMRVWEKOVNKBDKEEVCHJVFOYTJV
PROEDILJXAORHMQMPOSCOJALZBETLVXKW
QRAPRQUGECLYFPCYHUMRYPWHMAFZAPQOE
WMKZVJXMFBJNCAFEIKQQAEQEBHYNWROUS
ULXYHOVIEJOHSYKKBJELPIWYXKJBIAZIQ
DWTQIJCHMXEPZMPHEULUBRVSAJQRXEGAV
FNVEPVNOJCBBRPVYBTZPHDSHZFEUAVQGV
PHDMJWJBIHVRLJYCSQJCKMEZRGRJMSQKE
LVMBLOKXMBFAWCGFMCPFOAGQLXCMISLKU
JVNZGEAZYFSBSETXKSWLGTYRTDVAWQFLI
WFWFBMXMSPYZANJNJWNUJLJXMGOPHVZYQ
PXLLANBLXBXBCIIHZTVGYIBENPFFTFDIC

3

Python 3, pontuação = 1014

A partir de uma área de tamanho nulo, adicionamos palavras letra por letra à área de forma que a área sempre seja uma espiral retangular:

  .
32.
41.
567

Mantemos 10 candidatos a conselhos durante todo o cálculo. A cada passo de cada candidato, tentamos adicionar todas as palavras que o quadro deixou de todas as formas possíveis, mantendo o layout em espiral. Classificamos cada uma das novas placas resultantes com base na total used word length / total area usedfração. Mantemos as 10 melhores pranchas e repetimos o passo até que não haja mais palavras.

Para minimizar o espaço não utilizado no final da espiral, tentamos dar alguns passos à frente antes de espiralar para criar espirais não quadradas. Por exemplo:

98765
.1234
..

A lista de palavras é apresentada em stdin. O código (bastante feio) leva cerca de 30 minutos no meu laptop lento. (Se você quiser esperar menos, poderá escolher em nonspiral_length=13vez de repetir os valores possíveis.)

A placa resultante:

JFOOGCUZSFSQORKIJFYGDSDSEOQZUYWDFZTYBQZ
ISDHUZTIIHKTJNJDBCBOHIYOPBKVVGNAKBDKEEK
EHOJPSLCDRMYVPAWESSIMCLQEGAOKFPJLCAFCKI
BZMFYLPNMNKDKGRAVMCTBBXTWUUCGCBYHNREYPA
RFQTXESYGCDVKLFOVSSFQNYHALSVWESQVEQRIRI
EELQBZNGZLWOZSRJTCTZWDGUIHUUFVRVUICPKPG
UUAHROPSCPGBAVXCPZVHXAIKCOSPBXIFUBTMQHG
SRBXTQNSXYEIPLJIBKKYSHOJEFBEXRIPXFAOQZS
WZNBSVMAHKWZCEHVDHEGDGHIDTIGAVZBLQYSAOZ
OTLVQDLYXMTIVXKBYVRBCJONHVXULMVXGIRLEMP
LFXFBKVGHAFBGEXMSPSPBWFCIDWIMOUCLOTMQFY
YKBPSYJFBAWNTMRRQYNQDIGPALCHXLEDTADHWTC
FDXBEUBGEGMHJWLSMKFXTECBSFYVDSCVXWVGEWD
HPCARTLSSKMVVGUWZBBHMWSGEAZLBJCNKIMKBTY
UYIWKTRIUVZFPNQTYFXJJQWIVNDHMLPAOXCVHGM
SRNTHINYFSKXLFYIHXGKOUOZAEWQDJNIYAWAMDY
MEIPMHFGCEJRASBSXORTSHBSJNJWNUHTYUQHZBJ
XLZHQYSRCKNDGOUNNQEBGMFITLRPUDFGYXFVJLD
XITNMNSUECHSTQGDUZPSKQPHJAPDQKKHRTLCAQC
XAVCPHYOCZVGZXBVAVTNQNWPYOUSPVAVBMQHDLC
XFGQOJIALHWWAINTAGJRVMDGKKLLYZHPOGQWKBJ
XMYEDNOWESMKTBAYUUNZOSYYCIDGCETXQZEPYMA
XUICSCJAVJHPJAIWHMTHTQDZDERPZYQEMLBYVRA
XWBMFGWFBIMXBKWOLJPIVRYRHUGINDRSZBJPQJH
XDENPFTDZGFFVEFYJQASIBLULPMZPEXJMHIEMGT
XIQTYWXGUMJRGRZEMKCJQSCVYJLRVHIBWVJOJQI

O código de geração:

import sys

class b:
    def __init__(s,l,ws):
        s.d=[' ']*(l*l)
        s.x,s.y=l//2,l//2
        s.l=l
        s.dir=1j
        s.ws=ws[:]
        # last char pos, remaining word part, used positions
        s.wx,s.wy,s.wp,s.wu=None,None,None,None

    def copy(s):
        #print('copy',s.x,s.y,s.wp)
        c=b(s.l,s.ws)
        c.d=s.d[:]
        c.x,c.y=s.x,s.y
        c.dir=s.dir*1
        c.wx,c.wy=s.wx,s.wy
        c.wp=s.wp[:] if s.wp!=None else None
        c.wu=s.wu[:] if s.wu!=None else None
        return c#copy.deepcopy(s) is very slow

    def score(s):
        placed_chars=allwlen-sum([len(w) for w in s.ws])
        used_cells=0
        for i in range(s.l):
            for j in range(s.l):
                if s.d[i*s.l+j]!=' ':
                    used_cells+=1
        return placed_chars/used_cells

    def get_next_bs(s):
        bl=[]
        for wi in range(len(s.ws)):
            bl+=s.get_b_for_w(wi)
        return bl

    def get_b_for_w(s,wi):
        w=s.ws[wi]        
        bl=[]
        for i in range(1,s.l-1,3):
            for j in range(1,s.l-1,3):
                for reversed in True,False:
                    if abs(i-s.x)+abs(j-s.y)>5:
                        continue
                    bn=s.copy()
                    bn.wx,bn.wy=i,j
                    bn.wp=w if not reversed else w[::-1]
                    del bn.ws[wi]
                    bn.wu=[]
                    bnr=bn.get_bs_for_wp()
                    bl+=bnr        
        # only use the best for a given word
        best_b=max(bl,key=lambda b:b.score())
        return [best_b]

    def get_bs_for_wp(s):
        if len(s.wp)==0:
            return [s]
        bl=[]
        for ir in -1,0,1:
            for jr in -1,0,1:
                i=s.wx+ir
                j=s.wy+jr
                if (i,j) not in s.wu and (s.d[i*s.l+j]==s.wp[0] or (i==s.x and j==s.y)):
                    bn=s.copy()
                    assert bn.d[i*bn.l+j] in (bn.wp[0],' ')
                    #add/owerwrite char
                    bn.d[i*bn.l+j]=bn.wp[0]
                    bn.wp=bn.wp[1:]
                    bn.wu+=[(i,j)]
                    bn.wx,bn.wy=i,j
                    if (i==bn.x and j==bn.y):              
                        spiraling=not (bn.x==bn.l//2 and bn.l//2+nonspiral_length>bn.y>=bn.l//2 )
                        #turn
                        nd=bn.dir*1j
                        if bn.d[int(bn.x+nd.real)*bn.l+int(bn.y+nd.imag)]==' ' and spiraling:
                            bn.dir=nd
                        #move
                        bn.x+=bn.dir.real
                        bn.y+=bn.dir.imag

                    #add bs from new state
                    bl+=bn.get_bs_for_wp()
        return bl        

    def __repr__(s):
        #borders
        x1,x2,y1,y2=s.l,0,s.l,0
        for i in range(s.l):
            for j in range(s.l):
                if s.d[i*s.l+j]!=' ':
                    x1=min(i,x1)
                    x2=max(i,x2)
                    y1=min(j,y1)
                    y2=max(j,y2)
        r=''
        for i in range(x1,x2+1):
            for j in range(y1,y2+1):
                r+=s.d[i*s.l+j] if s.d[i*s.l+j]!=' ' else 'X'
            r+='\n'
        return r

progress_info=False # toggle to print progress info

allws=[w.rstrip() for w in sys.stdin.readlines()]
allws=allws[:]
allwlen=sum([len(w) for w in allws])
max_nonspiral_length=16
best_score=allwlen*2+1 # maxint
best_b=None

for nonspiral_length in range(1,max_nonspiral_length+1,3):

    length=int(allwlen**0.5)+nonspiral_length*2+5 #size with generous padding

    bl=[b(length,allws)]

    for wc in range(len(allws)):
        bln=[]
        for be in bl:
            bln+=be.get_next_bs()

        bln.sort(key=lambda b:b.score(),reverse=True)
        bl=bln[:10]
        if progress_info:
            print(wc,end=' ')
            sys.stdout.flush()
        #print(bl[0].score(),wc)

    real_score=len(repr(bl[0]))-repr(bl[0]).count('\n')
    #print(bl[0])
    if progress_info:
        print()
        print(nonspiral_length,'score =',real_score)

    if real_score<best_score:
        best_b=bl[0]
        best_score=real_score

if progress_info:
    print()
print(best_b)
if progress_info:
    print('score =',best_score)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.