Sp | Lit wo (r) dS, S (P) acceso wO | rds


15

m | Y bR | ain è We | iRd. F (o) RT (h) E La | sT fi (v) e YE | ars O | R s | o, (I) ha | ve C (u) T wO | rds in h (a) lf wh | En (I) s (e) e Th | em. Wh | EN Ho iniziato a farlo | it To it | oK a meN | TaL effort - B (u) TI quasi cou (l) d't N (o) T d | o it. N (o) w, lo d | o nella parte posteriore della mia testa, a (n) d difficilmente ev | en not | iCe. Tuttavia, ho pensato che questo avrebbe potuto essere una grande sfida.

definizioni

Per questa sfida, ad ogni lettera viene assegnato un punteggio, basato sul mio giudizio sulla sua larghezza in un carattere sans-serif. Utilizzerai questa larghezza per tagliare una parola in due metà di uguale larghezza. I personaggi che questa sfida utilizzerà saranno l'alfabeto in lettere minuscole e maiuscole, apostrofo e trattino.

Width  Characters
1      i l I '
2      f j r t -
3      a b c d e g h k n o p q s u v x y z
4      m w A B C D E F G H J K L N O P Q R S T U V X Y Z
5      M W

Per le mie spiegazioni e casi di test, |indica la posizione in cui una parola può essere divisa in modo netto a metà. (e )su entrambi i lati di una lettera indicano che quella lettera verrà divisa a metà per creare una divisione netta.

Ingresso

L'input consisterà in una singola "parola" (che non è richiesta per essere nel dizionario). Puoi prendere questa parola in qualsiasi input di testo desideri (String, char array, ecc.). Questa parola conterrà solo lettere 'e -(vedere la tabella sopra). A causa di ciò che farai con questa parola (vedi sotto), il caso di input è lasciato alla discrezione dello sviluppatore. Trascinamento di nuove righe consentite, se necessario.

L'obiettivo

Permuta attraverso tutte le forme dell'input (tutte le lettere in tutte le possibili posizioni maiuscole o minuscole). Ad esempio, per l'input it's, di seguito sono riportate tutte le permutazioni:

it's
it'S
iT's
iT'S
It's
It'S
IT's
IT'S

Per dividere una permutazione di una parola a metà, i punti su un lato della parola devono essere uguali ai punti dell'altro lato della parola. Tuttavia, se una lettera è incastrata tra due sezioni pari, puoi anche tagliare una lettera in modo pulito a metà.

Nota che "metà" non significa che ti sei spostato a metà della stringa. "Metà" significa che i punti su entrambi i lati sono uguali.

Esempi:

Wè di 5 punti. iè 1 punto. Dividendo la permutazione Wiiiiia metà si otterrà W | iiiii, con 5 punti su ciascun lato del |.

Tè di 3 punti. Dividendo la permutazione TTTTa metà si otterrà TT | TT, con 6 punti su ciascun lato del |.

wè di 4 punti. a è 3 punti. Dividendo la permutazione wawa metà si otterrà w (a) w, con 5,5 punti su ciascun lato. I punti da asono distribuiti su entrambi i lati, poiché aè diviso a metà.

Produzione

L'output è un numero intero del numero di permutazioni univoche dell'input che può essere diviso in modo netto a metà. Trailing newline consentito se necessario.

Casi test

Fornirò tutte le permutazioni valide dell'input per i casi di test. Ricorda che non fa parte delle specifiche per te.

Nel mio output intermedio, i numeri indicano il valore in punti della lettera sopra di loro, quindi l'output è un po 'più facile da visualizzare.

Input: a
( a ) 
  3   
( A ) 
  4   
Output: 2

Input: in
Output: 0

Input: ab
A | B 
4   4 
a | b 
3   3 
Output: 2

Input: abc
A ( B ) C 
4   4   4 
A ( b ) C 
4   3   4 
a ( B ) c 
3   4   3 
a ( b ) c 
3   3   3 
Output: 4

Input: will
W ( I ) L l 
5   1   4 1 
W ( I ) l L 
5   1   1 4 
W ( i ) L l 
5   1   4 1 
W ( i ) l L 
5   1   1 4 
w I | L l 
4 1   4 1 
w I | l L 
4 1   1 4 
w i | L l 
4 1   4 1 
w i | l L 
4 1   1 4 
Output: 8

