Sp | Lit wo(r)dS,S(P)lit 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)在h(a)lf wh | En中具有C(u)T wO | rds (I)s(e)e Th | em。当我开始执行操作时,我付出了很大的努力-B(u)TI几乎不会(n)T d | o。N(o)w,我将其放在脑后,几乎没有(| n | d)它。但是,我认为这将是一个巨大的挑战。

定义

对于这个挑战,根据我对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

对于我的解释和测试用例,|表示可以将单词整齐地分成两半的位置。()在字母的两边表示该字母将被拆分为两半,以创建整齐的拆分。

输入值

输入将包含单个“单词”(不需要在字典中)。您可以在所需的任何文本输入中使用此单词(字符串,字符数组等)。该单词仅包含字母,'-(请参见上表)。由于您将使用此词(请参见下文),因此输入的大小写由开发人员自行决定。如果需要,可以使用尾随换行符。

任务

排列所有形式的输入(所有可能的大写或小写位置的所有字母)。例如,对于input 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 rep赏金(一旦满足此赏金条件,我将立即启动它,因为对我来说似乎基本上是不可能的),该程序可以antidisestablishmentarianism在15秒钟内在普通计算机(又名我的)上输出正确的输出。请注意,不得以任何方式对该测试用例进行硬编码。

@DigitalTrauma压倒了我的赏金,不到两秒钟就到了。在这里查看他的答案。


2
@MackenzieMcClane,除了有五个“ i”使它降至2 ^ 23 = 8,388,608。
乔纳森·艾伦

2
我的第一个数字antidisestablishmentarianism(非高尔夫)是83307040(并且匹配所有测试用例),但是在我的笔记本电脑上大约需要37秒(请注意,它是Python)。有人也有理由吗?
乔纳森·艾伦,


8
我的大脑很奇怪您来对地方了
Luis Mendo

6
我不应该尝试这样做。我不应该尝试这样做。我应该| n(o)tt(r)yt | od | ot(h)e | me。O | h cr | ap ...
Arnauld

Answers:


8

Pyth75 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

如果是中间的分裂 |,则前缀的总和将加倍。

如果将其除以(),则前缀总和加倍减去括号中的值将是总和。


是的,我有时间的时候。(我为自己的日程安排感到抱歉。)
Leaky Nun

11

c,378个字节;大约0.6秒antidisestablishmentarianism

更新答案。我读@ JonathanAllan的有关评论iS,起初我不明白这种优化,但现在我看到的是,由于双方iI具有宽度为1的,那么我们就可以只为验证一旦算上相关排列的两倍。以前,我的解决方案使用多个线程将负载分散到多个CPU上,因此,我几乎可以处理机器上所有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()ed 的字符串中有一些不可打印的内容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;
}

我有一台运行MacOS 10.12.4的2015年中期MacBook Pro。编译器是默认的MacOS clang。我正在编译:

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-'lmwfjrt,和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){
Kevin Cruijssen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.