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


15

m | Y bR | ain Biz | iRd. F (o) RT (h) E La | sT fi (v) e YE | ars O | R s | o, (I) ha | ve C (u) T wO | r (h (a) lf wh | tr içinde (I) s (e) e Th | em. Wh | EN Başladım, | Yaptım | MÜCADELE ÇALIŞMASI - B (u) TI neredeyse cou (l) değil N (o) T d | o. N (o) w, başımın arkasına koydum, a (n) pek zor değil | iCe. Ancak, bu wo büyük bir meydan okuma olabilir düşündüm.

Tanımlar

Bu meydan okuma için, her harfe bir sans-serif yazı tipindeki genişliğini değerlendirdiğimden bir puan verilir. Bu genişliği, bir sözcüğü eşit genişlikte iki yarıya kesmek için kullanacaksınız. Bu zorluğun kullanacağı karakterler küçük ve büyük harf, kesme işareti ve kısa çizgi şeklindedir.

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

Açıklamalarım ve test |senaryolarım için , bir kelimenin temiz bir şekilde ikiye bölünebileceği konumu belirtir. (ve )bir mektubun her iki tarafında, temiz bir bölme oluşturmak için bu harfin ikiye bölüneceğini belirtir.

Giriş

Giriş tek bir "kelimeden" oluşur (sözlükte olması gerekmez). Bu kelimeyi istediğiniz metin girişinde (Dize, karakter dizisi vb.) Alabilirsiniz. Bu sözcük yalnızca ',, ve harflerini içerir -(yukarıdaki tabloya bakın). Bu sözcükle ne yapacağınız nedeniyle (aşağıya bakın), giriş durumu geliştiricinin takdirine bırakılmıştır. Gerekirse sondaki yeni satırlara izin verilir.

Görev

Girişin tüm formlarına izin verin (olası tüm büyük veya küçük harflerdeki tüm harfler). Örneğin, girdi için it's, aşağıdaki tüm permütasyonlardır:

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

Bir sözcüğün permütasyonunu ikiye bölmek için, kelimenin bir tarafındaki noktalar, kelimenin diğer tarafındaki noktalarla aynı olmalıdır. Ancak, bir harf iki çift bölüm arasında sıkışmışsa, bir harfi temiz bir şekilde ikiye kesebilirsiniz.

"Yarım" ifadesinin, dizenin yarısına geçtiğiniz anlamına gelmediğini lütfen unutmayın. "Yarım", her iki taraftaki noktaların eşit olduğu anlamına gelir.

Örnekler:

W5 puandır. i1 puan. Permütasyonun ikiye bölünmesi, her iki tarafında 5 puan ile Wiiiiisonuçlanacaktır .W | iiiii|

T3 puandır. Permütasyonun ikiye bölünmesi, her iki tarafında 6 puan ile TTTTsonuçlanacaktır .TT | TT|

w4 puandır. a 3 puandır. Permütasyonun ikiye bölünmesi, her iki tarafta 5.5 puan ile wawsonuçlanacaktır w (a) w. 'Dan alınan noktalar , ikiye bölünmüş aolarak her iki tarafa da dağıtılır a.

Çıktı

Çıktınız, girdinin temiz bir şekilde ikiye bölünebilen benzersiz permütasyon sayısının bir tamsayısıdır. Gerekirse sondaki yeni satırlara izin verilir.

Test Durumları

Test senaryoları için girdinin tüm geçerli permütasyonlarını çıktılayacağım. Bunun sizin için özelliklerin bir parçası olmadığını unutmayın.

Ara çıkışımda, sayılar üstlerindeki harfin puan değerini gösterir, bu nedenle çıktının görselleştirilmesi biraz daha kolaydır.

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

Zafer

Bu , bayt en kısa cevap kazanır. Tüm test senaryolarını (10 karaktere kadar olan tüm girişleri) makul bir sürede verebilmeniz gerekir. Girişinizi yapay olarak sınırlamayın.

Ödül

Bunun olasılık alanında olup olmadığını bilmiyorum. Ancak, golfçüsünüz - temsilcisi için her şeyi yapacaksınız. antidisestablishmentarianismOrtalama bir bilgisayarda (aka benimki) 15 saniyenin altında doğru çıktı veren bir program için 200 rep lütuf (temelde benim için imkansız göründüğü için bu lütuf durumu yerine getirildikten sonra başlatacağım) sunuyorum . Bu test senaryosunun hiçbir şekilde sabit kodlanmaması gerektiğini lütfen unutmayın.

@ DigitalTrauma ödülümü ezdi, iki saniyenin altında geliyor. Cevabını buradan kontrol edin .


2
@MackenzieMcClane dışında beş 'i 2 ^ 23 = 8.388.608'e indiriyor.
Jonathan Allan

2
antidisestablishmentarianism(Golf olmayan) için ilk sayım 83307040(ve tüm test senaryolarını eşleştirerek) ancak dizüstü bilgisayarımda ~ 37 saniye sürüyor (Python olduğunu unutmayın). Herkes bunun için bir sayım var mı?
Jonathan Allan

2
43 saniye TIO
Jonathan Allan

8
Beynim tuhaf Doğru yerdesiniz
Luis Mendo

6
Ben de aynısını yapmaya çalışmamalıyım. Aynı şeyi yapmaya çalışmamalıyım. Ben (beni) tt (r) yt | od | ot (h) e sa | me sho. O | h cr | ap ...
Arnauld

Yanıtlar:


8

Pyth , 75 74 73 70 bayt

lfsm} sT-Bysded._Tm.n] D * fmm k | qd \ ı + 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

Çevrimiçi deneyin!

Tanrı sevgisi için, lütfen antidisestablishmentarianismtercümanı bile denemeyin . Sen çökeceksin.