Input: stephen
S T E ( P ) H E N 
4 4 4   4   4 4 4 
S T E ( p ) H E N 
4 4 4   3   4 4 4 
S T E | p h e n 
4 4 4   3 3 3 3 
S T e ( P ) H E n 
4 4 3   4   4 4 3 
S T e ( P ) H e N 
4 4 3   4   4 3 4 
S T e ( P ) h E N 
4 4 3   4   3 4 4 
S T e ( p ) H E n 
4 4 3   3   4 4 3 
S T e ( p ) H e N 
4 4 3   3   4 3 4 
S T e ( p ) h E N 
4 4 3   3   3 4 4 
S t E ( P ) H e n 
4 2 4   4   4 3 3 
S t E ( P ) h E n 
4 2 4   4   3 4 3 
S t E ( P ) h e N 
4 2 4   4   3 3 4 
S t E ( p ) H e n 
4 2 4   3   4 3 3 
S t E ( p ) h E n 
4 2 4   3   3 4 3 
S t E ( p ) h e N 
4 2 4   3   3 3 4 
S t e ( P ) h e n 
4 2 3   4   3 3 3 
S t e p | H E N 
4 2 3 3   4 4 4 
S t e ( p ) h e n 
4 2 3   3   3 3 3 
s T E ( P ) H E n 
3 4 4   4   4 4 3 
s T E ( P ) H e N 
3 4 4   4   4 3 4 
s T E ( P ) h E N 
3 4 4   4   3 4 4 
s T E ( p ) H E n 
3 4 4   3   4 4 3 
s T E ( p ) H e N 
3 4 4   3   4 3 4 
s T E ( p ) h E N 
3 4 4   3   3 4 4 
s T e ( P ) H e n 
3 4 3   4   4 3 3 
s T e ( P ) h E n 
3 4 3   4   3 4 3 
s T e ( P ) h e N 
3 4 3   4   3 3 4 
s T e ( p ) H e n 
3 4 3   3   4 3 3 
s T e ( p ) h E n 
3 4 3   3   3 4 3 
s T e ( p ) h e N 
3 4 3   3   3 3 4 
s t E ( P ) h e n 
3 2 4   4   3 3 3 
s t E p | H E N 
3 2 4 3   4 4 4 
s t E ( p ) h e n 
3 2 4   3   3 3 3 
s t e P | H E N 
3 2 3 4   4 4 4 
s t e p | H E n 
3 2 3 3   4 4 3 
s t e p | H e N 
3 2 3 3   4 3 4 
s t e p | h E N 
3 2 3 3   3 4 4 
Output: 37

Input: splitwords
S P L I T | W O r d s 
4 4 4 1 4   5 4 2 3 3 
<snip>
s p l i t w | o R d S 
3 3 1 1 2 4   3 4 3 4 
Output: 228

Input: 'a-r
' a ( - ) R 
1 3   2   4 
' a | - r 
1 3   2 2 
Output: 2

