Sp | Запалений wo (r) dS, S (P) освітлений 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 Я почав це робити, це Для того, щоб докласти зусиль - B (u) TI майже cou (l) dn N (o) T d | o це. N (o) w, я d | o це в потилиці, a (n) d навряд чи ev | en не | iCe це. Однак я подумав, що це може зробити велике завдання.

Визначення

Для цього завдання кожному листу дається бальна оцінка, виходячи з моєї оцінки його ширини шрифтом sans-serif. Ви будете використовувати цю ширину, щоб розрізати слово на дві половини однакової ширини. Символи, які використовуватиме цей виклик, - це алфавіт у нижньому та верхньому регістрі, апостроф та дефіс.

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

Для моїх пояснень та тестових випадків |позначає місце, в якому слово можна чисто розділити навпіл. (і )по обидва боки листа вказують, що цей лист розділиться навпіл, щоб створити чистий розкол.

Вхідні дані

Введення складається з одного "слова" (яке не обов'язково містити в словнику). Ви можете взяти це слово в будь-якому іншому текстовому введенні (String, масив char тощо). Це слово буде містити лише літери ', та -(див. Вище в таблиці). Через те, що ви зробите з цим словом (див. Нижче), випадок введення залишається на розсуд розробника. За необхідності дозволено відстежувати нові рядки.

Завдання

Перестановка через усі форми вводу (усі літери у всіх можливих верхньому чи нижньому регістрі). Наприклад, для введення it'sнижче наведені всі перестановки:

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

Щоб розділити перестановку слова навпіл, точки на одній стороні слова повинні бути такими ж, як точки другої сторони слова. Однак якщо лист застряг між двома рівними ділянками, ви також можете розрізати лист навпіл.

Зверніть увагу, що "половина" не означає, що ви перейшли на півдороги. "Половина" означає, що точки з обох сторін рівні.

Приклади:

Wстановить 5 балів. iстановить 1 бал. Розбиття перестановки Wiiiiiнавпіл призведе W | iiiiiдо 5 балів на кожній стороні |.

Tстановить 3 бали. Розбиття перестановки TTTTнавпіл призведе TT | TTдо отримання 6 балів на кожній стороні |.

wстановить 4 бали. a - 3 бали. Розбиття перестановки wawнавпіл призведе w (a) wдо 5,5 балів на кожній стороні. Точки від aрозподіляються в обидві сторони, як aрозділено навпіл.

Вихідні дані

Ваш вихід - це ціле число кількості унікальних перестановок вхідних даних, які можна чітко розділити навпіл. За необхідності дозволено відстежувати нові рядки.

Випробування

Я буду виводити всі дійсні перестановки вхідних даних для тестових випадків. Пам'ятайте, що це не є частиною специфікацій для вас.

У моєму проміжному виході цифри вказують на точкове значення літери над ними, тому виведення трохи легше візуалізувати.

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

Перемога

Це , тому найкоротша відповідь у байтах виграє. Ви повинні мати можливість виводити всі тестові справи (таким чином, усі введення до 10 символів) за розумну кількість часу. Не штучно обмежуйте свої дані.

Баунті

Я не знаю, чи це в царині можливостей. Тим не менш, ви гольфісти - ви все зробите для реп. Я пропоную виграш у розмірі 200 повторень (я розпочну його після того, як ця умова баунті буде виконана, як це мені здається в принципі неможливим) для програми, яка antidisestablishmentarianismна середньому комп’ютері видає правильний вихід протягом менше 15 секунд (він же мій). Зверніть увагу, що цей тестовий випадок не повинен бути жодним чином кодованим.

@DigitalTrauma розчавив мою щедрість, пройшовши трохи менше двох секунд. Перевірте його відповідь тут .


2
@MackenzieMcClane, за винятком п’яти "я знімаю його до 2 ^ 23 = 8,388,608.
Джонатан Аллан

2
Перший мій рахунок antidisestablishmentarianism(non-golfy) - це 83307040(і відповідає всім тестовим випадкам), але це займає ~ 37 секунд на моєму ноутбуці (врахуйте, що це Python). У когось теж є рахунок?
Джонатан Аллан

2
43 секунди в TIO
Джонатан Аллан

8
Мій мозок дивно Ви знаходитесь у потрібному місці
Луїс Мендо

6
Я не повинен намагатися робити те саме. Я шо | uld не намагаюся зробити те саме. Я шо | uld n (o) tt (r) yt | od | ot (h) e sa | мене. O | h cr | ap ...
Арнольд

Відповіді:


8

Pyth , 75 74 73 70 байт

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

Спробуйте в Інтернеті!

Для любові до Бога, будь ласка, навіть не намагайся antidisestablishmentarianismперекладача. Ти розбиш його.

Пояснення

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

Розбиймо цей код на X частини.

Перша частина: генерація кесованих версій та відображення значень

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

Давайте нам тут буде зрозуміло. У жодній частині процесу букви не використовуються з великої літери. Нам просто потрібно зіставити одну букву на два значення (і розділові знаки на одне значення), не потребуючи великих літер. Ми вирішимо, для яких символів нам знадобляться два значення, а для яких символів нам буде потрібно одне:

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

Як бачите, навіть перша частина занадто довга.

Перше значення - для малої версії, яка включає 'і -. Друге значення для великої версії, з 'і -не прийме.

Перше значення:

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

Перший рядок містить "mw"індекс 0. Він має значення 4, що пояснює потребу логічного або. Зауважте, що Pyth використовує 0-індексацію. Крім того, простір перед цим 4має відокремити його 1.

Друге значення (великі літери):

|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

Якщо dє "i", то це дає 1на першому кроці. В іншому випадку це триває. Якщо dє "m"або "w", тоді видається третій крок 1, який додається, 4щоб дати 5. Якщо dнемає "m"або "w", то третій крок дає 0, який додається 4дати 4.

Друга частина: виконання роботи

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

Це передбачено першою частиною, яка технічно не відокремлена від другої частини (це все одно одна команда). Отже, значення з першої частини передається праворуч.

Підсумок: у першій частині ми зіставили літери на їх можливі значення (малі та великі літери для букв, лише одне значення для двох розділових знаків). Для введення "ab"можна отримати [[3,4],[3,4]].

Щоб генерувати різні розроблені версії (які повинні були бути зроблені в першій частині, але це переповнюватимуться), ми кілька разів використовуємо декартовий продукт, а потім вирівнюємо результат. Проблеми виникають, коли є лише одна літера (перша тестова скринька), оскільки декартовий продукт не дав би нам масиву, а команда flatten ( .n) переповнена, щоб дати дивні результати цифрам. Ми побачимо, як я обійшов цю проблему.

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

Якщо це розділення в середині на |, то префікс отримав би суму, подвоєну на суму загальної суми.

Якщо він розділений на (), то сума префікса, подвоєна мінус значення у дужках, буде сумою загальної суми.


Так, коли в мене є час. (Прошу вибачення за свій напружений графік.)
Лина монашка

11

c, 378 байт; близько 0,6s дляantidisestablishmentarianism

Оновлена ​​відповідь . Я прочитав @ коментар JonathanAllan в про iс, і спочатку я не розумів цю оптимізацію, але тепер я бачу , що з тих пір , як iі Iмають ширину 1, то ми можемо вважати пов'язані перестановки двічі тільки того , щоб перевірити один раз. Раніше моє рішення використовувало декілька потоків для розподілу навантаження на декілька процесорів, і з цим я вже майже змогла пройти всі 2 28 можливостей на своїй машині. Тепер з iоптимізацією немає необхідності возитися з нитками - один потік виконує цю роботу легко за обмеження часу.

Без додаткової оболонки - функція c гольф:

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

Рекурсивна функція fприймає 3 параметри - вказівник на рядок введення, довжина рядка та зміщення в рядку для початку обробки (має бути 0 для виклику верхнього рівня). Функція повертає кількість перестановок.

Спробуйте в Інтернеті . Здається, TIO зазвичай проходить через усі тести (включаючи antidisestablishmentarianismменше 2 секунд.

Зверніть увагу , що є деякі недруковані в рядку, bcopy()Еда m[]. Здається, TIO справляється з ними правильно.

Безголівки:

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

У мене в середині 2015 року MacBook Pro працює під управлінням MacOS 10.12.4. Компілятор - це кланг MacOS за замовчуванням. Я складаю:

cc splitwords.c -O2 -o splitwords

Запуск усіх тестів, у тому числі 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
$

Це аж ніяк не оптимально. Алгоритм просто перебирає всі можливості (модуль i- див. Коментарі вище) і підраховує слова, які можуть бути розділені за критеріями.


Хороша робота, на самом деле я думаю , що це, ймовірно , можна оцінити результат в O (N), використовуючи фіксовані ефекти 7 класів листи i, -, ', l, mw, fjrt, і abcdeghknopqsuvxyz, але це зайняло б додаток з Поліа перерахування теореми (або еквівалентний комбінаторний метод перерахування), в якому я не добре розбираюся.
Джонатан Аллан

Ви зруйнували мої сподівання, як я і очікував. Ось як ви використовуєте рекурсію :)
Stephen

1

JavaScript (ES6), 199 169 167 байт

Очікує введення рядка в малому регістрі. Надто повільно для щедроти.

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

Тестові справи


1

C, 403 394 байт,

Дякую Кевін!

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

Спробуйте в Інтернеті

Невикористаний код:

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

Ви забули тут f(char* w, int l){f(char*w,int l){
пограти в
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.