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

15

m | Y bR | ain ist We | iRd. F (o) RT (h) E La | sT fi (v) e JAHRE O | R s | o, (I) C (u) T wO | rds in h (a) lf wh | En (I) s (e) e | em. WENN ICH BEGANN, ES ZU TUN, UM EINE MENSCHLICHE ANSTREBUNG ZU MACHEN - B (u) T Ich konnte (l) nicht N (o) T d | o es. N (o) w, ich habe es in meinem Hinterkopf getan, und ich habe es kaum geglaubt, es nicht zu tun. Ich dachte jedoch, dass dies eine große Herausforderung sein würde.

Definitionen

Für diese Herausforderung erhält jeder Buchstabe eine Punktzahl, basierend auf meiner Einschätzung der Breite in einer serifenlosen Schrift. Mit dieser Breite schneiden Sie ein Wort in zwei gleich breite Hälften. Die Zeichen, die diese Herausforderung verwenden wird, sind das Alphabet in Groß- und Kleinbuchstaben, Apostroph und Bindestrich.

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

|Bezeichnet für meine Erklärungen und Testfälle die Stelle, an der ein Wort sauber in zwei Hälften geteilt werden kann. (und )auf jeder Seite eines Buchstabens geben Sie an, dass dieser Buchstabe in zwei Hälften geteilt wird, um eine saubere Trennung zu erzielen.

Eingang

Die Eingabe besteht aus einem einzelnen "Wort" (das nicht im Wörterbuch enthalten sein muss). Sie können dieses Wort in einer beliebigen Texteingabe verwenden (Zeichenfolge, Zeichen-Array usw.). Dieses Wort enthält nur die Buchstaben ', und -(siehe Tabelle oben). Aufgrund dessen, was Sie mit diesem Wort tun (siehe unten), liegt die Entscheidung über die Eingabe beim Entwickler. Nachgestellte Zeilenumbrüche sind bei Bedarf zulässig.

Die Aufgabe

Permutieren Sie durch alle Formen der Eingabe (alle Buchstaben an allen möglichen Groß- oder Kleinbuchstaben). Für die Eingabe it'ssind zum Beispiel alle folgenden Permutationen:

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

Um eine Permutation eines Wortes in zwei Hälften zu teilen, müssen die Punkte auf einer Seite des Wortes mit den Punkten auf der anderen Seite des Wortes übereinstimmen. Wenn ein Buchstabe jedoch zwischen zwei geraden Abschnitten steckt, können Sie einen Buchstaben auch sauber in zwei Hälften schneiden.

Bitte beachten Sie, dass "halb" nicht bedeutet, dass Sie sich auf halber Strecke in der Saite befinden. "Halb" bedeutet, dass die Punkte auf beiden Seiten gleich sind.

Beispiele:

Wbeträgt 5 Punkte. iist 1 Punkt. Wenn Sie die Permutation Wiiiiiin zwei Hälften teilen W | iiiii, erhalten Sie 5 Punkte auf jeder Seite des |.

Tbeträgt 3 Punkte. Wenn Sie die Permutation TTTTin zwei Hälften teilen TT | TT, erhalten Sie 6 Punkte auf jeder Seite des |.

wbeträgt 4 Punkte. a ist 3 Punkte. Wenn Sie die Permutation wawin zwei Hälften teilen w (a) w, erhalten Sie 5,5 Punkte auf jeder Seite. Die Punkte von awerden auf beide Seiten verteilt, da asie in zwei Hälften geteilt werden.

Ausgabe

Ihre Ausgabe ist eine ganze Zahl der Anzahl eindeutiger Permutationen der Eingabe, die sauber in zwei Hälften geteilt werden können. Nachgestellte Zeilenumbrüche sind bei Bedarf zulässig.

Testfälle

Ich werde alle gültigen Permutationen der Eingabe für die Testfälle ausgeben. Denken Sie daran, dass dies für Sie nicht Teil der Spezifikationen ist.

In meiner Zwischenausgabe geben die Zahlen den Punktwert des darüber liegenden Buchstabens an, sodass die Ausgabe etwas einfacher zu visualisieren ist.

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

Sieg

Das ist , also gewinnt die kürzeste Antwort in Bytes. Sie müssen in der Lage sein, alle Testfälle (also alle Eingaben mit bis zu 10 Zeichen) in angemessener Zeit auszugeben. Begrenzen Sie Ihre Eingabe nicht künstlich.