Input: '''''-
' ' ' ( ' ) ' - 
1 1 1   1   1 2 
Output: 1

Vittoria

Questo è , quindi vince la risposta più breve in byte. Devi essere in grado di emettere tutti i casi di test (quindi tutti gli input fino a 10 caratteri) in un ragionevole lasso di tempo. Non limitare artificialmente i tuoi input.

generosità

Non so se questo sia nel regno delle possibilità. Tuttavia, siete golfisti: farete qualsiasi cosa per i rappresentanti. Offro una ricompensa di 200 ripetizioni (la avvierò una volta soddisfatta questa condizione di ricompensa, poiché mi sembra sostanzialmente impossibile) per un programma che emette l'output corretto per antidisestablishmentarianismmeno di 15 secondi su un computer medio (aka mio). Si noti che questo caso di test non deve essere codificato in alcun modo.

@DigitalTrauma ha schiacciato la mia taglia, arrivando ben meno di due secondi. Controlla la sua risposta qui .


2
@MackenzieMcClane tranne per il fatto che ci sono cinque 'i che lo portano a 2 ^ 23 = 8.388.608.
Jonathan Allan,

2
Il mio primo conteggio per antidisestablishmentarianism(non golfoso) è 83307040(e corrisponde a tutti i casi di test) ma ci vogliono circa 37 secondi sul mio laptop (attenzione, è Python). Qualcuno ha anche un conto per questo?
Jonathan Allan,

2
43 secondi al TIO
Jonathan Allan,

8
Il mio cervello è strano. Sei nel posto giusto
Luis Mendo,

6
Non dovrei provare a fare lo stesso. Non potrei provare a fare lo stesso. Sho | uld n (o) tt (r) yt | od | ot (h) e sa | me. O | h cr | ap ...
Arnauld,

Risposte:


8

Pyth , 75 74 73 70 byte

lfsm} st-Bysded._Tm.n] D * Fmm k | qd \ i + 4} d "MW" |} D "il ' "h |?} d" fjrt - "+ 2} d" MW" -2 } d "'- 
lfsm} sT-Bysded._Tm.n] d * Fmm? k | qd \ i + 4} d" mw "| x} Ld + c" mw il' fjrt - ") G1 4-2} d "'- 
lfsm} sT-Bysded._Tm.n] d * Fm <, | x} Ld + c" mw il' fjrt - ") G1 4 | qd \ i + 4} d" mw "-2} d "'-
lfsm} sT-Bysded._Tm.n] d * Fm <, | x} Ld + c "mw il 'fjrt -") G1 4 | qd \ i + 4} d "mw" h} dG

Provalo online!

Per l'amore di Dio, per favore, non provare nemmeno antidisestablishmentarianismcon l'interprete. Lo schianterai.

Spiegazione

lfsm}sT-Bysded._Tm.n]d*Fm<,|x}Ld+c"mw il' fjrt-")G1 4|qd\i+4}d"mw"h}dG

Analizziamo questo codice in parti X.

La prima parte: generazione di versioni casate e mappatura ai valori

m<,|x}Ld+c"mw il' fjrt-")G1 4|qd\i+4}d"mw"h}dG

Cerchiamo di essere chiari qui. In nessuna parte del processo le lettere sono maiuscole. Dobbiamo solo mappare una lettera su due valori (e i segni di punteggiatura su un valore), senza la necessità di capitalizzarli. Decideremo per quali personaggi avremo bisogno di due valori e per quali personaggi avremo bisogno di uno:

m<,|x}Ld+c"mw il' fjrt-")G1 4|qd\i+4}d"mw"h}dGQ  Q implicitly appended
m                                             Q  for d in Q:
                                           }dG       d in alphabet?
                                          h          +1 (T/F as 1/0)
 <   take the first ^ elements of the following array
     for d in alphabet, it will take 2 elements;
     for d being ' or -, it will take 1 element.
  ,          pair up the following two values
   |x}Ld+c"mw il' fjrt-")G1 4                  this is the first value
                             |qd\i+4}d"mw"    this is the second value

Come vedi, anche la prima parte è troppo lunga.

Il primo valore è per la versione minuscola, che include 'e -. Il secondo valore è per la versione maiuscola, con 'e -non accetta.

Il primo valore:

|x}Ld+c"mw il' fjrt-")G1 4
       "mw il' fjrt-"        does what it says on the tin
      c              )       split on spaces, creating an
                             array with three elements
     +                G      append another element, which
                             is the alphabet, as a fail-safe;
                             now the array has 4 elements
  }Ld                        check if d is in each array
                             as with above, True becomes 1
                             and False becomes 0 (T/F as 1/0)
 x                     1     find the first occurrence of 1
|                        4   logical or with 4. If it was 0,
                             it would become 4 now.

La prima stringa contiene "mw"all'indice 0. Ha un valore di 4, che spiega la necessità del logico o. Nota che Pyth usa l'indicizzazione 0. Inoltre, lo spazio prima di 4è per separarlo 1.

Il secondo valore (maiuscolo):

|qd\i+4}d"mw"
 qd\i          d=="i"
|              logical OR
       }d"mw"  is d in "mw"? That is, is d "m" or "w"?
     +4        +4

Se lo dè "i", allora dà 1il primo passo. Altrimenti, continua. If dè "m"o "w", quindi il terzo passaggio dà 1, che viene aggiunto 4a dare 5. Se dnon lo è "m"o "w", quindi il terzo passaggio dà 0, che viene aggiunto 4a dare 4.

La seconda parte: portare a termine il lavoro

lfsm}sT-Bysded._Tm.n]d*F

Questo è anteposto alla prima parte, che tecnicamente non è separata dalla seconda parte (è ancora un comando). Quindi, il valore della prima parte viene passato a destra.

Riepilogo: nella prima parte, abbiamo mappato le lettere sui loro possibili valori (lettere minuscole e maiuscole per le lettere, solo un valore per i due segni di punteggiatura). Per input "ab", si otterrebbe [[3,4],[3,4]].

Per generare le diverse versioni con involucro (cosa che avrebbe dovuto essere fatto nella prima parte, ma che traboccerebbe), utilizziamo ripetutamente il prodotto cartesiano, quindi appiattiamo il risultato. I problemi sorgono quando c'è solo una lettera (prima testcase), perché il prodotto cartesiano non ci darebbe un array, e il comando appiattisci ( .n) viene traboccato per dare strani risultati ai numeri. Vedremo come ho aggirato questo problema.

lfsm}sT-Bysded._Tm.n]d*F
                      *F  reduce by Cartesian product
                 m   d    for d in each unflattened version:
                    ]         [d] (wrap in array)
                  .n          flatten
 f                filter for resulting arrays as T
              ._T all prefixes of T
   m              for d in each prefix:
          sd          find the sum of d
         y            double
       -B   ed        [above, above - last element of d]
    }sT               is the sum of T in the above array of 2 elements?
  s               sum the 1/0 generated in each prefix
                  any non-zero value is regarded as truthy
l                 length

Se è una divisione nel mezzo |, quindi il prefisso avrebbe la somma raddoppiata come la somma del totale.

Se viene diviso per (), la somma del prefisso raddoppiata meno il valore tra parentesi sarebbe la somma del totale.


Sì, quando ho tempo di farlo. (Chiedo scusa per il mio fitto programma.)
Leaky Nun,

11

c, 378 byte; circa 0,6 s perantidisestablishmentarianism

Risposta aggiornata . Ho letto il commento di @ JonathanAllan su is, e all'inizio non ho capito questa ottimizzazione, ma ora vedo che dato che entrambi ie Ihanno una larghezza di 1, possiamo contare due volte le permutazioni associate con la sola convalida una sola volta. In precedenza la mia soluzione utilizzava più thread per distribuire il carico su più CPU e con ciò ero quasi in grado di esaminare tutte le 2 28 possibilità sulla mia macchina. Ora con l' iottimizzazione non è necessario pasticciare con i thread: un singolo thread esegue facilmente il lavoro entro il limite di tempo.

Senza ulteriori funzioni aggiuntive:

char m[128]={[39]=10,[45]=20};f(s,l,p)char *s;{m[65]?:bcopy("PPPPPPPPPPPdPPPPPPPPPdPPP      <<<<<(<<(<P<<<<(<(<<P<<<",m+65,58);int g,h,u=0,v=0,x=0,y=0,c=0;if(p<l){g=s[p];if(g>64&&g-'i'){s[p]-=32;c+=f(s,l,p+1);}s[p]=g;c+=((g=='i')+1)*f(s,l,p+1);}else{for(l--,p=0,g=m[s[p]],h=m[s[l]];p<=l;){y=v;x=u;if(u+g>v+h){v+=h;h=m[s[--l]];}else{u+=g;g=m[s[++p]];}}c=u==v||y==x;}return c;}

La funzione ricorsiva faccetta 3 parametri: un puntatore alla stringa di input, la lunghezza della stringa e l'offset nella stringa per iniziare l'elaborazione (dovrebbe essere 0 per la chiamata di livello superiore). La funzione restituisce il numero di permutazioni.

Provalo online . TIO sembra in genere attraversare tutti i test (anche antidisestablishmentarianismin meno di 2 secondi.

Si noti che ci sono alcuni non stampabili nella stringa in cui è bcopy()ed m[]. Il TIO sembra gestirli correttamente.

Ungolfed:

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>

int width_tbl[] = {
    ['\''] = 1,
    ['-'] = 2,
    ['A'] = 4,4,4,4,4,4,4,4,1,4,4,4,5,4,4,4,4,4,4,4,4,4,5,4,4,4,
    ['a'] = 3,3,3,3,3,2,3,3,1,2,3,1,4,3,3,3,3,2,3,2,3,3,4,3,3,3
};

int
f (char *str, int len, int pos) {
    int lidx, ridx;
    int tot_width = 0;
    int lwidth, rwidth;
    int tot_lwidth = 0, tot_rwidth = 0;
    int prev_tot_lwidth = 0, prev_tot_rwidth = 0;
    char tmp;
    int perm_cnt = 0;

    if (pos < len) {
        tmp = str[pos];
        if (isalpha(tmp) && (tmp != 'i')) {
            str[pos] = toupper(str[pos]);
            perm_cnt += f(str, len, pos+1);
        }
        str[pos] = tmp;
        perm_cnt += ((tmp == 'i') + 1) * f(str, len, pos+1);
    } else {
        //puts(str);
        lidx = 0;
        ridx = len - 1;
        lwidth = width_tbl[str[lidx]];
        rwidth = width_tbl[str[ridx]];
        while (lidx <= ridx) {
            prev_tot_rwidth = tot_rwidth;
            prev_tot_lwidth = tot_lwidth;
            if (tot_lwidth + lwidth > tot_rwidth + rwidth) {
                tot_rwidth += rwidth;
                rwidth = width_tbl[str[--ridx]];
            } else {
                tot_lwidth += lwidth;
                lwidth = width_tbl[str[++lidx]];
            }
        }
        if (tot_lwidth == tot_rwidth) {
            perm_cnt = 1;
        } else if (prev_tot_rwidth == prev_tot_lwidth) {
            perm_cnt = 1;
        }
    }
    return perm_cnt;
}


int main (int argc, char **argv) {
    int i;
    int perm_cnt;

    if (argc > 0) {
        char *str = strdup(argv[1]);
        assert(str);

        perm_cnt = f(str, strlen(str), 0);

        printf("n = %d\n", perm_cnt);
    }

    return 0;
}

Ho un MacBook Pro di metà 2015 con MacOS 10.12.4. Il compilatore è il clang predefinito di MacOS. Sto compilando con:

cc splitwords.c -O2 -o splitwords

L'esecuzione di tutti i casi di prova, tra cui antidisestablishmentarianismdà:

$ time ./splitwords
Testcase "a": n = 2
Testcase "in": n = 0
Testcase "ab": n = 2
Testcase "abc": n = 4
Testcase "will": n = 8
Testcase "stephen": n = 37
Testcase "splitwords": n = 228
Testcase "'a-r": n = 2
Testcase "'''''-": n = 1
Testcase "antidisestablishmentarianism": n = 83307040