açıklama

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

Bu kodu X parçalarına ayıralım.

İlk bölüm: kasa versiyonları oluşturma ve değerlerle eşleme

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

Burada net olalım. Gelen hiçbir sürecin bir parçası harfle harfleri. Bir harfi büyük harflere gerek duymadan iki değere (ve noktalama işaretlerini bir değere) eşlememiz gerekir. Hangi karakter için iki değere ihtiyacımız olacağına ve hangi karakter için bir karaktere ihtiyacımız olacağına karar vereceğiz:

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

Gördüğünüz gibi, ilk kısım bile çok uzun.

İlk değer 've içeren küçük harfli sürüm içindir -. İkinci değer büyük harfli sürüm içindir 've -almaz.

İlk değer:

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

İlk dize "mw"0 dizininde bulunur. 4 değerine sahiptir, bu mantıksal veya. Pyth'in 0 dizinleme kullandığını unutmayın. Ayrıca, önceki boşluk 4onu ayırmaktır 1.

İkinci değer (büyük harf):

|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

Eğer dbir "i", o zaman verir 1ilk adım. Aksi halde devam eder. Eğer dbir "m"ya da "w"daha sonra, üçüncü aşama verir 1eklendiği, 4elde 5. Eğer ddeğil "m"veya "w"daha sonra, üçüncü bir adım sağlar, 0eklendiği, 4elde 4.

İkinci bölüm: işi yapmak

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

Bu, teknik olarak ikinci kısımdan ayrılmayan birinci kısma eklenir (hala bir komuttur). Böylece, ilk kısımdaki değer sağa geçirilir.

Özetle: ilk bölümde harfleri olası değerleriyle eşleştirdik (harfler için küçük ve büyük harf, iki noktalama işareti için sadece bir değer). Girdi için "ab"bir tane alacak [[3,4],[3,4]].

Farklı kasalı versiyonlar oluşturmak için (ilk kısımda yapılması gerekiyordu, ancak bu taştı), Kartezyen ürünü tekrar tekrar kullanıyoruz ve sonucu düzleştiriyoruz. Yalnızca bir harf (ilk testcase) olduğunda sorunlar ortaya çıkar, çünkü Kartezyen ürün bize bir dizi vermez ve düzleştir komutu ( .n) sayılara garip sonuçlar vermek için taşar. Bu sorunu nasıl atlattığımı göreceğiz.

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

Eğer ortada bir bölünme olursa |, önek toplamın toplamı olmak üzere toplamın iki katına çıkacaktır.

Eğer bölünürse (), önek toplamı iki katına çıkarılırsa, parantez içindeki değer toplamın toplamı olur.


Evet, vaktim olduğunda. (Yoğun programım için özür dilerim.)
Leaky Nun

11

c, 378 bayt; yaklaşık 0.6santidisestablishmentarianism

Cevap güncellendi . Ben yaklaşık JonathanAllan yorumuna @ okumak is ve ilk I'de Bu optimizasyonu anlamadı, ama şimdi hem beri görüyoruz ive I1 arasında bir genişliğe sahip, o zaman biz sadece bir kez doğrulamak zorunda olan iki kere ilişkili permütasyon sayabilir. Daha önce çözümüm, yükü birden fazla CPU'ya yaymak için birden fazla iş parçacığı kullandı ve bununla makinemdeki 2 28 olasılıktan da geçebildim . Şimdi ioptimizasyon ile dişleri karıştırmaya gerek yok - tek bir iş parçacığı zaman kısıtlaması içinde işi kolayca yapar.

Daha fazla uzatılmış c fonksiyonu olmadan:

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

Özyinelemeli işlev f3 parametre alır - giriş dizesine bir işaretçi, dize uzunluğu ve işlemeye başlamak için dizedeki ofset (üst düzey çağrı için 0 olmalıdır). İşlev, permütasyon sayısını döndürür.

Çevrimiçi deneyin . TIO tipik olarak tüm test senaryolarından geçmektedir ( antidisestablishmentarianism2 saniyenin altında dahil ).

Dize bazı unprintables orada Not olduğunu bcopy()için ed m[]. TIO bunları doğru bir şekilde ele alıyor gibi görünüyor.

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

MacOS 10.12.4 çalıştıran 2015'in ortalarında MacBook Pro'm var. Derleyici varsayılan MacOS clang'dır. Ben derleme:

cc splitwords.c -O2 -o splitwords

Aşağıdakiler dahil tüm test senaryolarını çalıştırmak 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
$

Bu hiçbir şekilde optimal değildir. Algoritma basitçe tüm olasılıklar boyunca yolunu zorlar (modulo i- yukarıdaki açıklamalara bakın) ve ölçütlere göre bölünebilecek kelimeleri sayar.


İyi iş, gerçekten bunu mektubun 7 sınıfların sabit efektler kullanarak, O (n) sonucu değerlendirmek muhtemelen mümkün olduğunu düşünüyorum, i, -, ', l, mw, fjrt, ve abcdeghknopqsuvxyzfakat bir uygulamayı alacağını Polya numaralandırma teoremi (veya eşdeğer bir kombinatoryal numaralandırma yöntemi).
Jonathan Allan

Beklediğim gibi beklentilerimi yok ettin. Özyineleme bu şekilde kullanılır :)
Stephen

1

JavaScript (ES6), 199 169 167 bayt

Girdi dizesini küçük harflerle bekler. Ödül için çok yavaş.

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

Test senaryoları


1

Cı, 403 394 bayt

Teşekkürler 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;}

Çevrimiçi deneyin

Kod çözülmemiş kod:

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

Burada bazı alanlarda golf unuttum: f(char* w, int l){->f(char*w,int l){
Kevin Cruijssen
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.