Kopfgeld

Ich weiß nicht, ob dies möglich ist. Sie sind jedoch Golfer - Sie werden alles für die Wiederholung tun. Ich biete ein Kopfgeld für 200 Wiederholungen (ich starte es, sobald diese Kopfgeldbedingung erfüllt ist, da es mir im Grunde unmöglich erscheint) für ein Programm an, das antidisestablishmentarianismauf einem durchschnittlichen Computer (auch bekannt als meiner) die korrekte Ausgabe für weniger als 15 Sekunden ausgibt . Bitte beachten Sie, dass dieser Testfall in keiner Weise fest codiert sein darf.

@DigitalTrauma zerquetschte mein Kopfgeld und kam in weniger als zwei Sekunden. Schauen Sie sich seine Antwort hier .

Stephen
quelle
2
@MackenzieMcClane, außer es gibt fünf 'ich nehme es auf 2 ^ 23 = 8.388.608.
Jonathan Allan
2
Meine erste Zählung für antidisestablishmentarianism(nicht-golfen) ist 83307040(und entspricht allen Testfällen), aber es dauert ~ 37 Sekunden auf meinem Laptop (wohlgemerkt, es ist Python). Hat jemand auch eine Zählung dafür?
Jonathan Allan
2
43 Sekunden bei TIO
Jonathan Allan
8
Mein Gehirn ist komisch Sie sind am richtigen Ort
Luis Mendo
6
Ich sollte nicht versuchen, das Gleiche zu tun. Ich sollte nicht versuchen, dasselbe zu tun. Ich sollte nicht (o) tt (r) yt | od | ot (h) e sa | me. O | h cr | ap ...
Arnauld

Antworten:

8

Pyth , 75 74 73 70 Bytes

lfsm} sT-Bysded._Tm.n] d * Fmm? k | qd \ i + 4} d mw | } d "'- 
lfsm} sT-Bysded._Tm.n] d * Fmm? k | qd \ i + 4} d '- 
lfsm} sT-Bysded "'-
lfsm} sT-Bysded

Probieren Sie es online!

Bitte versuchen Sie es nicht einmal antidisestablishmentarianismim Dolmetscher , um Gottes Willen . Sie werden es zum Absturz bringen.

Erläuterung

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

Lassen Sie uns diesen Code in X Teile zerlegen.

Der erste Teil: Generieren von Gehäuseversionen und Zuordnen zu den Werten

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

Lassen Sie uns hier klar sein. In keinem Teil des Prozesses werden Briefe mit Großbuchstaben geschrieben. Wir müssen nur einen Buchstaben auf zwei Werte abbilden (und die Interpunktionszeichen auf einen Wert), ohne sie großschreiben zu müssen. Wir werden entscheiden, für welche Zeichen wir zwei Werte benötigen und für welche Zeichen wir einen benötigen:

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

Wie Sie sehen, ist sogar der erste Teil zu lang.

Der erste Wert gilt für die Kleinbuchstabenversion, einschließlich 'und -. Der zweite Wert ist für die Großbuchstabenversion 'und -wird nicht verwendet.

Der erste Wert:

|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.

Die erste Zeichenfolge enthält den "mw"Index 0. Sie hat den Wert 4, was die Notwendigkeit des logischen oder erklärt. Beachten Sie, dass Pyth die 0-Indizierung verwendet. Auch der Raum vor dem 4soll ihn trennen 1.

Der zweite Wert (Großbuchstaben):

|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

Wenn dja "i", dann gibt es 1den ersten Schritt. Ansonsten geht es weiter. Wenn dist "m"oder "w", dann gibt der dritte Schritt an 1, was 4zu geben ist 5. Wenn dnicht "m"oder "w", dann gibt es den dritten Schritt 0, der 4zum Geben hinzugefügt wird 4.

Der zweite Teil: die Arbeit erledigen

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

Dies wird dem ersten Teil vorangestellt, der technisch nicht vom zweiten Teil getrennt ist (es ist immer noch ein Befehl). Der Wert aus dem ersten Teil wird also nach rechts übergeben.

Fazit: Im ersten Teil haben wir die Buchstaben auf ihre möglichen Werte abgebildet (Klein- und Großbuchstaben, nur ein Wert für die beiden Interpunktionszeichen). Für Input "ab"würde man bekommen [[3,4],[3,4]].