real    0m0.573s
user    0m0.564s
sys 0m0.003s
$

Questo non è affatto ottimale. L'algoritmo si fa semplicemente strada attraverso tutte le possibilità (modulo i- vedi commenti sopra) e conta le parole che possono essere divise in base ai criteri.


Buon lavoro, in realtà penso che probabilmente è possibile valutare il risultato in O (n), utilizzando gli effetti fissi delle 7 classi di lettera, i, -, ', l, mw, fjrt, e abcdeghknopqsuvxyz, ma ci vorrebbe un'applicazione del Pólya enumerazione teorema (o un metodo di enumerazione combinatoria equivalente), in cui non sono esperto.
Jonathan Allan,

Hai distrutto le mie aspettative, come mi aspettavo. Ecco come usi la ricorsione :)
Stephen,

1

JavaScript (ES6), 199 169 167 byte

Prevede la stringa di input in minuscolo. Troppo lento per la generosità.

f=(s,r=[],t=R=0,i=3,x=parseInt("k1048cccctt"["i'l-fjrtmw".search(c=s[0])+1],36)+8>>i&7)=>x&&(c?(i&&f(s,r,t,0),f(s.slice(1),[x,...r],t+x)):R+=r.some(x=>t==x|!(t-=2*x)))

Casi test