Um die verschiedenen Gehäuseversionen zu generieren (was im ersten Teil hätte geschehen sollen, aber das würde überlaufen), verwenden wir wiederholt das kartesische Produkt und reduzieren dann das Ergebnis. Probleme treten auf, wenn es nur einen Buchstaben gibt (erster Testfall), weil das kartesische Produkt uns kein Array geben würde und der Befehl flatten ( .n) übergelaufen ist, um seltsame Ergebnisse für Zahlen zu liefern. Wir werden sehen, wie ich dieses Problem umgangen habe.

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

Wenn es sich um eine Aufteilung in der Mitte von handelt |, würde das Präfix die Summe verdoppeln und die Summe der Gesamtsumme ergeben.

Wenn es durch geteilt wird (), ist die verdoppelte Präfixsumme abzüglich des Werts in Klammern die Summe der Gesamtsumme.

Undichte Nonne
quelle
Ja, wenn ich die Zeit dazu habe. (Ich entschuldige mich für meinen vollen Terminkalender.)
Undichte Nonne
11

c, 378 Bytes; etwa 0,6 s fürantidisestablishmentarianism

Aktualisierte Antwort . Ich habe @ JonathanAllans Kommentar über is gelesen , und zuerst habe ich diese Optimierung nicht verstanden, aber jetzt sehe ich, dass beide iund Ieine Breite von 1 haben. Dann können wir die zugehörigen Permutationen zweimal zählen, wobei wir nur einmal validieren müssen. Zuvor verwendete meine Lösung mehrere Threads, um die Last auf mehrere CPUs zu verteilen, und damit war ich in der Lage, alle 2 28 Möglichkeiten auf meiner Maschine zu durchlaufen . Dank der iOptimierung müssen Sie sich nicht mehr mit Threads herumschlagen - ein einziger Thread erledigt die Aufgabe problemlos innerhalb der Zeitbeschränkung.

Ohne weiteres golfen c Funktion:

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

Die rekursive Funktion fbenötigt 3 Parameter - einen Zeiger auf die Eingabezeichenfolge, die Zeichenfolgenlänge und den Offset in der Zeichenfolge, um die Verarbeitung zu starten (sollte für den Aufruf der obersten Ebene 0 sein). Die Funktion gibt die Anzahl der Permutationen zurück.

Probieren Sie es online aus . TIO scheint in der Regel alle Testfälle zu durchlaufen (auch antidisestablishmentarianismin weniger als 2 Sekunden).

Beachten Sie, dass es einige unprintables in der Zeichenfolge, die sich bcopy()auf ed m[]. Das TIO scheint damit richtig umzugehen.

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

Ich habe ein MacBook Pro Mitte 2015, auf dem MacOS 10.12.4 ausgeführt wird. Der Compiler ist der Standard-MacOS-Clang. Ich kompiliere mit:

cc splitwords.c -O2 -o splitwords

Ausführen aller Testfälle, einschließlich antidisestablishmentarianism:

$ 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
$

Dies ist keineswegs optimal. Der Algorithmus zwingt sich einfach durch alle Möglichkeiten (Modulo i- siehe Kommentare oben) und zählt die Wörter, die nach den Kriterien aufgeteilt werden können.

Digitales Trauma
quelle
Gute Arbeit, wirklich , ich denke , es ist wahrscheinlich möglich ist , das Ergebnis in O (n) unter Verwendung der festen Effekte der 7 Klassen von Buchstaben zu bewerten, i, -, ', l, mw, fjrt, und abcdeghknopqsuvxyz, aber es wäre eine Anwendung der nehmen Pólya Aufzählung Theorem (oder eine äquivalente kombinatorische Aufzählungsmethode), mit der ich mich nicht auskenne.
Jonathan Allan
Du hast meine Erwartungen zerstört, wie ich erwartet hatte. Dies ist, wie Sie Rekursion verwenden :)
Stephen
1

JavaScript (ES6), 199 169 167 Bytes

Erwartet die Eingabezeichenfolge in Kleinbuchstaben. Zu langsam für das Kopfgeld.

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

Testfälle

Arnauld
quelle
1

C, 403 394 Bytes,

Vielen Dank, 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;}

Probieren Sie es online aus

Ungolfed-Code:

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;
}
Johan du Toit
quelle
Sie haben vergessen, hier einige Plätze zu f(char* w, int l){f(char*w,int l){
golfen