1

C, 403 394 byte,

Grazie Kevin!

r;char*g[]={"","ilI'","fjrt-","","mw","MW",0},**p,b[99];q(c){for(p=g;*p;p++)if(strchr(*p,c))return p-g;return c>='a'&&c<='z'?3:4;}f(char*w,int l){int i,n,c,t,x,y;if(*w){for(i=0;i<2;i++)x=tolower(*w),y=toupper(*w),!i||x!=y?b[l]=i%2?x:y,b[l+1]=0,f(w+1,l+1):0;}else{t=0;for(c=0;c<2;c++)for(i=0;i<l;i++){x=y=0;for(n=0;n<l;n++)c==0||n!=i?((n<i)?(x+=q(b[n])):(y+=q(b[n]))):0;t|=x==y;}r+=t;}return r;}

Provalo online

Codice non golfato:

int getwidth(int c)
{
    char **p, *g[] = { "", "ilI'", "fjrt-", "", "mw", "MW", 0};
    for (p=g; *p; p++)
    {
        if (strchr(*p,c))
            return p-g;
    }
    return c >= 'a' && c <= 'z' ? 3 : 4;
}

int test(char* w, int l)
{
    int i, n, c, t, x, y;

    if (*w)
    {
        for (i=0;i<2; i++)
        {
            x = tolower(*w);
            y = toupper(*w);
            if (!i || x != y)
            {
                b[l] = i % 2 ? x : y;
                b[l + 1] = 0;
                test(w + 1, l+1);
            }
        }
    }
    else
    {
        t = 0;
        for (c=0; c<2; c++)
        {
            for (i=0; i<l; i++)
            {
                x = 0;
                y = 0;
                for (n=0; n<l; n++)
                {
                    if (c == 0 || n != i)
                    {
                        if (n < i)
                            x += getwidth(b[n]);
                        else
                            y += getwidth(b[n]);
                    }
                }
                t |= x == y;
            }
        }
        r += t;
    }
    return r;
}

Hai dimenticato di giocare a golf qui: f(char* w, int l){->f(char*w,int l){
Kevin Cruijssen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.